Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorJohn W. Linville <linville@tuxdriver.com>
Tue, 11 Dec 2012 21:24:55 +0000 (16:24 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 11 Dec 2012 21:24:55 +0000 (16:24 -0500)
2489 files changed:
.gitignore
CREDITS
Documentation/00-INDEX
Documentation/ABI/testing/sysfs-bus-mdio [new file with mode: 0644]
Documentation/ABI/testing/sysfs-class-net-batman-adv
Documentation/ABI/testing/sysfs-class-net-grcan [new file with mode: 0644]
Documentation/ABI/testing/sysfs-class-net-mesh
Documentation/DocBook/media/Makefile
Documentation/DocBook/networking.tmpl
Documentation/IPMI.txt
Documentation/arm64/memory.txt
Documentation/cgroups/memory.txt
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/can/grcan.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/cdns-emac.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/cpsw.txt
Documentation/devicetree/bindings/net/mdio-gpio.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
Documentation/filesystems/proc.txt
Documentation/firmware_class/README
Documentation/hwmon/coretemp
Documentation/hwmon/fam15h_power
Documentation/hwmon/submitting-patches
Documentation/kernel-parameters.txt
Documentation/networking/batman-adv.txt
Documentation/networking/ip-sysctl.txt
Documentation/networking/netdev-features.txt
Documentation/networking/packet_mmap.txt
Documentation/networking/stmmac.txt
Documentation/networking/vxlan.txt
Documentation/sysrq.txt
Documentation/zh_CN/IRQ.txt [new file with mode: 0644]
Documentation/zh_CN/arm64/booting.txt [new file with mode: 0644]
Documentation/zh_CN/arm64/memory.txt [new file with mode: 0644]
MAINTAINERS
Makefile
arch/alpha/include/asm/socket.h
arch/alpha/include/asm/thread_info.h
arch/alpha/kernel/osf_sys.c
arch/alpha/kernel/process.c
arch/alpha/kernel/traps.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/am335x-bone.dts
arch/arm/boot/dts/am335x-evm.dts
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/at91sam9g20ek_common.dtsi
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx6q-arm2.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/kirkwood-lsxl.dtsi
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/wm8505.dtsi
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/mvebu_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/versatile_defconfig
arch/arm/include/asm/flat.h
arch/arm/include/asm/io.h
arch/arm/include/asm/sched_clock.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/vfpmacros.h
arch/arm/include/asm/xen/interface.h
arch/arm/include/asm/xen/page.h
arch/arm/include/debug/8250_32.S [new file with mode: 0644]
arch/arm/include/debug/picoxcell.S
arch/arm/include/debug/socfpga.S
arch/arm/include/uapi/asm/hwcap.h
arch/arm/kernel/entry-common.S
arch/arm/kernel/irq.c
arch/arm/kernel/kprobes-test-arm.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/sched_clock.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_twd.c
arch/arm/lib/delay.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/at91x40.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/include/mach/at91rm9200_emac.h [deleted file]
arch/arm/mach-at91/irq.c
arch/arm/mach-at91/setup.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-dove/common.c
arch/arm/mach-dove/pcie.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/dma.c
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-highbank/system.c
arch/arm/mach-imx/clk-busy.c
arch/arm/mach-imx/clk-gate2.c
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/ehci-imx25.c
arch/arm/mach-imx/ehci-imx35.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-kirkwood/common.c
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/clock33xx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/common-board-devices.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/mux34xx.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-prima2/include/mach/gpio.h [deleted file]
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/spitz_pm.c
arch/arm/mach-s3c24xx/clock-s3c2440.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2443.c
arch/arm/mach-s5p64x0/common.c
arch/arm/mach-s5pc100/common.c
arch/arm/mach-s5pv210/common.c
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/clock-r8a7779.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h [deleted file]
arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h [deleted file]
arch/arm/mach-tegra/board-dt-tegra20.c
arch/arm/mach-tegra/board-dt-tegra30.c
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/tegra20_clocks_data.c
arch/arm/mach-tegra/tegra30_clocks.c
arch/arm/mach-tegra/tegra30_clocks_data.c
arch/arm/mach-tegra/timer.c
arch/arm/mach-ux500/cpu.c
arch/arm/mm/alignment.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/proc-v6.S
arch/arm/mm/vmregion.h
arch/arm/net/bpf_jit_32.c
arch/arm/net/bpf_jit_32.h
arch/arm/plat-mxc/devices/platform-mxc-mmc.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/debug-devices.c
arch/arm/plat-omap/i2c.c
arch/arm/plat-omap/include/plat/omap-serial.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-samsung/include/plat/spi-core.h [new file with mode: 0644]
arch/arm/tools/Makefile
arch/arm/vfp/vfpmodule.c
arch/arm/xen/enlighten.c
arch/arm/xen/grant-table.c
arch/arm/xen/hypercall.S
arch/arm64/Kconfig
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/elf.h
arch/arm64/include/asm/fpsimd.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/linkage.h [new file with mode: 0644]
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/processor.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/uapi/asm/ptrace.h
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/process.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/setup.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/vdso.c
arch/arm64/mm/init.c
arch/avr32/Kconfig
arch/avr32/include/uapi/asm/socket.h
arch/cris/include/asm/socket.h
arch/frv/Kconfig
arch/frv/boot/Makefile
arch/frv/include/asm/unistd.h
arch/frv/include/uapi/asm/socket.h
arch/frv/kernel/entry.S
arch/frv/kernel/process.c
arch/frv/kernel/setup.c
arch/frv/mb93090-mb00/pci-dma-nommu.c
arch/h8300/include/asm/cache.h
arch/h8300/include/asm/socket.h
arch/hexagon/include/asm/Kbuild
arch/hexagon/include/asm/atomic.h
arch/hexagon/include/asm/barrier.h
arch/hexagon/include/asm/bitops.h
arch/hexagon/include/asm/bitsperlong.h [deleted file]
arch/hexagon/include/asm/byteorder.h [deleted file]
arch/hexagon/include/asm/cache.h
arch/hexagon/include/asm/cacheflush.h
arch/hexagon/include/asm/checksum.h
arch/hexagon/include/asm/cmpxchg.h
arch/hexagon/include/asm/delay.h
arch/hexagon/include/asm/dma-mapping.h
arch/hexagon/include/asm/dma.h
arch/hexagon/include/asm/elf.h
arch/hexagon/include/asm/exec.h
arch/hexagon/include/asm/fixmap.h
arch/hexagon/include/asm/hexagon_vm.h
arch/hexagon/include/asm/intrinsics.h
arch/hexagon/include/asm/io.h
arch/hexagon/include/asm/irq.h
arch/hexagon/include/asm/irqflags.h
arch/hexagon/include/asm/kgdb.h
arch/hexagon/include/asm/kvm_para.h [deleted file]
arch/hexagon/include/asm/linkage.h
arch/hexagon/include/asm/mem-layout.h
arch/hexagon/include/asm/mmu.h
arch/hexagon/include/asm/mmu_context.h
arch/hexagon/include/asm/module.h
arch/hexagon/include/asm/page.h
arch/hexagon/include/asm/param.h [deleted file]
arch/hexagon/include/asm/perf_event.h
arch/hexagon/include/asm/pgalloc.h
arch/hexagon/include/asm/pgtable.h
arch/hexagon/include/asm/processor.h
arch/hexagon/include/asm/ptrace.h [deleted file]
arch/hexagon/include/asm/registers.h [deleted file]
arch/hexagon/include/asm/setup.h [deleted file]
arch/hexagon/include/asm/sigcontext.h [deleted file]
arch/hexagon/include/asm/signal.h [deleted file]
arch/hexagon/include/asm/smp.h
arch/hexagon/include/asm/spinlock.h
arch/hexagon/include/asm/spinlock_types.h
arch/hexagon/include/asm/string.h
arch/hexagon/include/asm/suspend.h
arch/hexagon/include/asm/swab.h [deleted file]
arch/hexagon/include/asm/switch_to.h
arch/hexagon/include/asm/syscall.h
arch/hexagon/include/asm/thread_info.h
arch/hexagon/include/asm/time.h
arch/hexagon/include/asm/timer-regs.h
arch/hexagon/include/asm/timex.h
arch/hexagon/include/asm/tlb.h
arch/hexagon/include/asm/tlbflush.h
arch/hexagon/include/asm/traps.h
arch/hexagon/include/asm/uaccess.h
arch/hexagon/include/asm/unistd.h [deleted file]
arch/hexagon/include/asm/user.h [deleted file]
arch/hexagon/include/asm/vdso.h
arch/hexagon/include/asm/vm_fault.h
arch/hexagon/include/asm/vm_mmu.h
arch/hexagon/include/uapi/asm/Kbuild
arch/hexagon/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/kvm_para.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/param.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/registers.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/setup.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/signal.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/swab.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/hexagon/include/uapi/asm/user.h [new file with mode: 0644]
arch/hexagon/kernel/asm-offsets.c
arch/hexagon/kernel/dma.c
arch/hexagon/kernel/head.S
arch/hexagon/kernel/hexagon_ksyms.c
arch/hexagon/kernel/irq_cpu.c
arch/hexagon/kernel/kgdb.c
arch/hexagon/kernel/module.c
arch/hexagon/kernel/process.c
arch/hexagon/kernel/ptrace.c
arch/hexagon/kernel/reset.c
arch/hexagon/kernel/setup.c
arch/hexagon/kernel/signal.c
arch/hexagon/kernel/smp.c
arch/hexagon/kernel/stacktrace.c
arch/hexagon/kernel/syscall.c
arch/hexagon/kernel/syscalltab.c
arch/hexagon/kernel/time.c
arch/hexagon/kernel/topology.c
arch/hexagon/kernel/trampoline.S
arch/hexagon/kernel/traps.c
arch/hexagon/kernel/vdso.c
arch/hexagon/kernel/vm_entry.S
arch/hexagon/kernel/vm_events.c
arch/hexagon/kernel/vm_init_segtable.S
arch/hexagon/kernel/vm_ops.S
arch/hexagon/kernel/vm_switch.S
arch/hexagon/kernel/vm_vectors.S
arch/hexagon/kernel/vmlinux.lds.S
arch/hexagon/lib/checksum.c
arch/hexagon/lib/io.c
arch/hexagon/lib/memcpy.S
arch/hexagon/lib/memset.S
arch/hexagon/mm/cache.c
arch/hexagon/mm/copy_from_user.S
arch/hexagon/mm/copy_to_user.S
arch/hexagon/mm/copy_user_template.S
arch/hexagon/mm/init.c
arch/hexagon/mm/ioremap.c
arch/hexagon/mm/pgalloc.c
arch/hexagon/mm/strnlen_user.S
arch/hexagon/mm/uaccess.c
arch/hexagon/mm/vm_fault.c
arch/hexagon/mm/vm_tlb.c
arch/ia64/include/asm/Kbuild
arch/ia64/include/asm/kvm_para.h [deleted file]
arch/ia64/include/uapi/asm/Kbuild
arch/ia64/include/uapi/asm/kvm_para.h [deleted file]
arch/ia64/include/uapi/asm/socket.h
arch/ia64/mm/init.c
arch/m32r/include/asm/socket.h
arch/m68k/include/asm/Kbuild
arch/m68k/include/asm/a.out.h [deleted file]
arch/m68k/include/asm/auxvec.h [deleted file]
arch/m68k/include/asm/byteorder.h [deleted file]
arch/m68k/include/asm/cachectl.h [deleted file]
arch/m68k/include/asm/fcntl.h [deleted file]
arch/m68k/include/asm/ioctls.h [deleted file]
arch/m68k/include/asm/msgbuf.h [deleted file]
arch/m68k/include/asm/param.h [deleted file]
arch/m68k/include/asm/poll.h [deleted file]
arch/m68k/include/asm/posix_types.h [deleted file]
arch/m68k/include/asm/ptrace.h
arch/m68k/include/asm/sembuf.h [deleted file]
arch/m68k/include/asm/setup.h
arch/m68k/include/asm/shmbuf.h [deleted file]
arch/m68k/include/asm/sigcontext.h [deleted file]
arch/m68k/include/asm/signal.h
arch/m68k/include/asm/socket.h [deleted file]
arch/m68k/include/asm/sockios.h [deleted file]
arch/m68k/include/asm/stat.h [deleted file]
arch/m68k/include/asm/swab.h [deleted file]
arch/m68k/include/asm/termbits.h [deleted file]
arch/m68k/include/asm/termios.h
arch/m68k/include/asm/unistd.h
arch/m68k/include/uapi/asm/Kbuild
arch/m68k/include/uapi/asm/a.out.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/auxvec.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/cachectl.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/fcntl.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/ioctls.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/msgbuf.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/param.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/poll.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/posix_types.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/sembuf.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/setup.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/shmbuf.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/signal.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/socket.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/sockios.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/stat.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/swab.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/termbits.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/termios.h [new file with mode: 0644]
arch/m68k/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/m68k/kernel/syscalltable.S
arch/mips/cavium-octeon/executive/cvmx-l2c.c
arch/mips/fw/arc/misc.c
arch/mips/include/asm/Kbuild
arch/mips/include/asm/bitops.h
arch/mips/include/asm/compat.h
arch/mips/include/asm/delay.h
arch/mips/include/asm/io.h
arch/mips/include/asm/irqflags.h
arch/mips/include/asm/pgtable-64.h
arch/mips/include/asm/thread_info.h
arch/mips/include/uapi/asm/socket.h
arch/mips/jz4740/serial.h
arch/mips/kernel/setup.c
arch/mips/kernel/smp-cmp.c
arch/mips/lib/Makefile
arch/mips/lib/bitops.c [new file with mode: 0644]
arch/mips/lib/delay.c
arch/mips/lib/dump_tlb.c
arch/mips/lib/mips-atomic.c [new file with mode: 0644]
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-platform.c
arch/mn10300/include/uapi/asm/setup.h
arch/mn10300/include/uapi/asm/socket.h
arch/parisc/include/asm/Kbuild
arch/parisc/include/asm/auxvec.h [deleted file]
arch/parisc/include/asm/bitsperlong.h [deleted file]
arch/parisc/include/asm/byteorder.h [deleted file]
arch/parisc/include/asm/compat_signal.h [deleted file]
arch/parisc/include/asm/cputime.h [deleted file]
arch/parisc/include/asm/device.h [deleted file]
arch/parisc/include/asm/div64.h [deleted file]
arch/parisc/include/asm/emergency-restart.h [deleted file]
arch/parisc/include/asm/errno.h [deleted file]
arch/parisc/include/asm/fcntl.h [deleted file]
arch/parisc/include/asm/hw_irq.h [deleted file]
arch/parisc/include/asm/ioctl.h [deleted file]
arch/parisc/include/asm/ioctls.h [deleted file]
arch/parisc/include/asm/ipcbuf.h [deleted file]
arch/parisc/include/asm/irq_regs.h [deleted file]
arch/parisc/include/asm/kdebug.h [deleted file]
arch/parisc/include/asm/kvm_para.h [deleted file]
arch/parisc/include/asm/local.h [deleted file]
arch/parisc/include/asm/local64.h [deleted file]
arch/parisc/include/asm/mman.h [deleted file]
arch/parisc/include/asm/msgbuf.h [deleted file]
arch/parisc/include/asm/mutex.h [deleted file]
arch/parisc/include/asm/param.h [deleted file]
arch/parisc/include/asm/pdc.h
arch/parisc/include/asm/percpu.h [deleted file]
arch/parisc/include/asm/poll.h [deleted file]
arch/parisc/include/asm/posix_types.h [deleted file]
arch/parisc/include/asm/ptrace.h
arch/parisc/include/asm/real.h [deleted file]
arch/parisc/include/asm/resource.h [deleted file]
arch/parisc/include/asm/segment.h [deleted file]
arch/parisc/include/asm/sembuf.h [deleted file]
arch/parisc/include/asm/setup.h [deleted file]
arch/parisc/include/asm/shmbuf.h [deleted file]
arch/parisc/include/asm/sigcontext.h [deleted file]
arch/parisc/include/asm/siginfo.h [deleted file]
arch/parisc/include/asm/signal.h
arch/parisc/include/asm/socket.h [deleted file]
arch/parisc/include/asm/sockios.h [deleted file]
arch/parisc/include/asm/stat.h [deleted file]
arch/parisc/include/asm/statfs.h [deleted file]
arch/parisc/include/asm/swab.h [deleted file]
arch/parisc/include/asm/termbits.h [deleted file]
arch/parisc/include/asm/termios.h
arch/parisc/include/asm/topology.h [deleted file]
arch/parisc/include/asm/types.h [deleted file]
arch/parisc/include/asm/unistd.h
arch/parisc/include/asm/user.h [deleted file]
arch/parisc/include/asm/vga.h [deleted file]
arch/parisc/include/asm/xor.h [deleted file]
arch/parisc/include/uapi/asm/Kbuild
arch/parisc/include/uapi/asm/bitsperlong.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/errno.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/fcntl.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/ioctl.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/ioctls.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/ipcbuf.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/mman.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/msgbuf.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/pdc.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/posix_types.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/resource.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/sembuf.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/setup.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/shmbuf.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/siginfo.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/signal.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/socket.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/sockios.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/stat.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/statfs.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/swab.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/termbits.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/termios.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/types.h [new file with mode: 0644]
arch/parisc/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/parisc/kernel/signal32.c
arch/parisc/kernel/sys_parisc.c
arch/powerpc/boot/dts/mpc5200b.dtsi
arch/powerpc/boot/dts/o2d.dtsi
arch/powerpc/boot/dts/pcm030.dts
arch/powerpc/include/asm/kvm_book3s_32.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/uapi/asm/socket.h
arch/powerpc/kernel/sysfs.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/net/bpf_jit.h
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/platforms/52xx/mpc52xx_pic.c
arch/powerpc/platforms/pseries/eeh_pe.c
arch/powerpc/platforms/pseries/msi.c
arch/powerpc/platforms/pseries/processor_idle.c
arch/s390/Kconfig
arch/s390/boot/compressed/vmlinux.lds.S
arch/s390/include/asm/cio.h
arch/s390/include/asm/compat.h
arch/s390/include/asm/perf_event.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/topology.h
arch/s390/include/uapi/asm/chpid.h
arch/s390/include/uapi/asm/kvm_para.h
arch/s390/include/uapi/asm/ptrace.h
arch/s390/include/uapi/asm/socket.h
arch/s390/kernel/cache.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/head_kdump.S
arch/s390/kernel/perf_cpum_cf.c
arch/s390/kernel/sclp.S
arch/s390/kernel/signal.c
arch/s390/kernel/topology.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/lib/uaccess_pt.c
arch/s390/mm/gup.c
arch/sh/include/asm/Kbuild
arch/sh/include/asm/auxvec.h [deleted file]
arch/sh/include/asm/byteorder.h [deleted file]
arch/sh/include/asm/cachectl.h [deleted file]
arch/sh/include/asm/cpu-features.h [deleted file]
arch/sh/include/asm/hw_breakpoint.h
arch/sh/include/asm/ioctls.h [deleted file]
arch/sh/include/asm/posix_types.h
arch/sh/include/asm/posix_types_32.h [deleted file]
arch/sh/include/asm/posix_types_64.h [deleted file]
arch/sh/include/asm/ptrace.h
arch/sh/include/asm/ptrace_32.h
arch/sh/include/asm/ptrace_64.h
arch/sh/include/asm/setup.h
arch/sh/include/asm/sigcontext.h [deleted file]
arch/sh/include/asm/signal.h [deleted file]
arch/sh/include/asm/sockios.h [deleted file]
arch/sh/include/asm/stat.h [deleted file]
arch/sh/include/asm/swab.h [deleted file]
arch/sh/include/asm/types.h
arch/sh/include/asm/unistd.h
arch/sh/include/asm/unistd_32.h [deleted file]
arch/sh/include/asm/unistd_64.h [deleted file]
arch/sh/include/uapi/asm/Kbuild
arch/sh/include/uapi/asm/auxvec.h [new file with mode: 0644]
arch/sh/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/sh/include/uapi/asm/cachectl.h [new file with mode: 0644]
arch/sh/include/uapi/asm/cpu-features.h [new file with mode: 0644]
arch/sh/include/uapi/asm/hw_breakpoint.h [new file with mode: 0644]
arch/sh/include/uapi/asm/ioctls.h [new file with mode: 0644]
arch/sh/include/uapi/asm/posix_types.h [new file with mode: 0644]
arch/sh/include/uapi/asm/posix_types_32.h [new file with mode: 0644]
arch/sh/include/uapi/asm/posix_types_64.h [new file with mode: 0644]
arch/sh/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/sh/include/uapi/asm/ptrace_32.h [new file with mode: 0644]
arch/sh/include/uapi/asm/ptrace_64.h [new file with mode: 0644]
arch/sh/include/uapi/asm/setup.h [new file with mode: 0644]
arch/sh/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/sh/include/uapi/asm/signal.h [new file with mode: 0644]
arch/sh/include/uapi/asm/sockios.h [new file with mode: 0644]
arch/sh/include/uapi/asm/stat.h [new file with mode: 0644]
arch/sh/include/uapi/asm/swab.h [new file with mode: 0644]
arch/sh/include/uapi/asm/types.h [new file with mode: 0644]
arch/sh/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/sh/include/uapi/asm/unistd_32.h [new file with mode: 0644]
arch/sh/include/uapi/asm/unistd_64.h [new file with mode: 0644]
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sparc/Kconfig
arch/sparc/crypto/Makefile
arch/sparc/crypto/aes_glue.c
arch/sparc/crypto/camellia_glue.c
arch/sparc/crypto/crc32c_glue.c
arch/sparc/crypto/des_glue.c
arch/sparc/crypto/md5_glue.c
arch/sparc/crypto/sha1_glue.c
arch/sparc/crypto/sha256_glue.c
arch/sparc/crypto/sha512_glue.c
arch/sparc/include/asm/atomic_64.h
arch/sparc/include/asm/backoff.h
arch/sparc/include/asm/compat.h
arch/sparc/include/asm/processor_64.h
arch/sparc/include/asm/prom.h
arch/sparc/include/asm/ptrace.h
arch/sparc/include/asm/smp_64.h
arch/sparc/include/asm/thread_info_64.h
arch/sparc/include/asm/ttable.h
arch/sparc/include/uapi/asm/sigcontext.h
arch/sparc/include/uapi/asm/socket.h
arch/sparc/include/uapi/asm/unistd.h
arch/sparc/kernel/entry.h
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/perf_event.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/ptrace_64.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/smp_64.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/kernel/unaligned_64.c
arch/sparc/kernel/visemul.c
arch/sparc/kernel/vmlinux.lds.S
arch/sparc/kernel/winfixup.S
arch/sparc/lib/atomic_64.S
arch/sparc/lib/ksyms.c
arch/sparc/math-emu/math_64.c
arch/sparc/mm/ultra.S
arch/sparc/net/bpf_jit_comp.c
arch/tile/Makefile
arch/tile/include/arch/Kbuild
arch/tile/include/asm/Kbuild
arch/tile/include/uapi/asm/Kbuild
arch/tile/kernel/module.c
arch/unicore32/Kconfig
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/asm/bug.h
arch/unicore32/include/asm/byteorder.h [deleted file]
arch/unicore32/include/asm/cmpxchg.h
arch/unicore32/include/asm/kvm_para.h [deleted file]
arch/unicore32/include/asm/processor.h
arch/unicore32/include/asm/ptrace.h
arch/unicore32/include/asm/sigcontext.h [deleted file]
arch/unicore32/include/asm/unistd.h [deleted file]
arch/unicore32/include/uapi/asm/Kbuild
arch/unicore32/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/unicore32/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/unicore32/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/unicore32/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/unicore32/kernel/entry.S
arch/unicore32/kernel/process.c
arch/unicore32/kernel/setup.h
arch/unicore32/kernel/sys.c
arch/unicore32/mm/fault.c
arch/x86/Makefile
arch/x86/boot/compressed/eboot.c
arch/x86/boot/header.S
arch/x86/crypto/aesni-intel_glue.c
arch/x86/include/asm/efi.h
arch/x86/include/asm/ptrace.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/include/asm/xen/hypervisor.h
arch/x86/include/asm/xen/interface.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mcheck/mce_intel.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/cpu/perf_event_knc.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/e820.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/kvm.c
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/ptrace.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/uprobes.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/init.c
arch/x86/mm/init_64.c
arch/x86/mm/tlb.c
arch/x86/net/bpf_jit_comp.c
arch/x86/oprofile/nmi_int.c
arch/x86/pci/ce4100.c
arch/x86/platform/ce4100/ce4100.c
arch/x86/platform/efi/efi.c
arch/x86/platform/efi/efi_64.c
arch/x86/realmode/rm/wakeup_asm.S
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/xtensa/Kconfig
arch/xtensa/boot/boot-redboot/bootstrap.S
arch/xtensa/include/asm/Kbuild
arch/xtensa/include/asm/atomic.h
arch/xtensa/include/asm/auxvec.h [deleted file]
arch/xtensa/include/asm/bitsperlong.h [deleted file]
arch/xtensa/include/asm/bug.h [deleted file]
arch/xtensa/include/asm/byteorder.h [deleted file]
arch/xtensa/include/asm/cacheflush.h
arch/xtensa/include/asm/cmpxchg.h
arch/xtensa/include/asm/coprocessor.h
arch/xtensa/include/asm/cputime.h [deleted file]
arch/xtensa/include/asm/delay.h
arch/xtensa/include/asm/device.h [deleted file]
arch/xtensa/include/asm/div64.h [deleted file]
arch/xtensa/include/asm/emergency-restart.h [deleted file]
arch/xtensa/include/asm/errno.h [deleted file]
arch/xtensa/include/asm/fcntl.h [deleted file]
arch/xtensa/include/asm/futex.h [deleted file]
arch/xtensa/include/asm/hardirq.h [deleted file]
arch/xtensa/include/asm/io.h
arch/xtensa/include/asm/ioctl.h [deleted file]
arch/xtensa/include/asm/ioctls.h [deleted file]
arch/xtensa/include/asm/ipcbuf.h [deleted file]
arch/xtensa/include/asm/irq_regs.h [deleted file]
arch/xtensa/include/asm/irqflags.h
arch/xtensa/include/asm/kdebug.h [deleted file]
arch/xtensa/include/asm/kmap_types.h [deleted file]
arch/xtensa/include/asm/kvm_para.h [deleted file]
arch/xtensa/include/asm/local.h [deleted file]
arch/xtensa/include/asm/local64.h [deleted file]
arch/xtensa/include/asm/mman.h [deleted file]
arch/xtensa/include/asm/mmu_context.h
arch/xtensa/include/asm/msgbuf.h [deleted file]
arch/xtensa/include/asm/param.h
arch/xtensa/include/asm/percpu.h [deleted file]
arch/xtensa/include/asm/poll.h [deleted file]
arch/xtensa/include/asm/posix_types.h [deleted file]
arch/xtensa/include/asm/processor.h
arch/xtensa/include/asm/ptrace.h
arch/xtensa/include/asm/regs.h
arch/xtensa/include/asm/resource.h [deleted file]
arch/xtensa/include/asm/scatterlist.h [deleted file]
arch/xtensa/include/asm/sections.h [deleted file]
arch/xtensa/include/asm/sembuf.h [deleted file]
arch/xtensa/include/asm/setup.h [deleted file]
arch/xtensa/include/asm/shmbuf.h [deleted file]
arch/xtensa/include/asm/sigcontext.h [deleted file]
arch/xtensa/include/asm/siginfo.h [deleted file]
arch/xtensa/include/asm/signal.h
arch/xtensa/include/asm/socket.h [deleted file]
arch/xtensa/include/asm/sockios.h [deleted file]
arch/xtensa/include/asm/stat.h [deleted file]
arch/xtensa/include/asm/statfs.h [deleted file]
arch/xtensa/include/asm/swab.h [deleted file]
arch/xtensa/include/asm/syscall.h
arch/xtensa/include/asm/termbits.h [deleted file]
arch/xtensa/include/asm/termios.h [deleted file]
arch/xtensa/include/asm/timex.h
arch/xtensa/include/asm/tlbflush.h
arch/xtensa/include/asm/topology.h [deleted file]
arch/xtensa/include/asm/types.h
arch/xtensa/include/asm/unistd.h
arch/xtensa/include/asm/xor.h [deleted file]
arch/xtensa/include/uapi/asm/Kbuild
arch/xtensa/include/uapi/asm/auxvec.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/byteorder.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/ioctls.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/ipcbuf.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/mman.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/msgbuf.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/param.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/poll.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/posix_types.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/sembuf.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/setup.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/shmbuf.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/sigcontext.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/signal.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/socket.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/sockios.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/stat.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/swab.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/termbits.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/types.h [new file with mode: 0644]
arch/xtensa/include/uapi/asm/unistd.h [new file with mode: 0644]
arch/xtensa/kernel/align.S
arch/xtensa/kernel/coprocessor.S
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/head.S
arch/xtensa/kernel/irq.c
arch/xtensa/kernel/process.c
arch/xtensa/kernel/setup.c
arch/xtensa/kernel/syscall.c
arch/xtensa/kernel/traps.c
arch/xtensa/kernel/vectors.S
arch/xtensa/kernel/xtensa_ksyms.c
arch/xtensa/lib/memcopy.S
arch/xtensa/mm/fault.c
arch/xtensa/platforms/iss/console.c
arch/xtensa/platforms/iss/include/platform/simcall.h
arch/xtensa/platforms/iss/setup.c
arch/xtensa/platforms/xt2000/setup.c
block/Kconfig
block/blk-cgroup.c
block/blk-core.c
block/blk-exec.c
crypto/cryptd.c
drivers/Makefile
drivers/acpi/Makefile
drivers/acpi/glue.c
drivers/acpi/processor_driver.c
drivers/acpi/video.c
drivers/ata/ahci_platform.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/pata_arasan_cf.c
drivers/ata/sata_highbank.c
drivers/ata/sata_svw.c
drivers/atm/ambassador.c
drivers/atm/solos-pci.c
drivers/base/Kconfig
drivers/base/dma-coherent.c
drivers/base/dma-contiguous.c
drivers/base/firmware_class.c
drivers/base/platform.c
drivers/base/power/domain.c
drivers/base/power/qos.c
drivers/base/regmap/Kconfig
drivers/block/Kconfig
drivers/block/aoe/aoecmd.c
drivers/block/cciss.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/bus/omap-ocp2scp.c
drivers/char/Makefile
drivers/char/agp/intel-gtt.c
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/sonypi.c
drivers/clk/ux500/u8500_clk.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/powernow-k8.c
drivers/dma/Kconfig
drivers/dma/dw_dmac_regs.h
drivers/dma/imx-dma.c
drivers/dma/ioat/dca.c
drivers/dma/sirf-dma.c
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/edac_stub.c
drivers/edac/mce_amd_inj.c
drivers/extcon/extcon-adc-jack.c
drivers/extcon/extcon-class.c
drivers/extcon/extcon-gpio.c
drivers/extcon/extcon-max77693.c
drivers/extcon/extcon-max8997.c
drivers/firewire/sbp2.c
drivers/firmware/memmap.c
drivers/gpio/Kconfig
drivers/gpio/gpio-74x164.c
drivers/gpio/gpio-mcp23s08.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-timberdale.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/drm_fb_cma_helper.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/drm_info.c
drivers/gpu/drm/drm_platform.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/i915/dvo_ch7xxx.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sdvo_regs.h
drivers/gpu/drm/nouveau/core/core/gpuobj.c
drivers/gpu/drm/nouveau/core/core/mm.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
drivers/gpu/drm/nouveau/core/engine/mpeg/nv40.c
drivers/gpu/drm/nouveau/core/include/core/mm.h
drivers/gpu/drm/nouveau/core/include/core/object.h
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
drivers/gpu/drm/nouveau/core/subdev/bios/pll.c
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv41.c
drivers/gpu/drm/nouveau/core/subdev/vm/nv44.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nouveau_irq.c
drivers/gpu/drm/nouveau/nouveau_pm.c
drivers/gpu/drm/nouveau/nv04_dac.c
drivers/gpu/drm/nouveau/nv04_dfp.c
drivers/gpu/drm/nouveau/nv04_tv.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/nid.h
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_acpi.c
drivers/gpu/drm/radeon/radeon_agp.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_gem.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_legacy_encoders.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_ring.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/radeon/sid.h
drivers/gpu/drm/shmobile/shmob_drm_drv.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/udl/udl_drv.h
drivers/gpu/drm/udl/udl_fb.c
drivers/gpu/drm/udl/udl_transfer.c
drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/hid/hid-apple.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-microsoft.c
drivers/hid/hid-multitouch.c
drivers/hid/hidraw.c
drivers/hv/channel.c
drivers/hwmon/asb100.c
drivers/hwmon/coretemp.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/pmbus/Kconfig
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/hwmon/w83791d.c
drivers/hwmon/w83792d.c
drivers/hwmon/w83l786ng.c
drivers/i2c/Makefile
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-stub.c [deleted file]
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/i2c-stub.c [new file with mode: 0644]
drivers/i2c/muxes/i2c-mux-pinctrl.c
drivers/iio/Kconfig
drivers/iio/Makefile
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/mlx4/alias_GUID.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/mcg.c
drivers/input/evdev.c
drivers/input/input-mt.c
drivers/input/joydev.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/pxa27x_keypad.c
drivers/input/misc/xen-kbdfront.c
drivers/input/mouse/bcm5974.c
drivers/input/mousedev.c
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/egalax_ts.c
drivers/input/touchscreen/tsc40.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/intel-iommu.c
drivers/iommu/tegra-smmu.c
drivers/irqchip/irq-bcm2835.c
drivers/isdn/Kconfig
drivers/isdn/gigaset/bas-gigaset.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/hardware/mISDN/mISDNisar.c
drivers/isdn/hisax/callc.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/hfc_sx.c
drivers/isdn/i4l/Kconfig
drivers/isdn/i4l/isdn_common.c
drivers/isdn/mISDN/l1oip_core.c
drivers/isdn/mISDN/tei.c
drivers/isdn/pcbit/layer2.c
drivers/leds/ledtrig-cpu.c
drivers/md/dm.c
drivers/md/faulty.c
drivers/md/md.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/Kconfig
drivers/media/dvb-frontends/stv0900_core.c
drivers/media/i2c/adv7604.c
drivers/media/i2c/soc_camera/mt9v022.c
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/omap3isp/ispccdc.c
drivers/media/platform/omap3isp/ispstat.c
drivers/media/platform/omap3isp/ispstat.h
drivers/media/platform/omap3isp/ispvideo.c
drivers/media/platform/s5p-fimc/Kconfig
drivers/media/platform/s5p-fimc/fimc-capture.c
drivers/media/platform/s5p-fimc/fimc-lite.c
drivers/media/platform/s5p-fimc/fimc-mdevice.c
drivers/media/platform/sh_vou.c
drivers/media/platform/soc_camera/mx1_camera.c
drivers/media/platform/soc_camera/mx2_camera.c
drivers/media/platform/soc_camera/mx3_camera.c
drivers/media/platform/soc_camera/omap1_camera.c
drivers/media/platform/soc_camera/pxa_camera.c
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
drivers/media/usb/dvb-usb-v2/rtl28xxu.c
drivers/mfd/arizona-core.c
drivers/mfd/arizona-irq.c
drivers/mfd/twl-core.c
drivers/mfd/twl4030-irq.c
drivers/mfd/wm5102-tables.c
drivers/mmc/host/dw_mmc-exynos.c
drivers/mmc/host/dw_mmc-pltfm.c
drivers/mmc/host/dw_mmc-pltfm.h
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mxcmmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pltfm.c
drivers/mmc/host/sdhci-s3c.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mmcif.c
drivers/mtd/devices/slram.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/nand_base.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/onenand_base.c
drivers/net/arcnet/com20020-pci.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_alb.h
drivers/net/bonding/bond_debugfs.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/bonding/bonding.h
drivers/net/can/Kconfig
drivers/net/can/Makefile
drivers/net/can/at91_can.c
drivers/net/can/bfin_can.c
drivers/net/can/c_can/c_can.c
drivers/net/can/c_can/c_can.h
drivers/net/can/c_can/c_can_pci.c
drivers/net/can/c_can/c_can_platform.c
drivers/net/can/cc770/cc770_isa.c
drivers/net/can/cc770/cc770_platform.c
drivers/net/can/dev.c
drivers/net/can/flexcan.c
drivers/net/can/grcan.c [new file with mode: 0644]
drivers/net/can/janz-ican3.c
drivers/net/can/mcp251x.c
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/can/mscan/mscan.c
drivers/net/can/mscan/mscan.h
drivers/net/can/pch_can.c
drivers/net/can/sja1000/Kconfig
drivers/net/can/sja1000/ems_pci.c
drivers/net/can/sja1000/ems_pcmcia.c
drivers/net/can/sja1000/kvaser_pci.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/can/sja1000/peak_pcmcia.c
drivers/net/can/sja1000/plx_pci.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/sja1000/sja1000.h
drivers/net/can/sja1000/sja1000_isa.c
drivers/net/can/sja1000/sja1000_of_platform.c
drivers/net/can/sja1000/sja1000_platform.c
drivers/net/can/sja1000/tscan1.c
drivers/net/can/softing/softing_cs.c
drivers/net/can/softing/softing_main.c
drivers/net/can/ti_hecc.c
drivers/net/can/usb/Kconfig
drivers/net/can/usb/Makefile
drivers/net/can/usb/ems_usb.c
drivers/net/can/usb/esd_usb2.c
drivers/net/can/usb/kvaser_usb.c [new file with mode: 0644]
drivers/net/can/usb/peak_usb/pcan_usb.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_core.h
drivers/net/can/usb/peak_usb/pcan_usb_pro.c
drivers/net/dsa/Kconfig
drivers/net/ethernet/3com/3c509.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/3com/Kconfig
drivers/net/ethernet/3com/typhoon.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/8390/etherh.c
drivers/net/ethernet/8390/hydra.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/8390/ne2k-pci.c
drivers/net/ethernet/8390/ne3210.c
drivers/net/ethernet/8390/zorro8390.c
drivers/net/ethernet/adaptec/starfire.c
drivers/net/ethernet/adi/Kconfig
drivers/net/ethernet/adi/bfin_mac.c
drivers/net/ethernet/adi/bfin_mac.h
drivers/net/ethernet/aeroflex/greth.c
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/amd/a2065.c
drivers/net/ethernet/amd/am79c961a.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/ariadne.c
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/ethernet/amd/declance.c
drivers/net/ethernet/amd/depca.c
drivers/net/ethernet/amd/hplance.c
drivers/net/ethernet/amd/pcnet32.c
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/apple/bmac.c
drivers/net/ethernet/apple/mace.c
drivers/net/ethernet/apple/macmace.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_param.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/atheros/atlx/atl2.c
drivers/net/ethernet/broadcom/Kconfig
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_fw_defs.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_hsi.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_init_ops.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
drivers/net/ethernet/broadcom/cnic.c
drivers/net/ethernet/broadcom/cnic.h
drivers/net/ethernet/broadcom/cnic_if.h
drivers/net/ethernet/broadcom/sb1250-mac.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/brocade/bna/bfa_ioc.c
drivers/net/ethernet/brocade/bna/bnad.c
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/cadence/at91_ether.c
drivers/net/ethernet/cadence/at91_ether.h [deleted file]
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/cadence/macb.h
drivers/net/ethernet/calxeda/xgmac.c
drivers/net/ethernet/chelsio/Kconfig
drivers/net/ethernet/chelsio/cxgb/cxgb2.c
drivers/net/ethernet/chelsio/cxgb/sge.c
drivers/net/ethernet/chelsio/cxgb/subr.c
drivers/net/ethernet/chelsio/cxgb/tp.c
drivers/net/ethernet/chelsio/cxgb3/common.h
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/cisco/Kconfig
drivers/net/ethernet/cisco/enic/Kconfig
drivers/net/ethernet/cisco/enic/enic_main.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/dec/ewrk3.c
drivers/net/ethernet/dec/tulip/de2104x.c
drivers/net/ethernet/dec/tulip/de4x5.c
drivers/net/ethernet/dec/tulip/dmfe.c
drivers/net/ethernet/dec/tulip/eeprom.c
drivers/net/ethernet/dec/tulip/media.c
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/dec/tulip/uli526x.c
drivers/net/ethernet/dec/tulip/winbond-840.c
drivers/net/ethernet/dec/tulip/xircom_cb.c
drivers/net/ethernet/dlink/dl2k.c
drivers/net/ethernet/dlink/sundance.c
drivers/net/ethernet/dnet.c
drivers/net/ethernet/emulex/Kconfig
drivers/net/ethernet/emulex/benet/Kconfig
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_cmds.h
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/emulex/benet/be_roce.c
drivers/net/ethernet/ethoc.c
drivers/net/ethernet/fealnx.c
drivers/net/ethernet/freescale/Kconfig
drivers/net/ethernet/freescale/Makefile
drivers/net/ethernet/freescale/fec.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_mpc52xx.c
drivers/net/ethernet/freescale/fec_ptp.c [new file with mode: 0644]
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/fs_enet/mii-bitbang.c
drivers/net/ethernet/freescale/fs_enet/mii-fec.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/freescale/xgmac_mdio.c
drivers/net/ethernet/hp/hp100.c
drivers/net/ethernet/i825xx/ether1.c
drivers/net/ethernet/i825xx/lasi_82596.c
drivers/net/ethernet/i825xx/lib82596.c
drivers/net/ethernet/i825xx/sni_82596.c
drivers/net/ethernet/ibm/Kconfig
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/emac/core.c
drivers/net/ethernet/ibm/emac/mal.c
drivers/net/ethernet/ibm/emac/rgmii.c
drivers/net/ethernet/ibm/emac/tah.c
drivers/net/ethernet/ibm/emac/zmii.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/icplus/ipg.c
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/e100.c
drivers/net/ethernet/intel/e1000/e1000_hw.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000/e1000_param.c
drivers/net/ethernet/intel/e1000e/80003es2lan.c
drivers/net/ethernet/intel/e1000e/82571.c
drivers/net/ethernet/intel/e1000e/defines.h
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/hw.h
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/mac.c
drivers/net/ethernet/intel/e1000e/manage.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/nvm.c
drivers/net/ethernet/intel/e1000e/param.c
drivers/net/ethernet/intel/e1000e/phy.c
drivers/net/ethernet/intel/igb/Makefile
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/e1000_82575.h
drivers/net/ethernet/intel/igb/e1000_defines.h
drivers/net/ethernet/intel/igb/e1000_i210.c
drivers/net/ethernet/intel/igb/e1000_i210.h
drivers/net/ethernet/intel/igb/e1000_mac.c
drivers/net/ethernet/intel/igb/e1000_mac.h
drivers/net/ethernet/intel/igb/e1000_nvm.c
drivers/net/ethernet/intel/igb/e1000_nvm.h
drivers/net/ethernet/intel/igb/e1000_phy.c
drivers/net/ethernet/intel/igb/e1000_phy.h
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igb/igb_ptp.c
drivers/net/ethernet/intel/igbvf/defines.h
drivers/net/ethernet/intel/igbvf/igbvf.h
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/intel/ixgb/ixgb_param.c
drivers/net/ethernet/intel/ixgbe/Makefile
drivers/net/ethernet/intel/ixgbe/ixgbe.h
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.h
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
drivers/net/ethernet/intel/ixgbevf/defines.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/intel/ixgbevf/mbx.h
drivers/net/ethernet/intel/ixgbevf/vf.c
drivers/net/ethernet/intel/ixgbevf/vf.h
drivers/net/ethernet/jme.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mellanox/Kconfig
drivers/net/ethernet/mellanox/mlx4/Kconfig
drivers/net/ethernet/mellanox/mlx4/en_dcb_nl.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_main.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/micrel/ks8695net.c
drivers/net/ethernet/micrel/ks8842.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/micrel/ks8851_mll.c
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/microchip/enc28j60.c
drivers/net/ethernet/myricom/Kconfig
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/natsemi/ibmlana.c
drivers/net/ethernet/natsemi/jazzsonic.c
drivers/net/ethernet/natsemi/macsonic.c
drivers/net/ethernet/natsemi/natsemi.c
drivers/net/ethernet/natsemi/ns83820.c
drivers/net/ethernet/natsemi/xtsonic.c
drivers/net/ethernet/neterion/Kconfig
drivers/net/ethernet/neterion/s2io.c
drivers/net/ethernet/neterion/s2io.h
drivers/net/ethernet/neterion/vxge/vxge-config.c
drivers/net/ethernet/neterion/vxge/vxge-config.h
drivers/net/ethernet/neterion/vxge/vxge-main.c
drivers/net/ethernet/nuvoton/w90p910_ether.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/octeon/octeon_mgmt.c
drivers/net/ethernet/oki-semi/pch_gbe/Kconfig
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe.h
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/packetengines/hamachi.c
drivers/net/ethernet/packetengines/yellowfin.c
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/qlogic/qlcnic/Makefile
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c [new file with mode: 0644]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c [new file with mode: 0644]
drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c [new file with mode: 0644]
drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/rdc/r6040.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/8139too.c
drivers/net/ethernet/realtek/atp.c
drivers/net/ethernet/realtek/atp.h
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/s6gmac.c
drivers/net/ethernet/seeq/ether3.c
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/sfc/Kconfig
drivers/net/ethernet/sfc/Makefile
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/ethtool.c
drivers/net/ethernet/sfc/falcon.c
drivers/net/ethernet/sfc/io.h
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/sfc/selftest.c
drivers/net/ethernet/sfc/siena.c
drivers/net/ethernet/sfc/siena_sriov.c
drivers/net/ethernet/sgi/ioc3-eth.c
drivers/net/ethernet/sgi/meth.c
drivers/net/ethernet/silan/sc92031.c
drivers/net/ethernet/sis/sis190.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/smsc/epic100.c
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/smsc/smc911x.h
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smc91x.h
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/smsc/smsc9420.c
drivers/net/ethernet/stmicro/stmmac/Kconfig
drivers/net/ethernet/stmicro/stmmac/Makefile
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c [deleted file]
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h [deleted file]
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/sun/sunqe.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/ti/Makefile
drivers/net/ethernet/ti/cpmac.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_ale.c
drivers/net/ethernet/ti/cpsw_ale.h
drivers/net/ethernet/ti/cpts.c [new file with mode: 0644]
drivers/net/ethernet/ti/cpts.h [new file with mode: 0644]
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/ethernet/ti/tlan.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
drivers/net/ethernet/toshiba/spider_net.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/wiznet/w5100.c
drivers/net/ethernet/wiznet/w5300.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/fddi/defxx.c
drivers/net/fddi/skfp/skfddi.c
drivers/net/hippi/rrunner.c
drivers/net/hyperv/rndis_filter.c
drivers/net/ieee802154/at86rf230.c
drivers/net/ieee802154/fakehard.c
drivers/net/ieee802154/fakelb.c
drivers/net/ieee802154/mrf24j40.c
drivers/net/irda/au1k_ir.c
drivers/net/irda/bfin_sir.c
drivers/net/irda/ep7211-sir.c
drivers/net/irda/sh_irda.c
drivers/net/irda/sh_sir.c
drivers/net/irda/sir_dev.c
drivers/net/irda/smsc-ircc2.c
drivers/net/irda/via-ircc.c
drivers/net/irda/vlsi_ir.c
drivers/net/netconsole.c
drivers/net/phy/Kconfig
drivers/net/phy/Makefile
drivers/net/phy/at803x.c [new file with mode: 0644]
drivers/net/phy/davicom.c
drivers/net/phy/dp83640.c
drivers/net/phy/mdio-gpio.c
drivers/net/phy/mdio-mux-gpio.c
drivers/net/phy/mdio-mux-mmioreg.c
drivers/net/phy/mdio-octeon.c
drivers/net/phy/mdio_bus.c
drivers/net/phy/micrel.c
drivers/net/phy/smsc.c
drivers/net/phy/spi_ks8995.c
drivers/net/ppp/ppp_generic.c
drivers/net/team/team.c
drivers/net/team/team_mode_broadcast.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/cdc_eem.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_mbim.c [new file with mode: 0644]
drivers/net/usb/cdc_ncm.c
drivers/net/usb/dm9601.c
drivers/net/usb/int51x1.c
drivers/net/usb/ipheth.c
drivers/net/usb/mcs7830.c
drivers/net/usb/net1080.c
drivers/net/usb/plusb.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/sierra_net.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/smsc95xx.h
drivers/net/usb/usbnet.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vxlan.c
drivers/net/wan/Makefile
drivers/net/wan/dscc4.c
drivers/net/wan/farsync.c
drivers/net/wan/hd64570.c
drivers/net/wan/hd64572.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wan/lmc/lmc_main.c
drivers/net/wan/pc300too.c
drivers/net/wan/pci200syn.c
drivers/net/wan/wanxl.c
drivers/net/wan/wanxlfw.S
drivers/net/wireless/b43legacy/pio.c
drivers/net/xen-netfront.c
drivers/of/address.c
drivers/of/irq.c
drivers/of/platform.c
drivers/pci/bus.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/aer/aerdrv_core.c
drivers/pci/pcie/portdrv_core.c
drivers/pci/proc.c
drivers/pcmcia/pxa2xx_sharpsl.c
drivers/pinctrl/Kconfig
drivers/pinctrl/core.c
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinctrl-bcm2835.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-sirf.c
drivers/pinctrl/pinctrl-tegra.c
drivers/pinctrl/pinctrl-tegra30.c
drivers/pinctrl/pinctrl-xway.c
drivers/pinctrl/spear/pinctrl-spear.c
drivers/pinctrl/spear/pinctrl-spear1310.c
drivers/pinctrl/spear/pinctrl-spear1340.c
drivers/pinctrl/spear/pinctrl-spear320.c
drivers/pinctrl/spear/pinctrl-spear3xx.h
drivers/pps/Kconfig
drivers/ptp/Kconfig
drivers/ptp/ptp_chardev.c
drivers/rapidio/rio.c
drivers/regulator/core.c
drivers/rtc/rtc-imxdi.c
drivers/s390/char/con3215.c
drivers/s390/cio/css.c
drivers/s390/cio/css.h
drivers/s390/cio/device.c
drivers/s390/cio/idset.c
drivers/s390/cio/idset.h
drivers/s390/net/claw.c
drivers/s390/net/ctcm_main.c
drivers/s390/net/ctcm_mpc.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/smsgiucv.c
drivers/scsi/arm/fas216.c
drivers/scsi/arm/oak.c
drivers/scsi/isci/request.c
drivers/scsi/qla2xxx/qla_mid.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla2xxx/tcm_qla2xxx.h
drivers/scsi/qlogicpti.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/sh/intc/access.c
drivers/sh/intc/chip.c
drivers/spi/spi-mxs.c
drivers/spi/spi-pl022.c
drivers/spi/spi-rspi.c
drivers/spi/spi-s3c64xx.c
drivers/staging/android/android_alarm.h
drivers/staging/android/binder.c
drivers/staging/comedi/drivers/8255_pci.c
drivers/staging/comedi/drivers/amplc_dio200.c
drivers/staging/comedi/drivers/amplc_pc236.c
drivers/staging/comedi/drivers/amplc_pc263.c
drivers/staging/comedi/drivers/das08.c
drivers/staging/comedi/drivers/ni_daq_700.c
drivers/staging/comedi/drivers/ni_labpc.c
drivers/staging/dgrp/dgrp_mon_ops.c
drivers/staging/dgrp/dgrp_specproc.c
drivers/staging/dgrp/dgrp_tty.c
drivers/staging/iio/accel/adis16201_core.c
drivers/staging/iio/accel/adis16203_core.c
drivers/staging/iio/accel/adis16204_core.c
drivers/staging/iio/accel/adis16209_core.c
drivers/staging/iio/accel/adis16220_core.c
drivers/staging/iio/accel/adis16240_core.c
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/iio/imu/adis16400.h
drivers/staging/iio/imu/adis16400_core.c
drivers/staging/ipack/bridges/tpci200.c
drivers/staging/omapdrm/omap_gem.c
drivers/staging/ramster/Kconfig
drivers/staging/tidspbridge/core/tiomap3430.c
drivers/staging/tidspbridge/hw/hw_mmu.c
drivers/staging/tidspbridge/hw/hw_mmu.h
drivers/staging/tidspbridge/include/dspbridge/cfgdefs.h
drivers/staging/tidspbridge/include/dspbridge/host_os.h
drivers/staging/tidspbridge/rmgr/drv.c
drivers/staging/tidspbridge/rmgr/node.c
drivers/staging/zram/zram_drv.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_util.c
drivers/target/iscsi/iscsi_target_util.h
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_sbc.c
drivers/target/target_core_spc.c
drivers/target/target_core_tmr.c
drivers/target/target_core_transport.c
drivers/thermal/Kconfig
drivers/thermal/exynos_thermal.c
drivers/thermal/rcar_thermal.c
drivers/tty/hvc/hvc_console.c
drivers/tty/serial/8250/8250_hp300.c
drivers/tty/serial/Kconfig
drivers/tty/serial/max310x.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/sccnxp.c
drivers/tty/serial/sh-sci.c
drivers/tty/sysrq.c
drivers/tty/vt/vt.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/devio.c
drivers/usb/core/driver.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/gadget.c
drivers/usb/early/ehci-dbgp.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/lpc32xx_udc.c
drivers/usb/gadget/net2272.c
drivers/usb/gadget/u_ether.c
drivers/usb/host/ehci-fsl.c
drivers/usb/host/ehci-ls1x.c
drivers/usb/host/ehci-orion.c
drivers/usb/host/ehci-vt8500.c
drivers/usb/host/ohci-xls.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/uhci-platform.c
drivers/usb/host/xhci-dbg.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/misc/ezusb.c
drivers/usb/musb/am35x.c
drivers/usb/musb/musb_dsps.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/ux500.c
drivers/usb/otg/Kconfig
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/renesas_usbhs/pipe.h
drivers/usb/serial/ark3116.c
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/ch341.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/f81232.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_tables.h
drivers/usb/serial/io_ti.c
drivers/usb/serial/ipw.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/metro-usb.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/omninet.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/sierra.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/ssu100.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-wwan.h
drivers/usb/serial/usb_wwan.c
drivers/usb/serial/whiteheat.c
drivers/usb/storage/scsiglue.c
drivers/usb/storage/unusual_devs.h
drivers/vhost/net.c
drivers/vhost/tcm_vhost.c
drivers/vhost/vhost.c
drivers/vhost/vhost.h
drivers/video/backlight/Kconfig
drivers/video/backlight/lm3639_bl.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/video/xen-fbfront.c
drivers/virtio/virtio.c
drivers/xen/Kconfig
drivers/xen/Makefile
drivers/xen/balloon.c
drivers/xen/dbgp.c
drivers/xen/events.c
drivers/xen/fallback.c [new file with mode: 0644]
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/privcmd.c
drivers/xen/sys-hypervisor.c
drivers/xen/xen-pciback/vpci.c
drivers/xen/xenbus/xenbus_dev_frontend.c
drivers/xen/xenbus/xenbus_xs.c
fs/bio.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/backref.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/ceph/export.c
fs/char_dev.c
fs/cifs/cifsacl.c
fs/cifs/dir.c
fs/compat_ioctl.c
fs/coredump.c
fs/eventpoll.c
fs/exec.c
fs/ext2/super.c
fs/ext3/balloc.c
fs/ext3/namei.c
fs/ext3/namei.h
fs/ext3/super.c
fs/ext4/balloc.c
fs/ext4/bitmap.c
fs/ext4/ext4.h
fs/ext4/ext4_jbd2.c
fs/ext4/extents.c
fs/ext4/ialloc.c
fs/ext4/mballoc.c
fs/ext4/resize.c
fs/ext4/super.c
fs/file.c
fs/fs-writeback.c
fs/gfs2/file.c
fs/gfs2/lops.c
fs/gfs2/quota.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/gfs2/trans.c
fs/inode.c
fs/internal.h
fs/jbd/transaction.c
fs/jffs2/file.c
fs/jfs/jfs_discard.c
fs/lockd/clntxdr.c
fs/lockd/mon.c
fs/lockd/svcproc.c
fs/namei.c
fs/nfs/callback.c
fs/nfs/dns_resolve.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/namespace.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4filelayout.h
fs/nfs/nfs4filelayoutdev.c
fs/nfs/nfs4getroot.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/super.c
fs/nfs/unlink.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/proc/base.c
fs/proc/internal.h
fs/proc/proc_sysctl.c
fs/proc/stat.c
fs/proc/task_mmu.c
fs/pstore/platform.c
fs/quota/dquot.c
fs/reiserfs/inode.c
fs/reiserfs/stree.c
fs/reiserfs/super.c
fs/sysfs/dir.c
fs/ubifs/find.c
fs/ubifs/lprops.c
fs/ubifs/ubifs.h
fs/xattr.c
fs/xfs/xfs_alloc.c
fs/xfs/xfs_alloc.h
fs/xfs/xfs_alloc_btree.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_bmap.c
fs/xfs/xfs_bmap.h
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_fsops.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_recover.c
include/Kbuild
include/asm-generic/Kbuild [deleted file]
include/drm/Kbuild [deleted file]
include/drm/drm_pciids.h
include/linux/Kbuild
include/linux/atmdev.h
include/linux/bug.h
include/linux/byteorder/Kbuild [deleted file]
include/linux/caif/Kbuild [deleted file]
include/linux/can/Kbuild [deleted file]
include/linux/clk-provider.h
include/linux/coredump.h
include/linux/dvb/Kbuild
include/linux/dvb/audio.h [deleted file]
include/linux/dvb/ca.h [deleted file]
include/linux/dvb/dmx.h
include/linux/dvb/frontend.h [deleted file]
include/linux/dvb/net.h [deleted file]
include/linux/dvb/osd.h [deleted file]
include/linux/dvb/version.h [deleted file]
include/linux/dvb/video.h
include/linux/dynamic_debug.h
include/linux/elf-fdpic.h [new file with mode: 0644]
include/linux/etherdevice.h
include/linux/extcon.h
include/linux/filter.h
include/linux/fs.h
include/linux/gfp.h
include/linux/hashtable.h [new file with mode: 0644]
include/linux/hdlc/Kbuild
include/linux/hdlc/ioctl.h [deleted file]
include/linux/hsi/Kbuild
include/linux/hsi/hsi_char.h [deleted file]
include/linux/i2c-omap.h
include/linux/if_tunnel.h
include/linux/iio/iio.h
include/linux/inetdevice.h
include/linux/ip.h
include/linux/ipv6.h
include/linux/isdn/Kbuild [deleted file]
include/linux/ktime.h
include/linux/kvm_host.h
include/linux/memblock.h
include/linux/mfd/max77693.h
include/linux/micrel_phy.h
include/linux/mm.h
include/linux/mmc/Kbuild [deleted file]
include/linux/mmc/dw_mmc.h
include/linux/mmc/sdhci.h
include/linux/mmzone.h
include/linux/netdevice.h
include/linux/netfilter/Kbuild [deleted file]
include/linux/netfilter/ipset/Kbuild [deleted file]
include/linux/netfilter_arp/Kbuild [deleted file]
include/linux/netfilter_bridge/Kbuild [deleted file]
include/linux/netfilter_ipv4/Kbuild [deleted file]
include/linux/netfilter_ipv6/Kbuild [deleted file]
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/nfsd/Kbuild [deleted file]
include/linux/of.h
include/linux/of_address.h
include/linux/of_irq.h
include/linux/openvswitch.h
include/linux/pci.h
include/linux/percpu-rwsem.h
include/linux/perf_event.h
include/linux/pid_namespace.h
include/linux/platform_data/cpsw.h
include/linux/platform_data/macb.h
include/linux/platform_data/omap_ocp2scp.h [new file with mode: 0644]
include/linux/ptp_clock_kernel.h
include/linux/raid/Kbuild
include/linux/raid/md_p.h [deleted file]
include/linux/raid/md_u.h
include/linux/ratelimit.h
include/linux/rbtree_augmented.h
include/linux/rio.h
include/linux/rtnetlink.h
include/linux/skbuff.h
include/linux/smscphy.h
include/linux/spi/Kbuild [deleted file]
include/linux/spi/ads7846.h
include/linux/spi/tsc2005.h
include/linux/stmmac.h
include/linux/sunrpc/Kbuild [deleted file]
include/linux/sysctl.h
include/linux/tc_act/Kbuild [deleted file]
include/linux/tc_ematch/Kbuild [deleted file]
include/linux/tcp.h
include/linux/timecompare.h [deleted file]
include/linux/udp.h
include/linux/uprobes.h
include/linux/usb.h
include/linux/usb/Kbuild
include/linux/usb/audio.h
include/linux/usb/cdc.h [deleted file]
include/linux/usb/cdc_ncm.h [new file with mode: 0644]
include/linux/usb/ch11.h [deleted file]
include/linux/usb/ch9.h
include/linux/usb/functionfs.h
include/linux/usb/g_printer.h [deleted file]
include/linux/usb/gadgetfs.h [deleted file]
include/linux/usb/midi.h [deleted file]
include/linux/usb/tmc.h [deleted file]
include/linux/usb/usbnet.h
include/linux/usb/video.h [deleted file]
include/linux/wimax/Kbuild [deleted file]
include/media/adv7604.h
include/mtd/Kbuild [deleted file]
include/net/addrconf.h
include/net/af_unix.h
include/net/cls_cgroup.h
include/net/gro_cells.h
include/net/inet_hashtables.h
include/net/inet_sock.h
include/net/inet_timewait_sock.h
include/net/ip6_checksum.h
include/net/ip6_fib.h
include/net/ip6_route.h
include/net/ip_vs.h
include/net/ipip.h
include/net/ipv6.h
include/net/net_namespace.h
include/net/netfilter/nf_conntrack.h
include/net/netfilter/nf_nat.h
include/net/netfilter/nf_queue.h
include/net/netns/sctp.h
include/net/protocol.h
include/net/request_sock.h
include/net/route.h
include/net/rtnetlink.h
include/net/sctp/command.h
include/net/sctp/constants.h
include/net/sctp/sctp.h
include/net/sctp/sm.h
include/net/sctp/structs.h
include/net/sctp/ulpqueue.h
include/net/sctp/user.h
include/net/sock.h
include/net/tcp.h
include/net/xfrm.h
include/scsi/scsi_device.h
include/sound/core.h
include/trace/events/gfpflags.h
include/trace/events/xen.h
include/uapi/asm-generic/kvm_para.h
include/uapi/asm-generic/socket.h
include/uapi/linux/dvb/Kbuild
include/uapi/linux/dvb/audio.h [new file with mode: 0644]
include/uapi/linux/dvb/ca.h [new file with mode: 0644]
include/uapi/linux/dvb/dmx.h [new file with mode: 0644]
include/uapi/linux/dvb/frontend.h [new file with mode: 0644]
include/uapi/linux/dvb/net.h [new file with mode: 0644]
include/uapi/linux/dvb/osd.h [new file with mode: 0644]
include/uapi/linux/dvb/version.h [new file with mode: 0644]
include/uapi/linux/dvb/video.h [new file with mode: 0644]
include/uapi/linux/elf-fdpic.h
include/uapi/linux/eventpoll.h
include/uapi/linux/filter.h
include/uapi/linux/fs.h
include/uapi/linux/hdlc/Kbuild
include/uapi/linux/hdlc/ioctl.h [new file with mode: 0644]
include/uapi/linux/hsi/Kbuild
include/uapi/linux/hsi/hsi_char.h [new file with mode: 0644]
include/uapi/linux/if_bridge.h
include/uapi/linux/if_ether.h
include/uapi/linux/if_link.h
include/uapi/linux/if_packet.h
include/uapi/linux/if_tun.h
include/uapi/linux/if_tunnel.h
include/uapi/linux/in6.h
include/uapi/linux/inet_diag.h
include/uapi/linux/ipv6.h
include/uapi/linux/ipv6_route.h
include/uapi/linux/irqnr.h
include/uapi/linux/netconf.h [new file with mode: 0644]
include/uapi/linux/netfilter/nfnetlink_conntrack.h
include/uapi/linux/netfilter_ipv6/ip6_tables.h
include/uapi/linux/oom.h
include/uapi/linux/ptp_clock.h
include/uapi/linux/raid/Kbuild
include/uapi/linux/raid/md_p.h [new file with mode: 0644]
include/uapi/linux/raid/md_u.h [new file with mode: 0644]
include/uapi/linux/rtnetlink.h
include/uapi/linux/tcp.h
include/uapi/linux/unix_diag.h
include/uapi/linux/usb/Kbuild
include/uapi/linux/usb/audio.h [new file with mode: 0644]
include/uapi/linux/usb/cdc.h [new file with mode: 0644]
include/uapi/linux/usb/ch11.h [new file with mode: 0644]
include/uapi/linux/usb/ch9.h [new file with mode: 0644]
include/uapi/linux/usb/functionfs.h [new file with mode: 0644]
include/uapi/linux/usb/g_printer.h [new file with mode: 0644]
include/uapi/linux/usb/gadgetfs.h [new file with mode: 0644]
include/uapi/linux/usb/midi.h [new file with mode: 0644]
include/uapi/linux/usb/tmc.h [new file with mode: 0644]
include/uapi/linux/usb/video.h [new file with mode: 0644]
include/uapi/linux/virtio_net.h
include/xen/Kbuild [deleted file]
include/xen/grant_table.h
include/xen/hvm.h
include/xen/interface/grant_table.h
include/xen/interface/memory.h
init/main.c
kernel/Makefile
kernel/cgroup.c
kernel/events/uprobes.c
kernel/futex.c
kernel/module-internal.h
kernel/module.c
kernel/module_signing.c
kernel/nsproxy.c
kernel/pid_namespace.c
kernel/printk.c
kernel/sys.c
kernel/time/Makefile
kernel/time/timecompare.c [deleted file]
kernel/trace/ring_buffer.c
kernel/watchdog.c
kernel/workqueue.c
lib/dma-debug.c
lib/genalloc.c
lib/mpi/longlong.h
mm/bootmem.c
mm/compaction.c
mm/fremap.c
mm/highmem.c
mm/huge_memory.c
mm/memblock.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mmap.c
mm/mmu_notifier.c
mm/mmzone.c
mm/nobootmem.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/slob.c
mm/swapfile.c
mm/vmscan.c
net/8021q/vlan.c
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/atm/br2684.c
net/atm/common.c
net/atm/pppoatm.c
net/batman-adv/Kconfig
net/batman-adv/Makefile
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bitarray.c
net/batman-adv/bridge_loop_avoidance.c
net/batman-adv/bridge_loop_avoidance.h
net/batman-adv/debugfs.c
net/batman-adv/distributed-arp-table.c [new file with mode: 0644]
net/batman-adv/distributed-arp-table.h [new file with mode: 0644]
net/batman-adv/gateway_client.c
net/batman-adv/hard-interface.c
net/batman-adv/hash.h
net/batman-adv/icmp_socket.c
net/batman-adv/main.c
net/batman-adv/main.h
net/batman-adv/originator.c
net/batman-adv/packet.h
net/batman-adv/routing.c
net/batman-adv/send.c
net/batman-adv/send.h
net/batman-adv/soft-interface.c
net/batman-adv/sysfs.c
net/batman-adv/translation-table.c
net/batman-adv/translation-table.h
net/batman-adv/types.h
net/batman-adv/unicast.c
net/batman-adv/unicast.h
net/batman-adv/vis.c
net/bridge/Makefile
net/bridge/br_device.c
net/bridge/br_input.c
net/bridge/br_ioctl.c
net/bridge/br_mdb.c [new file with mode: 0644]
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/bridge/br_stp.c
net/bridge/br_stp_bpdu.c
net/bridge/br_sysfs_br.c
net/bridge/br_sysfs_if.c
net/caif/caif_usb.c
net/caif/cfctrl.c
net/can/bcm.c
net/can/gw.c
net/ceph/messenger.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/ethtool.c
net/core/filter.c
net/core/flow.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/net_namespace.c
net/core/netpoll.c
net/core/netprio_cgroup.c
net/core/pktgen.c
net/core/rtnetlink.c
net/core/scm.c
net/core/skbuff.c
net/core/sock.c
net/core/sysctl_net_core.c
net/dcb/dcbnl.c
net/dccp/minisocks.c
net/decnet/dn_dev.c
net/decnet/dn_fib.c
net/dsa/Kconfig
net/ieee802154/6lowpan.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_semantics.c
net/ipv4/icmp.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_diag.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_fragment.c
net/ipv4/ip_gre.c
net/ipv4/ip_options.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_vti.c
net/ipv4/ipconfig.c
net/ipv4/ipip.c
net/ipv4/ipmr.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_CLUSTERIP.c
net/ipv4/netfilter/iptable_nat.c
net/ipv4/protocol.c
net/ipv4/route.c
net/ipv4/syncookies.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_cong.c
net/ipv4/tcp_illinois.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv4/xfrm4_policy.c
net/ipv6/Makefile
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ah6.c
net/ipv6/anycast.c
net/ipv6/datagram.c
net/ipv6/exthdrs.c
net/ipv6/exthdrs_core.c
net/ipv6/exthdrs_offload.c [new file with mode: 0644]
net/ipv6/fib6_rules.c
net/ipv6/icmp.c
net/ipv6/inet6_connection_sock.c
net/ipv6/inet6_hashtables.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_flowlabel.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_offload.c [new file with mode: 0644]
net/ipv6/ip6_offload.h [new file with mode: 0644]
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6mr.c
net/ipv6/ipv6_sockglue.c
net/ipv6/mcast.c
net/ipv6/ndisc.c
net/ipv6/netfilter/ip6_tables.c
net/ipv6/netfilter/ip6t_rpfilter.c
net/ipv6/netfilter/ip6table_nat.c
net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
net/ipv6/netfilter/nf_nat_proto_icmpv6.c
net/ipv6/output_core.c [new file with mode: 0644]
net/ipv6/protocol.c
net/ipv6/raw.c
net/ipv6/reassembly.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/ipv6/tcpv6_offload.c [new file with mode: 0644]
net/ipv6/udp.c
net/ipv6/udp_offload.c [new file with mode: 0644]
net/ipv6/xfrm6_policy.c
net/ipv6/xfrm6_state.c
net/irda/ircomm/ircomm_tty.c
net/irda/irttp.c
net/key/af_key.c
net/l2tp/l2tp_eth.c
net/l2tp/l2tp_netlink.c
net/llc/af_llc.c
net/mac80211/debugfs_sta.c
net/mac802154/tx.c
net/mac802154/wpan.c
net/netfilter/core.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_hash_ip.c
net/netfilter/ipset/ip_set_hash_ipport.c
net/netfilter/ipset/ip_set_hash_ipportip.c
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/ipset/ip_set_hash_netiface.c
net/netfilter/ipvs/Kconfig
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_dh.c
net/netfilter/ipvs/ip_vs_lblc.c
net/netfilter/ipvs/ip_vs_lblcr.c
net/netfilter/ipvs/ip_vs_nfct.c
net/netfilter/ipvs/ip_vs_pe_sip.c
net/netfilter/ipvs/ip_vs_proto.c
net/netfilter/ipvs/ip_vs_proto_ah_esp.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/ipvs/ip_vs_proto_tcp.c
net/netfilter/ipvs/ip_vs_proto_udp.c
net/netfilter/ipvs/ip_vs_sched.c
net/netfilter/ipvs/ip_vs_sh.c
net/netfilter/ipvs/ip_vs_xmit.c
net/netfilter/nf_conntrack_acct.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_ecache.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_dccp.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_conntrack_timestamp.c
net/netfilter/nf_queue.c
net/netfilter/nfnetlink.c
net/netfilter/nfnetlink_cttimeout.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/xt_CT.c
net/netfilter/xt_HMARK.c
net/netfilter/xt_TEE.c
net/netfilter/xt_ipvs.c
net/netfilter/xt_nat.c
net/netlink/af_netlink.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/flow.c
net/openvswitch/flow.h
net/openvswitch/vport-netdev.c
net/openvswitch/vport-netdev.h
net/openvswitch/vport.c
net/packet/af_packet.c
net/packet/internal.h
net/phonet/pn_netlink.c
net/rds/ib.h
net/rds/ib_recv.c
net/sched/Kconfig
net/sched/act_api.c
net/sched/cls_api.c
net/sched/cls_cgroup.c
net/sched/sch_api.c
net/sched/sch_cbq.c
net/sched/sch_htb.c
net/sched/sch_qfq.c
net/sctp/Kconfig
net/sctp/associola.c
net/sctp/chunk.c
net/sctp/endpointola.c
net/sctp/inqueue.c
net/sctp/ipv6.c
net/sctp/output.c
net/sctp/outqueue.c
net/sctp/proc.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/sm_statefuns.c
net/sctp/socket.c
net/sctp/sysctl.c
net/sctp/transport.c
net/sctp/tsnmap.c
net/sctp/ulpqueue.c
net/socket.c
net/sunrpc/backchannel_rqst.c
net/sunrpc/cache.c
net/sunrpc/xprtsock.c
net/sysctl_net.c
net/tipc/Kconfig
net/tipc/bcast.c
net/tipc/bearer.c
net/tipc/bearer.h
net/tipc/core.c
net/tipc/discover.c
net/tipc/handler.c
net/tipc/link.c
net/tipc/link.h
net/tipc/name_distr.c
net/tipc/node.c
net/tipc/node.h
net/tipc/port.c
net/tipc/port.h
net/tipc/socket.c
net/tipc/subscr.c
net/unix/diag.c
net/unix/sysctl_net_unix.c
net/xfrm/xfrm_ipcomp.c
net/xfrm/xfrm_replay.c
net/xfrm/xfrm_sysctl.c
net/xfrm/xfrm_user.c
scripts/Makefile.asm-generic
scripts/Makefile.fwinst
scripts/Makefile.modinst
scripts/Makefile.modpost
scripts/checkpatch.pl
scripts/dtc/dtc.h
scripts/headers_install.pl
scripts/kconfig/expr.h
scripts/kconfig/list.h [new file with mode: 0644]
scripts/kconfig/lkc_proto.h
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/sign-file [changed mode: 0644->0755]
scripts/x509keyid [deleted file]
security/apparmor/Makefile
security/apparmor/policy.c
security/device_cgroup.c
security/selinux/hooks.c
security/selinux/netnode.c
security/selinux/nlmsgtab.c
sound/core/compress_offload.c
sound/core/control.c
sound/core/hwdep.c
sound/core/init.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_oss.c
sound/core/pcm.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/sound.c
sound/core/sound_oss.c
sound/i2c/other/ak4113.c
sound/i2c/other/ak4114.c
sound/i2c/other/ak4117.c
sound/isa/opti9xx/miro.c
sound/pci/ac97/ac97_codec.c
sound/pci/als300.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/ice1724.c
sound/pci/rme9652/hdspm.c
sound/soc/Makefile
sound/soc/codecs/arizona.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/da9055.c
sound/soc/codecs/twl6040.c
sound/soc/codecs/wm2200.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm8978.c
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.h
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/mxs/mxs-saif.c
sound/soc/omap/ams-delta.c
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/zoom2.c
sound/soc/pxa/mmp-pcm.c
sound/soc/samsung/Kconfig
sound/soc/samsung/bells.c
sound/soc/sh/fsi.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-jack.c
sound/soc/ux500/mop500.c
sound/soc/ux500/ux500_msp_i2s.c
sound/usb/card.c
sound/usb/card.h
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/midi.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/pcm.c
sound/usb/proc.c
sound/usb/stream.c
sound/usb/usbaudio.h
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/parse-filter.c
tools/perf/Makefile
tools/perf/builtin-help.c
tools/perf/builtin-trace.c
tools/perf/perf.h
tools/perf/ui/browsers/hists.c
tools/perf/util/parse-events-test.c
tools/perf/util/parse-events.c
tools/perf/util/setup.py
tools/perf/util/sort.c
tools/perf/util/thread.c
tools/power/x86/turbostat/turbostat.c
tools/testing/ktest/ktest.pl
tools/testing/selftests/Makefile
tools/testing/selftests/epoll/Makefile [deleted file]
tools/testing/selftests/epoll/test_epoll.c [deleted file]
tools/virtio/virtio_test.c
tools/vm/page-types.c
usr/gen_init_cpio.c
virt/kvm/kvm_main.c

index 0f2f40f71915fcdbf1a10b1e975131d137cdf2fa..92bd0e45dfa165cfdaddb3de4f91e2db61a7a927 100644 (file)
 *.o.*
 *.a
 *.s
-*.ko.unsigned
-*.ko.stripped
-*.ko.stripped.dig
-*.ko.stripped.sig
 *.ko
 *.so
 *.so.dbg
@@ -95,6 +91,4 @@ GTAGS
 extra_certificates
 signing_key.priv
 signing_key.x509
-signing_key.x509.keyid
-signing_key.x509.signer
 x509.genkey
diff --git a/CREDITS b/CREDITS
index d8fe12a9421fa2a7145e7218cc7d664232d0d7ce..2346b09ca8bb9cfc3c4371eb5ad6058be818d990 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1823,6 +1823,11 @@ S: Kattreinstr 38
 S: D-64295
 S: Germany
 
+N: Avi Kivity
+E: avi.kivity@gmail.com
+D: Kernel-based Virtual Machine (KVM)
+S: Ra'annana, Israel
+
 N: Andi Kleen
 E: andi@firstfloor.org
 U: http://www.halobates.de
index f54273e2ac979a386e27c0174e4a9524e60eae5e..ceb1ff735469995b560f0cdf07227407be682235 100644 (file)
@@ -210,6 +210,8 @@ local_ops.txt
        - semantics and behavior of local atomic operations.
 lockdep-design.txt
        - documentation on the runtime locking correctness validator.
+lockup-watchdogs.txt
+       - info on soft and hard lockup detectors (aka nmi_watchdog).
 logo.gif
        - full colour GIF image of Linux logo (penguin - Tux).
 logo.txt
@@ -240,8 +242,6 @@ netlabel/
        - directory with information on the NetLabel subsystem.
 networking/
        - directory with info on various aspects of networking with Linux.
-nmi_watchdog.txt
-       - info on NMI watchdog for SMP systems.
 nommu-mmap.txt
        - documentation about no-mmu memory mapping support.
 numastat.txt
diff --git a/Documentation/ABI/testing/sysfs-bus-mdio b/Documentation/ABI/testing/sysfs-bus-mdio
new file mode 100644 (file)
index 0000000..6349749
--- /dev/null
@@ -0,0 +1,9 @@
+What:          /sys/bus/mdio_bus/devices/.../phy_id
+Date:          November 2012
+KernelVersion: 3.8
+Contact:       netdev@vger.kernel.org
+Description:
+               This attribute contains the 32-bit PHY Identifier as reported
+               by the device during bus enumeration, encoded in hexadecimal.
+               This ID is used to match the device with the appropriate
+               driver.
index 38dd762def4b8fda48daf66800b93ce2666bd01d..bdc00707c751b955d997aa7ce0c51bd8b0222ca5 100644 (file)
@@ -1,4 +1,10 @@
 
+What:           /sys/class/net/<iface>/batman-adv/iface_status
+Date:           May 2010
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
+Description:
+                Indicates the status of <iface> as it is seen by batman.
+
 What:           /sys/class/net/<iface>/batman-adv/mesh_iface
 Date:           May 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -7,8 +13,3 @@ Description:
                 displays the batman mesh interface this <iface>
                 currently is associated with.
 
-What:           /sys/class/net/<iface>/batman-adv/iface_status
-Date:           May 2010
-Contact:        Marek Lindner <lindner_marek@yahoo.de>
-Description:
-                Indicates the status of <iface> as it is seen by batman.
diff --git a/Documentation/ABI/testing/sysfs-class-net-grcan b/Documentation/ABI/testing/sysfs-class-net-grcan
new file mode 100644 (file)
index 0000000..f418c92
--- /dev/null
@@ -0,0 +1,35 @@
+
+What:          /sys/class/net/<iface>/grcan/enable0
+Date:          October 2012
+KernelVersion: 3.8
+Contact:       Andreas Larsson <andreas@gaisler.com>
+Description:
+               Hardware configuration of physical interface 0. This file reads
+               and writes the "Enable 0" bit of the configuration register.
+               Possible values: 0 or 1. See the GRCAN chapter of the GRLIB IP
+               core library documentation for details. The default value is 0
+               or set by the module parameter grcan.enable0 and can be read at
+               /sys/module/grcan/parameters/enable0.
+
+What:          /sys/class/net/<iface>/grcan/enable1
+Date:          October 2012
+KernelVersion: 3.8
+Contact:       Andreas Larsson <andreas@gaisler.com>
+Description:
+               Hardware configuration of physical interface 1. This file reads
+               and writes the "Enable 1" bit of the configuration register.
+               Possible values: 0 or 1. See the GRCAN chapter of the GRLIB IP
+               core library documentation for details. The default value is 0
+               or set by the module parameter grcan.enable1 and can be read at
+               /sys/module/grcan/parameters/enable1.
+
+What:          /sys/class/net/<iface>/grcan/select
+Date:          October 2012
+KernelVersion: 3.8
+Contact:       Andreas Larsson <andreas@gaisler.com>
+Description:
+               Configuration of which physical interface to be used. Possible
+               values: 0 or 1. See the GRCAN chapter of the GRLIB IP core
+               library documentation for details. The default value is 0 or is
+               set by the module parameter grcan.select and can be read at
+               /sys/module/grcan/parameters/select.
index c81fe89c4c46d4f48e7e3bc8954d587bb9e6d69d..bc41da61608d5dfc22e0c2836aa00c56499c9d98 100644 (file)
@@ -6,6 +6,14 @@ Description:
                 Indicates whether the batman protocol messages of the
                 mesh <mesh_iface> shall be aggregated or not.
 
+What:           /sys/class/net/<mesh_iface>/mesh/ap_isolation
+Date:           May 2011
+Contact:        Antonio Quartulli <ordex@autistici.org>
+Description:
+                Indicates whether the data traffic going from a
+                wireless client to another wireless client will be
+                silently dropped.
+
 What:           /sys/class/net/<mesh_iface>/mesh/bonding
 Date:           June 2010
 Contact:        Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
@@ -31,14 +39,6 @@ Description:
                 mesh will be fragmented or silently discarded if the
                 packet size exceeds the outgoing interface MTU.
 
-What:          /sys/class/net/<mesh_iface>/mesh/ap_isolation
-Date:          May 2011
-Contact:       Antonio Quartulli <ordex@autistici.org>
-Description:
-               Indicates whether the data traffic going from a
-               wireless client to another wireless client will be
-               silently dropped.
-
 What:           /sys/class/net/<mesh_iface>/mesh/gw_bandwidth
 Date:           October 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -60,6 +60,13 @@ Description:
                 Defines the selection criteria this node will use
                 to choose a gateway if gw_mode was set to 'client'.
 
+What:           /sys/class/net/<mesh_iface>/mesh/hop_penalty
+Date:           Oct 2010
+Contact:        Linus Lüssing <linus.luessing@web.de>
+Description:
+                Defines the penalty which will be applied to an
+                originator message's tq-field on every hop.
+
 What:           /sys/class/net/<mesh_iface>/mesh/orig_interval
 Date:           May 2010
 Contact:        Marek Lindner <lindner_marek@yahoo.de>
@@ -67,19 +74,12 @@ Description:
                 Defines the interval in milliseconds in which batman
                 sends its protocol messages.
 
-What:           /sys/class/net/<mesh_iface>/mesh/hop_penalty
-Date:           Oct 2010
-Contact:        Linus Lüssing <linus.luessing@web.de>
-Description:
-               Defines the penalty which will be applied to an
-               originator message's tq-field on every hop.
-
-What:          /sys/class/net/<mesh_iface>/mesh/routing_algo
-Date:          Dec 2011
-Contact:       Marek Lindner <lindner_marek@yahoo.de>
+What:           /sys/class/net/<mesh_iface>/mesh/routing_algo
+Date:           Dec 2011
+Contact:        Marek Lindner <lindner_marek@yahoo.de>
 Description:
-               Defines the routing procotol this mesh instance
-               uses to find the optimal paths through the mesh.
+                Defines the routing procotol this mesh instance
+                uses to find the optimal paths through the mesh.
 
 What:           /sys/class/net/<mesh_iface>/mesh/vis_mode
 Date:           May 2010
index 9b7e4c55792803b1c053bc99026860a5ce56e88d..f9fd615427fbd4c0a718d66ed1b7de006ab796e6 100644 (file)
@@ -56,15 +56,15 @@ FUNCS = \
        write \
 
 IOCTLS = \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/videodev2.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/audio.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/ca.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/dmx.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/frontend.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/net.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/dvb/video.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/media.h) \
-       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/linux/v4l2-subdev.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([A-Z][^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /\#define\s+([^\s]+)\s+_IO/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
        VIDIOC_SUBDEV_G_FRAME_INTERVAL \
        VIDIOC_SUBDEV_S_FRAME_INTERVAL \
        VIDIOC_SUBDEV_ENUM_MBUS_CODE \
@@ -74,32 +74,32 @@ IOCTLS = \
        VIDIOC_SUBDEV_S_SELECTION \
 
 TYPES = \
-       $(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/linux/videodev2.h) \
-       $(shell perl -ne 'print "$$1 " if /^}\s+([a-z0-9_]+_t)/' $(srctree)/include/linux/dvb/frontend.h)
+       $(shell perl -ne 'print "$$1 " if /^typedef\s+[^\s]+\s+([^\s]+)\;/' $(srctree)/include/uapi/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /^}\s+([a-z0-9_]+_t)/' $(srctree)/include/uapi/linux/dvb/frontend.h)
 
 ENUMS = \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/audio.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/ca.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/dmx.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/frontend.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/net.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/dvb/video.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h) \
-       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h)
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h) \
+       $(shell perl -ne 'print "$$1 " if /^enum\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h)
 
 STRUCTS = \
-       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/videodev2.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s\{]+)\s*/)' $(srctree)/include/linux/dvb/audio.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/ca.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/dmx.h) \
-       $(shell perl -ne 'print "$$1 " if (!/dtv\_cmds\_h/ && /^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/frontend.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([A-Z][^\s]+)\s+/)' $(srctree)/include/linux/dvb/net.h) \
-       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/linux/dvb/video.h) \
-       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/media.h) \
-       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-subdev.h) \
-       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/linux/v4l2-mediabus.h)
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/videodev2.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s\{]+)\s*/)' $(srctree)/include/uapi/linux/dvb/audio.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/ca.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/dmx.h) \
+       $(shell perl -ne 'print "$$1 " if (!/dtv\_cmds\_h/ && /^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/frontend.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([A-Z][^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/net.h) \
+       $(shell perl -ne 'print "$$1 " if (/^struct\s+([^\s]+)\s+/)' $(srctree)/include/uapi/linux/dvb/video.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/media.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-subdev.h) \
+       $(shell perl -ne 'print "$$1 " if /^struct\s+([^\s]+)\s+/' $(srctree)/include/uapi/linux/v4l2-mediabus.h)
 
 ERRORS = \
        E2BIG \
@@ -205,7 +205,7 @@ $(MEDIA_OBJ_DIR)/v4l2.xml: $(OBJIMGFILES)
        @(ln -sf $(MEDIA_SRC_DIR)/v4l/*xml $(MEDIA_OBJ_DIR)/)
        @(ln -sf $(MEDIA_SRC_DIR)/dvb/*xml $(MEDIA_OBJ_DIR)/)
 
-$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/linux/videodev2.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/uapi/linux/videodev2.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -216,7 +216,7 @@ $(MEDIA_OBJ_DIR)/videodev2.h.xml: $(srctree)/include/linux/videodev2.h $(MEDIA_O
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/linux/dvb/audio.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/uapi/linux/dvb/audio.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -227,7 +227,7 @@ $(MEDIA_OBJ_DIR)/audio.h.xml: $(srctree)/include/linux/dvb/audio.h $(MEDIA_OBJ_D
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/uapi/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -238,7 +238,7 @@ $(MEDIA_OBJ_DIR)/ca.h.xml: $(srctree)/include/linux/dvb/ca.h $(MEDIA_OBJ_DIR)/v4
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/uapi/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -249,7 +249,7 @@ $(MEDIA_OBJ_DIR)/dmx.h.xml: $(srctree)/include/linux/dvb/dmx.h $(MEDIA_OBJ_DIR)/
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/linux/dvb/frontend.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/uapi/linux/dvb/frontend.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -260,7 +260,7 @@ $(MEDIA_OBJ_DIR)/frontend.h.xml: $(srctree)/include/linux/dvb/frontend.h $(MEDIA
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/linux/dvb/net.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/uapi/linux/dvb/net.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
@@ -271,7 +271,7 @@ $(MEDIA_OBJ_DIR)/net.h.xml: $(srctree)/include/linux/dvb/net.h $(MEDIA_OBJ_DIR)/
        @(                                      \
        echo "</programlisting>") >> $@
 
-$(MEDIA_OBJ_DIR)/video.h.xml: $(srctree)/include/linux/dvb/video.h $(MEDIA_OBJ_DIR)/v4l2.xml
+$(MEDIA_OBJ_DIR)/video.h.xml: $(srctree)/include/uapi/linux/dvb/video.h $(MEDIA_OBJ_DIR)/v4l2.xml
        @$($(quiet)gen_xml)
        @(                                      \
        echo "<programlisting>") > $@
index 59ad69a9d777e768b26b9b21c63de8df59d805c7..29df25016c7c121b1965b7a79122a08b691c1ac4 100644 (file)
@@ -56,7 +56,7 @@
 !Enet/core/filter.c
      </sect1>
      <sect1><title>Generic Network Statistics</title>
-!Iinclude/linux/gen_stats.h
+!Iinclude/uapi/linux/gen_stats.h
 !Enet/core/gen_stats.c
 !Enet/core/gen_estimator.c
      </sect1>
@@ -80,7 +80,7 @@
 !Enet/wimax/op-rfkill.c
 !Enet/wimax/stack.c
 !Iinclude/net/wimax.h
-!Iinclude/linux/wimax.h
+!Iinclude/uapi/linux/wimax.h
      </sect1>
   </chapter>
 
index b2bea15137d29ce086d2666c4102358f2cafe207..16eb4c9e92330fe62214b3f6af5944c7bb92591e 100644 (file)
@@ -42,13 +42,7 @@ The driver interface depends on your hardware.  If your system
 properly provides the SMBIOS info for IPMI, the driver will detect it
 and just work.  If you have a board with a standard interface (These
 will generally be either "KCS", "SMIC", or "BT", consult your hardware
-manual), choose the 'IPMI SI handler' option.  A driver also exists
-for direct I2C access to the IPMI management controller.  Some boards
-support this, but it is unknown if it will work on every board.  For
-this, choose 'IPMI SMBus handler', but be ready to try to do some
-figuring to see if it will work on your system if the SMBIOS/APCI
-information is wrong or not present.  It is fairly safe to have both
-these enabled and let the drivers auto-detect what is present.
+manual), choose the 'IPMI SI handler' option.
 
 You should generally enable ACPI on your system, as systems with IPMI
 can have ACPI tables describing them.
@@ -58,8 +52,7 @@ their job correctly, the IPMI controller should be automatically
 detected (via ACPI or SMBIOS tables) and should just work.  Sadly,
 many boards do not have this information.  The driver attempts
 standard defaults, but they may not work.  If you fall into this
-situation, you need to read the section below named 'The SI Driver' or
-"The SMBus Driver" on how to hand-configure your system.
+situation, you need to read the section below named 'The SI Driver'.
 
 IPMI defines a standard watchdog timer.  You can enable this with the
 'IPMI Watchdog Timer' config option.  If you compile the driver into
@@ -104,12 +97,7 @@ driver, each open file for this device ties in to the message handler
 as an IPMI user.
 
 ipmi_si - A driver for various system interfaces.  This supports KCS,
-SMIC, and BT interfaces.  Unless you have an SMBus interface or your
-own custom interface, you probably need to use this.
-
-ipmi_smb - A driver for accessing BMCs on the SMBus. It uses the
-I2C kernel driver's SMBus interfaces to send and receive IPMI messages
-over the SMBus.
+SMIC, and BT interfaces.
 
 ipmi_watchdog - IPMI requires systems to have a very capable watchdog
 timer.  This driver implements the standard Linux watchdog timer
@@ -482,53 +470,6 @@ for specifying an interface.  Note that when removing an interface,
 only the first three parameters (si type, address type, and address)
 are used for the comparison.  Any options are ignored for removing.
 
-The SMBus Driver
-----------------
-
-The SMBus driver allows up to 4 SMBus devices to be configured in the
-system.  By default, the driver will register any SMBus interfaces it finds
-in the I2C address range of 0x20 to 0x4f on any adapter.  You can change this
-at module load time (for a module) with:
-
-  modprobe ipmi_smb.o
-       addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
-       dbg=<flags1>,<flags2>...
-       [defaultprobe=1] [dbg_probe=1]
-
-The addresses are specified in pairs, the first is the adapter ID and the
-second is the I2C address on that adapter.
-
-The debug flags are bit flags for each BMC found, they are:
-IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
-
-Setting smb_defaultprobe to zero disabled the default probing of SMBus
-interfaces at address range 0x20 to 0x4f.  This means that only the
-BMCs specified on the smb_addr line will be detected.
-
-Setting smb_dbg_probe to 1 will enable debugging of the probing and
-detection process for BMCs on the SMBusses.
-
-Discovering the IPMI compliant BMC on the SMBus can cause devices
-on the I2C bus to fail. The SMBus driver writes a "Get Device ID" IPMI
-message as a block write to the I2C bus and waits for a response.
-This action can be detrimental to some I2C devices. It is highly recommended
-that the known I2c address be given to the SMBus driver in the smb_addr
-parameter. The default address range will not be used when a smb_addr
-parameter is provided.
-
-When compiled into the kernel, the addresses can be specified on the
-kernel command line as:
-
-  ipmb_smb.addr=<adapter1>,<i2caddr1>[,<adapter2>,<i2caddr2>[,...]]
-       ipmi_smb.dbg=<flags1>,<flags2>...
-       ipmi_smb.defaultprobe=0 ipmi_smb.dbg_probe=1
-
-These are the same options as on the module command line.
-
-Note that you might need some I2C changes if CONFIG_IPMI_PANIC_EVENT
-is enabled along with this, so the I2C driver knows to run to
-completion during sending a panic event.
-
 
 Other Pieces
 ------------
index dbbdcbba75a34005ced4edea51e7a9a308aec1e6..4110cca96bd608f1b9d246d31fd482f503c2c5b4 100644 (file)
@@ -27,17 +27,17 @@ Start                       End                     Size            Use
 -----------------------------------------------------------------------
 0000000000000000       0000007fffffffff         512GB          user
 
-ffffff8000000000       ffffffbbfffcffff        ~240GB          vmalloc
+ffffff8000000000       ffffffbbfffeffff        ~240GB          vmalloc
 
-ffffffbbfffd0000       ffffffbcfffdffff          64KB          [guard page]
+ffffffbbffff0000       ffffffbbffffffff          64KB          [guard page]
 
-ffffffbbfffe0000       ffffffbcfffeffff          64KB          PCI I/O space
+ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
 
-ffffffbbffff0000       ffffffbcffffffff          64KB          [guard page]
+ffffffbe00000000       ffffffbffbbfffff          ~8GB          [guard, future vmmemap]
 
-ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
+ffffffbffbe00000       ffffffbffbe0ffff          64KB          PCI I/O space
 
-ffffffbe00000000       ffffffbffbffffff          ~8GB          [guard, future vmmemap]
+ffffffbbffff0000       ffffffbcffffffff          ~2MB          [guard]
 
 ffffffbffc000000       ffffffbfffffffff          64MB          modules
 
index c07f7b4fb88d162ad012e69a3d77aa90d62868ff..71c4da413444d969519ae464250774db5c05de63 100644 (file)
@@ -466,6 +466,10 @@ Note:
 5.3 swappiness
 
 Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
+Please note that unlike the global swappiness, memcg knob set to 0
+really prevents from any swapping even if there is a swap storage
+available. This might lead to memcg OOM killer if there are no file
+pages to reclaim.
 
 Following cgroups' swappiness can't be changed.
 - root cgroup (uses /proc/sys/vm/swappiness).
index ecc81e3687153689337859f910cecb33627e8f49..d187e9f7cf1cf8b7fcd5bda6c6507558360a9237 100644 (file)
@@ -8,7 +8,7 @@ PIT Timer required properties:
   shared across all System Controller members.
 
 TC/TCLIB Timer required properties:
-- compatible: Should be "atmel,<chip>-pit".
+- compatible: Should be "atmel,<chip>-tcb".
   <chip> can be "at91rm9200" or "at91sam9x5"
 - reg: Should contain registers location and length
 - interrupts: Should contain all interrupts for the TC block
diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt
new file mode 100644 (file)
index 0000000..df70318
--- /dev/null
@@ -0,0 +1,19 @@
+* EETI eGalax Multiple Touch Controller
+
+Required properties:
+- compatible: must be "eeti,egalax_ts"
+- reg: i2c slave address
+- interrupt-parent: the phandle for the interrupt controller
+- interrupts: touch controller interrupt
+- wakeup-gpios: the gpio pin to be used for waking up the controller
+  as well as uased as irq pin
+
+Example:
+
+       egalax_ts@04 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <9 2>;
+               wakeup-gpios = <&gpio1 9 0>;
+       };
diff --git a/Documentation/devicetree/bindings/net/can/grcan.txt b/Documentation/devicetree/bindings/net/can/grcan.txt
new file mode 100644 (file)
index 0000000..34ef349
--- /dev/null
@@ -0,0 +1,28 @@
+Aeroflex Gaisler GRCAN and GRHCAN CAN controllers.
+
+The GRCAN and CRHCAN CAN controllers are available in the GRLIB VHDL IP core
+library.
+
+Note: These properties are built from the AMBA plug&play in a Leon SPARC system
+(the ordinary environment for GRCAN and GRHCAN). There are no dts files for
+sparc.
+
+Required properties:
+
+- name : Should be "GAISLER_GRCAN", "01_03d", "GAISLER_GRHCAN" or "01_034"
+
+- reg : Address and length of the register set for the device
+
+- freq : Frequency of the external oscillator clock in Hz (the frequency of
+       the amba bus in the ordinary case)
+
+- interrupts : Interrupt number for this device
+
+Optional properties:
+
+- systemid : If not present or if the value of the least significant 16 bits
+       of this 32-bit property is smaller than GRCAN_TXBUG_SAFE_GRLIB_VERSION
+       a bug workaround is activated.
+
+For further information look in the documentation for the GLIB IP core library:
+http://www.gaisler.com/products/grlib/grip.pdf
diff --git a/Documentation/devicetree/bindings/net/cdns-emac.txt b/Documentation/devicetree/bindings/net/cdns-emac.txt
new file mode 100644 (file)
index 0000000..09055c2
--- /dev/null
@@ -0,0 +1,23 @@
+* Cadence EMAC Ethernet controller
+
+Required properties:
+- compatible: Should be "cdns,[<chip>-]{emac}"
+  Use "cdns,at91rm9200-emac" Atmel at91rm9200 SoC.
+  or the generic form: "cdns,emac".
+- reg: Address and length of the register set for the device
+- interrupts: Should contain macb interrupt
+- phy-mode: String, operation mode of the PHY interface.
+  Supported values are: "mii", "rmii".
+
+Optional properties:
+- local-mac-address: 6 bytes, mac address
+
+Examples:
+
+       macb0: ethernet@fffc4000 {
+               compatible = "cdns,at91rm9200-emac";
+               reg = <0xfffc4000 0x4000>;
+               interrupts = <21>;
+               phy-mode = "rmii";
+               local-mac-address = [3a 0e 03 04 05 06];
+       };
index dcaabe9fe869d7f029f413d6d97335549974fd05..6ddd0286a9b7514fe00a5f150e05859da0f25e36 100644 (file)
@@ -9,21 +9,15 @@ Required properties:
                          number
 - interrupt-parent     : The parent interrupt controller
 - cpdma_channels       : Specifies number of channels in CPDMA
-- host_port_no         : Specifies host port shift
-- cpdma_reg_ofs                : Specifies CPDMA submodule register offset
-- cpdma_sram_ofs       : Specifies CPDMA SRAM offset
-- ale_reg_ofs          : Specifies ALE submodule register offset
 - ale_entries          : Specifies No of entries ALE can hold
-- host_port_reg_ofs    : Specifies host port register offset
-- hw_stats_reg_ofs     : Specifies hardware statistics register offset
-- bd_ram_ofs           : Specifies internal desciptor RAM offset
 - bd_ram_size          : Specifies internal descriptor RAM size
 - rx_descs             : Specifies number of Rx descriptors
 - mac_control          : Specifies Default MAC control register content
                          for the specific platform
 - slaves               : Specifies number for slaves
-- slave_reg_ofs                : Specifies slave register offset
-- sliver_reg_ofs       : Specifies slave sliver register offset
+- cpts_active_slave    : Specifies the slave to use for time stamping
+- cpts_clock_mult      : Numerator to convert input clock ticks into nanoseconds
+- cpts_clock_shift     : Denominator to convert input clock ticks into nanoseconds
 - phy_id               : Specifies slave phy id
 - mac-address          : Specifies slave MAC address
 
@@ -45,30 +39,22 @@ Examples:
                interrupts = <55 0x4>;
                interrupt-parent = <&intc>;
                cpdma_channels = <8>;
-               host_port_no = <0>;
-               cpdma_reg_ofs = <0x800>;
-               cpdma_sram_ofs = <0xa00>;
-               ale_reg_ofs = <0xd00>;
                ale_entries = <1024>;
-               host_port_reg_ofs = <0x108>;
-               hw_stats_reg_ofs = <0x900>;
-               bd_ram_ofs = <0x2000>;
                bd_ram_size = <0x2000>;
                no_bd_ram = <0>;
                rx_descs = <64>;
                mac_control = <0x20>;
                slaves = <2>;
+               cpts_active_slave = <0>;
+               cpts_clock_mult = <0x80000000>;
+               cpts_clock_shift = <29>;
                cpsw_emac0: slave@0 {
-                       slave_reg_ofs = <0x208>;
-                       sliver_reg_ofs = <0xd80>;
-                       phy_id = "davinci_mdio.16:00";
+                       phy_id = <&davinci_mdio>, <0>;
                        /* Filled in by U-Boot */
                        mac-address = [ 00 00 00 00 00 00 ];
                };
                cpsw_emac1: slave@1 {
-                       slave_reg_ofs = <0x308>;
-                       sliver_reg_ofs = <0xdc0>;
-                       phy_id = "davinci_mdio.16:01";
+                       phy_id = <&davinci_mdio>, <1>;
                        /* Filled in by U-Boot */
                        mac-address = [ 00 00 00 00 00 00 ];
                };
@@ -79,30 +65,22 @@ Examples:
                compatible = "ti,cpsw";
                ti,hwmods = "cpgmac0";
                cpdma_channels = <8>;
-               host_port_no = <0>;
-               cpdma_reg_ofs = <0x800>;
-               cpdma_sram_ofs = <0xa00>;
-               ale_reg_ofs = <0xd00>;
                ale_entries = <1024>;
-               host_port_reg_ofs = <0x108>;
-               hw_stats_reg_ofs = <0x900>;
-               bd_ram_ofs = <0x2000>;
                bd_ram_size = <0x2000>;
                no_bd_ram = <0>;
                rx_descs = <64>;
                mac_control = <0x20>;
                slaves = <2>;
+               cpts_active_slave = <0>;
+               cpts_clock_mult = <0x80000000>;
+               cpts_clock_shift = <29>;
                cpsw_emac0: slave@0 {
-                       slave_reg_ofs = <0x208>;
-                       sliver_reg_ofs = <0xd80>;
-                       phy_id = "davinci_mdio.16:00";
+                       phy_id = <&davinci_mdio>, <0>;
                        /* Filled in by U-Boot */
                        mac-address = [ 00 00 00 00 00 00 ];
                };
                cpsw_emac1: slave@1 {
-                       slave_reg_ofs = <0x308>;
-                       sliver_reg_ofs = <0xdc0>;
-                       phy_id = "davinci_mdio.16:01";
+                       phy_id = <&davinci_mdio>, <1>;
                        /* Filled in by U-Boot */
                        mac-address = [ 00 00 00 00 00 00 ];
                };
index bc9549529014730bc6abd0cefba2d82824370e5e..c79bab025369af4bb6320ba0e90f7fb386942cc1 100644 (file)
@@ -8,9 +8,16 @@ gpios property as described in section VIII.1 in the following order:
 
 MDC, MDIO.
 
+Note: Each gpio-mdio bus should have an alias correctly numbered in "aliases"
+node.
+
 Example:
 
-mdio {
+aliases {
+       mdio-gpio0 = <&mdio0>;
+};
+
+mdio0: mdio {
        compatible = "virtual,mdio-gpio";
        #address-cells = <1>;
        #size-cells = <0>;
index c8e578263ce2654251aacde50bc1a55fe514e264..683fde93c4fb1ab9dac7d9472f1ad808202d7cf4 100644 (file)
@@ -93,7 +93,7 @@ Valid values for pin and group names are:
 
     With some exceptions, these support nvidia,high-speed-mode,
     nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
-    nvidia,pull-up-strength, nvidia,slew_rate-rising, nvidia,slew_rate-falling.
+    nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling.
 
     drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
     drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
index c275b70349c11aedb4e8db6a1982c57bfbfcb619..6f426ed7009e5e43461770787225b398fe68e67f 100644 (file)
@@ -83,7 +83,7 @@ Valid values for pin and group names are:
   drive groups:
 
     These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
-    nvidia,slew_rate-rising, nvidia,slew_rate-falling. Most but not all
+    nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all
     support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
 
     ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
index a1793d670cd01bd374eddf54ffdfc768504291ff..3844d21d6ca32223838b7856a2f353bf56ef2417 100644 (file)
@@ -33,7 +33,7 @@ Table of Contents
   2    Modifying System Parameters
 
   3    Per-Process Parameters
-  3.1  /proc/<pid>/oom_score_adj - Adjust the oom-killer
+  3.1  /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj - Adjust the oom-killer
                                                                score
   3.2  /proc/<pid>/oom_score - Display current oom-killer score
   3.3  /proc/<pid>/io - Display the IO accounting fields
@@ -1320,10 +1320,10 @@ of the kernel.
 CHAPTER 3: PER-PROCESS PARAMETERS
 ------------------------------------------------------------------------------
 
-3.1 /proc/<pid>/oom_score_adj- Adjust the oom-killer score
+3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj- Adjust the oom-killer score
 --------------------------------------------------------------------------------
 
-This file can be used to adjust the badness heuristic used to select which
+These file can be used to adjust the badness heuristic used to select which
 process gets killed in out of memory conditions.
 
 The badness heuristic assigns a value to each candidate task ranging from 0
@@ -1361,6 +1361,12 @@ same system, cpuset, mempolicy, or memory controller resources to use at least
 equivalent to discounting 50% of the task's allowed memory from being considered
 as scoring against the task.
 
+For backwards compatibility with previous kernels, /proc/<pid>/oom_adj may also
+be used to tune the badness score.  Its acceptable values range from -16
+(OOM_ADJUST_MIN) to +15 (OOM_ADJUST_MAX) and a special value of -17
+(OOM_DISABLE) to disable oom killing entirely for that task.  Its value is
+scaled linearly with /proc/<pid>/oom_score_adj.
+
 The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last
 value set by a CAP_SYS_RESOURCE process. To reduce the value any lower
 requires CAP_SYS_RESOURCE.
@@ -1375,7 +1381,9 @@ minimal amount of work.
 -------------------------------------------------------------
 
 This file can be used to check the current score used by the oom-killer is for
-any given <pid>.
+any given <pid>. Use it together with /proc/<pid>/oom_score_adj to tune which
+process should be killed in an out-of-memory situation.
+
 
 3.3  /proc/<pid>/io - Display the IO accounting fields
 -------------------------------------------------------
index 7eceaff63f5ffb8f45748d0cb1f46b864652b69a..815b711bcd85007569918048b2d3e36fe20fea19 100644 (file)
  High level behavior (mixed):
  ============================
 
- kernel(driver): calls request_firmware(&fw_entry, $FIRMWARE, device)
-
- userspace:
+ 1), kernel(driver):
+       - calls request_firmware(&fw_entry, $FIRMWARE, device)
+       - kernel searchs the fimware image with name $FIRMWARE directly
+       in the below search path of root filesystem:
+               "/lib/firmware/updates/" UTS_RELEASE,
+               "/lib/firmware/updates",
+               "/lib/firmware/" UTS_RELEASE,
+               "/lib/firmware"
+       - If found, goto 7), else goto 2)
+
+ 2), userspace:
        - /sys/class/firmware/xxx/{loading,data} appear.
        - hotplug gets called with a firmware identifier in $FIRMWARE
          and the usual hotplug environment.
                - hotplug: echo 1 > /sys/class/firmware/xxx/loading
 
- kernel: Discard any previous partial load.
3), kernel: Discard any previous partial load.
 
- userspace:
4), userspace:
                - hotplug: cat appropriate_firmware_image > \
                                        /sys/class/firmware/xxx/data
 
- kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
5), kernel: grows a buffer in PAGE_SIZE increments to hold the image as it
         comes in.
 
- userspace:
6), userspace:
                - hotplug: echo 0 > /sys/class/firmware/xxx/loading
 
- kernel: request_firmware() returns and the driver has the firmware
7), kernel: request_firmware() returns and the driver has the firmware
         image in fw_entry->{data,size}. If something went wrong
         request_firmware() returns non-zero and fw_entry is set to
         NULL.
 
- kernel(driver): Driver code calls release_firmware(fw_entry) releasing
8), kernel(driver): Driver code calls release_firmware(fw_entry) releasing
                 the firmware image and any related resource.
 
  High level behavior (driver code):
index c86b50c03ea8f02276d2a35deb4a6f5822d78be9..f17256f069baeebf2b8d8772ea9fa49147ccc2f2 100644 (file)
@@ -105,6 +105,7 @@ Process             Processor                                       TjMax(C)
                330/230                                         125
                E680/660/640/620                                90
                E680T/660T/640T/620T                            110
+               CE4170/4150/4110                                110
 
 45nm           Core2 Processors
                Solo ULV SU3500/3300                            100
index a92918e0bd6946f760af42cd984a28ee0e2db642..80654813d04afdf1e76d8388c8c51a1fb31ae825 100644 (file)
@@ -10,7 +10,7 @@ Supported chips:
   BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors
     (not yet published)
 
-Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
 
 Description
 -----------
index 790f774a303247c0693ed6c24c8d9dfd6103d2f0..843751c41fea59d207497d991a67bba5af1ee617 100644 (file)
@@ -60,8 +60,7 @@ increase the chances of your change being accepted.
 
 * Add the driver to Kconfig and Makefile in alphabetical order.
 
-* Make sure that all dependencies are listed in Kconfig. For new drivers, it
-  is most likely prudent to add a dependency on EXPERIMENTAL.
+* Make sure that all dependencies are listed in Kconfig.
 
 * Avoid forward declarations if you can. Rearrange the code if necessary.
 
index 9776f068306b7f7ec6425ec4c02b17f5dac4788a..3da4f9670d8b6a20d6b5e78de607f202f5bbb973 100644 (file)
@@ -905,6 +905,24 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
        gpt             [EFI] Forces disk with valid GPT signature but
                        invalid Protective MBR to be treated as GPT.
 
+       grcan.enable0=  [HW] Configuration of physical interface 0. Determines
+                       the "Enable 0" bit of the configuration register.
+                       Format: 0 | 1
+                       Default: 0
+       grcan.enable1=  [HW] Configuration of physical interface 1. Determines
+                       the "Enable 0" bit of the configuration register.
+                       Format: 0 | 1
+                       Default: 0
+       grcan.select=   [HW] Select which physical interface to use.
+                       Format: 0 | 1
+                       Default: 0
+       grcan.txsize=   [HW] Sets the size of the tx buffer.
+                       Format: <unsigned int> such that (txsize & ~0x1fffc0) == 0.
+                       Default: 1024
+       grcan.rxsize=   [HW] Sets the size of the rx buffer.
+                       Format: <unsigned int> such that (rxsize & ~0x1fffc0) == 0.
+                       Default: 1024
+
        hashdist=       [KNL,NUMA] Large hashes allocated during boot
                        are distributed across NUMA nodes.  Defaults on
                        for 64-bit NUMA, off otherwise.
index a173d2a879f5cf7619b221148edbbac4789bbe8a..c1d82047a4b151c35983656e5841e261ff22fd7f 100644 (file)
@@ -203,7 +203,8 @@ abled  during run time. Following log_levels are defined:
 2 - Enable messages related to route added / changed / deleted
 4 - Enable messages related to translation table operations
 8 - Enable messages related to bridge loop avoidance
-15 - enable all messages
+16 - Enable messaged related to DAT, ARP snooping and parsing
+31 - Enable all messages
 
 The debug output can be changed at runtime  using  the  file
 /sys/class/net/bat0/mesh/log_level. e.g.
index c7fc10724948629c98100b19250f8ee07d9dcd73..dd52d516cb8902da098bbb21a5006cea81b66a74 100644 (file)
@@ -30,16 +30,24 @@ neigh/default/gc_thresh3 - INTEGER
        Maximum number of neighbor entries allowed.  Increase this
        when using large numbers of interfaces and when communicating
        with large numbers of directly-connected peers.
+       Default: 1024
 
 neigh/default/unres_qlen_bytes - INTEGER
        The maximum number of bytes which may be used by packets
        queued for each unresolved address by other network layers.
        (added in linux 3.3)
+       Seting negative value is meaningless and will retrun error.
+       Default: 65536 Bytes(64KB)
 
 neigh/default/unres_qlen - INTEGER
        The maximum number of packets which may be queued for each
        unresolved address by other network layers.
        (deprecated in linux 3.3) : use unres_qlen_bytes instead.
+       Prior to linux 3.3, the default value is 3 which may cause
+       unexpected packet loss. The current default value is calculated
+       according to default value of unres_qlen_bytes and true size of
+       packet.
+       Default: 31
 
 mtu_expires - INTEGER
        Time, in seconds, that cached PMTU information is kept.
@@ -199,15 +207,16 @@ tcp_early_retrans - INTEGER
        Default: 2
 
 tcp_ecn - INTEGER
-       Enable Explicit Congestion Notification (ECN) in TCP. ECN is only
-       used when both ends of the TCP flow support it. It is useful to
-       avoid losses due to congestion (when the bottleneck router supports
-       ECN).
+       Control use of Explicit Congestion Notification (ECN) by TCP.
+       ECN is used only when both ends of the TCP connection indicate
+       support for it.  This feature is useful in avoiding losses due
+       to congestion by allowing supporting routers to signal
+       congestion before having to drop packets.
        Possible values are:
-               0 disable ECN
-               1 ECN enabled
-               2 Only server-side ECN enabled. If the other end does
-                 not support ECN, behavior is like with ECN disabled.
+               0 Disable ECN.  Neither initiate nor accept ECN.
+               1 Always request ECN on outgoing connection attempts.
+               2 Enable ECN when requested by incomming connections
+                 but do not request ECN on outgoing connections.
        Default: 2
 
 tcp_fack - BOOLEAN
@@ -215,15 +224,14 @@ tcp_fack - BOOLEAN
        The value is not used, if tcp_sack is not enabled.
 
 tcp_fin_timeout - INTEGER
-       Time to hold socket in state FIN-WAIT-2, if it was closed
-       by our side. Peer can be broken and never close its side,
-       or even died unexpectedly. Default value is 60sec.
-       Usual value used in 2.2 was 180 seconds, you may restore
-       it, but remember that if your machine is even underloaded WEB server,
-       you risk to overflow memory with kilotons of dead sockets,
-       FIN-WAIT-2 sockets are less dangerous than FIN-WAIT-1,
-       because they eat maximum 1.5K of memory, but they tend
-       to live longer. Cf. tcp_max_orphans.
+       The length of time an orphaned (no longer referenced by any
+       application) connection will remain in the FIN_WAIT_2 state
+       before it is aborted at the local end.  While a perfectly
+       valid "receive only" state for an un-orphaned connection, an
+       orphaned connection in FIN_WAIT_2 state could otherwise wait
+       forever for the remote to close its end of the connection.
+       Cf. tcp_max_orphans
+       Default: 60 seconds
 
 tcp_frto - INTEGER
        Enables Forward RTO-Recovery (F-RTO) defined in RFC4138.
@@ -1514,6 +1522,20 @@ cookie_preserve_enable - BOOLEAN
 
        Default: 1
 
+cookie_hmac_alg - STRING
+       Select the hmac algorithm used when generating the cookie value sent by
+       a listening sctp socket to a connecting client in the INIT-ACK chunk.
+       Valid values are:
+       * md5
+       * sha1
+       * none
+       Ability to assign md5 or sha1 as the selected alg is predicated on the
+       configuarion of those algorithms at build time (CONFIG_CRYPTO_MD5 and
+       CONFIG_CRYPTO_SHA1).
+
+       Default: Dependent on configuration.  MD5 if available, else SHA1 if
+       available, else none.
+
 rcvbuf_policy - INTEGER
        Determines if the receive buffer is attributed to the socket or to
        association.   SCTP supports the capability to create multiple
index 4164f5c02e4bbdf406956818fc34b8306610ba55..f310edec8a776f0a8ffb4a943a386ea45990b1a6 100644 (file)
@@ -164,4 +164,4 @@ read the CRC recorded by the NIC on receipt of the packet.
 This requests that the NIC receive all possible frames, including errored
 frames (such as bad FCS, etc).  This can be helpful when sniffing a link with
 bad packets on it.  Some NICs may receive more packets if also put into normal
-PROMISC mdoe.
+PROMISC mode.
index 1c08a4b0981fb7f648cee60ffea8b3c45bb319c4..94444b152fbcc7d56a3549a3578ededb357cf956 100644 (file)
@@ -3,9 +3,9 @@
 --------------------------------------------------------------------------------
 
 This file documents the mmap() facility available with the PACKET
-socket interface on 2.4 and 2.6 kernels. This type of sockets is used for 
-capture network traffic with utilities like tcpdump or any other that needs
-raw access to network interface.
+socket interface on 2.4/2.6/3.x kernels. This type of sockets is used for
+i) capture network traffic with utilities like tcpdump, ii) transmit network
+traffic, or any other that needs raw access to network interface.
 
 You can find the latest version of this document at:
     http://wiki.ipxwarzone.com/index.php5?title=Linux_packet_mmap
@@ -21,19 +21,18 @@ Please send your comments to
 + Why use PACKET_MMAP
 --------------------------------------------------------------------------------
 
-In Linux 2.4/2.6 if PACKET_MMAP is not enabled, the capture process is very
-inefficient. It uses very limited buffers and requires one system call
-to capture each packet, it requires two if you want to get packet's 
-timestamp (like libpcap always does).
+In Linux 2.4/2.6/3.x if PACKET_MMAP is not enabled, the capture process is very
+inefficient. It uses very limited buffers and requires one system call to
+capture each packet, it requires two if you want to get packet's timestamp
+(like libpcap always does).
 
 In the other hand PACKET_MMAP is very efficient. PACKET_MMAP provides a size 
 configurable circular buffer mapped in user space that can be used to either
 send or receive packets. This way reading packets just needs to wait for them,
 most of the time there is no need to issue a single system call. Concerning
 transmission, multiple packets can be sent through one system call to get the
-highest bandwidth.
-By using a shared buffer between the kernel and the user also has the benefit
-of minimizing packet copies.
+highest bandwidth. By using a shared buffer between the kernel and the user
+also has the benefit of minimizing packet copies.
 
 It's fine to use PACKET_MMAP to improve the performance of the capture and
 transmission process, but it isn't everything. At least, if you are capturing
@@ -41,7 +40,8 @@ at high speeds (this is relative to the cpu speed), you should check if the
 device driver of your network interface card supports some sort of interrupt
 load mitigation or (even better) if it supports NAPI, also make sure it is
 enabled. For transmission, check the MTU (Maximum Transmission Unit) used and
-supported by devices of your network.
+supported by devices of your network. CPU IRQ pinning of your network interface
+card can also be an advantage.
 
 --------------------------------------------------------------------------------
 + How to use mmap() to improve capture process
@@ -87,9 +87,7 @@ the following process:
 socket creation and destruction is straight forward, and is done 
 the same way with or without PACKET_MMAP:
 
-int fd;
-
-fd= socket(PF_PACKET, mode, htons(ETH_P_ALL))
+ int fd = socket(PF_PACKET, mode, htons(ETH_P_ALL));
 
 where mode is SOCK_RAW for the raw interface were link level
 information can be captured or SOCK_DGRAM for the cooked
@@ -163,11 +161,23 @@ As capture, each frame contains two parts:
 
  A complete tutorial is available at: http://wiki.gnu-log.net/
 
+By default, the user should put data at :
+ frame base + TPACKET_HDRLEN - sizeof(struct sockaddr_ll)
+
+So, whatever you choose for the socket mode (SOCK_DGRAM or SOCK_RAW),
+the beginning of the user data will be at :
+ frame base + TPACKET_ALIGN(sizeof(struct tpacket_hdr))
+
+If you wish to put user data at a custom offset from the beginning of
+the frame (for payload alignment with SOCK_RAW mode for instance) you
+can set tp_net (with SOCK_DGRAM) or tp_mac (with SOCK_RAW). In order
+to make this work it must be enabled previously with setsockopt()
+and the PACKET_TX_HAS_OFF option.
+
 --------------------------------------------------------------------------------
 + PACKET_MMAP settings
 --------------------------------------------------------------------------------
 
-
 To setup PACKET_MMAP from user level code is done with a call like
 
  - Capture process
@@ -201,7 +211,6 @@ indeed, packet_set_ring checks that the following condition is true
 
     frames_per_block * tp_block_nr == tp_frame_nr
 
-
 Lets see an example, with the following values:
 
      tp_block_size= 4096
@@ -227,7 +236,6 @@ be spawned across two blocks, so there are some details you have to take into
 account when choosing the frame_size. See "Mapping and use of the circular 
 buffer (ring)".
 
-
 --------------------------------------------------------------------------------
 + PACKET_MMAP setting constraints
 --------------------------------------------------------------------------------
@@ -264,7 +272,6 @@ User space programs can include /usr/include/sys/user.h and
 The pagesize can also be determined dynamically with the getpagesize (2) 
 system call. 
 
-
  Block number limit
 --------------------
 
@@ -284,7 +291,6 @@ called pg_vec, its size limits the number of blocks that can be allocated.
       v  block #2
      block #1
 
-
 kmalloc allocates any number of bytes of physically contiguous memory from 
 a pool of pre-determined sizes. This pool of memory is maintained by the slab 
 allocator which is at the end the responsible for doing the allocation and 
@@ -299,7 +305,6 @@ pointers to blocks is
 
      131072/4 = 32768 blocks
 
-
  PACKET_MMAP buffer size calculator
 ------------------------------------
 
@@ -340,7 +345,6 @@ and a value for <frame size> of 2048 bytes. These parameters will yield
 and hence the buffer will have a 262144 MiB size. So it can hold 
 262144 MiB / 2048 bytes = 134217728 frames
 
-
 Actually, this buffer size is not possible with an i386 architecture. 
 Remember that the memory is allocated in kernel space, in the case of 
 an i386 kernel's memory size is limited to 1GiB.
@@ -372,7 +376,6 @@ the following (from include/linux/if_packet.h):
    - Start+tp_net: Packet data, aligned to TPACKET_ALIGNMENT=16.
    - Pad to align to TPACKET_ALIGNMENT=16
  */
-           
  
  The following are conditions that are checked in packet_set_ring
 
@@ -413,7 +416,6 @@ and the following flags apply:
      #define TP_STATUS_LOSING        4 
      #define TP_STATUS_CSUMNOTREADY  8 
 
-
 TP_STATUS_COPY        : This flag indicates that the frame (and associated
                         meta information) has been truncated because it's 
                         larger than tp_frame_size. This packet can be 
@@ -462,7 +464,6 @@ packets are in the ring:
 It doesn't incur in a race condition to first check the status value and 
 then poll for frames.
 
-
 ++ Transmission process
 Those defines are also used for transmission:
 
@@ -493,6 +494,196 @@ The user can also use poll() to check if a buffer is available:
     pfd.events = POLLOUT;
     retval = poll(&pfd, 1, timeout);
 
+-------------------------------------------------------------------------------
++ What TPACKET versions are available and when to use them?
+-------------------------------------------------------------------------------
+
+ int val = tpacket_version;
+ setsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
+ getsockopt(fd, SOL_PACKET, PACKET_VERSION, &val, sizeof(val));
+
+where 'tpacket_version' can be TPACKET_V1 (default), TPACKET_V2, TPACKET_V3.
+
+TPACKET_V1:
+       - Default if not otherwise specified by setsockopt(2)
+       - RX_RING, TX_RING available
+       - VLAN metadata information available for packets
+         (TP_STATUS_VLAN_VALID)
+
+TPACKET_V1 --> TPACKET_V2:
+       - Made 64 bit clean due to unsigned long usage in TPACKET_V1
+         structures, thus this also works on 64 bit kernel with 32 bit
+         userspace and the like
+       - Timestamp resolution in nanoseconds instead of microseconds
+       - RX_RING, TX_RING available
+       - How to switch to TPACKET_V2:
+               1. Replace struct tpacket_hdr by struct tpacket2_hdr
+               2. Query header len and save
+               3. Set protocol version to 2, set up ring as usual
+               4. For getting the sockaddr_ll,
+                  use (void *)hdr + TPACKET_ALIGN(hdrlen) instead of
+                  (void *)hdr + TPACKET_ALIGN(sizeof(struct tpacket_hdr))
+
+TPACKET_V2 --> TPACKET_V3:
+       - Flexible buffer implementation:
+               1. Blocks can be configured with non-static frame-size
+               2. Read/poll is at a block-level (as opposed to packet-level)
+               3. Added poll timeout to avoid indefinite user-space wait
+                  on idle links
+               4. Added user-configurable knobs:
+                       4.1 block::timeout
+                       4.2 tpkt_hdr::sk_rxhash
+       - RX Hash data available in user space
+       - Currently only RX_RING available
+
+-------------------------------------------------------------------------------
++ AF_PACKET fanout mode
+-------------------------------------------------------------------------------
+
+In the AF_PACKET fanout mode, packet reception can be load balanced among
+processes. This also works in combination with mmap(2) on packet sockets.
+
+Minimal example code by David S. Miller (try things like "./test eth0 hash",
+"./test eth0 lb", etc.):
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <unistd.h>
+
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+
+#include <net/if.h>
+
+static const char *device_name;
+static int fanout_type;
+static int fanout_id;
+
+#ifndef PACKET_FANOUT
+# define PACKET_FANOUT                 18
+# define PACKET_FANOUT_HASH            0
+# define PACKET_FANOUT_LB              1
+#endif
+
+static int setup_socket(void)
+{
+       int err, fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_IP));
+       struct sockaddr_ll ll;
+       struct ifreq ifr;
+       int fanout_arg;
+
+       if (fd < 0) {
+               perror("socket");
+               return EXIT_FAILURE;
+       }
+
+       memset(&ifr, 0, sizeof(ifr));
+       strcpy(ifr.ifr_name, device_name);
+       err = ioctl(fd, SIOCGIFINDEX, &ifr);
+       if (err < 0) {
+               perror("SIOCGIFINDEX");
+               return EXIT_FAILURE;
+       }
+
+       memset(&ll, 0, sizeof(ll));
+       ll.sll_family = AF_PACKET;
+       ll.sll_ifindex = ifr.ifr_ifindex;
+       err = bind(fd, (struct sockaddr *) &ll, sizeof(ll));
+       if (err < 0) {
+               perror("bind");
+               return EXIT_FAILURE;
+       }
+
+       fanout_arg = (fanout_id | (fanout_type << 16));
+       err = setsockopt(fd, SOL_PACKET, PACKET_FANOUT,
+                        &fanout_arg, sizeof(fanout_arg));
+       if (err) {
+               perror("setsockopt");
+               return EXIT_FAILURE;
+       }
+
+       return fd;
+}
+
+static void fanout_thread(void)
+{
+       int fd = setup_socket();
+       int limit = 10000;
+
+       if (fd < 0)
+               exit(fd);
+
+       while (limit-- > 0) {
+               char buf[1600];
+               int err;
+
+               err = read(fd, buf, sizeof(buf));
+               if (err < 0) {
+                       perror("read");
+                       exit(EXIT_FAILURE);
+               }
+               if ((limit % 10) == 0)
+                       fprintf(stdout, "(%d) \n", getpid());
+       }
+
+       fprintf(stdout, "%d: Received 10000 packets\n", getpid());
+
+       close(fd);
+       exit(0);
+}
+
+int main(int argc, char **argp)
+{
+       int fd, err;
+       int i;
+
+       if (argc != 3) {
+               fprintf(stderr, "Usage: %s INTERFACE {hash|lb}\n", argp[0]);
+               return EXIT_FAILURE;
+       }
+
+       if (!strcmp(argp[2], "hash"))
+               fanout_type = PACKET_FANOUT_HASH;
+       else if (!strcmp(argp[2], "lb"))
+               fanout_type = PACKET_FANOUT_LB;
+       else {
+               fprintf(stderr, "Unknown fanout type [%s]\n", argp[2]);
+               exit(EXIT_FAILURE);
+       }
+
+       device_name = argp[1];
+       fanout_id = getpid() & 0xffff;
+
+       for (i = 0; i < 4; i++) {
+               pid_t pid = fork();
+
+               switch (pid) {
+               case 0:
+                       fanout_thread();
+
+               case -1:
+                       perror("fork");
+                       exit(EXIT_FAILURE);
+               }
+       }
+
+       for (i = 0; i < 4; i++) {
+               int status;
+
+               wait(&status);
+       }
+
+       return 0;
+}
+
 -------------------------------------------------------------------------------
 + PACKET_TIMESTAMP
 -------------------------------------------------------------------------------
@@ -519,6 +710,13 @@ the networking stack is used (the behavior before this setting was added).
 See include/linux/net_tstamp.h and Documentation/networking/timestamping
 for more information on hardware timestamps.
 
+-------------------------------------------------------------------------------
++ Miscellaneous bits
+-------------------------------------------------------------------------------
+
+- Packet sockets work well together with Linux socket filters, thus you also
+  might want to have a look at Documentation/networking/filter.txt
+
 --------------------------------------------------------------------------------
 + THANKS
 --------------------------------------------------------------------------------
index ef9ee71b4d7fcc71a38dc94454828e74a606cded..f9fa6db40a5291155d4f39141d82f89b46d0c0b5 100644 (file)
@@ -29,11 +29,9 @@ The kernel configuration option is STMMAC_ETH:
        dma_txsize: DMA tx ring size;
        buf_sz: DMA buffer size;
        tc: control the HW FIFO threshold;
-       tx_coe: Enable/Disable Tx Checksum Offload engine;
        watchdog: transmit timeout (in milliseconds);
        flow_ctrl: Flow control ability [on/off];
        pause: Flow Control Pause Time;
-       tmrate: timer period (only if timer optimisation is configured).
 
 3) Command line options
 Driver parameters can be also passed in command line by using:
@@ -60,17 +58,19 @@ Then the poll method will be scheduled at some future point.
 The incoming packets are stored, by the DMA, in a list of pre-allocated socket
 buffers in order to avoid the memcpy (Zero-copy).
 
-4.3) Timer-Driver Interrupt
-Instead of having the device that asynchronously notifies the frame receptions,
-the driver configures a timer to generate an interrupt at regular intervals.
-Based on the granularity of the timer, the frames that are received by the
-device will experience different levels of latency. Some NICs have dedicated
-timer device to perform this task. STMMAC can use either the RTC device or the
-TMU channel 2  on STLinux platforms.
-The timers frequency can be passed to the driver as parameter; when change it,
-take care of both hardware capability and network stability/performance impact.
-Several performance tests on STM platforms showed this optimisation allows to
-spare the CPU while having the maximum throughput.
+4.3) Interrupt Mitigation
+The driver is able to mitigate the number of its DMA interrupts
+using NAPI for the reception on chips older than the 3.50.
+New chips have an HW RX-Watchdog used for this mitigation.
+
+On Tx-side, the mitigation schema is based on a SW timer that calls the
+tx function (stmmac_tx) to reclaim the resource after transmitting the
+frames.
+Also there is another parameter (like a threshold) used to program
+the descriptors avoiding to set the interrupt on completion bit in
+when the frame is sent (xmit).
+
+Mitigation parameters can be tuned by ethtool.
 
 4.4) WOL
 Wake up on Lan feature through Magic and Unicast frames are supported for the
@@ -121,6 +121,7 @@ struct plat_stmmacenet_data {
        int bugged_jumbo;
        int pmt;
        int force_sf_dma_mode;
+       int riwt_off;
        void (*fix_mac_speed)(void *priv, unsigned int speed);
        void (*bus_setup)(void __iomem *ioaddr);
        int (*init)(struct platform_device *pdev);
@@ -156,6 +157,7 @@ Where:
  o pmt: core has the embedded power module (optional).
  o force_sf_dma_mode: force DMA to use the Store and Forward mode
                     instead of the Threshold.
+ o riwt_off: force to disable the RX watchdog feature and switch to NAPI mode.
  o fix_mac_speed: this callback is used for modifying some syscfg registers
                 (on ST SoCs) according to the link speed negotiated by the
                 physical layer .
index 5b34b762d7d5139a8cf0a9a8eacf739cae279a5b..6d993510f091c2088877ccfc1edf15474c5c723f 100644 (file)
@@ -32,7 +32,7 @@ no entry is in the forwarding table.
   # ip link delete vxlan0
 
 3. Show vxlan info
-  # ip -d show vxlan0
+  # ip -d link show vxlan0
 
 It is possible to create, destroy and display the vxlan
 forwarding table using the new bridge command.
@@ -41,7 +41,7 @@ forwarding table using the new bridge command.
   # bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0
 
 2. Delete forwarding table entry
-  # bridge fdb delete 00:17:42:8a:b4:05
+  # bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0
 
 3. Show forwarding table
   # bridge fdb show dev vxlan0
index 642f84495b29888c5ff937d3b5f01faef5674ecc..2a4cdda4828ed8382809be4219e931565210d2d8 100644 (file)
@@ -116,6 +116,7 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 'w'    - Dumps tasks that are in uninterruptable (blocked) state.
 
 'x'    - Used by xmon interface on ppc/powerpc platforms.
+          Show global PMU Registers on sparc64.
 
 'y'    - Show global CPU Registers [SPARC-64 specific]
 
diff --git a/Documentation/zh_CN/IRQ.txt b/Documentation/zh_CN/IRQ.txt
new file mode 100644 (file)
index 0000000..956026d
--- /dev/null
@@ -0,0 +1,39 @@
+Chinese translated version of Documentation/IRQ.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Eric W. Biederman <ebiederman@xmission.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/IRQ.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+英文版维护者: Eric W. Biederman <ebiederman@xmission.com>
+中文版维护者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜 Fu Wei <tekkamanninja@gmail.com>
+
+
+以下为正文
+---------------------------------------------------------------------
+何为 IRQ?
+
+一个 IRQ 是来自某个设备的一个中断请求。目前,它们可以来自一个硬件引脚,
+或来自一个数据包。多个设备可能连接到同个硬件引脚,从而共享一个 IRQ。
+
+一个 IRQ 编号是用于告知硬件中断源的内核标识。通常情况下,这是一个
+全局 irq_desc 数组的索引,但是除了在 linux/interrupt.h 中的实现,
+具体的细节是体系结构特定的。
+
+一个 IRQ 编号是设备上某个可能的中断源的枚举。通常情况下,枚举的编号是
+该引脚在系统内中断控制器的所有输入引脚中的编号。对于 ISA 总线中的情况,
+枚举的是在两个 i8259 中断控制器中 16 个输入引脚。
+
+架构可以对 IRQ 编号指定额外的含义,在硬件涉及任何手工配置的情况下,
+是被提倡的。ISA 的 IRQ 是一个分配这类额外含义的典型例子。
diff --git a/Documentation/zh_CN/arm64/booting.txt b/Documentation/zh_CN/arm64/booting.txt
new file mode 100644 (file)
index 0000000..28fa325
--- /dev/null
@@ -0,0 +1,156 @@
+Chinese translated version of Documentation/arm64/booting.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Will Deacon <will.deacon@arm.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm64/booting.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Will Deacon <will.deacon@arm.com>
+中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+                       启动 AArch64 Linux
+                       ==================
+
+作者: Will Deacon <will.deacon@arm.com>
+日期: 2012 年 09 月 07 日
+
+本文档基于 Russell King 的 ARM 启动文档,且适用于所有公开发布的
+AArch64 Linux 内核代码。
+
+AArch64 异常模型由多个异常级别(EL0 - EL3)组成,对于 EL0 和 EL1
+异常级有对应的安全和非安全模式。EL2 是系统管理级,且仅存在于
+非安全模式下。EL3 是最高特权级,且仅存在于安全模式下。
+
+基于本文档的目的,我们将简单地使用‘引导装载程序’(‘boot loader’)
+这个术语来定义在将控制权交给 Linux 内核前 CPU 上执行的所有软件。
+这可能包含安全监控和系统管理代码,或者它可能只是一些用于准备最小启动
+环境的指令。
+
+基本上,引导装载程序(至少)应实现以下操作:
+
+1、设置和初始化 RAM
+2、设置设备树数据
+3、解压内核映像
+4、调用内核映像
+
+
+1、设置和初始化 RAM
+-----------------
+
+必要性: 强制
+
+引导装载程序应该找到并初始化系统中所有内核用于保持系统变量数据的 RAM。
+这个操作的执行是设备依赖的。(它可能使用内部算法来自动定位和计算所有
+RAM,或可能使用对这个设备已知的 RAM 信息,还可能使用任何引导装载程序
+设计者想到的匹配方法。)
+
+
+2、设置设备树数据
+---------------
+
+必要性: 强制
+
+设备树数据块(dtb)大小必须不大于 2 MB,且位于从内核映像起始算起第一个
+512MB 内的 2MB 边界上。这使得内核可以通过初始页表中的单个节描述符来
+映射此数据块。
+
+
+3、解压内核映像
+-------------
+
+必要性: 可选
+
+AArch64 内核当前没有提供自解压代码,因此如果使用了压缩内核映像文件
+(比如 Image.gz),则需要通过引导装载程序(使用 gzip 等)来进行解压。
+若引导装载程序没有实现这个需求,就要使用非压缩内核映像文件。
+
+
+4、调用内核映像
+-------------
+
+必要性: 强制
+
+已解压的内核映像包含一个 32 字节的头,内容如下:
+
+  u32 magic    = 0x14000008;   /* 跳转到 stext, 小端 */
+  u32 res0     = 0;            /* 保留 */
+  u64 text_offset;             /* 映像装载偏移 */
+  u64 res1     = 0;            /* 保留 */
+  u64 res2     = 0;            /* 保留 */
+
+映像必须位于系统 RAM 起始处的特定偏移(当前是 0x80000)。系统 RAM
+的起始地址必须是以 2MB 对齐的。
+
+在跳转入内核前,必须符合以下状态:
+
+- 停止所有 DMA 设备,这样内存数据就不会因为虚假网络包或磁盘数据而
+  被破坏。这可能可以节省你许多的调试时间。
+
+- 主 CPU 通用寄存器设置
+  x0 = 系统 RAM 中设备树数据块(dtb)的物理地址。
+  x1 = 0 (保留,将来可能使用)
+  x2 = 0 (保留,将来可能使用)
+  x3 = 0 (保留,将来可能使用)
+
+- CPU 模式
+  所有形式的中断必须在 PSTATE.DAIF 中被屏蔽(Debug、SError、IRQ
+  和 FIQ)。
+  CPU 必须处于 EL2(推荐,可访问虚拟化扩展)或非安全 EL1 模式下。
+
+- 高速缓存、MMU
+  MMU 必须关闭。
+  指令缓存开启或关闭都可以。
+  数据缓存必须关闭且无效。
+  外部高速缓存(如果存在)必须配置并禁用。
+
+- 架构计时器
+  CNTFRQ 必须设定为计时器的频率。
+  如果在 EL1 模式下进入内核,则 CNTHCTL_EL2 中的 EL1PCTEN (bit 0)
+  必须置位。
+
+- 一致性
+  通过内核启动的所有 CPU 在内核入口地址上必须处于相同的一致性域中。
+  这可能要根据具体实现来定义初始化过程,以使能每个CPU上对维护操作的
+  接收。
+
+- 系统寄存器
+  在进入内核映像的异常级中,所有构架中可写的系统寄存器必须通过软件
+  在一个更高的异常级别下初始化,以防止在 未知 状态下运行。
+
+引导装载程序必须在每个 CPU 处于以下状态时跳入内核入口:
+
+- 主 CPU 必须直接跳入内核映像的第一条指令。通过此 CPU 传递的设备树
+  数据块必须在每个 CPU 节点中包含以下内容:
+
+    1、‘enable-method’属性。目前,此字段支持的值仅为字符串“spin-table”。
+
+    2、‘cpu-release-addr’标识一个 64-bit、初始化为零的内存位置。
+
+  引导装载程序必须生成这些设备树属性,并在跳入内核入口之前将其插入
+  数据块。
+
+- 任何辅助 CPU 必须在内存保留区(通过设备树中的 /memreserve/ 域传递
+  给内核)中自旋于内核之外,轮询它们的 cpu-release-addr 位置(必须
+  包含在保留区中)。可通过插入 wfe 指令来降低忙循环开销,而主 CPU 将
+  发出 sev 指令。当对 cpu-release-addr 所指位置的读取操作返回非零值
+  时,CPU 必须直接跳入此值所指向的地址。
+
+- 辅助 CPU 通用寄存器设置
+  x0 = 0 (保留,将来可能使用)
+  x1 = 0 (保留,将来可能使用)
+  x2 = 0 (保留,将来可能使用)
+  x3 = 0 (保留,将来可能使用)
diff --git a/Documentation/zh_CN/arm64/memory.txt b/Documentation/zh_CN/arm64/memory.txt
new file mode 100644 (file)
index 0000000..83b5193
--- /dev/null
@@ -0,0 +1,93 @@
+Chinese translated version of Documentation/arm64/memory.txt
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Maintainer: Catalin Marinas <catalin.marinas@arm.com>
+Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
+---------------------------------------------------------------------
+Documentation/arm64/memory.txt 的中文翻译
+
+如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
+交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
+译存在问题,请联系中文版维护者。
+
+英文版维护者: Catalin Marinas <catalin.marinas@arm.com>
+中文版维护者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版翻译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+中文版校译者: 傅炜  Fu Wei <tekkamanninja@gmail.com>
+
+以下为正文
+---------------------------------------------------------------------
+                    Linux 在 AArch64 中的内存布局
+                    ===========================
+
+作者: Catalin Marinas <catalin.marinas@arm.com>
+日期: 2012 年 02 月 20 日
+
+本文档描述 AArch64 Linux 内核所使用的虚拟内存布局。此构架可以实现
+页大小为 4KB 的 4 级转换表和页大小为 64KB 的 3 级转换表。
+
+AArch64 Linux 使用页大小为 4KB 的 3 级转换表配置,对于用户和内核
+都有 39-bit (512GB) 的虚拟地址空间。对于页大小为 64KB的配置,仅
+使用 2 级转换表,但内存布局相同。
+
+用户地址空间的 63:39 位为 0,而内核地址空间的相应位为 1。TTBRx 的
+选择由虚拟地址的 63 位给出。swapper_pg_dir 仅包含内核(全局)映射,
+而用户 pgd 仅包含用户(非全局)映射。swapper_pgd_dir 地址被写入
+TTBR1 中,且从不写入 TTBR0。
+
+
+AArch64 Linux 内存布局:
+
+起始地址                   结束地址                    大小          用途
+-----------------------------------------------------------------------
+0000000000000000       0000007fffffffff         512GB          用户空间
+
+ffffff8000000000       ffffffbbfffcffff        ~240GB          vmalloc
+
+ffffffbbfffd0000       ffffffbcfffdffff          64KB          [防护页]
+
+ffffffbbfffe0000       ffffffbcfffeffff          64KB          PCI I/O 空间
+
+ffffffbbffff0000       ffffffbcffffffff          64KB          [防护页]
+
+ffffffbc00000000       ffffffbdffffffff           8GB          vmemmap
+
+ffffffbe00000000       ffffffbffbffffff          ~8GB          [防护页,未来用于 vmmemap]
+
+ffffffbffc000000       ffffffbfffffffff          64MB          模块
+
+ffffffc000000000       ffffffffffffffff         256GB          内存空间
+
+
+4KB 页大小的转换表查找:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |         |         |         |         |
+ |                 |         |         |         |         v
+ |                 |         |         |         |   [11:0]  页内偏移
+ |                 |         |         |         +-> [20:12] L3 索引
+ |                 |         |         +-----------> [29:21] L2 索引
+ |                 |         +---------------------> [38:30] L1 索引
+ |                 +-------------------------------> [47:39] L0 索引 (未使用)
+ +-------------------------------------------------> [63] TTBR0/1
+
+
+64KB 页大小的转换表查找:
+
++--------+--------+--------+--------+--------+--------+--------+--------+
+|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
++--------+--------+--------+--------+--------+--------+--------+--------+
+ |                 |    |               |              |
+ |                 |    |               |              v
+ |                 |    |               |            [15:0]  页内偏移
+ |                 |    |               +----------> [28:16] L3 索引
+ |                 |    +--------------------------> [41:29] L2 索引 (仅使用 38:29 )
+ |                 +-------------------------------> [47:42] L1 索引 (未使用)
+ +-------------------------------------------------> [63] TTBR0/1
index 46ce7c6d527d3a1c5e16a209bdb2594428a949cb..14cffbfbd041b52d8eaf074374bf3a977560d3e7 100644 (file)
@@ -235,6 +235,7 @@ F:  drivers/platform/x86/acer-wmi.c
 
 ACPI
 M:     Len Brown <lenb@kernel.org>
+M:     Rafael J. Wysocki <rjw@sisk.pl>
 L:     linux-acpi@vger.kernel.org
 W:     http://www.lesswatts.org/projects/acpi/
 Q:     http://patchwork.kernel.org/project/linux-acpi/list/
@@ -502,7 +503,7 @@ F:  include/linux/altera_uart.h
 F:     include/linux/altera_jtaguart.h
 
 AMD FAM15H PROCESSOR POWER MONITORING DRIVER
-M:     Andreas Herrmann <andreas.herrmann3@amd.com>
+M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/fam15h_power
@@ -525,17 +526,17 @@ F:        drivers/video/geode/
 F:     arch/x86/include/asm/geode.h
 
 AMD IOMMU (AMD-VI)
-M:     Joerg Roedel <joerg.roedel@amd.com>
+M:     Joerg Roedel <joro@8bytes.org>
 L:     iommu@lists.linux-foundation.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
-S:     Supported
+S:     Maintained
 F:     drivers/iommu/amd_iommu*.[ch]
 F:     include/linux/amd-iommu.h
 
 AMD MICROCODE UPDATE SUPPORT
-M:     Andreas Herrmann <andreas.herrmann3@amd.com>
+M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     amd64-microcode@amd64.org
-S:     Supported
+S:     Maintained
 F:     arch/x86/kernel/microcode_amd.c
 
 AMS (Apple Motion Sensor) DRIVER
@@ -636,6 +637,13 @@ W: http://www.arm.linux.org.uk/
 S:     Maintained
 F:     arch/arm/
 
+ARM SUB-ARCHITECTURES
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     MAINTAINED
+F:     arch/arm/mach-*/
+F:     arch/arm/plat-*/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
+
 ARM PRIMECELL AACI PL041 DRIVER
 M:     Russell King <linux@arm.linux.org.uk>
 S:     Maintained
@@ -833,6 +841,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
 F:     arch/arm/mach-sa1100/jornada720.c
 F:     arch/arm/mach-sa1100/include/mach/jornada720.h
 
+ARM/IGEP MACHINE SUPPORT
+M:     Enric Balletbo i Serra <eballetbo@gmail.com>
+M:     Javier Martinez Canillas <javier@dowhile0.org>
+L:     linux-omap@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-omap2/board-igep0020.c
+
 ARM/INCOME PXA270 SUPPORT
 M:     Marek Vasut <marek.vasut@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -2498,6 +2514,7 @@ M:        Joonyoung Shim <jy0922.shim@samsung.com>
 M:     Seung-Woo Kim <sw0312.kim@samsung.com>
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     dri-devel@lists.freedesktop.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git
 S:     Supported
 F:     drivers/gpu/drm/exynos
 F:     include/drm/exynos*
@@ -2698,10 +2715,10 @@ F:      include/linux/edac.h
 
 EDAC-AMD64
 M:     Doug Thompson <dougthompson@xmission.com>
-M:     Borislav Petkov <borislav.petkov@amd.com>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
-S:     Supported
+S:     Maintained
 F:     drivers/edac/amd64_edac*
 
 EDAC-E752X
@@ -2800,6 +2817,7 @@ F:        sound/usb/misc/ua101.c
 EXTENSIBLE FIRMWARE INTERFACE (EFI)
 M:     Matt Fleming <matt.fleming@intel.com>
 L:     linux-efi@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mfleming/efi.git
 S:     Maintained
 F:     Documentation/x86/efi-stub.txt
 F:     arch/ia64/kernel/efi.c
@@ -3587,6 +3605,49 @@ F:       drivers/hid/hid-hyperv.c
 F:     drivers/net/hyperv/
 F:     drivers/staging/hv/
 
+I2C OVER PARALLEL PORT
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-parport
+F:     Documentation/i2c/busses/i2c-parport-light
+F:     drivers/i2c/busses/i2c-parport.c
+F:     drivers/i2c/busses/i2c-parport-light.c
+
+I2C/SMBUS CONTROLLER DRIVERS FOR PC
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-ali1535
+F:     Documentation/i2c/busses/i2c-ali1563
+F:     Documentation/i2c/busses/i2c-ali15x3
+F:     Documentation/i2c/busses/i2c-amd756
+F:     Documentation/i2c/busses/i2c-amd8111
+F:     Documentation/i2c/busses/i2c-i801
+F:     Documentation/i2c/busses/i2c-nforce2
+F:     Documentation/i2c/busses/i2c-piix4
+F:     Documentation/i2c/busses/i2c-sis5595
+F:     Documentation/i2c/busses/i2c-sis630
+F:     Documentation/i2c/busses/i2c-sis96x
+F:     Documentation/i2c/busses/i2c-via
+F:     Documentation/i2c/busses/i2c-viapro
+F:     drivers/i2c/busses/i2c-ali1535.c
+F:     drivers/i2c/busses/i2c-ali1563.c
+F:     drivers/i2c/busses/i2c-ali15x3.c
+F:     drivers/i2c/busses/i2c-amd756.c
+F:     drivers/i2c/busses/i2c-amd756-s4882.c
+F:     drivers/i2c/busses/i2c-amd8111.c
+F:     drivers/i2c/busses/i2c-i801.c
+F:     drivers/i2c/busses/i2c-isch.c
+F:     drivers/i2c/busses/i2c-nforce2.c
+F:     drivers/i2c/busses/i2c-nforce2-s4985.c
+F:     drivers/i2c/busses/i2c-piix4.c
+F:     drivers/i2c/busses/i2c-sis5595.c
+F:     drivers/i2c/busses/i2c-sis630.c
+F:     drivers/i2c/busses/i2c-sis96x.c
+F:     drivers/i2c/busses/i2c-via.c
+F:     drivers/i2c/busses/i2c-viapro.c
+
 I2C/SMBUS STUB DRIVER
 M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     linux-i2c@vger.kernel.org
@@ -3594,9 +3655,8 @@ S:        Maintained
 F:     drivers/i2c/busses/i2c-stub.c
 
 I2C SUBSYSTEM
-M:     "Jean Delvare (PC drivers, core)" <khali@linux-fr.org>
+M:     Wolfram Sang <w.sang@pengutronix.de>
 M:     "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
-M:     "Wolfram Sang (embedded platforms)" <w.sang@pengutronix.de>
 L:     linux-i2c@vger.kernel.org
 W:     http://i2c.wiki.kernel.org/
 T:     quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
@@ -3607,6 +3667,13 @@ F:       drivers/i2c/
 F:     include/linux/i2c.h
 F:     include/linux/i2c-*.h
 
+I2C-TAOS-EVM DRIVER
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-taos-evm
+F:     drivers/i2c/busses/i2c-taos-evm.c
+
 I2C-TINY-USB DRIVER
 M:     Till Harbaum <till@harbaum.org>
 L:     linux-i2c@vger.kernel.org
@@ -3693,7 +3760,7 @@ S:        Maintained
 F:     drivers/platform/x86/ideapad-laptop.c
 
 IDE/ATAPI DRIVERS
-M:     Borislav Petkov <petkovbb@gmail.com>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-ide@vger.kernel.org
 S:     Maintained
 F:     Documentation/cdrom/ide-cd
@@ -3868,7 +3935,9 @@ M:        Greg Rose <gregory.v.rose@intel.com>
 M:     Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
 M:     Alex Duyck <alexander.h.duyck@intel.com>
 M:     John Ronciak <john.ronciak@intel.com>
+M:     Tushar Dave <tushar.n.dave@intel.com>
 L:     e1000-devel@lists.sourceforge.net
+W:     http://www.intel.com/support/feedback.htm
 W:     http://e1000.sourceforge.net/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next.git
@@ -4220,8 +4289,8 @@ F:        include/linux/lockd/
 F:     include/linux/sunrpc/
 
 KERNEL VIRTUAL MACHINE (KVM)
-M:     Avi Kivity <avi@redhat.com>
 M:     Marcelo Tosatti <mtosatti@redhat.com>
+M:     Gleb Natapov <gleb@redhat.com>
 L:     kvm@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -4371,7 +4440,7 @@ F:        Documentation/scsi/53c700.txt
 F:     drivers/scsi/53c700*
 
 LED SUBSYSTEM
-M:     Bryan Wu <bryan.wu@canonical.com>
+M:     Bryan Wu <cooloney@gmail.com>
 M:     Richard Purdie <rpurdie@rpsys.net>
 L:     linux-leds@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git
@@ -4752,6 +4821,14 @@ F:       Documentation/scsi/megaraid.txt
 F:     drivers/scsi/megaraid.*
 F:     drivers/scsi/megaraid/
 
+MELLANOX ETHERNET DRIVER (mlx4_en)
+M:     Amir Vadai <amirv@mellanox.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+W:     http://www.mellanox.com
+Q:     http://patchwork.ozlabs.org/project/netdev/list/
+F:     drivers/net/ethernet/mellanox/mlx4/en_*
+
 MEMORY MANAGEMENT
 L:     linux-mm@kvack.org
 W:     http://www.linux-mm.org
@@ -4994,7 +5071,7 @@ NETWORKING [GENERAL]
 M:     "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
-W:     http://patchwork.ozlabs.org/project/netdev/list/
+Q:     http://patchwork.ozlabs.org/project/netdev/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:     Maintained
@@ -5018,6 +5095,20 @@ F:       net/ipv6/
 F:     include/net/ip*
 F:     arch/x86/net/*
 
+NETWORKING [IPSEC]
+M:     Steffen Klassert <steffen.klassert@secunet.com>
+M:     Herbert Xu <herbert@gondor.apana.org.au>
+M:     "David S. Miller" <davem@davemloft.net>
+L:     netdev@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+S:     Maintained
+F:     net/xfrm/
+F:     net/key/
+F:     net/ipv4/xfrm*
+F:     net/ipv6/xfrm*
+F:     include/uapi/linux/xfrm.h
+F:     include/net/xfrm.h
+
 NETWORKING [LABELED] (NetLabel, CIPSO, Labeled IPsec, SECMARK)
 M:     Paul Moore <paul@paul-moore.com>
 L:     netdev@vger.kernel.org
@@ -5040,12 +5131,19 @@ F:      drivers/net/wireless/
 NETWORKING DRIVERS
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
+Q:     http://patchwork.ozlabs.org/project/netdev/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
 S:     Odd Fixes
 F:     drivers/net/
 F:     include/linux/if_*
-F:     include/linux/*device.h
+F:     include/linux/netdevice.h
+F:     include/linux/arcdevice.h
+F:     include/linux/etherdevice.h
+F:     include/linux/fcdevice.h
+F:     include/linux/fddidevice.h
+F:     include/linux/hippidevice.h
+F:     include/linux/inetdevice.h
 
 NETXEN (1/10) GbE SUPPORT
 M:     Sony Chacko <sony.chacko@qlogic.com>
@@ -5334,7 +5432,7 @@ S:        Maintained
 F:     sound/drivers/opl4/
 
 OPROFILE
-M:     Robert Richter <robert.richter@amd.com>
+M:     Robert Richter <rric@kernel.org>
 L:     oprofile-list@lists.sf.net
 S:     Maintained
 F:     arch/*/include/asm/oprofile*.h
@@ -5618,7 +5716,7 @@ S:        Maintained
 F:     drivers/pinctrl/spear/
 
 PKTCDVD DRIVER
-M:     Peter Osterlund <petero2@telia.com>
+M:     Jiri Kosina <jkosina@suse.cz>
 S:     Maintained
 F:     drivers/block/pktcdvd.c
 F:     include/linux/pktcdvd.h
@@ -6336,6 +6434,7 @@ F:        drivers/scsi/st*
 SCTP PROTOCOL
 M:     Vlad Yasevich <vyasevich@gmail.com>
 M:     Sridhar Samudrala <sri@us.ibm.com>
+M:     Neil Horman <nhorman@tuxdriver.com>
 L:     linux-sctp@vger.kernel.org
 W:     http://lksctp.sourceforge.net
 S:     Maintained
@@ -7180,6 +7279,14 @@ L:       linux-xtensa@linux-xtensa.org
 S:     Maintained
 F:     arch/xtensa/
 
+THERMAL
+M:      Zhang Rui <rui.zhang@intel.com>
+L:      linux-pm@vger.kernel.org
+T:      git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
+S:      Supported
+F:      drivers/thermal/
+F:      include/linux/thermal.h
+
 THINKPAD ACPI EXTRAS DRIVER
 M:     Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
 L:     ibm-acpi-devel@lists.sourceforge.net
@@ -7354,8 +7461,7 @@ S:        Maintained
 F:     drivers/net/ethernet/dec/tulip/
 
 TUN/TAP driver
-M:     Maxim Krasnyansky <maxk@qualcomm.com>
-L:     vtun@office.satix.net
+M:     Maxim Krasnyansky <maxk@qti.qualcomm.com>
 W:     http://vtun.sourceforge.net/tun
 S:     Maintained
 F:     Documentation/networking/tuntap.txt
@@ -7737,6 +7843,13 @@ W:       http://www.ideasonboard.org/uvc/
 S:     Maintained
 F:     drivers/media/usb/uvc/
 
+USB WEBCAM GADGET
+M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+L:     linux-usb@vger.kernel.org
+S:     Maintained
+F:     drivers/usb/gadget/*uvc*.c
+F:     drivers/usb/gadget/webcam.c
+
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
 M:     Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
 L:     linux-wireless@vger.kernel.org
@@ -7856,13 +7969,6 @@ M:       Roger Luethi <rl@hellgate.ch>
 S:     Maintained
 F:     drivers/net/ethernet/via/via-rhine.c
 
-VIAPRO SMBUS DRIVER
-M:     Jean Delvare <khali@linux-fr.org>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     Documentation/i2c/busses/i2c-viapro
-F:     drivers/i2c/busses/i2c-viapro.c
-
 VIA SD/MMC CARD CONTROLLER DRIVER
 M:     Bruce Chang <brucechang@via.com.tw>
 M:     Harald Welte <HaraldWelte@viatech.com>
@@ -8117,7 +8223,7 @@ F:        drivers/platform/x86
 
 X86 MCE INFRASTRUCTURE
 M:     Tony Luck <tony.luck@intel.com>
-M:     Borislav Petkov <bp@amd64.org>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
index 5be2ee8c90e4247b90ec1aed9421492226d5f7f8..3d2fc460b22f38b6d37ba31016a96c6926bdc0b1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 7
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc7
 NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
@@ -437,7 +437,9 @@ endif
 PHONY += asm-generic
 asm-generic:
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
-                   obj=arch/$(SRCARCH)/include/generated/asm
+                   src=asm obj=arch/$(SRCARCH)/include/generated/asm
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.asm-generic \
+                   src=uapi/asm obj=arch/$(SRCARCH)/include/generated/uapi/asm
 
 # To make sure we do not include .config for any of the *config targets
 # catch them early, and hand them over to scripts/kconfig/Makefile
@@ -717,6 +719,17 @@ endif # INSTALL_MOD_STRIP
 export mod_strip_cmd
 
 
+ifeq ($(CONFIG_MODULE_SIG),y)
+MODSECKEY = ./signing_key.priv
+MODPUBKEY = ./signing_key.x509
+export MODPUBKEY
+mod_sign_cmd = perl $(srctree)/scripts/sign-file $(MODSECKEY) $(MODPUBKEY)
+else
+mod_sign_cmd = true
+endif
+export mod_sign_cmd
+
+
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
 
index 7d2f75be932e6d16e4ceba058fe0e0c769a8be32..0087d053b77f9ada256b4d58fec451552d48eb63 100644 (file)
@@ -47,6 +47,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index 4554ecbff7c6527be35fea7d20e255cc0770b653..1f8c72959fb6c7a1a9891833ae8d9b037cb179d5 100644 (file)
@@ -7,6 +7,7 @@
 #include <asm/processor.h>
 #include <asm/types.h>
 #include <asm/hwrpb.h>
+#include <asm/sysinfo.h>
 #endif
 
 #ifndef __ASSEMBLY__
@@ -21,6 +22,7 @@ struct thread_info {
        mm_segment_t            addr_limit;     /* thread address space */
        unsigned                cpu;            /* current CPU */
        int                     preempt_count; /* 0 => preemptable, <0 => BUG */
+       unsigned int            status;         /* thread-synchronous flags */
 
        int bpt_nsaved;
        unsigned long bpt_addr[2];              /* breakpoint handling  */
@@ -63,8 +65,6 @@ register struct thread_info *__current_thread_info __asm__("$8");
  * - these are process state flags and used from assembly
  * - pending work-to-be-done flags come first and must be assigned to be
  *   within bits 0 to 7 to fit in and immediate operand.
- * - ALPHA_UAC_SHIFT below must be kept consistent with the unaligned
- *   control flags.
  *
  * TIF_SYSCALL_TRACE is known to be 0 via blbs.
  */
@@ -72,18 +72,12 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define TIF_NOTIFY_RESUME      1       /* callback before returning to user */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
-#define TIF_POLLING_NRFLAG     8       /* poll_idle is polling NEED_RESCHED */
 #define TIF_DIE_IF_KERNEL      9       /* dik recursion lock */
-#define TIF_UAC_NOPRINT                10      /* ! Preserve sequence of following */
-#define TIF_UAC_NOFIX          11      /* ! flags as they match            */
-#define TIF_UAC_SIGBUS         12      /* ! userspace part of 'osf_sysinfo' */
 #define TIF_MEMDIE             13      /* is terminating due to OOM killer */
-#define TIF_RESTORE_SIGMASK    14      /* restore signal mask in do_signal */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 
 /* Work to do on interrupt/exception return.  */
@@ -94,29 +88,63 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK         \
                                 | _TIF_SYSCALL_TRACE)
 
-#define ALPHA_UAC_SHIFT                TIF_UAC_NOPRINT
-#define ALPHA_UAC_MASK         (1 << TIF_UAC_NOPRINT | 1 << TIF_UAC_NOFIX | \
-                                1 << TIF_UAC_SIGBUS)
+#define TS_UAC_NOPRINT         0x0001  /* ! Preserve the following three */
+#define TS_UAC_NOFIX           0x0002  /* ! flags as they match          */
+#define TS_UAC_SIGBUS          0x0004  /* ! userspace part of 'osf_sysinfo' */
+#define TS_RESTORE_SIGMASK     0x0008  /* restore signal mask in do_signal() */
+#define TS_POLLING             0x0010  /* idle task polling need_resched,
+                                          skip sending interrupt */
 
-#define SET_UNALIGN_CTL(task,value)    ({                                   \
-       task_thread_info(task)->flags = ((task_thread_info(task)->flags &    \
-               ~ALPHA_UAC_MASK)                                             \
-               | (((value) << ALPHA_UAC_SHIFT)       & (1<<TIF_UAC_NOPRINT))\
-               | (((value) << (ALPHA_UAC_SHIFT + 1)) & (1<<TIF_UAC_SIGBUS)) \
-               | (((value) << (ALPHA_UAC_SHIFT - 1)) & (1<<TIF_UAC_NOFIX)));\
+#define tsk_is_polling(t) (task_thread_info(t)->status & TS_POLLING)
+
+#ifndef __ASSEMBLY__
+#define HAVE_SET_RESTORE_SIGMASK       1
+static inline void set_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       ti->status |= TS_RESTORE_SIGMASK;
+       WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
+}
+#endif
+
+#define SET_UNALIGN_CTL(task,value)    ({                              \
+       __u32 status = task_thread_info(task)->status & ~UAC_BITMASK;   \
+       if (value & PR_UNALIGN_NOPRINT)                                 \
+               status |= TS_UAC_NOPRINT;                               \
+       if (value & PR_UNALIGN_SIGBUS)                                  \
+               status |= TS_UAC_SIGBUS;                                \
+       if (value & 4)  /* alpha-specific */                            \
+               status |= TS_UAC_NOFIX;                                 \
+       task_thread_info(task)->status = status;                        \
        0; })
 
 #define GET_UNALIGN_CTL(task,value)    ({                              \
-       put_user((task_thread_info(task)->flags & (1 << TIF_UAC_NOPRINT))\
-                 >> ALPHA_UAC_SHIFT                                    \
-                | (task_thread_info(task)->flags & (1 << TIF_UAC_SIGBUS))\
-                >> (ALPHA_UAC_SHIFT + 1)                               \
-                | (task_thread_info(task)->flags & (1 << TIF_UAC_NOFIX))\
-                >> (ALPHA_UAC_SHIFT - 1),                              \
-                (int __user *)(value));                                \
+       __u32 status = task_thread_info(task)->status & ~UAC_BITMASK;   \
+       __u32 res = 0;                                                  \
+       if (status & TS_UAC_NOPRINT)                                    \
+               res |= PR_UNALIGN_NOPRINT;                              \
+       if (status & TS_UAC_SIGBUS)                                     \
+               res |= PR_UNALIGN_SIGBUS;                               \
+       if (status & TS_UAC_NOFIX)                                      \
+               res |= 4;                                               \
+       put_user(res, (int __user *)(value));                           \
        })
 
-#define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
-
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_THREAD_INFO_H */
index 9eb090582cf1eb2c557e03025bafc73846fde02f..14db93e4c8a83662d459a6ff1a818318dbc61eeb 100644 (file)
@@ -445,7 +445,7 @@ struct procfs_args {
  * unhappy with OSF UFS. [CHECKME]
  */
 static int
-osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
+osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
@@ -465,7 +465,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
 }
 
 static int
-osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
+osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
@@ -485,7 +485,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
 }
 
 static int
-osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
+osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags)
 {
        struct procfs_args tmp;
 
@@ -793,8 +793,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
        case GSI_UACPROC:
                if (nbytes < sizeof(unsigned int))
                        return -EINVAL;
-               w = (current_thread_info()->flags >> ALPHA_UAC_SHIFT) &
-                       UAC_BITMASK;
+               w = current_thread_info()->status & UAC_BITMASK;
                if (put_user(w, (unsigned int __user *)buffer))
                        return -EFAULT;
                return 1;
@@ -904,24 +903,20 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
                break;
 
        case SSI_NVPAIRS: {
-               unsigned long v, w, i;
-               unsigned int old, new;
+               unsigned __user *p = buffer;
+               unsigned i;
                
-               for (i = 0; i < nbytes; ++i) {
+               for (i = 0, p = buffer; i < nbytes; ++i, p += 2) {
+                       unsigned v, w, status;
 
-                       if (get_user(v, 2*i + (unsigned int __user *)buffer))
-                               return -EFAULT;
-                       if (get_user(w, 2*i + 1 + (unsigned int __user *)buffer))
+                       if (get_user(v, p) || get_user(w, p + 1))
                                return -EFAULT;
                        switch (v) {
                        case SSIN_UACPROC:
-                       again:
-                               old = current_thread_info()->flags;
-                               new = old & ~(UAC_BITMASK << ALPHA_UAC_SHIFT);
-                               new = new | (w & UAC_BITMASK) << ALPHA_UAC_SHIFT;
-                               if (cmpxchg(&current_thread_info()->flags,
-                                           old, new) != old)
-                                       goto again;
+                               w &= UAC_BITMASK;
+                               status = current_thread_info()->status;
+                               status = (status & ~UAC_BITMASK) | w;
+                               current_thread_info()->status = status;
                                break;
  
                        default:
index 4054e0ffe2b25a1055deb3946167755dc73fb201..51987dcf79b83904bd6d5d564db39abe7b7c73f3 100644 (file)
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(pm_power_off);
 void
 cpu_idle(void)
 {
-       set_thread_flag(TIF_POLLING_NRFLAG);
+       current_thread_info()->status |= TS_POLLING;
 
        while (1) {
                /* FIXME -- EV6 and LCA45 know how to power down
index 80d987c0e9aa55889aa3b8ed5d8a25fe9309b1c2..272666d006df1ddd67635caf229221c9b92244c6 100644 (file)
@@ -780,17 +780,17 @@ do_entUnaUser(void __user * va, unsigned long opcode,
        /* Check the UAC bits to decide what the user wants us to do
           with the unaliged access.  */
 
-       if (!test_thread_flag (TIF_UAC_NOPRINT)) {
+       if (!(current_thread_info()->status & TS_UAC_NOPRINT)) {
                if (__ratelimit(&ratelimit)) {
                        printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
                               current->comm, task_pid_nr(current),
                               regs->pc - 4, va, opcode, reg);
                }
        }
-       if (test_thread_flag (TIF_UAC_SIGBUS))
+       if ((current_thread_info()->status & TS_UAC_SIGBUS))
                goto give_sigbus;
        /* Not sure why you'd want to use this, but... */
-       if (test_thread_flag (TIF_UAC_NOFIX))
+       if ((current_thread_info()->status & TS_UAC_NOFIX))
                return;
 
        /* Don't bother reading ds in the access check since we already
index 73067efd484530d4021a220fecce329b4752b3c0..ade7e924bef5faaf00de76c0354e025ed4371b35 100644 (file)
@@ -1603,8 +1603,8 @@ config NR_CPUS
        default "4"
 
 config HOTPLUG_CPU
-       bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
-       depends on SMP && HOTPLUG && EXPERIMENTAL
+       bool "Support for hot-pluggable CPUs"
+       depends on SMP && HOTPLUG
        help
          Say Y here to experiment with turning CPUs off and on.  CPUs
          can be controlled through /sys/devices/system/cpu.
@@ -1645,8 +1645,8 @@ config HZ
        default 100
 
 config THUMB2_KERNEL
-       bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
-       depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
+       bool "Compile the kernel in Thumb-2 mode"
+       depends on CPU_V7 && !CPU_V6 && !CPU_V6K
        select AEABI
        select ARM_ASM_UNIFIED
        select ARM_UNWIND
@@ -1850,6 +1850,7 @@ config XEN_DOM0
 config XEN
        bool "Xen guest support on ARM (EXPERIMENTAL)"
        depends on EXPERIMENTAL && ARM && OF
+       depends on CPU_V7 && !CPU_V6
        help
          Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
 
index f023e3acdfbd8c7c17335cfa9518df05119f4ab7..5f914fca911b77b747dd43569b84a76883abcef7 100644 (file)
@@ -21,8 +21,6 @@ endif
 OBJCOPYFLAGS   :=-O binary -R .comment -S
 GZFLAGS                :=-9
 #KBUILD_CFLAGS +=-pipe
-# Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb:
-KBUILD_CFLAGS  +=$(call cc-option,-marm,)
 
 # Never generate .eh_frame
 KBUILD_CFLAGS  += $(call cc-option,-fno-dwarf2-cfi-asm)
@@ -105,17 +103,20 @@ endif
 ifeq ($(CONFIG_THUMB2_KERNEL),y)
 AFLAGS_AUTOIT  :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it)
 AFLAGS_NOWARN  :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
-CFLAGS_THUMB2  :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
-AFLAGS_THUMB2  :=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
+CFLAGS_ISA     :=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
+AFLAGS_ISA     :=$(CFLAGS_ISA) -Wa$(comma)-mthumb
 # Work around buggy relocation from gas if requested:
 ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)
 CFLAGS_MODULE  +=-fno-optimize-sibling-calls
 endif
+else
+CFLAGS_ISA     :=$(call cc-option,-marm,)
+AFLAGS_ISA     :=$(CFLAGS_ISA)
 endif
 
 # Need -Uarm for gcc < 3.x
-KBUILD_CFLAGS  +=$(CFLAGS_ABI) $(CFLAGS_THUMB2) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-KBUILD_AFLAGS  +=$(CFLAGS_ABI) $(AFLAGS_THUMB2) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
+KBUILD_CFLAGS  +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
+KBUILD_AFLAGS  +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
 
 CHECKFLAGS     += -D__arm__
 
index 3fdab016aa5cfdc9132813f4c5be44348fb1c539..9137df539b61c649b218e26d8f56365f289a5c84 100644 (file)
@@ -33,7 +33,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)
 
 $(obj)/xipImage: vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
+       @$(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
 
 $(obj)/Image $(obj)/zImage: FORCE
        @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@@ -48,14 +48,14 @@ $(obj)/xipImage: FORCE
 
 $(obj)/Image: vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 endif
 
@@ -90,7 +90,7 @@ fi
 $(obj)/uImage: $(obj)/zImage FORCE
        @$(check_for_multiple_loadaddr)
        $(call if_changed,uimage)
-       @echo '  Image $@ is ready'
+       @$(kecho) '  Image $@ is ready'
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
        $(Q)$(MAKE) $(build)=$(obj)/bootp $@
@@ -98,7 +98,7 @@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
        $(call if_changed,objcopy)
-       @echo '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 PHONY += initrd FORCE
 initrd:
index 90275f036cd14517affdb724ea4c6adf5194b72c..49ca86e37b8d3c0cbe2b0e84a5ab3abeacee6926 100644 (file)
@@ -652,6 +652,15 @@ __setup_mmu:       sub     r3, r4, #16384          @ Page directory size
                mov     pc, lr
 ENDPROC(__setup_mmu)
 
+@ Enable unaligned access on v6, to allow better code generation
+@ for the decompressor C code:
+__armv6_mmu_cache_on:
+               mrc     p15, 0, r0, c1, c0, 0   @ read SCTLR
+               bic     r0, r0, #2              @ A (no unaligned access fault)
+               orr     r0, r0, #1 << 22        @ U (v6 unaligned access model)
+               mcr     p15, 0, r0, c1, c0, 0   @ write SCTLR
+               b       __armv4_mmu_cache_on
+
 __arm926ejs_mmu_cache_on:
 #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
                mov     r0, #4                  @ put dcache in WT mode
@@ -694,6 +703,9 @@ __armv7_mmu_cache_on:
                bic     r0, r0, #1 << 28        @ clear SCTLR.TRE
                orr     r0, r0, #0x5000         @ I-cache enable, RR cache replacement
                orr     r0, r0, #0x003c         @ write buffer
+               bic     r0, r0, #2              @ A (no unaligned access fault)
+               orr     r0, r0, #1 << 22        @ U (v6 unaligned access model)
+                                               @ (needed for ARM1176)
 #ifdef CONFIG_MMU
 #ifdef CONFIG_CPU_ENDIAN_BE8
                orr     r0, r0, #1 << 25        @ big-endian page tables
@@ -914,7 +926,7 @@ proc_types:
 
                .word   0x0007b000              @ ARMv6
                .word   0x000ff000
-               W(b)    __armv4_mmu_cache_on
+               W(b)    __armv6_mmu_cache_on
                W(b)    __armv4_mmu_cache_off
                W(b)    __armv6_mmu_cache_flush
 
index c1ce813fcc4a1ea9094eb450ce4e50efd3d6048b..f37cf9fa5fa073318b3c6faad5d0a1480bd99826 100644 (file)
@@ -25,6 +25,8 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
        exynos4210-trats.dtb \
        exynos5250-smdk5250.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb
+dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
+       integratorcp.dtb
 dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
 dtb-$(CONFIG_ARCH_KIRKWOOD) += kirkwood-dns320.dtb \
        kirkwood-dns325.dtb \
index c634f87e230e110422f246e9228a6a26cbbcb6cb..4fcd21837bd3bfbbf8360ccf868f66ac7c15af10 100644 (file)
                };
        };
 };
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <1>;
+};
index 185d6325a458856768dde864a8c6f9921d9fd88f..366d9290c0ddddfa78618a159adf4f83ef58a974 100644 (file)
                };
        };
 };
+
+&cpsw_emac0 {
+       phy_id = <&davinci_mdio>, <0>;
+};
+
+&cpsw_emac1 {
+       phy_id = <&davinci_mdio>, <1>;
+};
index bb31bff0199830e989ef39259a89b20b4eb5b4a5..a4615b44f25e02e21a6c7ab7e391e93cbadb3f48 100644 (file)
                        interrupt-parent = <&intc>;
                        interrupts = <91>;
                };
+
+               mac: ethernet@4a100000 {
+                       compatible = "ti,cpsw";
+                       ti,hwmods = "cpgmac0";
+                       cpdma_channels = <8>;
+                       ale_entries = <1024>;
+                       bd_ram_size = <0x2000>;
+                       no_bd_ram = <0>;
+                       rx_descs = <64>;
+                       mac_control = <0x20>;
+                       slaves = <2>;
+                       cpts_active_slave = <0>;
+                       cpts_clock_mult = <0x80000000>;
+                       cpts_clock_shift = <29>;
+                       reg = <0x4a100000 0x800
+                              0x4a101200 0x100>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       interrupt-parent = <&intc>;
+                       /*
+                        * c0_rx_thresh_pend
+                        * c0_rx_pend
+                        * c0_tx_pend
+                        * c0_misc_pend
+                        */
+                       interrupts = <40 41 42 43>;
+                       ranges;
+
+                       davinci_mdio: mdio@4a101000 {
+                               compatible = "ti,davinci_mdio";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               ti,hwmods = "davinci_mdio";
+                               bus_freq = <1000000>;
+                               reg = <0x4a101000 0x100>;
+                       };
+
+                       cpsw_emac0: slave@4a100200 {
+                               /* Filled in by U-Boot */
+                               mac-address = [ 00 00 00 00 00 00 ];
+                       };
+
+                       cpsw_emac1: slave@4a100300 {
+                               /* Filled in by U-Boot */
+                               mac-address = [ 00 00 00 00 00 00 ];
+                       };
+
+               };
        };
 };
index b06c0db273b1fff820543d692b2a0470efe6b8f2..e6391a4e6649cc3787ba14d7ed1d190b2d932964 100644 (file)
                #size-cells = <0>;
 
                btn3 {
-                       label = "Buttin 3";
+                       label = "Button 3";
                        gpios = <&pioA 30 1>;
                        linux,code = <0x103>;
                        gpio-key,wakeup;
                };
 
                btn4 {
-                       label = "Buttin 4";
+                       label = "Button 4";
                        gpios = <&pioA 31 1>;
                        linux,code = <0x104>;
                        gpio-key,wakeup;
index 748ba7aa746cde3e14b8f04105f2dbd86fc6b214..4b0e0ca08f40d3d81b90be09b8cce47b9b225fac 100644 (file)
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80004000 0x1000>;
                        interrupts = <0 21 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80122000 0x1000>;
                        interrupts = <0 22 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80128000 0x1000>;
                        interrupts = <0 55 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x80110000 0x1000>;
                        interrupts = <0 12 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        compatible = "stericsson,db8500-i2c", "st,nomadik-i2c", "arm,primecell";
                        reg = <0x8012a000 0x1000>;
                        interrupts = <0 51 0x4>;
+                       arm,primecell-periphid = <0x180024>;
+
                        #address-cells = <1>;
                        #size-cells = <0>;
                        v-i2c-supply = <&db8500_vape_reg>;
                        interrupts = <0 60 0x4>;
                        status = "disabled";
                };
+
                sdi@80118000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80118000 0x1000>;
                        interrupts = <0 50 0x4>;
                        status = "disabled";
                };
+
                sdi@80005000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80005000 0x1000>;
                        interrupts = <0 41 0x4>;
                        status = "disabled";
                };
+
                sdi@80119000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80119000 0x1000>;
                        interrupts = <0 59 0x4>;
                        status = "disabled";
                };
+
                sdi@80114000 {
                        compatible = "arm,pl18x", "arm,primecell";
                        reg = <0x80114000 0x1000>;
                        interrupts = <0 99 0x4>;
                        status = "disabled";
                };
+
                sdi@80008000 {
                        compatible = "arm,pl18x", "arm,primecell";
-                       reg = <0x80114000 0x1000>;
+                       reg = <0x80008000 0x1000>;
                        interrupts = <0 100 0x4>;
                        status = "disabled";
                };
index 96fb824b5e6ecb3dd26481dcdbd3d67bb691772d..5a00022383e74d7e457c34be0331eb3edf7c0521 100644 (file)
@@ -4,21 +4,32 @@
        compatible = "marvell,dove";
        model = "Marvell Armada 88AP510 SoC";
 
-       interrupt-parent = <&intc>;
-
-       intc: interrupt-controller {
-               compatible = "marvell,orion-intc";
-               interrupt-controller;
-               #interrupt-cells = <1>;
-               reg = <0xf1020204 0x04>,
-                     <0xf1020214 0x04>;
-       };
-
-       mbus@f1000000 {
+       soc@f1000000 {
                compatible = "simple-bus";
-               ranges = <0 0xf1000000 0x4000000>;
                #address-cells = <1>;
                #size-cells = <1>;
+               interrupt-parent = <&intc>;
+
+               ranges = <0xc8000000 0xc8000000 0x0100000   /* CESA SRAM   1M */
+                         0xe0000000 0xe0000000 0x8000000   /* PCIe0 Mem 128M */
+                         0xe8000000 0xe8000000 0x8000000   /* PCIe1 Mem 128M */
+                         0xf0000000 0xf0000000 0x0100000   /* ScratchPad  1M */
+                         0x00000000 0xf1000000 0x1000000   /* SB/NB regs 16M */
+                         0xf2000000 0xf2000000 0x0100000   /* PCIe0 I/O   1M */
+                         0xf2100000 0xf2100000 0x0100000   /* PCIe0 I/O   1M */
+                         0xf8000000 0xf8000000 0x8000000>; /* BootROM   128M */
+
+               l2: l2-cache {
+                       compatible = "marvell,tauros2-cache";
+                       marvell,tauros2-cache-features = <0>;
+               };
+
+               intc: interrupt-controller {
+                       compatible = "marvell,orion-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       reg = <0x20204 0x04>, <0x20214 0x04>;
+               };
 
                uart0: serial@12000 {
                        compatible = "ns16550a";
                        status = "disabled";
                };
 
-               wdt: wdt@20300 {
-                       compatible = "marvell,orion-wdt";
-                       reg = <0x20300 0x28>;
-               };
-
                gpio0: gpio@d0400 {
                        compatible = "marvell,orion-gpio";
                        #gpio-cells = <2>;
                        nr-ports = <1>;
                        status = "disabled";
                };
+
+               crypto: crypto@30000 {
+                       compatible = "marvell,orion-crypto";
+                       reg = <0x30000 0x10000>,
+                             <0xc8000000 0x800>;
+                       reg-names = "regs", "sram";
+                       interrupts = <31>;
+                       status = "okay";
+               };
        };
 };
index 73567b843e72ae28e9ba4e721c8607a6135bf288..a21511c140712e24c4759293ac66248bbb8ae309 100644 (file)
        compatible = "samsung,trats", "samsung,exynos4210";
 
        memory {
-               reg =  <0x40000000 0x20000000
-                       0x60000000 0x20000000>;
+               reg =  <0x40000000 0x10000000
+                       0x50000000 0x10000000
+                       0x60000000 0x10000000
+                       0x70000000 0x10000000>;
        };
 
        chosen {
index 9ca4ca70c1bcb8f680fde33b924045eb6666839d..6d31aa3834608d41d84d848ec954f00a064a4659 100644 (file)
@@ -69,6 +69,7 @@
                                interrupts = <13>, <56>;
                                interrupt-names = "gpmi-dma", "bch";
                                clocks = <&clks 34>;
+                               clock-names = "gpmi_io";
                                fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
index e16d631554802f73227de6bcab58368d9e049227..55c57ea6169e02ec9dc81bb8e38407c608678bbd 100644 (file)
@@ -85,6 +85,7 @@
                                interrupts = <88>, <41>;
                                interrupt-names = "gpmi-dma", "bch";
                                clocks = <&clks 50>;
+                               clock-names = "gpmi_io";
                                fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
index 15df4c105e89c3b0ac20c7c0800307f4aa644a62..5bfa02a3f85cdd027d25d488513272ec4082579c 100644 (file)
                                        pinctrl_hog: hoggrp {
                                                fsl,pins = <
                                                        176  0x80000000 /* MX6Q_PAD_EIM_D25__GPIO_3_25 */
+                                               >;
+                                       };
+                               };
+
+                               arm2 {
+                                       pinctrl_usdhc3_arm2: usdhc3grp-arm2 {
+                                               fsl,pins = <
                                                        1363 0x80000000 /* MX6Q_PAD_NANDF_CS0__GPIO_6_11 */
                                                        1369 0x80000000 /* MX6Q_PAD_NANDF_CS1__GPIO_6_14 */
                                                >;
@@ -58,7 +65,8 @@
                                wp-gpios = <&gpio6 14 0>;
                                vmmc-supply = <&reg_3p3v>;
                                pinctrl-names = "default";
-                               pinctrl-0 = <&pinctrl_usdhc3_1>;
+                               pinctrl-0 = <&pinctrl_usdhc3_1
+                                            &pinctrl_usdhc3_arm2>;
                                status = "okay";
                        };
 
index f3990b04fecf4661216c9cf321dc817c72e1a0b7..3290e61be3e1c185e697ee406a22b5b2808db5b0 100644 (file)
                                                        66  0x1b0b0     /* MX6Q_PAD_RGMII_RD2__ENET_RGMII_RD2 */
                                                        70  0x1b0b0     /* MX6Q_PAD_RGMII_RD3__ENET_RGMII_RD3 */
                                                        48  0x1b0b0     /* MX6Q_PAD_RGMII_RX_CTL__RGMII_RX_CTL */
+                                                       1033 0x4001b0a8 /* MX6Q_PAD_GPIO_16__ENET_ANATOP_ETHERNET_REF_OUT*/
                                                >;
                                        };
 
                                compatible = "fsl,imx6q-fec";
                                reg = <0x02188000 0x4000>;
                                interrupts = <0 118 0x04 0 119 0x04>;
-                               clocks = <&clks 117>, <&clks 117>;
-                               clock-names = "ipg", "ahb";
+                               clocks = <&clks 117>, <&clks 117>, <&clks 177>;
+                               clock-names = "ipg", "ahb", "ptp";
                                status = "disabled";
                        };
 
index 8ac51c08269d303b77cd0560133e475dc7bfa927..8fea375c734d75e99ad06adac9f65f5413989285 100644 (file)
                #size-cells = <0>;
                button@1 {
                        label = "Function Button";
-                       linux,code = <132>;
+                       linux,code = <357>;
                        gpios = <&gpio1 9 1>;
                };
                button@2 {
                        label = "Power-on Switch";
-                       linux,code = <116>;
+                       linux,code = <0>;
+                       linux,input-type = <5>;
                        gpios = <&gpio1 10 1>;
                };
                button@3 {
                        label = "Power-auto Switch";
-                       linux,code = <142>;
+                       linux,code = <1>;
+                       linux,input-type = <5>;
                        gpios = <&gpio1 11 1>;
                };
        };
                compatible = "gpio-leds";
 
                led@1 {
-                       label = "lschlv2:blue:func";
+                       label = "lsxl:blue:func";
                        gpios = <&gpio1 4 1>;
                };
 
                led@2 {
-                       label = "lschlv2:red:alarm";
+                       label = "lsxl:red:alarm";
                        gpios = <&gpio1 5 1>;
                };
 
                led@3 {
-                       label = "lschlv2:amber:info";
+                       label = "lsxl:amber:info";
                        gpios = <&gpio1 6 1>;
                };
 
                led@4 {
-                       label = "lschlv2:blue:power";
+                       label = "lsxl:blue:power";
                        gpios = <&gpio1 7 1>;
                        linux,default-trigger = "default-on";
                };
 
                led@5 {
-                       label = "lschlv2:red:func";
+                       label = "lsxl:red:func";
                        gpios = <&gpio1 16 1>;
                };
        };
index f38ea8771b44fb1b1ffe71830e74bed6d628ef66..696e929d0304ff72580e83510771c1ba0048b91f 100644 (file)
                        interrupt-names = "common", "tx", "rx", "sidetone";
                        interrupt-parent = <&intc>;
                        ti,buffer-size = <1280>;
-                       ti,hwmods = "mcbsp2";
+                       ti,hwmods = "mcbsp2", "mcbsp2_sidetone";
                };
 
                mcbsp3: mcbsp@49024000 {
                        interrupt-names = "common", "tx", "rx", "sidetone";
                        interrupt-parent = <&intc>;
                        ti,buffer-size = <128>;
-                       ti,hwmods = "mcbsp3";
+                       ti,hwmods = "mcbsp3", "mcbsp3_sidetone";
                };
 
                mcbsp4: mcbsp@49026000 {
index b1497c7d7d6851db3753c1210e974cb9e47888c2..df7f2270fc91a4f98d0d7dd067817bb2ce8b62c0 100644 (file)
@@ -73,8 +73,8 @@
 
        pinmux: pinmux {
                compatible = "nvidia,tegra30-pinmux";
-               reg = <0x70000868 0xd0    /* Pad control registers */
-                      0x70003000 0x3e0>; /* Mux registers */
+               reg = <0x70000868 0xd4    /* Pad control registers */
+                      0x70003000 0x3e4>; /* Mux registers */
        };
 
        serial@70006000 {
index b459691655ab653182817134a5b358696bab18d8..330f833ac3b03e97b376bbcdcf418770b3431a23 100644 (file)
                ehci@d8007100 {
                        compatible = "via,vt8500-ehci";
                        reg = <0xd8007100 0x200>;
-                       interrupts = <43>;
+                       interrupts = <1>;
                };
 
                uhci@d8007300 {
                        compatible = "platform-uhci";
                        reg = <0xd8007300 0x200>;
-                       interrupts = <43>;
+                       interrupts = <0>;
                };
 
                fb@d8050800 {
index 66aa7a6db884c14668be9f20a6d27166c85a8c1f..394ded624e375a8e1e36b04ee5b85cefbf5c9391 100644 (file)
@@ -139,6 +139,7 @@ CONFIG_I2C_IMX=y
 CONFIG_SPI=y
 CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MC9S08DZ60=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
@@ -155,6 +156,7 @@ CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
 CONFIG_VIDEO_MX3=y
 CONFIG_FB=y
+CONFIG_LCD_PLATFORM=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
index 7bcf850eddcd7f2c843c0b297eda1f24125cc03c..3458752c4bb277da7d3574e050f847add462cc0a 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
-CONFIG_NO_HZ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
@@ -9,10 +9,12 @@ CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_MVEBU=y
-CONFIG_MACH_ARMADA_370_XP=y
+CONFIG_MACH_ARMADA_370=y
+CONFIG_MACH_ARMADA_XP=y
+# CONFIG_CACHE_L2X0 is not set
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
-CONFIG_USE_OF=y
+# CONFIG_COMPACTION is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
@@ -23,6 +25,8 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
index 62303043db9cf5913938e74c6ec5c6c66bd0d62d..a1dc5c071e71250879e27ae3c92632a3409375cb 100644 (file)
@@ -240,3 +240,6 @@ CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
 CONFIG_LIBCRC32C=y
 CONFIG_SOC_OMAP5=y
+CONFIG_TI_DAVINCI_MDIO=y
+CONFIG_TI_DAVINCI_CPDMA=y
+CONFIG_TI_CPSW=y
index cdd4d2bd39620bf97bfecfdc8c0bcc35e0ee0356..2ba9e63d0f177142699a56e4a4b3408cee10df43 100644 (file)
@@ -1,3 +1,4 @@
+CONFIG_ARCH_VERSATILE=y
 CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
index 59426a4595c9cb90bcb765843f89295bd20f6797..e847d23351eda71ada1bc200476ee7f427a4e8ac 100644 (file)
@@ -8,7 +8,7 @@
 #define        flat_argvp_envp_on_stack()              1
 #define        flat_old_ram_flag(flags)                (flags)
 #define        flat_reloc_valid(reloc, size)           ((reloc) <= (size))
-#define        flat_get_addr_from_rp(rp, relval, flags, persistent) get_unaligned(rp)
+#define        flat_get_addr_from_rp(rp, relval, flags, persistent) ((void)persistent,get_unaligned(rp))
 #define        flat_put_addr_at_rp(rp, val, relval)    put_unaligned(val,rp)
 #define        flat_get_relocate_addr(rel)             (rel)
 #define        flat_set_persistent(relval, p)          0
index 35c1ed89b93652688dc99ede919b55b0d5051b1d..42f042ee4ada2563aac52e7449c062011042839c 100644 (file)
@@ -64,7 +64,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 static inline void __raw_writew(u16 val, volatile void __iomem *addr)
 {
        asm volatile("strh %1, %0"
-                    : "+Qo" (*(volatile u16 __force *)addr)
+                    : "+Q" (*(volatile u16 __force *)addr)
                     : "r" (val));
 }
 
@@ -72,7 +72,7 @@ static inline u16 __raw_readw(const volatile void __iomem *addr)
 {
        u16 val;
        asm volatile("ldrh %1, %0"
-                    : "+Qo" (*(volatile u16 __force *)addr),
+                    : "+Q" (*(volatile u16 __force *)addr),
                       "=r" (val));
        return val;
 }
index 05b8e82ec9f5b66744305de1094df1115fc92798..e3f7572634381bd28fbf3225eb375788431ee3fc 100644 (file)
@@ -10,7 +10,5 @@
 
 extern void sched_clock_postinit(void);
 extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate);
-extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-               unsigned long rate);
 
 #endif
index 77bd79f2ffdbd0344d096ca7fb2db809fb52d387..7e1f76027f666e252c35bd320d4518e110548c47 100644 (file)
@@ -200,8 +200,8 @@ extern int __put_user_8(void *, unsigned long long);
 #define USER_DS                        KERNEL_DS
 
 #define segment_eq(a,b)                (1)
-#define __addr_ok(addr)                (1)
-#define __range_ok(addr,size)  (0)
+#define __addr_ok(addr)                ((void)(addr),1)
+#define __range_ok(addr,size)  ((void)(addr),0)
 #define get_fs()               (KERNEL_DS)
 
 static inline void set_fs(mm_segment_t fs)
index 6a6f1e485f41a2b9402534c435b79c183cb5cdb2..301c1db3e99b13e95a6e8882013e7c518b6011c7 100644 (file)
@@ -27,9 +27,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
-       tst     \tmp, #HWCAP_VFPv3D16
-       ldceql  p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
-       addne   \base, \base, #32*4                 @ step over unused register space
+       tst     \tmp, #HWCAP_VFPD32
+       ldcnel  p11, cr0, [\base],#32*4             @ FLDMIAD \base!, {d16-d31}
+       addeq   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
        and     \tmp, \tmp, #MVFR0_A_SIMD_MASK      @ A_SIMD field
@@ -51,9 +51,9 @@
 #if __LINUX_ARM_ARCH__ <= 6
        ldr     \tmp, =elf_hwcap                    @ may not have MVFR regs
        ldr     \tmp, [\tmp, #0]
-       tst     \tmp, #HWCAP_VFPv3D16
-       stceql  p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
-       addne   \base, \base, #32*4                 @ step over unused register space
+       tst     \tmp, #HWCAP_VFPD32
+       stcnel  p11, cr0, [\base],#32*4             @ FSTMIAD \base!, {d16-d31}
+       addeq   \base, \base, #32*4                 @ step over unused register space
 #else
        VFPFMRX \tmp, MVFR0                         @ Media and VFP Feature Register 0
        and     \tmp, \tmp, #MVFR0_A_SIMD_MASK      @ A_SIMD field
index ae05e56dd17d6eb2e270117172dbc327f27b82d2..5000397134b4e5ceb06521ecf1d22622a0918a82 100644 (file)
 
 #ifndef __ASSEMBLY__
 /* Explicitly size integers that represent pfns in the interface with
- * Xen so that we can have one ABI that works for 32 and 64 bit guests. */
+ * Xen so that we can have one ABI that works for 32 and 64 bit guests.
+ * Note that this means that the xen_pfn_t type may be capable of
+ * representing pfn's which the guest cannot represent in its own pfn
+ * type. However since pfn space is controlled by the guest this is
+ * fine since it simply wouldn't be able to create any sure pfns in
+ * the first place.
+ */
 typedef uint64_t xen_pfn_t;
+#define PRI_xen_pfn "llx"
 typedef uint64_t xen_ulong_t;
+#define PRI_xen_ulong "llx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
 DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
index 174202318dfff2779ece119e7b45949b82f429e0..c6b9096cef9593fe6508f13768802e1fba98d64c 100644 (file)
@@ -10,7 +10,7 @@
 #include <xen/interface/grant_table.h>
 
 #define pfn_to_mfn(pfn)                        (pfn)
-#define phys_to_machine_mapping_valid  (1)
+#define phys_to_machine_mapping_valid(pfn) (1)
 #define mfn_to_pfn(mfn)                        (mfn)
 #define mfn_to_virt(m)                 (__va(mfn_to_pfn(m) << PAGE_SHIFT))
 
@@ -30,6 +30,8 @@ typedef struct xpaddr {
 #define XMADDR(x)      ((xmaddr_t) { .maddr = (x) })
 #define XPADDR(x)      ((xpaddr_t) { .paddr = (x) })
 
+#define INVALID_P2M_ENTRY      (~0UL)
+
 static inline xmaddr_t phys_to_machine(xpaddr_t phys)
 {
        unsigned offset = phys.paddr & ~PAGE_MASK;
@@ -74,9 +76,14 @@ static inline int m2p_remove_override(struct page *page, bool clear_pte)
        return 0;
 }
 
+static inline bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
+{
+       BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+       return true;
+}
+
 static inline bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
-       BUG();
-       return false;
+       return __set_phys_to_machine(pfn, mfn);
 }
 #endif /* _ASM_ARM_XEN_PAGE_H */
diff --git a/arch/arm/include/debug/8250_32.S b/arch/arm/include/debug/8250_32.S
new file mode 100644 (file)
index 0000000..8db01ee
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
+ * accesses to the 8250.
+ */
+
+#include <linux/serial_reg.h>
+
+               .macro  senduart,rd,rx
+               str     \rd, [\rx, #UART_TX << UART_SHIFT]
+               .endm
+
+               .macro  busyuart,rd,rx
+1002:          ldr     \rd, [\rx, #UART_LSR << UART_SHIFT]
+               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
+               bne     1002b
+               .endm
+
+               /* The UART's don't have any flow control IO's wired up. */
+               .macro  waituart,rd,rx
+               .endm
index 7419deb1b948f1b8954a6579db72b951b30880bb..bc1f07c49cd4a5628a9e7c2957597589b2d42f2a 100644 (file)
@@ -5,10 +5,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Derived from arch/arm/mach-davinci/include/mach/debug-macro.S to use 32-bit
- * accesses to the 8250.
  */
-#include <linux/serial_reg.h>
 
 #define UART_SHIFT 2
 #define PICOXCELL_UART1_BASE           0x80230000
                ldr     \rp, =PICOXCELL_UART1_BASE
                .endm
 
-               .macro  senduart,rd,rx
-               str     \rd, [\rx, #UART_TX << UART_SHIFT]
-               .endm
-
-               .macro  busyuart,rd,rx
-1002:          ldr     \rd, [\rx, #UART_LSR << UART_SHIFT]
-               and     \rd, \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               teq     \rd, #UART_LSR_TEMT | UART_LSR_THRE
-               bne     1002b
-               .endm
-
-               /* The UART's don't have any flow control IO's wired up. */
-               .macro  waituart,rd,rx
-               .endm
+#include "8250_32.S"
index d6f26d23374fbe9e224c7f65e0a0fc6bac85b81b..966b2f994946daf901631bfa690f86535eb70f1b 100644 (file)
@@ -7,6 +7,9 @@
  * published by the Free Software Foundation.
  */
 
+#define UART_SHIFT 2
+#define DEBUG_LL_UART_OFFSET   0x00002000
+
                .macro  addruart, rp, rv, tmp
                mov     \rp, #DEBUG_LL_UART_OFFSET
                orr     \rp, \rp, #0x00c00000
@@ -14,3 +17,5 @@
                orr     \rp, \rp, #0xff000000   @ physical base
                .endm
 
+#include "8250_32.S"
+
index f254f6503cce7df8aedc3104db344417913d44c1..3688fd15a32dd5a5e5f81aef148cf397022fc2d7 100644 (file)
 #define HWCAP_THUMBEE  (1 << 11)
 #define HWCAP_NEON     (1 << 12)
 #define HWCAP_VFPv3    (1 << 13)
-#define HWCAP_VFPv3D16 (1 << 14)
+#define HWCAP_VFPv3D16 (1 << 14)       /* also set for VFPv4-D16 */
 #define HWCAP_TLS      (1 << 15)
 #define HWCAP_VFPv4    (1 << 16)
 #define HWCAP_IDIVA    (1 << 17)
 #define HWCAP_IDIVT    (1 << 18)
+#define HWCAP_VFPD32   (1 << 19)       /* set if VFP has 32 regs (not 16) */
 #define HWCAP_IDIV     (HWCAP_IDIVA | HWCAP_IDIVT)
 
 
index 417bac1846bdeb71dc475bfe7bee3e729623caa4..34711757ba59a958592d31ea527170c1356c282c 100644 (file)
@@ -88,9 +88,9 @@ ENTRY(ret_from_fork)
        bl      schedule_tail
        cmp     r5, #0
        movne   r0, r4
-       movne   lr, pc
+       adrne   lr, BSYM(1f)
        movne   pc, r5
-       get_thread_info tsk
+1:     get_thread_info tsk
        b       ret_slow_syscall
 ENDPROC(ret_from_fork)
 
index 16cedb42c0c39c0169008e45488b279cd9b32821..896165096d6a936572bdcfd0d21cc23f01cb9ea2 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/list.h>
 #include <linux/kallsyms.h>
 #include <linux/proc_fs.h>
+#include <linux/export.h>
 
 #include <asm/exception.h>
 #include <asm/mach/arch.h>
@@ -109,6 +110,7 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
        /* Order is clear bits in "clr" then set bits in "set" */
        irq_modify_status(irq, clr, set & ~clr);
 }
+EXPORT_SYMBOL_GPL(set_irq_flags);
 
 void __init init_IRQ(void)
 {
index 38c1a3b103a0684b5b579bb74ca07f38bb91eb13..83931290506704ad226e8a8cb2a15b52a33d4494 100644 (file)
@@ -366,7 +366,9 @@ void kprobe_arm_test_cases(void)
        TEST_UNSUPPORTED(".word 0xe04f0392 @ umaal r0, pc, r2, r3")
        TEST_UNSUPPORTED(".word 0xe0500090 @ undef")
        TEST_UNSUPPORTED(".word 0xe05fff9f @ undef")
+#endif
 
+#if __LINUX_ARM_ARCH__ >= 7
        TEST_RRR(  "mls         r0, r",1, VAL1,", r",2, VAL2,", r",3,  VAL3,"")
        TEST_RRR(  "mlshi       r7, r",8, VAL3,", r",9, VAL1,", r",10, VAL2,"")
        TEST_RR(   "mls         lr, r",1, VAL2,", r",2, VAL3,", r13")
@@ -456,6 +458,8 @@ void kprobe_arm_test_cases(void)
        TEST_UNSUPPORTED(".word 0xe1700090") /* Unallocated space */
 #if __LINUX_ARM_ARCH__ >= 6
        TEST_UNSUPPORTED("ldrex r2, [sp]")
+#endif
+#if (__LINUX_ARM_ARCH__ >= 7) || defined(CONFIG_CPU_32v6K)
        TEST_UNSUPPORTED("strexd        r0, r2, r3, [sp]")
        TEST_UNSUPPORTED("ldrexd        r2, r3, [sp]")
        TEST_UNSUPPORTED("strexb        r0, r2, [sp]")
index e29c3337ca8142aeb6f4bb755e3947d6aecd4fbe..8ef8c9337809cbe5ccb91b33525c38a379e9e986 100644 (file)
@@ -45,10 +45,9 @@ int machine_kexec_prepare(struct kimage *image)
        for (i = 0; i < image->nr_segments; i++) {
                current_segment = &image->segment[i];
 
-               err = memblock_is_region_memory(current_segment->mem,
-                                               current_segment->memsz);
-               if (err)
-                       return - EINVAL;
+               if (!memblock_is_region_memory(current_segment->mem,
+                                              current_segment->memsz))
+                       return -EINVAL;
 
                err = get_user(header, (__be32*)current_segment->buf);
                if (err)
index 93971b1a4f0bb0d38eebd573f8618e994273b079..53c0304b734a4e6ad7b1806b147baa3d2d43986f 100644 (file)
@@ -96,6 +96,10 @@ armpmu_event_set_period(struct perf_event *event,
        s64 period = hwc->sample_period;
        int ret = 0;
 
+       /* The period may have been changed by PERF_EVENT_IOC_PERIOD */
+       if (unlikely(period != hwc->last_period))
+               left = period - (hwc->last_period - left);
+
        if (unlikely(left <= -period)) {
                left = period;
                local64_set(&hwc->period_left, left);
index e21bac20d90da1558000125586623bdb9cbe328c..fc6692e2b603b747553835f04a85bf3b1f9c5f3b 100644 (file)
@@ -107,13 +107,6 @@ static void sched_clock_poll(unsigned long wrap_ticks)
        update_sched_clock();
 }
 
-void __init setup_sched_clock_needs_suspend(u32 (*read)(void), int bits,
-               unsigned long rate)
-{
-       setup_sched_clock(read, bits, rate);
-       cd.needs_suspend = true;
-}
-
 void __init setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate)
 {
        unsigned long r, w;
@@ -189,18 +182,15 @@ void __init sched_clock_postinit(void)
 static int sched_clock_suspend(void)
 {
        sched_clock_poll(sched_clock_timer.data);
-       if (cd.needs_suspend)
-               cd.suspended = true;
+       cd.suspended = true;
        return 0;
 }
 
 static void sched_clock_resume(void)
 {
-       if (cd.needs_suspend) {
-               cd.epoch_cyc = read_sched_clock();
-               cd.epoch_cyc_copy = cd.epoch_cyc;
-               cd.suspended = false;
-       }
+       cd.epoch_cyc = read_sched_clock();
+       cd.epoch_cyc_copy = cd.epoch_cyc;
+       cd.suspended = false;
 }
 
 static struct syscore_ops sched_clock_ops = {
index 8e20754dd31d5946f5297aae2023ae2c8d5cd572..fbc8b2623d82f08c8c2926375a7b8a31f943361b 100644 (file)
@@ -294,18 +294,24 @@ static void percpu_timer_setup(void);
 asmlinkage void __cpuinit secondary_start_kernel(void)
 {
        struct mm_struct *mm = &init_mm;
-       unsigned int cpu = smp_processor_id();
+       unsigned int cpu;
+
+       /*
+        * The identity mapping is uncached (strongly ordered), so
+        * switch away from it before attempting any exclusive accesses.
+        */
+       cpu_switch_mm(mm->pgd, mm);
+       enter_lazy_tlb(mm, current);
+       local_flush_tlb_all();
 
        /*
         * All kernel threads share the same mm context; grab a
         * reference and switch to it.
         */
+       cpu = smp_processor_id();
        atomic_inc(&mm->mm_count);
        current->active_mm = mm;
        cpumask_set_cpu(cpu, mm_cpumask(mm));
-       cpu_switch_mm(mm->pgd, mm);
-       enter_lazy_tlb(mm, current);
-       local_flush_tlb_all();
 
        printk("CPU%u: Booted secondary processor\n", cpu);
 
index e1f906989bb8161963d8a714073a8d84a8e2c2e6..b22d700fea2751c60b5dbad689ee0b18305108b3 100644 (file)
@@ -42,10 +42,10 @@ static void twd_set_mode(enum clock_event_mode mode,
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               /* timer load already set up */
                ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
                        | TWD_TIMER_CONTROL_PERIODIC;
-               __raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
+               __raw_writel(DIV_ROUND_CLOSEST(twd_timer_rate, HZ),
+                       twd_base + TWD_TIMER_LOAD);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
                /* period set, and timer enabled in 'next_event' hook */
index 9d0a30032d7f0f2ae50f0cbe9eebb80d6da827a3..0dc53854a5d8eb423e468fe255cb0f7c1fa30e15 100644 (file)
@@ -45,6 +45,7 @@ int read_current_timer(unsigned long *timer_val)
        *timer_val = delay_timer->read_current_timer();
        return 0;
 }
+EXPORT_SYMBOL_GPL(read_current_timer);
 
 static void __timer_delay(unsigned long cycles)
 {
index b14207101938adb03c852a708a2261e4a58d6f3d..92857683cb616356a30b026349e3c885886fac62 100644 (file)
@@ -21,19 +21,13 @@ config SOC_AT91SAM9
        bool
        select CPU_ARM926T
        select GENERIC_CLOCKEVENTS
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
 
 menu "Atmel AT91 System-on-Chip"
 
 comment "Atmel AT91 Processor"
 
-config SOC_AT91SAM9
-       bool
-       select AT91_SAM9_SMC
-       select AT91_SAM9_TIME
-       select CPU_ARM926T
-       select MULTI_IRQ_HANDLER
-       select SPARSE_IRQ
-
 config SOC_AT91RM9200
        bool "AT91RM9200"
        select CPU_ARM920T
@@ -45,7 +39,6 @@ config SOC_AT91RM9200
 config SOC_AT91SAM9260
        bool "AT91SAM9260, AT91SAM9XE or AT91SAM9G20"
        select HAVE_AT91_DBGU0
-       select HAVE_NET_MACB
        select SOC_AT91SAM9
        help
          Select this if you are using one of Atmel's AT91SAM9260, AT91SAM9XE
@@ -63,7 +56,6 @@ config SOC_AT91SAM9263
        bool "AT91SAM9263"
        select HAVE_AT91_DBGU1
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
        select SOC_AT91SAM9
 
 config SOC_AT91SAM9RL
@@ -76,7 +68,6 @@ config SOC_AT91SAM9G45
        bool "AT91SAM9G45 or AT91SAM9M10 families"
        select HAVE_AT91_DBGU1
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
        select SOC_AT91SAM9
        help
          Select this if you are using one of Atmel's AT91SAM9G45 family SoC.
@@ -86,7 +77,6 @@ config SOC_AT91SAM9X5
        bool "AT91SAM9x5 family"
        select HAVE_AT91_DBGU0
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
        select SOC_AT91SAM9
        help
          Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
index b4f0565aff638af135c7797b430bbfeb2a29b439..5269825194a8a41c620ffa3da9f5a2cf5269bcb5 100644 (file)
@@ -187,7 +187,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91rm9200.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index a563189cdfc3e1bfd4bdc2e71049073de01cd712..3cee0e6ea7c3c126ec3b319497b01cf335f3f16a 100644 (file)
@@ -68,7 +68,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -479,7 +479,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91rm9200_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -512,7 +512,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91rm9200_twi_device = {
        .name           = "i2c-at91rm9200",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index ad29f93f20cab175555cd2a8c2974deff0fe31fd..f8202615f4a867f32ffe970cde12f0b6887d2375 100644 (file)
@@ -211,8 +211,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
        CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g20.0", &twi_clk),
        /* more usart lookup table for DT entries */
        CLKDEV_CON_DEV_ID("usart", "fffff200.serial", &mck),
        CLKDEV_CON_DEV_ID("usart", "fffb0000.serial", &usart0_clk),
index a76b8684f52d07328fcfe2f4a08726124b643f5a..414bd855fb0cb7fd1d0295012016937175d9c449 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -389,7 +389,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9260_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -421,7 +421,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9260_twi_device = {
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index 8d999eb1a137f1ed72529d296774c084d17da1a4..04295c04b3e03cb99d31aa2f226908ab2a975ec4 100644 (file)
@@ -178,8 +178,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &hck0),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261", &twi_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9261.0", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9g10.0", &twi_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
        CLKDEV_CON_ID("pioB", &pioB_clk),
        CLKDEV_CON_ID("pioC", &pioC_clk),
index 9752f17efba9926501a23b8e5209fbabcdfedc6d..cd604aad8e963c217301df7fa421637d1b0315a3 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9261_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -317,7 +317,7 @@ static struct resource twi_resources[] = {
 };
 
 static struct platform_device at91sam9261_twi_device = {
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index 6a01d0360dfb8940cbaaa2affc9bb58f88d702d9..d6f9c23927c48c92202776d049a582af01b8f520 100644 (file)
@@ -193,7 +193,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
-       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260", &twi_clk),
+       CLKDEV_CON_DEV_ID(NULL, "i2c-at91sam9260.0", &twi_clk),
        /* fake hclk clock */
        CLKDEV_CON_DEV_ID("hclk", "at91_ohci", &ohci_clk),
        CLKDEV_CON_ID("pioA", &pioA_clk),
index 8dde220b42b69c785c70118a16e48a1aa20acb95..9c61e59a2104e7f0399fc0dca4ea926d7136d4f9 100644 (file)
@@ -78,7 +78,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
@@ -567,7 +567,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9263_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -600,7 +600,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91sam9263_twi_device = {
        .name           = "i2c-at91sam9260",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index b1596072dcc23cd1414a8449eb4c25a35ed11222..fcd233cb33d25d68417a992c3b09fac45e63501a 100644 (file)
@@ -1841,8 +1841,8 @@ static struct resource sha_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1874,8 +1874,8 @@ static struct resource tdes_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1910,8 +1910,8 @@ static struct resource aes_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
index d6ca0543ce8d7f1054d8f25614cd17369efe283d..5047bdc92adfdb79395143d973468862219d33c4 100644 (file)
@@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = {
 
 static struct platform_device at91sam9rl_twi_device = {
        .name                   = "i2c-gpio",
-       .id                     = -1,
+       .id                     = 0,
        .dev.platform_data      = &pdata,
 };
 
@@ -347,7 +347,7 @@ static struct resource twi_resources[] = {
 
 static struct platform_device at91sam9rl_twi_device = {
        .name           = "i2c-at91sam9g20",
-       .id             = -1,
+       .id             = 0,
        .resource       = twi_resources,
        .num_resources  = ARRAY_SIZE(twi_resources),
 };
index 6bd7300a2bc507855f28153e5871a4fcb6c4d5ed..bb7f54474b92e7f7fef65e1c504dbf4544c84992 100644 (file)
@@ -88,6 +88,6 @@ void __init at91x40_init_interrupts(unsigned int priority[NR_AIC_IRQS])
        if (!priority)
                priority = at91x40_default_irq_priority;
 
-       at91_aic_init(priority);
+       at91_aic_init(priority, at91_extern_irq);
 }
 
index 3e37437a7a613222245df1f297e18cde4a02dc97..aa9b320bad5961877f36117111e19b06314cb7c6 100644 (file)
@@ -53,6 +53,8 @@ static void __init csb337_init_early(void)
 static struct macb_platform_data __initdata csb337_eth_data = {
        .phy_irq_pin    = AT91_PIN_PC2,
        .is_rmii        = 0,
+       /* The CSB337 bootloader stores the MAC the wrong-way around */
+       .rev_eth_addr   = 1,
 };
 
 static struct at91_usbh_data __initdata csb337_usbh_data = {
index 9cda3fd346ae3e4657cf415b6dbe1e4040c20db5..6960778af4c2c07eae98b998962c327d4af1632c 100644 (file)
@@ -129,7 +129,7 @@ static struct spi_board_info neocore926_spi_devices[] = {
                .max_speed_hz   = 125000 * 16,
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9263_ID_IRQ1,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
        },
 #endif
 };
index 27b3af1a3047e4bcf209e602f1fcc23a1561de0d..a9167dd45f96b68af3e216d90ececba5150b5f32 100644 (file)
@@ -309,7 +309,7 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9261_ID_IRQ0,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9261_ID_IRQ0,
                .controller_data = (void *) AT91_PIN_PA28,      /* CS pin */
        },
 #endif
index 073e17403d982dad660126f0323754d0b36532c4..b87dbe2be0d63e71a700e116df0a3f06a389a8b3 100644 (file)
@@ -132,7 +132,7 @@ static struct spi_board_info ek_spi_devices[] = {
                .max_speed_hz   = 125000 * 26,  /* (max sample rate @ 3V) * (cmd + data + overhead) */
                .bus_num        = 0,
                .platform_data  = &ads_info,
-               .irq            = AT91SAM9263_ID_IRQ1,
+               .irq            = NR_IRQS_LEGACY + AT91SAM9263_ID_IRQ1,
        },
 #endif
 };
index f49650677653a0f0488e6c64346fcf07e46ae555..b62f560e6c75fbe838200cb03b3347a8c3a15241 100644 (file)
@@ -26,7 +26,8 @@ extern void __init at91_dt_initialize(void);
 extern void __init at91_init_irq_default(void);
 extern void __init at91_init_interrupts(unsigned int priority[]);
 extern void __init at91x40_init_interrupts(unsigned int priority[]);
-extern void __init at91_aic_init(unsigned int priority[]);
+extern void __init at91_aic_init(unsigned int priority[],
+                                unsigned int ext_irq_mask);
 extern int  __init at91_aic_of_init(struct device_node *node,
                                    struct device_node *parent);
 extern int  __init at91_aic5_of_init(struct device_node *node,
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200_emac.h b/arch/arm/mach-at91/include/mach/at91rm9200_emac.h
deleted file mode 100644 (file)
index b8260cd..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91rm9200_emac.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Ethernet MAC registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91RM9200_EMAC_H
-#define AT91RM9200_EMAC_H
-
-#define        AT91_EMAC_CTL           0x00    /* Control Register */
-#define                AT91_EMAC_LB            (1 <<  0)       /* Loopback */
-#define                AT91_EMAC_LBL           (1 <<  1)       /* Loopback Local */
-#define                AT91_EMAC_RE            (1 <<  2)       /* Receive Enable */
-#define                AT91_EMAC_TE            (1 <<  3)       /* Transmit Enable */
-#define                AT91_EMAC_MPE           (1 <<  4)       /* Management Port Enable */
-#define                AT91_EMAC_CSR           (1 <<  5)       /* Clear Statistics Registers */
-#define                AT91_EMAC_INCSTAT       (1 <<  6)       /* Increment Statistics Registers */
-#define                AT91_EMAC_WES           (1 <<  7)       /* Write Enable for Statistics Registers */
-#define                AT91_EMAC_BP            (1 <<  8)       /* Back Pressure */
-
-#define        AT91_EMAC_CFG           0x04    /* Configuration Register */
-#define                AT91_EMAC_SPD           (1 <<  0)       /* Speed */
-#define                AT91_EMAC_FD            (1 <<  1)       /* Full Duplex */
-#define                AT91_EMAC_BR            (1 <<  2)       /* Bit Rate */
-#define                AT91_EMAC_CAF           (1 <<  4)       /* Copy All Frames */
-#define                AT91_EMAC_NBC           (1 <<  5)       /* No Broadcast */
-#define                AT91_EMAC_MTI           (1 <<  6)       /* Multicast Hash Enable */
-#define                AT91_EMAC_UNI           (1 <<  7)       /* Unicast Hash Enable */
-#define                AT91_EMAC_BIG           (1 <<  8)       /* Receive 1522 Bytes */
-#define                AT91_EMAC_EAE           (1 <<  9)       /* External Address Match Enable */
-#define                AT91_EMAC_CLK           (3 << 10)       /* MDC Clock Divisor */
-#define                AT91_EMAC_CLK_DIV8              (0 << 10)
-#define                AT91_EMAC_CLK_DIV16             (1 << 10)
-#define                AT91_EMAC_CLK_DIV32             (2 << 10)
-#define                AT91_EMAC_CLK_DIV64             (3 << 10)
-#define                AT91_EMAC_RTY           (1 << 12)       /* Retry Test */
-#define                AT91_EMAC_RMII          (1 << 13)       /* Reduce MII (RMII) */
-
-#define        AT91_EMAC_SR            0x08    /* Status Register */
-#define                AT91_EMAC_SR_LINK       (1 <<  0)       /* Link */
-#define                AT91_EMAC_SR_MDIO       (1 <<  1)       /* MDIO pin */
-#define                AT91_EMAC_SR_IDLE       (1 <<  2)       /* PHY idle */
-
-#define        AT91_EMAC_TAR           0x0c    /* Transmit Address Register */
-
-#define        AT91_EMAC_TCR           0x10    /* Transmit Control Register */
-#define                AT91_EMAC_LEN           (0x7ff << 0)    /* Transmit Frame Length */
-#define                AT91_EMAC_NCRC          (1     << 15)   /* No CRC */
-
-#define        AT91_EMAC_TSR           0x14    /* Transmit Status Register */
-#define                AT91_EMAC_TSR_OVR       (1 <<  0)       /* Transmit Buffer Overrun */
-#define                AT91_EMAC_TSR_COL       (1 <<  1)       /* Collision Occurred */
-#define                AT91_EMAC_TSR_RLE       (1 <<  2)       /* Retry Limit Exceeded */
-#define                AT91_EMAC_TSR_IDLE      (1 <<  3)       /* Transmitter Idle */
-#define                AT91_EMAC_TSR_BNQ       (1 <<  4)       /* Transmit Buffer not Queued */
-#define                AT91_EMAC_TSR_COMP      (1 <<  5)       /* Transmit Complete */
-#define                AT91_EMAC_TSR_UND       (1 <<  6)       /* Transmit Underrun */
-
-#define        AT91_EMAC_RBQP          0x18    /* Receive Buffer Queue Pointer */
-
-#define        AT91_EMAC_RSR           0x20    /* Receive Status Register */
-#define                AT91_EMAC_RSR_BNA       (1 <<  0)       /* Buffer Not Available */
-#define                AT91_EMAC_RSR_REC       (1 <<  1)       /* Frame Received */
-#define                AT91_EMAC_RSR_OVR       (1 <<  2)       /* RX Overrun */
-
-#define        AT91_EMAC_ISR           0x24    /* Interrupt Status Register */
-#define                AT91_EMAC_DONE          (1 <<  0)       /* Management Done */
-#define                AT91_EMAC_RCOM          (1 <<  1)       /* Receive Complete */
-#define                AT91_EMAC_RBNA          (1 <<  2)       /* Receive Buffer Not Available */
-#define                AT91_EMAC_TOVR          (1 <<  3)       /* Transmit Buffer Overrun */
-#define                AT91_EMAC_TUND          (1 <<  4)       /* Transmit Buffer Underrun */
-#define                AT91_EMAC_RTRY          (1 <<  5)       /* Retry Limit */
-#define                AT91_EMAC_TBRE          (1 <<  6)       /* Transmit Buffer Register Empty */
-#define                AT91_EMAC_TCOM          (1 <<  7)       /* Transmit Complete */
-#define                AT91_EMAC_TIDLE         (1 <<  8)       /* Transmit Idle */
-#define                AT91_EMAC_LINK          (1 <<  9)       /* Link */
-#define                AT91_EMAC_ROVR          (1 << 10)       /* RX Overrun */
-#define                AT91_EMAC_ABT           (1 << 11)       /* Abort */
-
-#define        AT91_EMAC_IER           0x28    /* Interrupt Enable Register */
-#define        AT91_EMAC_IDR           0x2c    /* Interrupt Disable Register */
-#define        AT91_EMAC_IMR           0x30    /* Interrupt Mask Register */
-
-#define        AT91_EMAC_MAN           0x34    /* PHY Maintenance Register */
-#define                AT91_EMAC_DATA          (0xffff << 0)   /* MDIO Data */
-#define                AT91_EMAC_REGA          (0x1f   << 18)  /* MDIO Register */
-#define                AT91_EMAC_PHYA          (0x1f   << 23)  /* MDIO PHY Address */
-#define                AT91_EMAC_RW            (3      << 28)  /* Read/Write operation */
-#define                        AT91_EMAC_RW_W          (1 << 28)
-#define                        AT91_EMAC_RW_R          (2 << 28)
-#define                AT91_EMAC_MAN_802_3     0x40020000      /* IEEE 802.3 value */
-
-/*
- * Statistics Registers.
- */
-#define AT91_EMAC_FRA          0x40    /* Frames Transmitted OK */
-#define AT91_EMAC_SCOL         0x44    /* Single Collision Frame */
-#define AT91_EMAC_MCOL         0x48    /* Multiple Collision Frame */
-#define AT91_EMAC_OK           0x4c    /* Frames Received OK */
-#define AT91_EMAC_SEQE         0x50    /* Frame Check Sequence Error */
-#define AT91_EMAC_ALE          0x54    /* Alignmemt Error */
-#define AT91_EMAC_DTE          0x58    /* Deffered Transmission Frame */
-#define AT91_EMAC_LCOL         0x5c    /* Late Collision */
-#define AT91_EMAC_ECOL         0x60    /* Excessive Collision */
-#define AT91_EMAC_TUE          0x64    /* Transmit Underrun Error */
-#define AT91_EMAC_CSE          0x68    /* Carrier Sense Error */
-#define AT91_EMAC_DRFC         0x6c    /* Discard RX Frame */
-#define AT91_EMAC_ROV          0x70    /* Receive Overrun */
-#define AT91_EMAC_CDE          0x74    /* Code Error */
-#define AT91_EMAC_ELR          0x78    /* Excessive Length Error */
-#define AT91_EMAC_RJB          0x7c    /* Receive Jabber */
-#define AT91_EMAC_USF          0x80    /* Undersize Frame */
-#define AT91_EMAC_SQEE         0x84    /* SQE Test Error */
-
-/*
- * Address Registers.
- */
-#define AT91_EMAC_HSL          0x90    /* Hash Address Low [31:0] */
-#define AT91_EMAC_HSH          0x94    /* Hash Address High [63:32] */
-#define AT91_EMAC_SA1L         0x98    /* Specific Address 1 Low, bytes 0-3 */
-#define AT91_EMAC_SA1H         0x9c    /* Specific Address 1 High, bytes 4-5 */
-#define AT91_EMAC_SA2L         0xa0    /* Specific Address 2 Low, bytes 0-3 */
-#define AT91_EMAC_SA2H         0xa4    /* Specific Address 2 High, bytes 4-5 */
-#define AT91_EMAC_SA3L         0xa8    /* Specific Address 3 Low, bytes 0-3 */
-#define AT91_EMAC_SA3H         0xac    /* Specific Address 3 High, bytes 4-5 */
-#define AT91_EMAC_SA4L         0xb0    /* Specific Address 4 Low, bytes 0-3 */
-#define AT91_EMAC_SA4H         0xb4    /* Specific Address 4 High, bytes 4-5 */
-
-#endif
index 1e02c0e49dccb76949be0fc9d855a5a3bb3504bc..febc2ee901a544458a9a47c0e55473263a7c54a6 100644 (file)
@@ -502,14 +502,19 @@ int __init at91_aic5_of_init(struct device_node *node,
 /*
  * Initialize the AIC interrupt controller.
  */
-void __init at91_aic_init(unsigned int *priority)
+void __init at91_aic_init(unsigned int *priority, unsigned int ext_irq_mask)
 {
        unsigned int i;
        int irq_base;
 
-       if (at91_aic_pm_init())
+       at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
+                                 * sizeof(*at91_extern_irq), GFP_KERNEL);
+
+       if (at91_aic_pm_init() || at91_extern_irq == NULL)
                panic("Unable to allocate bit maps\n");
 
+       *at91_extern_irq = ext_irq_mask;
+
        at91_aic_base = ioremap(AT91_AIC, 512);
        if (!at91_aic_base)
                panic("Unable to ioremap AIC registers\n");
index da9881b161e1e15dc0693a74c2ce2716a0ebd5d3..0b32c81730a571484a600577e3037aa5d1573c65 100644 (file)
@@ -47,7 +47,7 @@ void __init at91_init_irq_default(void)
 void __init at91_init_interrupts(unsigned int *priority)
 {
        /* Initialize the AIC interrupt controller */
-       at91_aic_init(priority);
+       at91_aic_init(priority, at91_extern_irq);
 
        /* Enable GPIO interrupts */
        at91_gpio_irq_setup();
@@ -151,7 +151,7 @@ static void __init soc_detect(u32 dbgu_base)
        }
 
        /* at91sam9g10 */
-       if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
+       if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) {
                at91_soc_initdata.type = AT91_SOC_SAM9G10;
                at91_boot_soc = at91sam9261_soc;
        }
index cd0c8b1e1ecfad4a868b9aae3f6180a1b1794ed1..14e9947bad6e028bc9c41aecb5e1f36b045fe79a 100644 (file)
@@ -713,8 +713,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
                break;
        case VPBE_ENC_CUSTOM_TIMINGS:
                if (pclock <= 27000000) {
-                       v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
-                            DM644X_VPSS_DACCLKEN;
+                       v |= DM644X_VPSS_DACCLKEN;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
                } else {
                        /*
index b37bef1d5ffad9828f6734eb9a50262327ea950d..f723fe13d0f032c48126c1e745c894e296d7ccbf 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/irq.h>
 #include <plat/time.h>
 #include <linux/platform_data/usb-ehci-orion.h>
+#include <plat/irq.h>
 #include <plat/common.h>
 #include <plat/addr-map.h>
 #include "common.h"
@@ -109,8 +110,8 @@ static void __init dove_clk_init(void)
 
        orion_clkdev_add(NULL, "orion-ehci.0", usb0);
        orion_clkdev_add(NULL, "orion-ehci.1", usb1);
-       orion_clkdev_add(NULL, "mv643xx_eth.0", ge);
-       orion_clkdev_add("0", "sata_mv.0", sata);
+       orion_clkdev_add(NULL, "mv643xx_eth_port.0", ge);
+       orion_clkdev_add(NULL, "sata_mv.0", sata);
        orion_clkdev_add("0", "pcie", pex0);
        orion_clkdev_add("1", "pcie", pex1);
        orion_clkdev_add(NULL, "sdhci-dove.0", sdio0);
@@ -399,7 +400,7 @@ static void __init dove_dt_init(void)
                (dove_tclk + 499999) / 1000000);
 
 #ifdef CONFIG_CACHE_TAUROS2
-       tauros2_init();
+       tauros2_init(0);
 #endif
        dove_setup_cpu_mbus();
 
@@ -415,7 +416,6 @@ static void __init dove_dt_init(void)
        dove_ehci0_init();
        dove_ehci1_init();
        dove_pcie_init(1, 1);
-       dove_crypto_init();
 
        of_platform_populate(NULL, of_default_bus_match_table,
                             dove_auxdata_lookup, NULL);
index bb15b26041cb7d6bd13a5ca4d5532cb66632e2cc..0ef4435b16570dccde5af41737bf25987051270d 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/clk.h>
 #include <video/vga.h>
 #include <asm/mach/pci.h>
 #include <asm/mach/arch.h>
@@ -188,6 +189,10 @@ static void __init add_pcie_port(int index, void __iomem *base)
 
        if (orion_pcie_link_up(base)) {
                struct pcie_port *pp = &pcie_port[num_pcie_ports++];
+               struct clk *clk = clk_get_sys("pcie", (index ? "1" : "0"));
+
+               if (!IS_ERR(clk))
+                       clk_prepare_enable(clk);
 
                printk(KERN_INFO "link up\n");
 
index 715b690e5009608c9d9bfa42b1bb6e2d595b79ee..1947be8e5f5bffec59d1542e8ebbbc6bbce36970 100644 (file)
@@ -47,6 +47,7 @@
 #include <plat/fimc-core.h>
 #include <plat/iic-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -346,6 +347,8 @@ static void __init exynos4_map_io(void)
 
        s5p_fb_setname(0, "exynos4-fb");
        s5p_hdmi_setname("exynos4-hdmi");
+
+       s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos5_map_io(void)
@@ -366,6 +369,8 @@ static void __init exynos5_map_io(void)
        s3c_i2c0_setname("s3c2440-i2c");
        s3c_i2c1_setname("s3c2440-i2c");
        s3c_i2c2_setname("s3c2440-i2c");
+
+       s3c64xx_spi_setname("exynos4210-spi");
 }
 
 static void __init exynos4_init_clocks(int xtal)
index 21d568b3b1497c90bb79eb841f45595020351db9..87e07d6fc615769df8edfe0af8be1569859d5422 100644 (file)
@@ -275,6 +275,9 @@ static int __init exynos_dma_init(void)
                exynos_pdma1_pdata.nr_valid_peri =
                        ARRAY_SIZE(exynos4210_pdma1_peri);
                exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
+
+               if (samsung_rev() == EXYNOS4210_REV_0)
+                       exynos_mdma1_device.res.start = EXYNOS4_PA_S_MDMA1;
        } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
                exynos_pdma0_pdata.nr_valid_peri =
                        ARRAY_SIZE(exynos4212_pdma0_peri);
index 8480849affb922789d73b597c81b76c6778a16ba..ed4da4544cd2fded70c65dd7d5d5539635a94557 100644 (file)
@@ -90,6 +90,7 @@
 
 #define EXYNOS4_PA_MDMA0               0x10810000
 #define EXYNOS4_PA_MDMA1               0x12850000
+#define EXYNOS4_PA_S_MDMA1             0x12840000
 #define EXYNOS4_PA_PDMA0               0x12680000
 #define EXYNOS4_PA_PDMA1               0x12690000
 #define EXYNOS5_PA_MDMA0               0x10800000
index e58d786faf78c773636f10b168415df2c0ac61ef..eadf4b59e7d28e6ae1d254f0f86a398759d5f9bc 100644 (file)
@@ -99,6 +99,7 @@ static char const *exynos4_dt_compat[] __initdata = {
 
 DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
        /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
+       .smp            = smp_ops(exynos_smp_ops),
        .init_irq       = exynos4_init_irq,
        .map_io         = exynos4_dt_map_io,
        .handle_irq     = gic_handle_irq,
index 82c27230d4a93e657ca4c4a4e1e79439c422bbae..86e37cd9376cc7a522a17a65ca39cc127dd7deeb 100644 (file)
@@ -28,6 +28,7 @@ void highbank_restart(char mode, const char *cmd)
                hignbank_set_pwr_soft_reset();
 
        scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
-       cpu_do_idle();
+       while (1)
+               cpu_do_idle();
 }
 
index 1a7a8dd045a13ab6481bcc653e877d899b0597b7..1ab91b5209e6503e7742450c4dc424a15b2e651c 100644 (file)
@@ -108,7 +108,7 @@ struct clk *imx_clk_busy_divider(const char *name, const char *parent_name,
        busy->div.hw.init = &init;
 
        clk = clk_register(NULL, &busy->div.hw);
-       if (!clk)
+       if (IS_ERR(clk))
                kfree(busy);
 
        return clk;
index 3c1b8ff9a0a61c24f2e7d6647a62168cd8a7e146..cc49c7ae186ed2bc0d3519bf7648a153ddb45d55 100644 (file)
@@ -112,7 +112,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
 
        clk = clk_register(dev, &gate->hw);
        if (IS_ERR(clk))
-               kfree(clk);
+               kfree(gate);
 
        return clk;
 }
index d20d4795f4eaebeb633c73ec441c36a661949a47..01e2f843bf2e0d65910bf0951f12555077f7693e 100644 (file)
@@ -127,8 +127,8 @@ int __init mx25_clocks_init(void)
        clk[esdhc2_ipg_per] = imx_clk_gate("esdhc2_ipg_per", "per4", ccm(CCM_CGCR0),  4);
        clk[gpt_ipg_per] = imx_clk_gate("gpt_ipg_per", "per5", ccm(CCM_CGCR0),  5);
        clk[i2c_ipg_per] = imx_clk_gate("i2c_ipg_per", "per6", ccm(CCM_CGCR0),  6);
-       clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per8", ccm(CCM_CGCR0),  7);
-       clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "ipg_per", ccm(CCM_CGCR0),  8);
+       clk[lcdc_ipg_per] = imx_clk_gate("lcdc_ipg_per", "per7", ccm(CCM_CGCR0),  7);
+       clk[nfc_ipg_per] = imx_clk_gate("nfc_ipg_per", "per8", ccm(CCM_CGCR0),  8);
        clk[ssi1_ipg_per] = imx_clk_gate("ssi1_ipg_per", "per13", ccm(CCM_CGCR0), 13);
        clk[ssi2_ipg_per] = imx_clk_gate("ssi2_ipg_per", "per14", ccm(CCM_CGCR0), 14);
        clk[uart_ipg_per] = imx_clk_gate("uart_ipg_per", "per15", ccm(CCM_CGCR0), 15);
index 3b6b640eed247ea1b7848c7a7fa01801f0190cde..366e5d59d886f7cd43bb79bfe50a70c9fa6a6c5b 100644 (file)
@@ -109,7 +109,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk[per3_div] = imx_clk_divider("per3_div", "mpll_main2", CCM_PCDR1, 16, 6);
        clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
        clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
-       clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 3);
+       clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
        clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);
        clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
        clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
@@ -121,7 +121,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk[ssi1_sel] = imx_clk_mux("ssi1_sel", CCM_CSCR, 22, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
        clk[ssi2_sel] = imx_clk_mux("ssi2_sel", CCM_CSCR, 23, 1, ssi_sel_clks, ARRAY_SIZE(ssi_sel_clks));
        clk[ssi1_div] = imx_clk_divider("ssi1_div", "ssi1_sel", CCM_PCDR0, 16, 6);
-       clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 3);
+       clk[ssi2_div] = imx_clk_divider("ssi2_div", "ssi2_sel", CCM_PCDR0, 26, 6);
        clk[clko_en] = imx_clk_gate("clko_en", "clko_div", CCM_PCCR0, 0);
        clk[ssi2_ipg_gate] = imx_clk_gate("ssi2_ipg_gate", "ipg", CCM_PCCR0, 0);
        clk[ssi1_ipg_gate] = imx_clk_gate("ssi1_ipg_gate", "ipg", CCM_PCCR0, 1);
index 412c583a24b01a7e35fc976572cdafc50e08e13e..576af7446952553acab68a77207cfd3d71298dbe 100644 (file)
@@ -30,7 +30,7 @@
 #define MX25_H1_SIC_SHIFT      21
 #define MX25_H1_SIC_MASK       (0x3 << MX25_H1_SIC_SHIFT)
 #define MX25_H1_PP_BIT         (1 << 18)
-#define MX25_H1_PM_BIT         (1 << 8)
+#define MX25_H1_PM_BIT         (1 << 16)
 #define MX25_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX25_H1_TLL_BIT                (1 << 5)
index 779e16eb65cb49aeaa58af79b19aac4e08b9bb47..293397852e4e6506bb1e46e590c292ef10fb116c 100644 (file)
@@ -30,7 +30,7 @@
 #define MX35_H1_SIC_SHIFT      21
 #define MX35_H1_SIC_MASK       (0x3 << MX35_H1_SIC_SHIFT)
 #define MX35_H1_PP_BIT         (1 << 18)
-#define MX35_H1_PM_BIT         (1 << 8)
+#define MX35_H1_PM_BIT         (1 << 16)
 #define MX35_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX35_H1_TLL_BIT                (1 << 5)
index 47c91f7185d2fb7cdef048388e5cf82620e68a87..38d69100398d9d6bb5a174aaa7c25dec150b746c 100644 (file)
@@ -117,6 +117,17 @@ static void __init imx6q_sabrelite_init(void)
        imx6q_sabrelite_cko1_setup();
 }
 
+static void __init imx6q_1588_init(void)
+{
+       struct regmap *gpr;
+
+       gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+       if (!IS_ERR(gpr))
+               regmap_update_bits(gpr, 0x4, 1 << 21, 1 << 21);
+       else
+               pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
+
+}
 static void __init imx6q_usb_init(void)
 {
        struct regmap *anatop;
@@ -153,6 +164,7 @@ static void __init imx6q_init_machine(void)
 
        imx6q_pm_init();
        imx6q_usb_init();
+       imx6q_1588_init();
 }
 
 static struct cpuidle_driver imx6q_cpuidle_driver = {
index 9d2c843bde02438ccd79b2b5552397b97aeb1b65..b5deb0554552d1bbe586fcf2b7fd2d1bc0a33c06 100644 (file)
@@ -108,9 +108,8 @@ void __init imx3_init_l2x0(void)
        }
 
        l2x0_base = ioremap(MX3x_L2CC_BASE_ADDR, 4096);
-       if (IS_ERR(l2x0_base)) {
-               printk(KERN_ERR "remapping L2 cache area failed with %ld\n",
-                               PTR_ERR(l2x0_base));
+       if (!l2x0_base) {
+               printk(KERN_ERR "remapping L2 cache area failed\n");
                return;
        }
 
index 70c5a28824093f675880aab0c5c595206ac7e1d6..d94872fed8c0cb2a5529260cb2ceca68d1c75a14 100644 (file)
@@ -51,9 +51,7 @@ static void __init kirkwood_dt_init(void)
 
        kirkwood_setup_cpu_mbus();
 
-#ifdef CONFIG_CACHE_FEROCEON_L2
        kirkwood_l2_init();
-#endif
 
        /* Setup root of clk tree */
        kirkwood_clk_init();
index 3991077f58a26aa5f3a77c2ff005e7c7838a1edb..2c6c218fb79e217cf607da9ad510ac7dece3222f 100644 (file)
@@ -633,6 +633,7 @@ char * __init kirkwood_id(void)
 
 void __init kirkwood_l2_init(void)
 {
+#ifdef CONFIG_CACHE_FEROCEON_L2
 #ifdef CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH
        writel(readl(L2_CONFIG_REG) | L2_WRITETHROUGH, L2_CONFIG_REG);
        feroceon_l2_init(1);
@@ -640,6 +641,7 @@ void __init kirkwood_l2_init(void)
        writel(readl(L2_CONFIG_REG) & ~L2_WRITETHROUGH, L2_CONFIG_REG);
        feroceon_l2_init(0);
 #endif
+#endif
 }
 
 void __init kirkwood_init(void)
@@ -657,9 +659,7 @@ void __init kirkwood_init(void)
 
        kirkwood_setup_cpu_mbus();
 
-#ifdef CONFIG_CACHE_FEROCEON_L2
        kirkwood_l2_init();
-#endif
 
        /* Setup root of clk tree */
        kirkwood_clk_init();
index 9518bf5996dccffbf11b284227837c4a96f61a59..e255164ff087ebbb40dcd7e167abbeab71ca27d3 100644 (file)
@@ -444,16 +444,28 @@ static struct omap1_cam_platform_data ams_delta_camera_platform_data = {
        .lclk_khz_max   = 1334,         /* results in 5fps CIF, 10fps QCIF */
 };
 
+static struct platform_device ams_delta_audio_device = {
+       .name   = "ams-delta-audio",
+       .id     = -1,
+};
+
+static struct platform_device cx20442_codec_device = {
+       .name   = "cx20442-codec",
+       .id     = -1,
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
        &latch1_gpio_device,
        &latch2_gpio_device,
        &ams_delta_kp_device,
        &ams_delta_camera_device,
+       &ams_delta_audio_device,
 };
 
 static struct platform_device *late_devices[] __initdata = {
        &ams_delta_nand_device,
        &ams_delta_lcd_device,
+       &cx20442_codec_device,
 };
 
 static void __init ams_delta_init(void)
index 2a1a898c7f90c661ec641aead23acd8d00a634cb..d669e227e00c18ac1c9783fd4e370d6f3b9e51e6 100644 (file)
@@ -11,7 +11,6 @@ config ARCH_OMAP2PLUS_TYPICAL
        select I2C_OMAP
        select MENELAUS if ARCH_OMAP2
        select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5
-       select PINCTRL
        select PM_RUNTIME
        select REGULATOR
        select SERIAL_OMAP
index 48d5e41dfbfabe3da59ef00f7457f5012cf2ec1a..378590694447bdbdd3ed4d7862624ac5d000c402 100644 (file)
@@ -580,6 +580,11 @@ static void __init igep_wlan_bt_init(void)
        } else
                return;
 
+       /* Make sure that the GPIO pins are muxed correctly */
+       omap_mux_init_gpio(igep_wlan_bt_gpios[0].gpio, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(igep_wlan_bt_gpios[1].gpio, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(igep_wlan_bt_gpios[2].gpio, OMAP_PIN_OUTPUT);
+
        err = gpio_request_array(igep_wlan_bt_gpios,
                                 ARRAY_SIZE(igep_wlan_bt_gpios));
        if (err) {
index 388c431c745a0e4134c847f96f84b73912053bf7..d41ab98890ffcc45731c7625b3ad7f44d53bb855 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
 #include <linux/opp.h>
+#include <linux/cpu.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -444,27 +445,31 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
-static void __init beagle_opp_init(void)
+static int __init beagle_opp_init(void)
 {
        int r = 0;
 
-       /* Initialize the omap3 opp table */
-       if (omap3_opp_init()) {
+       if (!machine_is_omap3_beagle())
+               return 0;
+
+       /* Initialize the omap3 opp table if not already created. */
+       r = omap3_opp_init();
+       if (IS_ERR_VALUE(r) && (r != -EEXIST)) {
                pr_err("%s: opp default init failed\n", __func__);
-               return;
+               return r;
        }
 
        /* Custom OPP enabled for all xM versions */
        if (cpu_is_omap3630()) {
                struct device *mpu_dev, *iva_dev;
 
-               mpu_dev = omap_device_get_by_hwmod_name("mpu");
+               mpu_dev = get_cpu_device(0);
                iva_dev = omap_device_get_by_hwmod_name("iva");
 
                if (IS_ERR(mpu_dev) || IS_ERR(iva_dev)) {
                        pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
                                __func__, mpu_dev, iva_dev);
-                       return;
+                       return -ENODEV;
                }
                /* Enable MPU 1GHz and lower opps */
                r = opp_enable(mpu_dev, 800000000);
@@ -484,8 +489,9 @@ static void __init beagle_opp_init(void)
                        opp_disable(iva_dev, 660000000);
                }
        }
-       return;
+       return 0;
 }
+device_initcall(beagle_opp_init);
 
 static void __init omap3_beagle_init(void)
 {
@@ -522,8 +528,6 @@ static void __init omap3_beagle_init(void)
        /* Ensure SDRC pins are mux'd for self-refresh */
        omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
        omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-
-       beagle_opp_init();
 }
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
index 114ab4b8e0e356883192bb847237172df9d46ab3..1a45d6bd253921a9b8e8f646f568c868a0b4df85 100644 (file)
@@ -1073,6 +1073,8 @@ static struct omap_clk am33xx_clks[] = {
        CLK(NULL,       "gfx_fck_div_ck",       &gfx_fck_div_ck,        CK_AM33XX),
        CLK(NULL,       "sysclkout_pre_ck",     &sysclkout_pre_ck,      CK_AM33XX),
        CLK(NULL,       "clkout2_ck",           &clkout2_ck,    CK_AM33XX),
+       CLK(NULL,       "timer_32k_ck",         &clkdiv32k_ick, CK_AM33XX),
+       CLK(NULL,       "timer_sys_ck",         &sys_clkin_ck,  CK_AM33XX),
 };
 
 int __init am33xx_clk_init(void)
index d661d138f27057d2dcc2130d741f6c0fa53bcb9d..6efc30c961a5806dbecff3fb595bab1abfbc9082 100644 (file)
@@ -3294,7 +3294,7 @@ static struct omap_clk omap44xx_clks[] = {
        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("omap-gpmc",        "fck",                          &dummy_ck,      CK_443X),
        CLK("omap_i2c.1",       "ick",                          &dummy_ck,      CK_443X),
        CLK("omap_i2c.2",       "ick",                          &dummy_ck,      CK_443X),
        CLK("omap_i2c.3",       "ick",                          &dummy_ck,      CK_443X),
index cbb879139c51fd915c7ea50d00a6e91ad730d8b3..512e79a842cb94760eddcf6223363511f08bac8c 100644 (file)
@@ -925,15 +925,18 @@ static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
        if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
                return -EINVAL;
 
+       spin_lock_irqsave(&clkdm->lock, flags);
+
        /*
         * 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)
+       if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
+               spin_unlock_irqrestore(&clkdm->lock, flags);
                return 0;
+       }
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        arch_clkdm->clkdm_clk_enable(clkdm);
        pwrdm_state_switch(clkdm->pwrdm.ptr);
        spin_unlock_irqrestore(&clkdm->lock, flags);
@@ -950,15 +953,19 @@ static int _clkdm_clk_hwmod_disable(struct clockdomain *clkdm)
        if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
                return -EINVAL;
 
+       spin_lock_irqsave(&clkdm->lock, flags);
+
        if (atomic_read(&clkdm->usecount) == 0) {
+               spin_unlock_irqrestore(&clkdm->lock, flags);
                WARN_ON(1); /* underflow */
                return -ERANGE;
        }
 
-       if (atomic_dec_return(&clkdm->usecount) > 0)
+       if (atomic_dec_return(&clkdm->usecount) > 0) {
+               spin_unlock_irqrestore(&clkdm->lock, flags);
                return 0;
+       }
 
-       spin_lock_irqsave(&clkdm->lock, flags);
        arch_clkdm->clkdm_clk_disable(clkdm);
        pwrdm_state_switch(clkdm->pwrdm.ptr);
        spin_unlock_irqrestore(&clkdm->lock, flags);
index b56d06b48782a8608f77c43f9902972c1cb24bd5..95192a062d5db4b8401e73a78492c2990c26a463 100644 (file)
@@ -359,7 +359,7 @@ static struct clockdomain iss_44xx_clkdm = {
        .clkdm_offs       = OMAP4430_CM2_CAM_CAM_CDOFFS,
        .wkdep_srcs       = iss_wkup_sleep_deps,
        .sleepdep_srcs    = iss_wkup_sleep_deps,
-       .flags            = CLKDM_CAN_HWSUP_SWSUP,
+       .flags            = CLKDM_CAN_SWSUP,
 };
 
 static struct clockdomain l3_dss_44xx_clkdm = {
index 48daac2581b4a154a768923681ac108c084a5c98..84551f205e46fd20d5ef47849d279643f80f3b18 100644 (file)
@@ -64,30 +64,36 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
        struct spi_board_info *spi_bi = &ads7846_spi_board_info;
        int err;
 
-       err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
-       if (err) {
-               pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
-               return;
-       }
+       /*
+        * If a board defines get_pendown_state() function, request the pendown
+        * GPIO and set the GPIO debounce time.
+        * If a board does not define the get_pendown_state() function, then
+        * the ads7846 driver will setup the pendown GPIO itself.
+        */
+       if (board_pdata && board_pdata->get_pendown_state) {
+               err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
+               if (err) {
+                       pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
+                       return;
+               }
 
-       if (gpio_debounce)
-               gpio_set_debounce(gpio_pendown, gpio_debounce);
+               if (gpio_debounce)
+                       gpio_set_debounce(gpio_pendown, gpio_debounce);
+
+               gpio_export(gpio_pendown, 0);
+       }
 
        spi_bi->bus_num = bus_num;
        spi_bi->irq     = gpio_to_irq(gpio_pendown);
 
+       ads7846_config.gpio_pendown = gpio_pendown;
+
        if (board_pdata) {
                board_pdata->gpio_pendown = gpio_pendown;
+               board_pdata->gpio_pendown_debounce = gpio_debounce;
                spi_bi->platform_data = board_pdata;
-               if (board_pdata->get_pendown_state)
-                       gpio_export(gpio_pendown, 0);
-       } else {
-               ads7846_config.gpio_pendown = gpio_pendown;
        }
 
-       if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state))
-               gpio_free(gpio_pendown);
-
        spi_register_board_info(&ads7846_spi_board_info, 1);
 }
 #else
index c8c211731d267a233b7b8ac56cd042f472d46985..c72b5a7277200d08bc28e3b5348bfedcb677fefc 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
@@ -341,7 +342,7 @@ static void __init omap_init_dmic(void)
 
        oh = omap_hwmod_lookup("dmic");
        if (!oh) {
-               printk(KERN_ERR "Could not look up mcpdm hw_mod\n");
+               pr_err("Could not look up dmic hw_mod\n");
                return;
        }
 
@@ -613,6 +614,83 @@ static void omap_init_vout(void)
 static inline void omap_init_vout(void) {}
 #endif
 
+#if defined(CONFIG_OMAP_OCP2SCP) || defined(CONFIG_OMAP_OCP2SCP_MODULE)
+static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev)
+{
+       int cnt = 0;
+
+       while (ocp2scp_dev->drv_name != NULL) {
+               cnt++;
+               ocp2scp_dev++;
+       }
+
+       return cnt;
+}
+
+static void omap_init_ocp2scp(void)
+{
+       struct omap_hwmod       *oh;
+       struct platform_device  *pdev;
+       int                     bus_id = -1, dev_cnt = 0, i;
+       struct omap_ocp2scp_dev *ocp2scp_dev;
+       const char              *oh_name, *name;
+       struct omap_ocp2scp_platform_data *pdata;
+
+       if (!cpu_is_omap44xx())
+               return;
+
+       oh_name = "ocp2scp_usb_phy";
+       name    = "omap-ocp2scp";
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("%s: could not find omap_hwmod for %s\n", __func__,
+                                                               oh_name);
+               return;
+       }
+
+       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s: No memory for ocp2scp pdata\n", __func__);
+               return;
+       }
+
+       ocp2scp_dev = oh->dev_attr;
+       dev_cnt = count_ocp2scp_devices(ocp2scp_dev);
+
+       if (!dev_cnt) {
+               pr_err("%s: No devices connected to ocp2scp\n", __func__);
+               kfree(pdata);
+               return;
+       }
+
+       pdata->devices = kzalloc(sizeof(struct omap_ocp2scp_dev *)
+                                       * dev_cnt, GFP_KERNEL);
+       if (!pdata->devices) {
+               pr_err("%s: No memory for ocp2scp pdata devices\n", __func__);
+               kfree(pdata);
+               return;
+       }
+
+       for (i = 0; i < dev_cnt; i++, ocp2scp_dev++)
+               pdata->devices[i] = ocp2scp_dev;
+
+       pdata->dev_cnt  = dev_cnt;
+
+       pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata), NULL,
+                                                               0, false);
+       if (IS_ERR(pdev)) {
+               pr_err("Could not build omap_device for %s %s\n",
+                                               name, oh_name);
+               kfree(pdata->devices);
+               kfree(pdata);
+               return;
+       }
+}
+#else
+static inline void omap_init_ocp2scp(void) { }
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -640,6 +718,7 @@ static int __init omap2_init_devices(void)
        omap_init_sham();
        omap_init_aes();
        omap_init_vout();
+       omap_init_ocp2scp();
 
        return 0;
 }
index 5ac5cf30406a81aef651ae361bab6351903d4c3e..92b5718fa722ce129b240245fa5e60978bc77ffb 100644 (file)
@@ -868,9 +868,9 @@ static void __devexit gpmc_mem_exit(void)
 
 }
 
-static void __devinit gpmc_mem_init(void)
+static int __devinit gpmc_mem_init(void)
 {
-       int cs;
+       int cs, rc;
        unsigned long boot_rom_space = 0;
 
        /* never allocate the first page, to facilitate bug detection;
@@ -890,13 +890,21 @@ static void __devinit gpmc_mem_init(void)
                if (!gpmc_cs_mem_enabled(cs))
                        continue;
                gpmc_cs_get_memconf(cs, &base, &size);
-               if (gpmc_cs_insert_mem(cs, base, size) < 0)
-                       BUG();
+               rc = gpmc_cs_insert_mem(cs, base, size);
+               if (IS_ERR_VALUE(rc)) {
+                       while (--cs >= 0)
+                               if (gpmc_cs_mem_enabled(cs))
+                                       gpmc_cs_delete_mem(cs);
+                       return rc;
+               }
        }
+
+       return 0;
 }
 
 static __devinit int gpmc_probe(struct platform_device *pdev)
 {
+       int rc;
        u32 l;
        struct resource *res;
 
@@ -936,7 +944,13 @@ static __devinit int gpmc_probe(struct platform_device *pdev)
        dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
                 GPMC_REVISION_MINOR(l));
 
-       gpmc_mem_init();
+       rc = gpmc_mem_init();
+       if (IS_ERR_VALUE(rc)) {
+               clk_disable_unprepare(gpmc_l3_clk);
+               clk_put(gpmc_l3_clk);
+               dev_err(gpmc_dev, "failed to reserve memory\n");
+               return rc;
+       }
 
        if (IS_ERR_VALUE(gpmc_setup_irq()))
                dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
index 17f80e4ab162e4f2d4f15f8d99ccfa03496e225b..c47140bbbec4d8a5243110a68703d2861a7f3cb0 100644 (file)
@@ -614,16 +614,16 @@ static struct omap_mux __initdata omap3_muxmodes[] = {
                "sys_off_mode", NULL, NULL, NULL,
                "gpio_9", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_CTS, 150,
-               "uart1_cts", NULL, NULL, NULL,
+               "uart1_cts", "ssi1_rdy_tx", NULL, NULL,
                "gpio_150", "hsusb3_tll_clk", NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RTS, 149,
-               "uart1_rts", NULL, NULL, NULL,
+               "uart1_rts", "ssi1_flag_tx", NULL, NULL,
                "gpio_149", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_RX, 151,
-               "uart1_rx", NULL, "mcbsp1_clkr", "mcspi4_clk",
+               "uart1_rx", "ss1_wake_tx", "mcbsp1_clkr", "mcspi4_clk",
                "gpio_151", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART1_TX, 148,
-               "uart1_tx", NULL, NULL, NULL,
+               "uart1_tx", "ssi1_dat_tx", NULL, NULL,
                "gpio_148", NULL, NULL, "safe_mode"),
        _OMAP3_MUXENTRY(UART2_CTS, 144,
                "uart2_cts", "mcbsp3_dx", "gpt9_pwm_evt", NULL,
index b969ab1d258b91894415c3507bd8b50cd2aefa50..87cc6d058de25cf2552c1b274af1a06f5d3ee509 100644 (file)
@@ -421,6 +421,38 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
        return 0;
 }
 
+/**
+ * _wait_softreset_complete - wait for an OCP softreset to complete
+ * @oh: struct omap_hwmod * to wait on
+ *
+ * Wait until the IP block represented by @oh reports that its OCP
+ * softreset is complete.  This can be triggered by software (see
+ * _ocp_softreset()) or by hardware upon returning from off-mode (one
+ * example is HSMMC).  Waits for up to MAX_MODULE_SOFTRESET_WAIT
+ * microseconds.  Returns the number of microseconds waited.
+ */
+static int _wait_softreset_complete(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_class_sysconfig *sysc;
+       u32 softrst_mask;
+       int c = 0;
+
+       sysc = oh->class->sysc;
+
+       if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+               omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs)
+                                  & SYSS_RESETDONE_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       else if (sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
+               softrst_mask = (0x1 << sysc->sysc_fields->srst_shift);
+               omap_test_timeout(!(omap_hwmod_read(oh, sysc->sysc_offs)
+                                   & softrst_mask),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       }
+
+       return c;
+}
+
 /**
  * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v
  * @oh: struct omap_hwmod *
@@ -1282,6 +1314,18 @@ static void _enable_sysc(struct omap_hwmod *oh)
        if (!oh->class->sysc)
                return;
 
+       /*
+        * Wait until reset has completed, this is needed as the IP
+        * block is reset automatically by hardware in some cases
+        * (off-mode for example), and the drivers require the
+        * IP to be ready when they access it
+        */
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _enable_optional_clocks(oh);
+       _wait_softreset_complete(oh);
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _disable_optional_clocks(oh);
+
        v = oh->_sysc_cache;
        sf = oh->class->sysc->sysc_flags;
 
@@ -1804,7 +1848,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh)
  */
 static int _ocp_softreset(struct omap_hwmod *oh)
 {
-       u32 v, softrst_mask;
+       u32 v;
        int c = 0;
        int ret = 0;
 
@@ -1834,19 +1878,7 @@ static int _ocp_softreset(struct omap_hwmod *oh)
        if (oh->class->sysc->srst_udelay)
                udelay(oh->class->sysc->srst_udelay);
 
-       if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
-               omap_test_timeout((omap_hwmod_read(oh,
-                                                   oh->class->sysc->syss_offs)
-                                  & SYSS_RESETDONE_MASK),
-                                 MAX_MODULE_SOFTRESET_WAIT, c);
-       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
-               softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
-               omap_test_timeout(!(omap_hwmod_read(oh,
-                                                    oh->class->sysc->sysc_offs)
-                                  & softrst_mask),
-                                 MAX_MODULE_SOFTRESET_WAIT, c);
-       }
-
+       c = _wait_softreset_complete(oh);
        if (c == MAX_MODULE_SOFTRESET_WAIT)
                pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
                           oh->name, MAX_MODULE_SOFTRESET_WAIT);
@@ -2352,6 +2384,9 @@ static int __init _setup_reset(struct omap_hwmod *oh)
        if (oh->_state != _HWMOD_STATE_INITIALIZED)
                return -EINVAL;
 
+       if (oh->flags & HWMOD_EXT_OPT_MAIN_CLK)
+               return -EPERM;
+
        if (oh->rst_lines_cnt == 0) {
                r = _enable(oh);
                if (r) {
index 59d5c1cd316d5eb71c924b3b945ff166e94b9088..3125835dcaa5fef2391fa34a63663f576fefc986 100644 (file)
@@ -674,6 +674,7 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
        .name           = "cpgmac0",
        .class          = &am33xx_cpgmac0_hwmod_class,
        .clkdm_name     = "cpsw_125mhz_clkdm",
+       .flags          = (HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY),
        .mpu_irqs       = am33xx_cpgmac0_irqs,
        .main_clk       = "cpsw_125mhz_gclk",
        .prcm           = {
@@ -684,6 +685,20 @@ static struct omap_hwmod am33xx_cpgmac0_hwmod = {
        },
 };
 
+/*
+ * mdio class
+ */
+static struct omap_hwmod_class am33xx_mdio_hwmod_class = {
+       .name           = "davinci_mdio",
+};
+
+static struct omap_hwmod am33xx_mdio_hwmod = {
+       .name           = "davinci_mdio",
+       .class          = &am33xx_mdio_hwmod_class,
+       .clkdm_name     = "cpsw_125mhz_clkdm",
+       .main_clk       = "cpsw_125mhz_gclk",
+};
+
 /*
  * dcan class
  */
@@ -2501,6 +2516,21 @@ static struct omap_hwmod_ocp_if am33xx_l4_hs__cpgmac0 = {
        .user           = OCP_USER_MPU,
 };
 
+struct omap_hwmod_addr_space am33xx_mdio_addr_space[] = {
+       {
+               .pa_start       = 0x4A101000,
+               .pa_end         = 0x4A101000 + SZ_256 - 1,
+       },
+       { }
+};
+
+struct omap_hwmod_ocp_if am33xx_cpgmac0__mdio = {
+       .master         = &am33xx_cpgmac0_hwmod,
+       .slave          = &am33xx_mdio_hwmod,
+       .addr           = am33xx_mdio_addr_space,
+       .user           = OCP_USER_MPU,
+};
+
 static struct omap_hwmod_addr_space am33xx_elm_addr_space[] = {
        {
                .pa_start       = 0x48080000,
@@ -3371,6 +3401,7 @@ static struct omap_hwmod_ocp_if *am33xx_hwmod_ocp_ifs[] __initdata = {
        &am33xx_l3_main__tptc2,
        &am33xx_l3_s__usbss,
        &am33xx_l4_hs__cpgmac0,
+       &am33xx_cpgmac0__mdio,
        NULL,
 };
 
index 652d0285bd6dd7b1a445bcbab02e395e04c5e11a..0b1249e003987da276c2072aed5d39bcc334e8f5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/power/smartreflex.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/i2c.h>
@@ -2125,6 +2126,14 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
        .name           = "mcpdm",
        .class          = &omap44xx_mcpdm_hwmod_class,
        .clkdm_name     = "abe_clkdm",
+       /*
+        * It's suspected that the McPDM requires an off-chip main
+        * functional clock, controlled via I2C.  This IP block is
+        * currently reset very early during boot, before I2C is
+        * available, so it doesn't seem that we have any choice in
+        * the kernel other than to avoid resetting it.
+        */
+       .flags          = HWMOD_EXT_OPT_MAIN_CLK,
        .mpu_irqs       = omap44xx_mcpdm_irqs,
        .sdma_reqs      = omap44xx_mcpdm_sdma_reqs,
        .main_clk       = "mcpdm_fck",
@@ -2681,6 +2690,32 @@ static struct omap_hwmod_class omap44xx_ocp2scp_hwmod_class = {
        .sysc   = &omap44xx_ocp2scp_sysc,
 };
 
+/* ocp2scp dev_attr */
+static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
+       {
+               .name           = "usb_phy",
+               .start          = 0x4a0ad080,
+               .end            = 0x4a0ae000,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               /* XXX: Remove this once control module driver is in place */
+               .name           = "ctrl_dev",
+               .start          = 0x4a002300,
+               .end            = 0x4a002303,
+               .flags          = IORESOURCE_MEM,
+       },
+       { }
+};
+
+static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = {
+       {
+               .drv_name       = "omap-usb2",
+               .res            = omap44xx_usb_phy_and_pll_addrs,
+       },
+       { }
+};
+
 /* ocp2scp_usb_phy */
 static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
        .name           = "ocp2scp_usb_phy",
@@ -2694,6 +2729,7 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
                        .modulemode   = MODULEMODE_HWCTRL,
                },
        },
+       .dev_attr       = ocp2scp_dev_attr,
 };
 
 /*
index 686137d164dac9faee69b2293e524fa08c69bcea..67d66131cfa796c9f0724e43a2820a0752e1fa73 100644 (file)
@@ -91,6 +91,7 @@ extern void omap3_save_scratchpad_contents(void);
 
 #define PM_RTA_ERRATUM_i608            (1 << 0)
 #define PM_SDRC_WAKEUP_ERRATUM_i583    (1 << 1)
+#define PM_PER_MEMORIES_ERRATUM_i582   (1 << 2)
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
 extern u16 pm34xx_errata;
index ba670db1fd37416a8da3e1d343b319afa8161adf..3a904de4313ec82deb6b4f2e61d460e318ef0e87 100644 (file)
@@ -652,14 +652,17 @@ static void __init pm_errata_configure(void)
                /* Enable the l2 cache toggling in sleep logic */
                enable_omap3630_toggle_l2_on_restore();
                if (omap_rev() < OMAP3630_REV_ES1_2)
-                       pm34xx_errata |= PM_SDRC_WAKEUP_ERRATUM_i583;
+                       pm34xx_errata |= (PM_SDRC_WAKEUP_ERRATUM_i583 |
+                                         PM_PER_MEMORIES_ERRATUM_i582);
+       } else if (cpu_is_omap34xx()) {
+               pm34xx_errata |= PM_PER_MEMORIES_ERRATUM_i582;
        }
 }
 
 int __init omap3_pm_init(void)
 {
        struct power_state *pwrst, *tmp;
-       struct clockdomain *neon_clkdm, *mpu_clkdm;
+       struct clockdomain *neon_clkdm, *mpu_clkdm, *per_clkdm, *wkup_clkdm;
        int ret;
 
        if (!omap3_has_io_chain_ctrl())
@@ -711,6 +714,8 @@ int __init omap3_pm_init(void)
 
        neon_clkdm = clkdm_lookup("neon_clkdm");
        mpu_clkdm = clkdm_lookup("mpu_clkdm");
+       per_clkdm = clkdm_lookup("per_clkdm");
+       wkup_clkdm = clkdm_lookup("wkup_clkdm");
 
 #ifdef CONFIG_SUSPEND
        omap_pm_suspend = omap3_pm_suspend;
@@ -727,6 +732,27 @@ int __init omap3_pm_init(void)
        if (IS_PM34XX_ERRATUM(PM_RTA_ERRATUM_i608))
                omap3630_ctrl_disable_rta();
 
+       /*
+        * The UART3/4 FIFO and the sidetone memory in McBSP2/3 are
+        * not correctly reset when the PER powerdomain comes back
+        * from OFF or OSWR when the CORE powerdomain is kept active.
+        * See OMAP36xx Erratum i582 "PER Domain reset issue after
+        * Domain-OFF/OSWR Wakeup".  This wakeup dependency is not a
+        * complete workaround.  The kernel must also prevent the PER
+        * powerdomain from going to OSWR/OFF while the CORE
+        * powerdomain is not going to OSWR/OFF.  And if PER last
+        * power state was off while CORE last power state was ON, the
+        * UART3/4 and McBSP2/3 SIDETONE devices need to run a
+        * self-test using their loopback tests; if that fails, those
+        * devices are unusable until the PER/CORE can complete a transition
+        * from ON to OSWR/OFF and then back to ON.
+        *
+        * XXX Technically this workaround is only needed if off-mode
+        * or OSWR is enabled.
+        */
+       if (IS_PM34XX_ERRATUM(PM_PER_MEMORIES_ERRATUM_i582))
+               clkdm_add_wkdep(per_clkdm, wkup_clkdm);
+
        clkdm_add_wkdep(neon_clkdm, mpu_clkdm);
        if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
                omap3_secure_ram_storage =
index 0405c8190803a34ef666dd197a15f18dccdcad8f..a507cd6cf4f12259ab6a0bbad75fdc2e38bbe3a8 100644 (file)
@@ -329,6 +329,11 @@ void __init omap_serial_init_port(struct omap_board_data *bdata,
 
        oh->mux = omap_hwmod_mux_init(bdata->pads, bdata->pads_cnt);
 
+       if (console_uart_id == bdata->id) {
+               omap_device_enable(pdev);
+               pm_runtime_set_active(&pdev->dev);
+       }
+
        oh->dev_attr = uart;
 
        if (((cpu_is_omap34xx() || cpu_is_omap44xx()) && bdata->pads)
index 44f9aa7ec0c0a63e089137342accb6a52ab48ef7..69e46631a7cdc45142af9909d52c40b8e84286a3 100644 (file)
@@ -467,7 +467,7 @@ OMAP_SYS_TIMER(3_am33xx)
 #ifdef CONFIG_ARCH_OMAP4
 #ifdef CONFIG_LOCAL_TIMERS
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
-                             OMAP44XX_LOCAL_TWD_BASE, 29 + OMAP_INTC_START);
+                             OMAP44XX_LOCAL_TWD_BASE, 29);
 #endif
 
 static void __init omap4_timer_init(void)
index 635e109f5ad352e97e04dfad00c11e8728c72c98..a256135d8e48f59c0a6a103b2d449682caac9be2 100644 (file)
@@ -73,6 +73,7 @@ void __init omap4_pmic_init(const char *pmic_type,
 {
        /* PMIC part*/
        omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
+       omap_mux_init_signal("fref_clk0_out.sys_drm_msecure", OMAP_PIN_OUTPUT);
        omap_pmic_init(1, 400, pmic_type, 7 + OMAP44XX_IRQ_GIC_START, pmic_data);
 
        /* Register additional devices on i2c1 bus if needed */
@@ -366,7 +367,7 @@ static struct regulator_init_data omap4_clk32kg_idata = {
 };
 
 static struct regulator_consumer_supply omap4_vdd1_supply[] = {
-       REGULATOR_SUPPLY("vcc", "mpu.0"),
+       REGULATOR_SUPPLY("vcc", "cpu0"),
 };
 
 static struct regulator_consumer_supply omap4_vdd2_supply[] = {
index 880249b170125b0c9f6b4d870e9f3d6a6420fc53..75878c37959bff682bfdefca0548afb001891734 100644 (file)
@@ -264,7 +264,7 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
 
        if (initialized) {
                if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
-                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).",
+                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).\n",
                                __func__, voltdm->name, i2c_high_speed);
                return;
        }
diff --git a/arch/arm/mach-prima2/include/mach/gpio.h b/arch/arm/mach-prima2/include/mach/gpio.h
deleted file mode 100644 (file)
index 1904bb0..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __MACH_GPIO_H
-#define __MACH_GPIO_H
-
-/* Pull up/down values */
-enum sirfsoc_gpio_pull {
-       SIRFSOC_GPIO_PULL_NONE,
-       SIRFSOC_GPIO_PULL_UP,
-       SIRFSOC_GPIO_PULL_DOWN,
-};
-
-void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode);
-
-#endif
index 5ecbd17b56416a40c0e966508b37066d29b81d55..e2c6391863fedd9b008d594c516eea1f55936e64 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mfd/asic3.h>
 #include <linux/mtd/physmap.h>
 #include <linux/pda_power.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/gpio-regulator.h>
@@ -556,7 +557,7 @@ static struct platform_device hx4700_lcd = {
  */
 
 static struct platform_pwm_backlight_data backlight_data = {
-       .pwm_id         = 1,
+       .pwm_id         = -1,   /* Superseded by pwm_lookup */
        .max_brightness = 200,
        .dft_brightness = 100,
        .pwm_period_ns  = 30923,
@@ -571,6 +572,10 @@ static struct platform_device backlight = {
        },
 };
 
+static struct pwm_lookup hx4700_pwm_lookup[] = {
+       PWM_LOOKUP("pxa27x-pwm.1", 0, "pwm-backlight", NULL),
+};
+
 /*
  * USB "Transceiver"
  */
@@ -872,6 +877,7 @@ static void __init hx4700_init(void)
        pxa_set_stuart_info(NULL);
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
+       pwm_add_table(hx4700_pwm_lookup, ARRAY_SIZE(hx4700_pwm_lookup));
 
        pxa_set_ficp_info(&ficp_info);
        pxa27x_set_i2c_power_info(NULL);
index 438f02fe122a6d1d727671675af53b7564b99ae4..842596d4d31e19e59cd898084125944a03db7b90 100644 (file)
@@ -86,10 +86,7 @@ static void spitz_discharge1(int on)
        gpio_set_value(SPITZ_GPIO_LED_GREEN, on);
 }
 
-static unsigned long gpio18_config[] = {
-       GPIO18_RDY,
-       GPIO18_GPIO,
-};
+static unsigned long gpio18_config = GPIO18_GPIO;
 
 static void spitz_presuspend(void)
 {
@@ -112,7 +109,7 @@ static void spitz_presuspend(void)
        PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
        PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0);
 
-       pxa2xx_mfp_config(&gpio18_config[0], 1);
+       pxa2xx_mfp_config(&gpio18_config, 1);
        gpio_request_one(18, GPIOF_OUT_INIT_HIGH, "Unknown");
        gpio_free(18);
 
@@ -131,7 +128,6 @@ static void spitz_presuspend(void)
 
 static void spitz_postsuspend(void)
 {
-       pxa2xx_mfp_config(&gpio18_config[1], 1);
 }
 
 static int spitz_should_wakeup(unsigned int resume_on_alarm)
index 749220f91a7079e8a4a1e65561189497e9743c36..4407b17305396267b56d407f3ae80fb3dd4ef8b4 100644 (file)
@@ -163,7 +163,7 @@ static struct clk_lookup s3c2440_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud3", &s3c2440_clk_fclk_n),
 };
 
-static int s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
+static int __init_refok s3c2440_clk_add(struct device *dev, struct subsys_interface *sif)
 {
        struct clk *clock_upll;
        struct clk *clock_h;
index ed5a95ece9eb2d365b7152cdb4bd5cfe508e672b..77ee0b732237d93de59c80632279a00dbf5dc2bd 100644 (file)
@@ -61,6 +61,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2416_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -132,6 +133,7 @@ void __init s3c2416_map_io(void)
        /* initialize device information early */
        s3c2416_default_sdhci0();
        s3c2416_default_sdhci1();
+       s3c64xx_spi_setname("s3c2443-spi");
 
        iotable_init(s3c2416_iodesc, ARRAY_SIZE(s3c2416_iodesc));
 }
index ab648ad8fa508651624054ca2d9693f9d34fb1e5..165b6a6b3daaa9450201db7b0c721f76c62574f2 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/nand-core.h>
 #include <plat/adc-core.h>
 #include <plat/rtc-core.h>
+#include <plat/spi-core.h>
 
 static struct map_desc s3c2443_iodesc[] __initdata = {
        IODESC_ENT(WATCHDOG),
@@ -100,6 +101,9 @@ void __init s3c2443_map_io(void)
        s3c24xx_gpiocfg_default.set_pull = s3c2443_gpio_setpull;
        s3c24xx_gpiocfg_default.get_pull = s3c2443_gpio_getpull;
 
+       /* initialize device information early */
+       s3c64xx_spi_setname("s3c2443-spi");
+
        iotable_init(s3c2443_iodesc, ARRAY_SIZE(s3c2443_iodesc));
 }
 
index 6e6a0a9d6778b0b1fe41a6857cef015ee55bc39d..111e404a81fd44a8627025c975898e12f20598b7 100644 (file)
@@ -44,6 +44,7 @@
 #include <plat/sdhci.h>
 #include <plat/adc-core.h>
 #include <plat/fb-core.h>
+#include <plat/spi-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-irqtype.h>
 #include <plat/regs-serial.h>
@@ -179,6 +180,7 @@ void __init s5p6440_map_io(void)
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
        s3c_fb_setname("s5p64x0-fb");
+       s3c64xx_spi_setname("s5p64x0-spi");
 
        s5p64x0_default_sdhci0();
        s5p64x0_default_sdhci1();
@@ -193,6 +195,7 @@ void __init s5p6450_map_io(void)
        /* initialize any device information early */
        s3c_adc_setname("s3c64xx-adc");
        s3c_fb_setname("s5p64x0-fb");
+       s3c64xx_spi_setname("s5p64x0-spi");
 
        s5p64x0_default_sdhci0();
        s5p64x0_default_sdhci1();
index 621908658861596a43e4817f6978e352eab7604d..cc6e561c99588430f7e3b99993d761ffebecf949 100644 (file)
@@ -45,6 +45,7 @@
 #include <plat/fb-core.h>
 #include <plat/iic-core.h>
 #include <plat/onenand-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 #include <plat/watchdog-reset.h>
 
@@ -165,6 +166,8 @@ void __init s5pc100_map_io(void)
        s3c_onenand_setname("s5pc100-onenand");
        s3c_fb_setname("s5pc100-fb");
        s3c_cfcon_setname("s5pc100-pata");
+
+       s3c64xx_spi_setname("s5pc100-spi");
 }
 
 void __init s5pc100_init_clocks(int xtal)
index 4c9e9027df9aed2cbd0314ec1cebc0d80a1d3530..a0c50efe8145f167b4482a814e15329d7f32db27 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/iic-core.h>
 #include <plat/keypad-core.h>
 #include <plat/tv-core.h>
+#include <plat/spi-core.h>
 #include <plat/regs-serial.h>
 
 #include "common.h"
@@ -196,6 +197,8 @@ void __init s5pv210_map_io(void)
 
        /* setup TV devices */
        s5p_hdmi_setname("s5pv210-hdmi");
+
+       s3c64xx_spi_setname("s5pv210-spi");
 }
 
 void __init s5pv210_init_clocks(int xtal)
index 2912eab3b967bddedb8a42e39747e9612f04d237..3cc8b1c21da9edffc4dfc7dd8a0d2288a4f69e05 100644 (file)
@@ -1196,7 +1196,7 @@ static void __init eva_init(void)
 
 #ifdef CONFIG_CACHE_L2X0
        /* Early BRESP enable, Shared attribute override enable, 32K*8way */
-       l2x0_init(__io(0xf0002000), 0x40440000, 0x82000fff);
+       l2x0_init(IOMEM(0xf0002000), 0x40440000, 0x82000fff);
 #endif
 
        i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices));
index 3cafb6ab5e9aafb09e900b4821e291eab3493e29..37b2a3133b3b8681f3de1cdf0511dc0d51013823 100644 (file)
 #include <linux/clkdev.h>
 #include <mach/common.h>
 
-#define FRQMR   0xffc80014
-#define MSTPCR0 0xffc80030
-#define MSTPCR1 0xffc80034
-#define MSTPCR3 0xffc8003c
-#define MSTPSR1 0xffc80044
-#define MSTPSR4 0xffc80048
-#define MSTPSR6 0xffc8004c
-#define MSTPCR4 0xffc80050
-#define MSTPCR5 0xffc80054
-#define MSTPCR6 0xffc80058
-#define MSTPCR7 0xffc80040
+#define FRQMR          IOMEM(0xffc80014)
+#define MSTPCR0                IOMEM(0xffc80030)
+#define MSTPCR1                IOMEM(0xffc80034)
+#define MSTPCR3                IOMEM(0xffc8003c)
+#define MSTPSR1                IOMEM(0xffc80044)
+#define MSTPSR4                IOMEM(0xffc80048)
+#define MSTPSR6                IOMEM(0xffc8004c)
+#define MSTPCR4                IOMEM(0xffc80050)
+#define MSTPCR5                IOMEM(0xffc80054)
+#define MSTPCR6                IOMEM(0xffc80058)
+#define MSTPCR7                IOMEM(0xffc80040)
 
 /* ioremap() through clock mapping mandatory to avoid
  * collision with ARM coherent DMA virtual memory range.
index 2917668f0091c1042a70e512f50c12bacdb3ebb2..ebbffc25f24fc1ad48c75d36ee10d36709cc7a1e 100644 (file)
@@ -247,7 +247,7 @@ void __init r8a7779_add_standard_devices(void)
 {
 #ifdef CONFIG_CACHE_L2X0
        /* Early BRESP enable, Shared attribute override enable, 64K*16way */
-       l2x0_init((void __iomem __force *)(0xf0100000), 0x40470000, 0x82000fff);
+       l2x0_init(IOMEM(0xf0100000), 0x40470000, 0x82000fff);
 #endif
        r8a7779_pm_init();
 
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1310_misc_regs.h
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h b/arch/arm/mach-spear13xx/include/mach/spear1340_misc_regs.h
deleted file mode 100644 (file)
index e69de29..0000000
index 57e235f4ac74a81da9ff15619ca44a69bc0b1509..aa5325cd1c4289ab16d9a6566ac4ee8c740bbc24 100644 (file)
@@ -182,7 +182,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
        .init_early     = tegra20_init_early,
        .init_irq       = tegra_dt_init_irq,
        .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
+       .timer          = &tegra_sys_timer,
        .init_machine   = tegra_dt_init,
        .init_late      = tegra_dt_init_late,
        .restart        = tegra_assert_system_reset,
index e4a676d4ddf720316ba5c7e96ed72e9ac7ad3616..5e92a81f9a2e24b6e02f7237a37d78229dda3543 100644 (file)
@@ -89,7 +89,7 @@ DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
        .init_early     = tegra30_init_early,
        .init_irq       = tegra_dt_init_irq,
        .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
+       .timer          = &tegra_sys_timer,
        .init_machine   = tegra30_dt_init,
        .init_late      = tegra_init_late,
        .restart        = tegra_assert_system_reset,
index f88e5143c767989e7cc8e634635d858055f9de61..91fbe733a21eae9be6a5e24df8740ab3d3474efd 100644 (file)
@@ -55,5 +55,5 @@ static inline int harmony_pcie_init(void) { return 0; }
 
 void __init tegra_paz00_wifikill_init(void);
 
-extern struct sys_timer tegra_timer;
+extern struct sys_timer tegra_sys_timer;
 #endif
index cc9b5fd8c3d314d10c560074f9b833cb69bad4bc..8d398a33adf738e7c263ef04cba9b8e5eaa773b9 100644 (file)
@@ -953,6 +953,7 @@ PERIPH_CLK(pcie_xclk,       NULL,             "pcie_xclk",  74,     0,      26000000,  mux_clk_m,
 static struct clk *tegra_list_clks[] = {
        &tegra_apbdma,
        &tegra_rtc,
+       &tegra_timer,
        &tegra_i2s1,
        &tegra_i2s2,
        &tegra_spdif_out,
index 5cd502c271631d24a9c4e18af47afa5f8f752d1f..e9de5dfd94ec339e5f5c0c7c15eaad1f5a7944c4 100644 (file)
@@ -1199,7 +1199,7 @@ static long tegra30_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_tegra *c = to_clk_tegra(hw);
        unsigned long input_rate = *prate;
-       unsigned long output_rate = *prate;
+       u64 output_rate = *prate;
        const struct clk_pll_freq_table *sel;
        struct clk_pll_freq_table cfg;
        int mul;
index d92cb556ae351fb81b1a581133ac6400a3d84352..3d2e5532a9ea27d4a9eb561ddd1db0f65ecf46a0 100644 (file)
@@ -1143,6 +1143,7 @@ struct clk *tegra_list_clks[] = {
        &tegra_apbdma,
        &tegra_rtc,
        &tegra_kbc,
+       &tegra_timer,
        &tegra_kfuse,
        &tegra_fuse,
        &tegra_fuse_burn,
index eccdce983043a46439b67610c3fe2488c937faca..d3b8c8e7368fd938285438cafb6d77f2d5ee7ebf 100644 (file)
@@ -245,7 +245,7 @@ static void __init tegra_init_timer(void)
        register_persistent_clock(NULL, tegra_read_persistent_clock);
 }
 
-struct sys_timer tegra_timer = {
+struct sys_timer tegra_sys_timer = {
        .init = tegra_init_timer,
 };
 
index 2236cbd03cd79c11d897353d33401ddc4a3c962e..1f3fbc2bb7768a4389e8c7796affdfb65f521d1b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/stat.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
+#include <linux/irq.h>
 #include <linux/platform_data/clk-ux500.h>
 
 #include <asm/hardware/gic.h>
index b9f60ebe3bc4f13f3dc13e4e4531da549890eca4..b820edaf31843fb309fc29f882ce9d4e80c04c62 100644 (file)
@@ -745,7 +745,7 @@ do_alignment_t32_to_handler(unsigned long *pinstr, struct pt_regs *regs,
 static int
 do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
-       union offset_union offset;
+       union offset_union uninitialized_var(offset);
        unsigned long instr = 0, instrptr;
        int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs);
        unsigned int type;
@@ -856,8 +856,10 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                if (thumb2_32b) {
                        offset.un = 0;
                        handler = do_alignment_t32_to_handler(&instr, regs, &offset);
-               } else
+               } else {
+                       offset.un = 0;
                        handler = do_alignment_ldmstm;
+               }
                break;
 
        default:
index 477a2d23ddf17efb95af55cebbc25d35793a417d..58bc3e4d3bd0a76094d8a2a40c0be9bece4eaf7a 100644 (file)
@@ -610,7 +610,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
                         gfp_t gfp, pgprot_t prot, bool is_coherent, const void *caller)
 {
        u64 mask = get_coherent_dma_mask(dev);
-       struct page *page;
+       struct page *page = NULL;
        void *addr;
 
 #ifdef CONFIG_DMA_API_DEBUG
index 86b8b480634fbc652dbf11dd9d9abaec84fa5e00..09c5233f4dfc81993312734e1ce434b92c131553 100644 (file)
@@ -89,7 +89,7 @@ ENTRY(cpu_v6_dcache_clean_area)
        mov     pc, lr
 
 /*
- *     cpu_arm926_switch_mm(pgd_phys, tsk)
+ *     cpu_v6_switch_mm(pgd_phys, tsk)
  *
  *     Set the translation table base pointer to be pgd_phys
  *
index bf312c354a214761646a3a3738fb6080b84fff33..0f5a5f2a2c7bbc1bb79668ac291dde283741be7a 100644 (file)
@@ -17,7 +17,6 @@ struct arm_vmregion {
        struct list_head        vm_list;
        unsigned long           vm_start;
        unsigned long           vm_end;
-       void                    *priv;
        int                     vm_active;
        const void              *caller;
 };
index c641fb6850170be36e7e47846a0fe4562af4fc52..9af9a690dbda4fbf75a98b024253e416d4e2cc56 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/netdevice.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/if_vlan.h>
 #include <asm/cacheflush.h>
 #include <asm/hwcap.h>
 
@@ -168,6 +169,8 @@ static inline bool is_load_to_a(u16 inst)
        case BPF_S_ANC_MARK:
        case BPF_S_ANC_PROTOCOL:
        case BPF_S_ANC_RXHASH:
+       case BPF_S_ANC_VLAN_TAG:
+       case BPF_S_ANC_VLAN_TAG_PRESENT:
        case BPF_S_ANC_QUEUE:
                return true;
        default:
@@ -646,6 +649,16 @@ load_ind:
                        update_on_xread(ctx);
                        emit(ARM_ORR_R(r_A, r_A, r_X), ctx);
                        break;
+               case BPF_S_ALU_XOR_K:
+                       /* A ^= K; */
+                       OP_IMM3(ARM_EOR, r_A, r_A, k, ctx);
+                       break;
+               case BPF_S_ANC_ALU_XOR_X:
+               case BPF_S_ALU_XOR_X:
+                       /* A ^= X */
+                       update_on_xread(ctx);
+                       emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
+                       break;
                case BPF_S_ALU_AND_K:
                        /* A &= K */
                        OP_IMM3(ARM_AND, r_A, r_A, k, ctx);
@@ -762,11 +775,6 @@ b_epilogue:
                        update_on_xread(ctx);
                        emit(ARM_MOV_R(r_A, r_X), ctx);
                        break;
-               case BPF_S_ANC_ALU_XOR_X:
-                       /* A ^= X */
-                       update_on_xread(ctx);
-                       emit(ARM_EOR_R(r_A, r_A, r_X), ctx);
-                       break;
                case BPF_S_ANC_PROTOCOL:
                        /* A = ntohs(skb->protocol) */
                        ctx->seen |= SEEN_SKB;
@@ -810,6 +818,17 @@ b_epilogue:
                        off = offsetof(struct sk_buff, rxhash);
                        emit(ARM_LDR_I(r_A, r_skb, off), ctx);
                        break;
+               case BPF_S_ANC_VLAN_TAG:
+               case BPF_S_ANC_VLAN_TAG_PRESENT:
+                       ctx->seen |= SEEN_SKB;
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+                       off = offsetof(struct sk_buff, vlan_tci);
+                       emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
+                       if (inst->code == BPF_S_ANC_VLAN_TAG)
+                               OP_IMM3(ARM_AND, r_A, r_A, VLAN_VID_MASK, ctx);
+                       else
+                               OP_IMM3(ARM_AND, r_A, r_A, VLAN_TAG_PRESENT, ctx);
+                       break;
                case BPF_S_ANC_QUEUE:
                        ctx->seen |= SEEN_SKB;
                        BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
index 7fa2f7d3cb90a4329f2f844b6555a9d81a42f3a8..afb84621ff6f210eb390c37fdd929c66cc32cbb3 100644 (file)
@@ -69,6 +69,7 @@
 #define ARM_INST_CMP_I         0x03500000
 
 #define ARM_INST_EOR_R         0x00200000
+#define ARM_INST_EOR_I         0x02200000
 
 #define ARM_INST_LDRB_I                0x05d00000
 #define ARM_INST_LDRB_R                0x07d00000
 #define ARM_CMP_I(rn, imm)     _AL3_I(ARM_INST_CMP, 0, rn, imm)
 
 #define ARM_EOR_R(rd, rn, rm)  _AL3_R(ARM_INST_EOR, rd, rn, rm)
+#define ARM_EOR_I(rd, rn, imm) _AL3_I(ARM_INST_EOR, rd, rn, imm)
 
 #define ARM_LDR_I(rt, rn, off) (ARM_INST_LDR_I | (rt) << 12 | (rn) << 16 \
                                 | (off))
index 540d3a7d92dfaacf8fd82cbd745327c7d2e094a9..e7b920b58675d79bab4b1ef598b18e0f05fb14ed 100644 (file)
@@ -55,7 +55,7 @@ struct platform_device *__init imx_add_mxc_mmc(
        struct resource res[] = {
                {
                        .start = data->iobase,
-                       .end = data->iobase + SZ_4K - 1,
+                       .end = data->iobase + data->iosize - 1,
                        .flags = IORESOURCE_MEM,
                }, {
                        .start = data->irq,
index 7cd56ed5cd949b25c0ae4ad02729241006b42783..82fcb206b5b25c679434c8217b72978c2a68df1f 100644 (file)
@@ -26,6 +26,7 @@ config ARCH_OMAP2PLUS
        select CLKDEV_LOOKUP
        select GENERIC_IRQ_CHIP
        select OMAP_DM_TIMER
+       select PINCTRL
        select PROC_DEVICETREE if PROC_FS
        select SPARSE_IRQ
        select USE_OF
index c7a4c0902b386f90e8e6d37a21fc7ead498b6ea5..5a4678edd65a9a8eb31a766fd566ee86a968e8f9 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/smc91x.h>
 
 #include <mach/hardware.h>
+#include "../mach-omap2/debug-devices.h"
 
 /* Many OMAP development platforms reuse the same "debug board"; these
  * platforms include H2, H3, H4, and Perseus2.
index a5683a84c6ee0e313cb8f9daeeb7c72106952a4e..6013831a043e320fafd5e718a558d422fa67a624 100644 (file)
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c-omap.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 
 #include <mach/irqs.h>
 #include <plat/i2c.h>
+#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE          0x3f
@@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
+/*
+ * XXX This function is a temporary compatibility wrapper - only
+ * needed until the I2C driver can be converted to call
+ * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
+ */
+static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
+{
+       omap_pm_set_max_mpu_wakeup_lat(dev, t);
+}
+
 static inline int omap2_i2c_add_bus(int bus_id)
 {
        int l;
@@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id)
        dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
        pdata->flags = dev_attr->flags;
 
+       /*
+        * When waiting for completion of a i2c transfer, we need to
+        * set a wake up latency constraint for the MPU. This is to
+        * ensure quick enough wakeup from idle, when transfer
+        * completes.
+        * Only omap3 has support for constraints
+        */
+       if (cpu_is_omap34xx())
+               pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
        pdev = omap_device_build(name, bus_id, oh, pdata,
                        sizeof(struct omap_i2c_bus_platform_data),
                        NULL, 0, 0);
index f4a4cd014795d676d85ffdc05622a4ac3e889a5c..1957a8516e938e2d9f42b690903211095e6ed959 100644 (file)
 #define OMAP_UART_WER_MOD_WKUP 0X7F
 
 /* Enable XON/XOFF flow control on output */
-#define OMAP_UART_SW_TX                0x8
+#define OMAP_UART_SW_TX                0x04
 
 /* Enable XON/XOFF flow control on input */
-#define OMAP_UART_SW_RX                0x2
+#define OMAP_UART_SW_RX                0x04
 
 #define OMAP_UART_SYSC_RESET   0X07
 #define OMAP_UART_TCR_TRIG     0X0F
index b3349f7b1a2cda6458ed75b541a07298c84e7234..1db029438022066311c858079bf5753b08e359f5 100644 (file)
@@ -443,6 +443,11 @@ struct omap_hwmod_omap4_prcm {
  *     in order to complete the reset. Optional clocks will be disabled
  *     again after the reset.
  * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_EXT_OPT_MAIN_CLK: The only main functional clock source for
+ *     this IP block comes from an off-chip source and is not always
+ *     enabled.  This prevents the hwmod code from being able to
+ *     enable and reset the IP block early.  XXX Eventually it should
+ *     be possible to query the clock framework for this information.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -453,6 +458,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_IDLEST                                (1 << 6)
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET                (1 << 7)
 #define HWMOD_16BIT_REG                                (1 << 8)
+#define HWMOD_EXT_OPT_MAIN_CLK                 (1 << 9)
 
 /*
  * omap_hwmod._int_flags definitions
diff --git a/arch/arm/plat-samsung/include/plat/spi-core.h b/arch/arm/plat-samsung/include/plat/spi-core.h
new file mode 100644 (file)
index 0000000..0b9428a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __PLAT_S3C_SPI_CORE_H
+#define __PLAT_S3C_SPI_CORE_H
+
+/* These functions are only for use with the core support code, such as
+ * the cpu specific initialisation code
+ */
+
+/* re-define device name depending on support. */
+static inline void s3c64xx_spi_setname(char *name)
+{
+#ifdef CONFIG_S3C64XX_DEV_SPI0
+       s3c64xx_device_spi0.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI1
+       s3c64xx_device_spi1.name = name;
+#endif
+#ifdef CONFIG_S3C64XX_DEV_SPI2
+       s3c64xx_device_spi2.name = name;
+#endif
+}
+
+#endif /* __PLAT_S3C_SPI_CORE_H */
index 635cb1865e4d56af08b8579eb72dbaadfa77f211..32d05c8219dc35acf9db46a49e521ca312fc336e 100644 (file)
@@ -5,6 +5,6 @@
 #
 
 include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
-       @echo '  Generating $@'
+       @$(kecho) '  Generating $@'
        @mkdir -p $(dir $@)
        $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
index c834b32af275d73d4cd760efeb4a365e940f1df7..3b44e0dd0a9327f8d75fc72c7bc8838a913f8571 100644 (file)
@@ -701,11 +701,14 @@ static int __init vfp_init(void)
                        elf_hwcap |= HWCAP_VFPv3;
 
                        /*
-                        * Check for VFPv3 D16. CPUs in this configuration
-                        * only have 16 x 64bit registers.
+                        * Check for VFPv3 D16 and VFPv4 D16.  CPUs in
+                        * this configuration only have 16 x 64bit
+                        * registers.
                         */
                        if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1)
-                               elf_hwcap |= HWCAP_VFPv3D16;
+                               elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */
+                       else
+                               elf_hwcap |= HWCAP_VFPD32;
                }
 #endif
                /*
index 59bcb96ac3692446989501f363301daa81674d5b..f57609275449e704892101a514ecc40ee3021a3c 100644 (file)
@@ -166,3 +166,14 @@ void free_xenballooned_pages(int nr_pages, struct page **pages)
        *pages = NULL;
 }
 EXPORT_SYMBOL_GPL(free_xenballooned_pages);
+
+/* In the hypervisor.S file. */
+EXPORT_SYMBOL_GPL(HYPERVISOR_event_channel_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_grant_table_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_xen_version);
+EXPORT_SYMBOL_GPL(HYPERVISOR_console_io);
+EXPORT_SYMBOL_GPL(HYPERVISOR_sched_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_hvm_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_memory_op);
+EXPORT_SYMBOL_GPL(HYPERVISOR_physdev_op);
+EXPORT_SYMBOL_GPL(privcmd_call);
index dbd1330c01966c20667853b6d9de97754b869d91..859a9bb002d54875e5089a940442d5015a9fe1a4 100644 (file)
@@ -33,7 +33,7 @@
 #include <xen/page.h>
 #include <xen/grant_table.h>
 
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
                           unsigned long max_nr_gframes,
                           void **__shared)
 {
index 074f5ed101b9d17bf49c2a0cd13b078408fcb64c..71f723984cbd94eced133e49bc7fd0db8dbdf92b 100644 (file)
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/opcodes-virt.h>
 #include <xen/interface/xen.h>
 
 
-/* HVC 0xEA1 */
-#ifdef CONFIG_THUMB2_KERNEL
-#define xen_hvc .word 0xf7e08ea1
-#else
-#define xen_hvc .word 0xe140ea71
-#endif
+#define XEN_IMM 0xEA1
 
 #define HYPERCALL_SIMPLE(hypercall)            \
 ENTRY(HYPERVISOR_##hypercall)                  \
        mov r12, #__HYPERVISOR_##hypercall;     \
-       xen_hvc;                                                        \
+       __HVC(XEN_IMM);                                         \
        mov pc, lr;                                                     \
 ENDPROC(HYPERVISOR_##hypercall)
 
@@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall)                 \
        stmdb sp!, {r4}                                         \
        ldr r4, [sp, #4]                                        \
        mov r12, #__HYPERVISOR_##hypercall;     \
-       xen_hvc                                                         \
+       __HVC(XEN_IMM);                                         \
        ldm sp!, {r4}                                           \
        mov pc, lr                                                      \
 ENDPROC(HYPERVISOR_##hypercall)
@@ -100,7 +96,7 @@ ENTRY(privcmd_call)
        mov r2, r3
        ldr r3, [sp, #8]
        ldr r4, [sp, #4]
-       xen_hvc
+       __HVC(XEN_IMM)
        ldm sp!, {r4}
        mov pc, lr
 ENDPROC(privcmd_call);
index 7ff68c9460737d7b016763475c9a01dfdf882a57..15ac18a56c93b78a2d3972e7196ce89875c2135c 100644 (file)
@@ -1,6 +1,7 @@
 config ARM64
        def_bool y
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
+       select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        select GENERIC_CLOCKEVENTS
        select GENERIC_HARDIRQS_NO_DEPRECATED
        select GENERIC_IOMAP
@@ -22,6 +23,7 @@ config ARM64
        select HAVE_PERF_EVENTS
        select HAVE_SPARSE_IRQ
        select IRQ_DOMAIN
+       select MODULES_USE_ELF_RELA
        select NO_BOOTMEM
        select OF
        select OF_EARLY_FLATTREE
index fe77e51a7847bf872ebcc7cb18102d71c1b0af4a..a581a2205938db09064604a53244b756ca650d0a 100644 (file)
@@ -18,7 +18,6 @@ generic-y += ipcbuf.h
 generic-y += irq_regs.h
 generic-y += kdebug.h
 generic-y += kmap_types.h
-generic-y += linkage.h
 generic-y += local.h
 generic-y += local64.h
 generic-y += mman.h
index cf284649dfcbff5c84501ad539f4bc880e6766a7..07fea290d7c15b211e881856bb48d943a80c337a 100644 (file)
 #include <asm/user.h>
 
 typedef unsigned long elf_greg_t;
-typedef unsigned long elf_freg_t[3];
 
 #define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
-
-typedef struct user_fp elf_fpregset_t;
+typedef struct user_fpsimd_state elf_fpregset_t;
 
 #define EM_AARCH64             183
 
@@ -87,7 +85,6 @@ typedef struct user_fp elf_fpregset_t;
 #define R_AARCH64_MOVW_PREL_G2_NC      292
 #define R_AARCH64_MOVW_PREL_G3         293
 
-
 /*
  * These are used to set parameters in the core dumps.
  */
index b42fab9f62a955f0e5ec864b186520103ebda60c..c43b4ac13008ffec8f0b39101e5cfd77e43fd3b5 100644 (file)
@@ -25,9 +25,8 @@
  *  - FPSR and FPCR
  *  - 32 128-bit data registers
  *
- * Note that user_fp forms a prefix of this structure, which is relied
- * upon in the ptrace FP/SIMD accessors. struct user_fpsimd_state must
- * form a prefix of struct fpsimd_state.
+ * Note that user_fpsimd forms a prefix of this structure, which is
+ * relied upon in the ptrace FP/SIMD accessors.
  */
 struct fpsimd_state {
        union {
index 74a2a7d304a959159e3cf69c94f0ede77a8232c2..d2f05a608274534a08180fc3866658a225bb560c 100644 (file)
@@ -114,7 +114,7 @@ static inline u64 __raw_readq(const volatile void __iomem *addr)
  *  I/O port access primitives.
  */
 #define IO_SPACE_LIMIT         0xffff
-#define PCI_IOBASE             ((void __iomem *)0xffffffbbfffe0000UL)
+#define PCI_IOBASE             ((void __iomem *)(MODULES_VADDR - SZ_2M))
 
 static inline u8 inb(unsigned long addr)
 {
@@ -222,12 +222,12 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
 extern void __iounmap(volatile void __iomem *addr);
 
 #define PROT_DEFAULT           (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
-#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
+#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
 
-#define ioremap(addr, size)            __ioremap((addr), (size), PROT_DEVICE_nGnRE)
-#define ioremap_nocache(addr, size)    __ioremap((addr), (size), PROT_DEVICE_nGnRE)
-#define ioremap_wc(addr, size)         __ioremap((addr), (size), PROT_NORMAL_NC)
+#define ioremap(addr, size)            __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
+#define ioremap_nocache(addr, size)    __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
+#define ioremap_wc(addr, size)         __ioremap((addr), (size), __pgprot(PROT_NORMAL_NC))
 #define iounmap                                __iounmap
 
 #define ARCH_HAS_IOREMAP_WC
diff --git a/arch/arm64/include/asm/linkage.h b/arch/arm64/include/asm/linkage.h
new file mode 100644 (file)
index 0000000..636c1bc
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_LINKAGE_H
+#define __ASM_LINKAGE_H
+
+#define __ALIGN                .align 4
+#define __ALIGN_STR    ".align 4"
+
+#endif
index 0f3b4581d9251ab17b4750eb8501c8d77cbee428..75fd13d289b93193f261c89fa83fb6973738f6f2 100644 (file)
@@ -38,7 +38,8 @@
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
 #define PMD_SECT_AF            (_AT(pmdval_t, 1) << 10)
 #define PMD_SECT_NG            (_AT(pmdval_t, 1) << 11)
-#define PMD_SECT_XN            (_AT(pmdval_t, 1) << 54)
+#define PMD_SECT_PXN           (_AT(pmdval_t, 1) << 53)
+#define PMD_SECT_UXN           (_AT(pmdval_t, 1) << 54)
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
@@ -57,7 +58,8 @@
 #define PTE_SHARED             (_AT(pteval_t, 3) << 8)         /* SH[1:0], inner shareable */
 #define PTE_AF                 (_AT(pteval_t, 1) << 10)        /* Access Flag */
 #define PTE_NG                 (_AT(pteval_t, 1) << 11)        /* nG */
-#define PTE_XN                 (_AT(pteval_t, 1) << 54)        /* XN */
+#define PTE_PXN                        (_AT(pteval_t, 1) << 53)        /* Privileged XN */
+#define PTE_UXN                        (_AT(pteval_t, 1) << 54)        /* User XN */
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
index 8960239be722893a8094ceef323da22ff26eef63..14aba2db6776d099935c76e95bd4797f3a707376 100644 (file)
@@ -62,23 +62,23 @@ extern pgprot_t pgprot_default;
 
 #define _MOD_PROT(p, b)        __pgprot(pgprot_val(p) | (b))
 
-#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_SHARED            _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN)
-#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_default, PTE_USER | PTE_NG)
-#define PAGE_COPY              _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
-#define PAGE_READONLY          _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
-#define PAGE_KERNEL            _MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY)
-#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_default, PTE_DIRTY)
-
-#define __PAGE_NONE            __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_SHARED          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN)
-#define __PAGE_SHARED_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG)
-#define __PAGE_COPY            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_COPY_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
-#define __PAGE_READONLY                __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_READONLY_EXEC   __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
+#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_SHARED            _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
+#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
+#define PAGE_COPY              _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define PAGE_READONLY          _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define PAGE_KERNEL            _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
+#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
+
+#define __PAGE_NONE            __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_SHARED          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
+#define __PAGE_SHARED_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
+#define __PAGE_COPY            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_COPY_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define __PAGE_READONLY                __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_READONLY_EXEC   __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
 
 #endif /* __ASSEMBLY__ */
 
@@ -130,10 +130,10 @@ extern struct page *empty_zero_page;
 #define pte_young(pte)         (pte_val(pte) & PTE_AF)
 #define pte_special(pte)       (pte_val(pte) & PTE_SPECIAL)
 #define pte_write(pte)         (!(pte_val(pte) & PTE_RDONLY))
-#define pte_exec(pte)          (!(pte_val(pte) & PTE_XN))
+#define pte_exec(pte)          (!(pte_val(pte) & PTE_UXN))
 
 #define pte_present_exec_user(pte) \
-       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \
+       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \
         (PTE_VALID | PTE_USER))
 
 #define PTE_BIT_FUNC(fn,op) \
@@ -262,7 +262,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY;
+       const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY;
        pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
        return pte;
 }
index 39a208a392f7df5b372c2cda150f2164121e8446..77f696c143396d9bf93521d6444bf12dd4b82c01 100644 (file)
@@ -43,6 +43,8 @@
 #else
 #define STACK_TOP              STACK_TOP_MAX
 #endif /* CONFIG_COMPAT */
+
+#define ARCH_LOW_ADDRESS_LIMIT PHYS_MASK
 #endif /* __KERNEL__ */
 
 struct debug_info {
@@ -92,30 +94,20 @@ static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
 static inline void start_thread(struct pt_regs *regs, unsigned long pc,
                                unsigned long sp)
 {
-       unsigned long *stack = (unsigned long *)sp;
-
        start_thread_common(regs, pc);
        regs->pstate = PSR_MODE_EL0t;
        regs->sp = sp;
-       regs->regs[2] = stack[2];       /* x2 (envp) */
-       regs->regs[1] = stack[1];       /* x1 (argv) */
-       regs->regs[0] = stack[0];       /* x0 (argc) */
 }
 
 #ifdef CONFIG_COMPAT
 static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
                                       unsigned long sp)
 {
-       unsigned int *stack = (unsigned int *)sp;
-
        start_thread_common(regs, pc);
        regs->pstate = COMPAT_PSR_MODE_USR;
        if (pc & 1)
                regs->pstate |= COMPAT_PSR_T_BIT;
        regs->compat_sp = sp;
-       regs->regs[2] = stack[2];       /* x2 (envp) */
-       regs->regs[1] = stack[1];       /* x1 (argv) */
-       regs->regs[0] = stack[0];       /* x0 (argc) */
 }
 #endif
 
index 63f853f8b718026a69342ce8bb46ff6fd948066e..68aff2816e8605113945a66e60e1dd2f5b5c2ade 100644 (file)
@@ -14,7 +14,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #ifdef CONFIG_COMPAT
-#define __ARCH_WANT_COMPAT_IPC_PARSE_VERSION
 #define __ARCH_WANT_COMPAT_STAT64
 #define __ARCH_WANT_SYS_GETHOSTNAME
 #define __ARCH_WANT_SYS_PAUSE
index 9b131b4efa0bb1caaa51348be06be65950d10aca..6913643bbe54ebd5005bfeb74302329fa5e2d0f5 100644 (file)
@@ -79,13 +79,14 @@ struct user_fpsimd_state {
 
 struct user_hwdebug_state {
        __u32           dbg_info;
+       __u32           pad;
        struct {
                __u64   addr;
                __u32   ctrl;
+               __u32   pad;
        }               dbg_regs[16];
 };
 
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _UAPI__ASM_PTRACE_H */
index ecbf2d81ec5ce483416bf57e2030bff2431c1972..c76c7241125b66d8ee762b13bdae3f73328f8fe7 100644 (file)
@@ -613,17 +613,11 @@ enum armv8_pmuv3_perf_types {
        ARMV8_PMUV3_PERFCTR_BUS_ACCESS                          = 0x19,
        ARMV8_PMUV3_PERFCTR_MEM_ERROR                           = 0x1A,
        ARMV8_PMUV3_PERFCTR_BUS_CYCLES                          = 0x1D,
-
-       /*
-        * This isn't an architected event.
-        * We detect this event number and use the cycle counter instead.
-        */
-       ARMV8_PMUV3_PERFCTR_CPU_CYCLES                          = 0xFF,
 };
 
 /* PMUv3 HW events mapping. */
 static const unsigned armv8_pmuv3_perf_map[PERF_COUNT_HW_MAX] = {
-       [PERF_COUNT_HW_CPU_CYCLES]              = ARMV8_PMUV3_PERFCTR_CPU_CYCLES,
+       [PERF_COUNT_HW_CPU_CYCLES]              = ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES,
        [PERF_COUNT_HW_INSTRUCTIONS]            = ARMV8_PMUV3_PERFCTR_INSTR_EXECUTED,
        [PERF_COUNT_HW_CACHE_REFERENCES]        = ARMV8_PMUV3_PERFCTR_L1_DCACHE_ACCESS,
        [PERF_COUNT_HW_CACHE_MISSES]            = ARMV8_PMUV3_PERFCTR_L1_DCACHE_REFILL,
@@ -1106,7 +1100,7 @@ static int armv8pmu_get_event_idx(struct pmu_hw_events *cpuc,
        unsigned long evtype = event->config_base & ARMV8_EVTYPE_EVENT;
 
        /* Always place a cycle counter into the cycle counter. */
-       if (evtype == ARMV8_PMUV3_PERFCTR_CPU_CYCLES) {
+       if (evtype == ARMV8_PMUV3_PERFCTR_CLOCK_CYCLES) {
                if (test_and_set_bit(ARMV8_IDX_CYCLE_COUNTER, cpuc->used_mask))
                        return -EAGAIN;
 
index f22965ea1cfcd4bd2a5c6a276ed8675c49de19e4..e04cebdbb47fc5a82ae6042169b098b8fae13d54 100644 (file)
@@ -309,24 +309,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
        return last;
 }
 
-/*
- * Fill in the task's elfregs structure for a core dump.
- */
-int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
-{
-       elf_core_copy_regs(elfregs, task_pt_regs(t));
-       return 1;
-}
-
-/*
- * fill in the fpe structure for a core dump...
- */
-int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
-{
-       return 0;
-}
-EXPORT_SYMBOL(dump_fpu);
-
 /*
  * Shuffle the argument into the correct register before calling the
  * thread function.  x1 is the thread argument, x2 is the pointer to
index 2ea3968367c265f99830db7f365668919f5f6a7c..6e1e77f1831c0cb0bf31306822ebc72ba8d3158a 100644 (file)
@@ -234,28 +234,33 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,
                                     struct arch_hw_breakpoint_ctrl ctrl,
                                     struct perf_event_attr *attr)
 {
-       int err, len, type;
+       int err, len, type, disabled = !ctrl.enabled;
 
-       err = arch_bp_generic_fields(ctrl, &len, &type);
-       if (err)
-               return err;
-
-       switch (note_type) {
-       case NT_ARM_HW_BREAK:
-               if ((type & HW_BREAKPOINT_X) != type)
-                       return -EINVAL;
-               break;
-       case NT_ARM_HW_WATCH:
-               if ((type & HW_BREAKPOINT_RW) != type)
+       if (disabled) {
+               len = 0;
+               type = HW_BREAKPOINT_EMPTY;
+       } else {
+               err = arch_bp_generic_fields(ctrl, &len, &type);
+               if (err)
+                       return err;
+
+               switch (note_type) {
+               case NT_ARM_HW_BREAK:
+                       if ((type & HW_BREAKPOINT_X) != type)
+                               return -EINVAL;
+                       break;
+               case NT_ARM_HW_WATCH:
+                       if ((type & HW_BREAKPOINT_RW) != type)
+                               return -EINVAL;
+                       break;
+               default:
                        return -EINVAL;
-               break;
-       default:
-               return -EINVAL;
+               }
        }
 
        attr->bp_len    = len;
        attr->bp_type   = type;
-       attr->disabled  = !ctrl.enabled;
+       attr->disabled  = disabled;
 
        return 0;
 }
@@ -372,7 +377,7 @@ static int ptrace_hbp_set_addr(unsigned int note_type,
 
 #define PTRACE_HBP_ADDR_SZ     sizeof(u64)
 #define PTRACE_HBP_CTRL_SZ     sizeof(u32)
-#define PTRACE_HBP_REG_OFF     sizeof(u32)
+#define PTRACE_HBP_PAD_SZ      sizeof(u32)
 
 static int hw_break_get(struct task_struct *target,
                        const struct user_regset *regset,
@@ -380,7 +385,7 @@ static int hw_break_get(struct task_struct *target,
                        void *kbuf, void __user *ubuf)
 {
        unsigned int note_type = regset->core_note_type;
-       int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit;
+       int ret, idx = 0, offset, limit;
        u32 info, ctrl;
        u64 addr;
 
@@ -389,11 +394,20 @@ static int hw_break_get(struct task_struct *target,
        if (ret)
                return ret;
 
-       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0, 4);
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &info, 0,
+                                 sizeof(info));
+       if (ret)
+               return ret;
+
+       /* Pad */
+       offset = offsetof(struct user_hwdebug_state, pad);
+       ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, offset,
+                                      offset + PTRACE_HBP_PAD_SZ);
        if (ret)
                return ret;
 
        /* (address, ctrl) registers */
+       offset = offsetof(struct user_hwdebug_state, dbg_regs);
        limit = regset->n * regset->size;
        while (count && offset < limit) {
                ret = ptrace_hbp_get_addr(note_type, target, idx, &addr);
@@ -413,6 +427,13 @@ static int hw_break_get(struct task_struct *target,
                if (ret)
                        return ret;
                offset += PTRACE_HBP_CTRL_SZ;
+
+               ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+                                              offset,
+                                              offset + PTRACE_HBP_PAD_SZ);
+               if (ret)
+                       return ret;
+               offset += PTRACE_HBP_PAD_SZ;
                idx++;
        }
 
@@ -425,12 +446,13 @@ static int hw_break_set(struct task_struct *target,
                        const void *kbuf, const void __user *ubuf)
 {
        unsigned int note_type = regset->core_note_type;
-       int ret, idx = 0, offset = PTRACE_HBP_REG_OFF, limit;
+       int ret, idx = 0, offset, limit;
        u32 ctrl;
        u64 addr;
 
-       /* Resource info */
-       ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
+       /* Resource info and pad */
+       offset = offsetof(struct user_hwdebug_state, dbg_regs);
+       ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
        if (ret)
                return ret;
 
@@ -454,6 +476,13 @@ static int hw_break_set(struct task_struct *target,
                if (ret)
                        return ret;
                offset += PTRACE_HBP_CTRL_SZ;
+
+               ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                               offset,
+                                               offset + PTRACE_HBP_PAD_SZ);
+               if (ret)
+                       return ret;
+               offset += PTRACE_HBP_PAD_SZ;
                idx++;
        }
 
index 48ffb9fb3fe3619c6bc600452554e6e76b29ec51..7665a9bfdb1e53ebe689033eac02a78d8cf7ab99 100644 (file)
@@ -170,7 +170,19 @@ static void __init setup_machine_fdt(phys_addr_t dt_phys)
 
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
+       base &= PAGE_MASK;
        size &= PAGE_MASK;
+       if (base + size < PHYS_OFFSET) {
+               pr_warning("Ignoring memory block 0x%llx - 0x%llx\n",
+                          base, base + size);
+               return;
+       }
+       if (base < PHYS_OFFSET) {
+               pr_warning("Ignoring memory range 0x%llx - 0x%llx\n",
+                          base, PHYS_OFFSET);
+               size -= PHYS_OFFSET - base;
+               base = PHYS_OFFSET;
+       }
        memblock_add(base, size);
 }
 
index b711525be21fb0116ecdfacdeeb7d0d7ca89ec73..538300f2273d82420973a0697a6d145aef60366a 100644 (file)
@@ -46,7 +46,6 @@
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
-#include <asm/mmu_context.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
@@ -212,8 +211,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
         * before we continue.
         */
        set_cpu_online(cpu, true);
-       while (!cpu_active(cpu))
-               cpu_relax();
+       complete(&cpu_running);
 
        /*
         * OK, it's off to the idle thread for us
index 17948fc7d663b21269f3ae738ea545b0df9ceb09..ba457943a16b26f8fb3301ef2f65e192ccbe3c94 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/slab.h>
+#include <linux/timekeeper_internal.h>
 #include <linux/vmalloc.h>
 
 #include <asm/cacheflush.h>
@@ -222,11 +223,10 @@ struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
 /*
  * Update the vDSO data page to keep in sync with kernel timekeeping.
  */
-void update_vsyscall(struct timespec *ts, struct timespec *wtm,
-                    struct clocksource *clock, u32 mult)
+void update_vsyscall(struct timekeeper *tk)
 {
        struct timespec xtime_coarse;
-       u32 use_syscall = strcmp(clock->name, "arch_sys_counter");
+       u32 use_syscall = strcmp(tk->clock->name, "arch_sys_counter");
 
        ++vdso_data->tb_seq_count;
        smp_wmb();
@@ -237,13 +237,13 @@ void update_vsyscall(struct timespec *ts, struct timespec *wtm,
        vdso_data->xtime_coarse_nsec            = xtime_coarse.tv_nsec;
 
        if (!use_syscall) {
-               vdso_data->cs_cycle_last        = clock->cycle_last;
-               vdso_data->xtime_clock_sec      = ts->tv_sec;
-               vdso_data->xtime_clock_nsec     = ts->tv_nsec;
-               vdso_data->cs_mult              = mult;
-               vdso_data->cs_shift             = clock->shift;
-               vdso_data->wtm_clock_sec        = wtm->tv_sec;
-               vdso_data->wtm_clock_nsec       = wtm->tv_nsec;
+               vdso_data->cs_cycle_last        = tk->clock->cycle_last;
+               vdso_data->xtime_clock_sec      = tk->xtime_sec;
+               vdso_data->xtime_clock_nsec     = tk->xtime_nsec >> tk->shift;
+               vdso_data->cs_mult              = tk->mult;
+               vdso_data->cs_shift             = tk->shift;
+               vdso_data->wtm_clock_sec        = tk->wall_to_monotonic.tv_sec;
+               vdso_data->wtm_clock_nsec       = tk->wall_to_monotonic.tv_nsec;
        }
 
        smp_wmb();
index efbf7df05d3f6e2ffe4b6105b8cdb0e49a97ab1b..4cd28931dba95da0711a4aeabed694613febce5f 100644 (file)
@@ -80,7 +80,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
 #ifdef CONFIG_ZONE_DMA32
        /* 4GB maximum for 32-bit only capable devices */
        max_dma32 = min(max, MAX_DMA32_PFN);
-       zone_size[ZONE_DMA32] = max_dma32 - min;
+       zone_size[ZONE_DMA32] = max(min, max_dma32) - min;
 #endif
        zone_size[ZONE_NORMAL] = max - max_dma32;
 
index 06e73bf665e92cba042590dbe68a50a463d50f76..09f9fa800b33400d79ce08433c648936cdb1bfb6 100644 (file)
@@ -80,7 +80,6 @@ config PLATFORM_AT32AP
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_ALLOCATOR
        select HAVE_FB_ATMEL
-       select HAVE_NET_MACB
 
 #
 # CPU types
index a473f8c6a9aa2be66f04f375ef7b7820b7c0683a..486df68abeecc955757a352cf64e70ad9b39a020 100644 (file)
@@ -40,6 +40,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index ae52825021afd98237557656abf77dad4a75491f..b681b043f6c819fedc4b819c5ffa59a72cd7059f 100644 (file)
@@ -42,6 +42,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index b7412504f08a2c91635c6f75da624a59b6a6a953..df2eb4bd9fa2abbaa06c6978537fcabc88c22cf7 100644 (file)
@@ -13,6 +13,7 @@ config FRV
        select GENERIC_CPU_DEVICES
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
 
 config ZONE_DMA
        bool
index 6ae3254da01976b6fdaa374f588c3c58a081058c..636d5bbcd53f31ca5cbbb96ca9f3e29f501fdfff 100644 (file)
@@ -17,6 +17,8 @@ PARAMS_PHYS    = 0x0207c000
 INITRD_PHYS     = 0x02180000
 INITRD_VIRT     = 0x02180000
 
+OBJCOPYFLAGS   :=-O binary -R .note -R .note.gnu.build-id -R .comment
+
 #
 # If you don't define ZRELADDR above,
 # then it defaults to ZTEXTADDR
@@ -32,18 +34,18 @@ Image: $(obj)/Image
 targets: $(obj)/Image
 
 $(obj)/Image: vmlinux FORCE
-       $(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@
 
 #$(obj)/Image: $(CONFIGURE) $(SYSTEM)
-#      $(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@
+#      $(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@
 
 bzImage: zImage
 
 zImage:        $(CONFIGURE) compressed/$(LINUX)
-       $(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@
 
 bootpImage: bootp/bootp
-       $(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@
+       $(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@
 
 compressed/$(LINUX): $(LINUX) dep
        @$(MAKE) -C compressed $(LINUX)
index 266a5b25a0c1698347715c91fd45b7e95b8eb864..2358634caccaa6b50a8cad83fb0601e1350e71d0 100644 (file)
@@ -30,7 +30,6 @@
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_EXECVE
-#define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index a5b1d7dbb205389eef5e2d5627f0aad3744778fe..871f89b7fbdaf08a0629679f01d804337804cbc7 100644 (file)
@@ -40,6 +40,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME             28
 #define SO_TIMESTAMP           29
index 002732960315ee429d3cce6a95c8a0440064c64d..dfcd263c05176ea6cdbf3c169070a93fe79b8f5b 100644 (file)
@@ -867,13 +867,8 @@ ret_from_fork:
 ret_from_kernel_thread:
        lddi.p          @(gr28,#REG_GR(8)),gr20
        call            schedule_tail
-       or.p            gr20,gr20,gr8
-       calll           @(gr21,gr0)
-       bra             sys_exit
-
-       .globl          ret_from_kernel_execve
-ret_from_kernel_execve:
-       ori             gr28,0,sp
+       calll.p         @(gr21,gr0)
+       or              gr20,gr20,gr8
        bra             __syscall_exit
 
 ###################################################################################################
@@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:
        subicc          gr5,#0,gr0,icc0
        beq             icc0,#0,__entry_return_direct
 
-__entry_preempt_need_resched:
-       ldi             @(gr15,#TI_FLAGS),gr4
-       andicc          gr4,#_TIF_NEED_RESCHED,gr0,icc0
-       beq             icc0,#1,__entry_return_direct
-
-       setlos          #PREEMPT_ACTIVE,gr5
-       sti             gr5,@(gr15,#TI_FLAGS)
-
-       andi            gr23,#~PSR_PIL,gr23
-       movgs           gr23,psr
-
-       call            schedule
-       sti             gr0,@(gr15,#TI_PRE_COUNT)
-
-       movsg           psr,gr23
-       ori             gr23,#PSR_PIL_14,gr23
-       movgs           gr23,psr
-       bra             __entry_preempt_need_resched
-#else
-       bra             __entry_return_direct
+       subcc           gr0,gr0,gr0,icc2                /* set Z and clear C */
+       call            preempt_schedule_irq
 #endif
+       bra             __entry_return_direct
 
 
 ###############################################################################
index 655d90d20bb0cad25df015e7bdc9dee6dbf4e37b..7e33215f1d8fabfd28a1aa5c5144a8e73f621a90 100644 (file)
@@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,
        childregs = (struct pt_regs *)
                (task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);
 
+       /* set up the userspace frame (the only place that the USP is stored) */
+       *childregs = *__kernel_frame0_ptr;
+
        p->set_child_tid = p->clear_child_tid = NULL;
 
        p->thread.frame  = childregs;
@@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,
        p->thread.frame0 = childregs;
 
        if (unlikely(!regs)) {
-               memset(childregs, 0, sizeof(struct pt_regs));
                childregs->gr9 = usp; /* function */
                childregs->gr8 = arg;
-               chilregs->psr = PSR_S;
                p->thread.pc = (unsigned long) ret_from_kernel_thread;
                save_user_regs(p->thread.user);
                return 0;
index 1f1e5efb338514c17171b31c037427d1d5c5d5a4..b8993c87d3de8473d95141560fdb82aef0aa1085 100644 (file)
@@ -112,9 +112,11 @@ char __initdata redboot_command_line[COMMAND_LINE_SIZE];
 #ifdef CONFIG_PM
 #define __pminit
 #define __pminitdata
+#define __pminitconst
 #else
 #define __pminit __init
 #define __pminitdata __initdata
+#define __pminitconst __initconst
 #endif
 
 struct clock_cmode {
index e47857f889b6d2a18dcf839249bae5f7af66f334..b99c2a7cc7a41f6a0398c4a34715749d2a935afc 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/export.h>
 #include <linux/dma-mapping.h>
 #include <linux/list.h>
 #include <linux/pci.h>
index c6350283649d47ad3bfa50a8ef61f8f582896857..05887a1d80e5cc3755e995637e008fcf753deb94 100644 (file)
@@ -2,7 +2,8 @@
 #define __ARCH_H8300_CACHE_H
 
 /* bytes per L1 cache line */
-#define        L1_CACHE_BYTES  4
+#define        L1_CACHE_SHIFT  2
+#define        L1_CACHE_BYTES  (1 << L1_CACHE_SHIFT)
 
 /* m68k-elf-gcc  2.95.2 doesn't like these */
 
index ec4554e7b04b68ab4c41ad93e612469ac896708c..90a2e573c7e679ac92300734e3641f7d5d5b45e0 100644 (file)
@@ -40,6 +40,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME             28
 #define SO_TIMESTAMP           29
index 3364b6966d268b3f82fda0ae501be048b6d858c1..3bfa9b30f448b3f464d5087ba622f6dde4523446 100644 (file)
@@ -1,8 +1,5 @@
-include include/asm-generic/Kbuild.asm
 
-header-y += registers.h
 header-y += ucontext.h
-header-y += user.h
 
 generic-y += auxvec.h
 generic-y += bug.h
index 3e258043337b322a44322bfda4b2eb1f70595df5..468fbb0781cdfb9a4ebc6d2b1b2a7ccb16c55dd3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Atomic operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index a4ed6e26cb1df2948d4ac74132854ca3865d5665..1041a8e70ce85cea7e8b2d9372dbb8fef19c8496 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Memory barrier definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 4caa649ad78b06551120f7be0749e2e986892132..9b1e4afbab3c6530c2e28b0179ac0597ed567137 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Bit operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/arch/hexagon/include/asm/bitsperlong.h b/arch/hexagon/include/asm/bitsperlong.h
deleted file mode 100644 (file)
index 2701cae..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef __ASM_HEXAGON_BITSPERLONG_H
-#define __ASM_HEXAGON_BITSPERLONG_H
-
-#define __BITS_PER_LONG 32
-
-#include <asm-generic/bitsperlong.h>
-
-#endif
diff --git a/arch/hexagon/include/asm/byteorder.h b/arch/hexagon/include/asm/byteorder.h
deleted file mode 100644 (file)
index 0e19b9f..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_BYTEORDER_H
-#define _ASM_BYTEORDER_H
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#  define __BYTEORDER_HAS_U64__
-#endif
-
-#include <linux/byteorder/little_endian.h>
-
-#endif /* _ASM_BYTEORDER_H */
index 0f01de2eb4abf9fc8b6bc58d548c652782221ff5..f4ca594fdf8c258a13d1d2e99849a820041442f8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Cache definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 6865c1be927a1662bbf4c27148dfbadf7d0e6945..49e0896ec2401464f93ef32ba4f279d1ca88181c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Cache flush operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 3ce4ecd44f824c54502f8b2e39e7b636d3b663aa..46ec8a7fd65f876a0de86d36abd5392bf505c1c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index c5f9527e1df6983c4a7c90694781596377c64e13..9e7802911a57f22b01d9f6852d3c11b2f34c1869 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * xchg/cmpxchg operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 9ab12e9a872bcaf025396e09ef58384e3971f34c..53079719d6678d4105437986a371f901966a4c39 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 233ed3d2d25e61ede6d63ccff367f860c969f421..85e9935660cbaf70626f61bda3e6a4a3f60cc0ef 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DMA operations for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index da6d2f61a93a9ff2491f81cd677dd14c8d68631d..9e34ff49f3b7d22536c4c9111e885bdf105f344e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 82b499621e052f2a272cd137c81f23c84fe2ccf3..1ba4b3bff5edee550741adfb7762e6eb7f34bae2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ELF definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 350e6d497d44732edf3270609a965eb0e07322f5..c32b2132614bae75f7f0fbf1fee5906754d43e55 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Process execution related definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index b27f4941645b3fedefc9297b60795e07b46c9c3c..b75b6bf4269c6a3e2a3152f1402f5ae63cfd5a65 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Fixmap support for Hexagon - enough to support highmem features
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 182cb9d547691748075b632acd29878655a107a5..c144bee6cabe506afc9f99071ad741c9727da8d7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Declarations for to Hexagon Virtal Machine.
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 1c02186d2e9a18da7639248570e57bd91f2a49c5..ca587737fb2af875d5ee1edd21942092c9333182 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index b3acc2cc71bff7277cedb0dc32c5c291bc523d4b..e527cfeff5bac6dd18473deb1930ffc77034c13f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * IO definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index ded8c15cf3e50548348f13acde7bcbe33871536c..51661db389d6f0c9f14cdecdc57f60a45408a790 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index ec1523655416f641cae39ca3a98afb20db960104..e5fd9492d60fbcdc65259e1f6d38d62dbeea6ac6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * IRQ support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 9e8779702f100b0dd651871738ed332bf90b2eea..32a6fb66944a96e889a2b861d0f461b3a115d332 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/hexagon/include/asm/kgdb.h - Hexagon KGDB Support
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. 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
diff --git a/arch/hexagon/include/asm/kvm_para.h b/arch/hexagon/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
index a00b85f680b8f0ef63386623f9b7fbe05110bbce..31b4cbe7e5831c3c9e59d6b874a749c0f5ba0423 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 72e5dcda79f5078ad227445eaa0ce480d3efa4f4..af16e977c55ee4a43cb56e0087c13935640541cf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Memory layout definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 30a5d8d2659d9f4acf1ba7bb0ee06208673746e5..2288b19fd0f2d09cf3107419fac8d05775053ea3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index b4fe5a5411b6f9cba29a590a68b5fa879cdbd82e..d423d2e73c3088d428e1a48de233d2f0d752dc05 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * MM context support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 72ba494e6d7d5e2e8452465e6eb5ec8947e9aedd..6b4323acef44161a0970d00473029b96e9d52613 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index edd97626c482eb3b3e71e74f75699b55eebe9cf9..692adc213429a3e2d85a6c7955e43d54ba62261e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Page management definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
diff --git a/arch/hexagon/include/asm/param.h b/arch/hexagon/include/asm/param.h
deleted file mode 100644 (file)
index 285344b..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_PARAM_H
-#define _ASM_PARAM_H
-
-#define EXEC_PAGESIZE  16384
-
-#include <asm-generic/param.h>
-
-#endif
index 8b8526b491c7ae8d57a10583d8e23d7cedb56d2e..430978b1de381a54aeb09732541138aa8879056b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 13443c7751315e3b8e7c25e1b0f28ab8da6fa3d5..679bf6d664871377ef33a7c16f5cb6b25169c253 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Page table support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index ca619bf225ef3d5402c02fe0c5ce65b7843c8a7b..20d55f69fe5571cd6a32a1515dbf1db7eb70db61 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Page table support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index e8ea459002a4cf6adfc824092c87b94a5cacc891..a03323ab9d44040a3db7902b1215615ff9fc5ef2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Process/processor support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
diff --git a/arch/hexagon/include/asm/ptrace.h b/arch/hexagon/include/asm/ptrace.h
deleted file mode 100644 (file)
index 3d2f607..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Ptrace definitions for the Hexagon architecture
- *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_PTRACE_H
-#define _ASM_PTRACE_H
-
-#include <asm/registers.h>
-
-#define instruction_pointer(regs) pt_elr(regs)
-#define user_stack_pointer(regs) ((regs)->r29)
-
-#define profile_pc(regs) instruction_pointer(regs)
-
-/* kprobe-based event tracer support */
-extern int regs_query_register_offset(const char *name);
-extern const char *regs_query_register_name(unsigned int offset);
-
-#endif
diff --git a/arch/hexagon/include/asm/registers.h b/arch/hexagon/include/asm/registers.h
deleted file mode 100644 (file)
index 4dd741b..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Register definitions for the Hexagon architecture
- *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_REGISTERS_H
-#define _ASM_REGISTERS_H
-
-#define SP r29
-
-#ifndef __ASSEMBLY__
-
-/*  See kernel/entry.S for further documentation.  */
-
-/*
- * Entry code copies the event record out of guest registers into
- * this structure (which is on the stack).
- */
-
-struct hvm_event_record {
-       unsigned long vmel;     /* Event Linkage (return address) */
-       unsigned long vmest;    /* Event context - pre-event SSR values */
-       unsigned long vmpsp;    /* Previous stack pointer */
-       unsigned long vmbadva;  /* Bad virtual address for addressing events */
-};
-
-struct pt_regs {
-       long restart_r0;        /* R0 checkpoint for syscall restart */
-       long syscall_nr;        /* Only used in system calls */
-       union {
-               struct {
-                       unsigned long usr;
-                       unsigned long preds;
-               };
-               long long int predsusr;
-       };
-       union {
-               struct {
-                       unsigned long m0;
-                       unsigned long m1;
-               };
-               long long int m1m0;
-       };
-       union {
-               struct {
-                       unsigned long sa1;
-                       unsigned long lc1;
-               };
-               long long int lc1sa1;
-       };
-       union {
-               struct {
-                       unsigned long sa0;
-                       unsigned long lc0;
-               };
-               long long int lc0sa0;
-       };
-       union {
-               struct {
-                       unsigned long gp;
-                       unsigned long ugp;
-               };
-               long long int ugpgp;
-       };
-       /*
-       * Be extremely careful with rearranging these, if at all.  Some code
-       * assumes the 32 registers exist exactly like this in memory;
-       * e.g. kernel/ptrace.c
-       * e.g. kernel/signal.c (restore_sigcontext)
-       */
-       union {
-               struct {
-                       unsigned long r00;
-                       unsigned long r01;
-               };
-               long long int r0100;
-       };
-       union {
-               struct {
-                       unsigned long r02;
-                       unsigned long r03;
-               };
-               long long int r0302;
-       };
-       union {
-               struct {
-                       unsigned long r04;
-                       unsigned long r05;
-               };
-               long long int r0504;
-       };
-       union {
-               struct {
-                       unsigned long r06;
-                       unsigned long r07;
-               };
-               long long int r0706;
-       };
-       union {
-               struct {
-                       unsigned long r08;
-                       unsigned long r09;
-               };
-               long long int r0908;
-       };
-       union {
-              struct {
-                       unsigned long r10;
-                       unsigned long r11;
-              };
-              long long int r1110;
-       };
-       union {
-              struct {
-                       unsigned long r12;
-                       unsigned long r13;
-              };
-              long long int r1312;
-       };
-       union {
-              struct {
-                       unsigned long r14;
-                       unsigned long r15;
-              };
-              long long int r1514;
-       };
-       union {
-               struct {
-                       unsigned long r16;
-                       unsigned long r17;
-               };
-               long long int r1716;
-       };
-       union {
-               struct {
-                       unsigned long r18;
-                       unsigned long r19;
-               };
-               long long int r1918;
-       };
-       union {
-               struct {
-                       unsigned long r20;
-                       unsigned long r21;
-               };
-               long long int r2120;
-       };
-       union {
-               struct {
-                       unsigned long r22;
-                       unsigned long r23;
-               };
-               long long int r2322;
-       };
-       union {
-               struct {
-                       unsigned long r24;
-                       unsigned long r25;
-               };
-               long long int r2524;
-       };
-       union {
-               struct {
-                       unsigned long r26;
-                       unsigned long r27;
-               };
-               long long int r2726;
-       };
-       union {
-               struct {
-                       unsigned long r28;
-                       unsigned long r29;
-              };
-              long long int r2928;
-       };
-       union {
-               struct {
-                       unsigned long r30;
-                       unsigned long r31;
-               };
-               long long int r3130;
-       };
-       /* VM dispatch pushes event record onto stack - we can build on it */
-       struct hvm_event_record hvmer;
-};
-
-/* Defines to conveniently access the values  */
-
-/*
- * As of the VM spec 0.5, these registers are now set/retrieved via a
- * VM call.  On the in-bound side, we just fetch the values
- * at the entry points and stuff them into the old record in pt_regs.
- * However, on the outbound side, probably at VM rte, we set the
- * registers back.
- */
-
-#define pt_elr(regs) ((regs)->hvmer.vmel)
-#define pt_set_elr(regs, val) ((regs)->hvmer.vmel = (val))
-#define pt_cause(regs) ((regs)->hvmer.vmest & (HVM_VMEST_CAUSE_MSK))
-#define user_mode(regs) \
-       (((regs)->hvmer.vmest & (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT)) != 0)
-#define ints_enabled(regs) \
-       (((regs)->hvmer.vmest & (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)) != 0)
-#define pt_psp(regs) ((regs)->hvmer.vmpsp)
-#define pt_badva(regs) ((regs)->hvmer.vmbadva)
-
-#define pt_set_rte_sp(regs, sp) do {\
-       pt_psp(regs) = (sp);\
-       (regs)->SP = (unsigned long) &((regs)->hvmer);\
-       } while (0)
-
-#define pt_set_kmode(regs) \
-       (regs)->hvmer.vmest = (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
-
-#define pt_set_usermode(regs) \
-       (regs)->hvmer.vmest = (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT) \
-                           | (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
-
-#endif  /*  ifndef __ASSEMBLY  */
-
-#endif
diff --git a/arch/hexagon/include/asm/setup.h b/arch/hexagon/include/asm/setup.h
deleted file mode 100644 (file)
index 3b754c5..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_SETUP_H
-#define _ASM_SETUP_H
-
-#include <linux/init.h>
-#include <asm-generic/setup.h>
-
-extern char external_cmdline_buffer;
-
-void __init setup_arch_memory(void);
-
-#endif
diff --git a/arch/hexagon/include/asm/sigcontext.h b/arch/hexagon/include/asm/sigcontext.h
deleted file mode 100644 (file)
index ce6dcd9..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_SIGCONTEXT_H
-#define _ASM_SIGCONTEXT_H
-
-#include <asm/user.h>
-
-/*
- * Signal context structure - contains all info to do with the state
- * before the signal handler was invoked.  Note: only add new entries
- * to the end of the structure.
- */
-struct sigcontext {
-       struct user_regs_struct sc_regs;
-} __aligned(8);
-
-#endif
diff --git a/arch/hexagon/include/asm/signal.h b/arch/hexagon/include/asm/signal.h
deleted file mode 100644 (file)
index 471c056..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_SIGNAL_H
-#define _ASM_SIGNAL_H
-
-extern unsigned long __rt_sigtramp_template[2];
-
-#include <asm-generic/signal.h>
-
-#endif
index 87c869a6a897d9e52a17d5f75e0886252458c5fa..2b9b974e09522bcbaac7e0e4deac5935694d31e0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SMP definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 168a920485a85973d1e78ec4406eacbdd6e9a675..12ca4ebc033855c93879c81bafc65af93b9bde97 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Spinlock support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 99b5a7575c21416449c856e17e9a85b15088a6fc..7a906b5214a430602b851775388057bfbc9b59c3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Spinlock support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index f4489c15942c39cd905eef8760135b69dd371c80..7d37f47a1d070213c9ffbf1c8c2ba6047ffb9958 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 089dd82687919b827f03748cf2bf1c59b9947d73..18b44b557fbc0cf08833bf9ca0ffb795cb1f10cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
diff --git a/arch/hexagon/include/asm/swab.h b/arch/hexagon/include/asm/swab.h
deleted file mode 100644 (file)
index 99cf0be..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef _ASM_SWAB_H
-#define _ASM_SWAB_H
-
-#define __SWAB_64_THRU_32__
-
-#endif
index 28ca0dfb6064fc97d9e414f8ea93e5091ba561b1..96745e7b3e3ca5c02119d206eb82f8f1049eebcc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Task switching definitions for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 3e7d61d38d9761f076c70ccb9dc329ed390c3558..fb0e9d48faa668fe62dc174ac13bf3b5b8a67c87 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Syscall support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index e4a0aad69cbbb0164bbe3cbbb007aade36c31df7..f7c32406a711a5b619d53037fe76d8689107e3c6 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Thread support for the Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 081b82cac9a9d18d02c343d0c42d9878c7115bf6..deda170c03b8ccc8bb336bbb86318534ca424506 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index d80db239a7b6a341f591da7bb237b2daea3b94cb..79912b8c1e5baef2f47c9ebf4135797d60e4136f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Timer support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index b11c62b23f31050f285bbc1f5723d3a840fb2bde..f63fe132f072ca8323a63d9363178a513d7a28a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 473abde01d62aa4e7a4c5cf5a7105730da69c781..2f00772cc08a551df873985b29647ac388fb1e55 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index b89a90251225aa74a9daba05f21b6827fd1901ee..62d95a9705c4a319f3ba750bc58a3af702b1618e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * TLB flush support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 6a407f6e5e24bac942576b048e1a726771446578..ec11285012cf1d3e82943c6c777190acde5a2772 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Trap support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 7e706eadbf0a2f7f80a10fd5e79bc5de994c634c..e4127e4d6a5bbde7f1d0ec42017df98353177c93 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User memory access support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
diff --git a/arch/hexagon/include/asm/unistd.h b/arch/hexagon/include/asm/unistd.h
deleted file mode 100644 (file)
index c0d5565..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Syscall support for Hexagon
- *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-/*
- *  The kernel pulls this unistd.h in three different ways:
- *  1.  the "normal" way which gets all the __NR defines
- *  2.  with __SYSCALL defined to produce function declarations
- *  3.  with __SYSCALL defined to produce syscall table initialization
- *  See also:  syscalltab.c
- */
-
-#define sys_mmap2 sys_mmap_pgoff
-
-#include <asm-generic/unistd.h>
diff --git a/arch/hexagon/include/asm/user.h b/arch/hexagon/include/asm/user.h
deleted file mode 100644 (file)
index 3a55078..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifndef HEXAGON_ASM_USER_H
-#define HEXAGON_ASM_USER_H
-
-/*
- * Layout for registers passed in elf core dumps to userspace.
- *
- * Basically a rearranged subset of "pt_regs".
- *
- * Interested parties:  libc, gdb...
- */
-
-struct user_regs_struct {
-       unsigned long r0;
-       unsigned long r1;
-       unsigned long r2;
-       unsigned long r3;
-       unsigned long r4;
-       unsigned long r5;
-       unsigned long r6;
-       unsigned long r7;
-       unsigned long r8;
-       unsigned long r9;
-       unsigned long r10;
-       unsigned long r11;
-       unsigned long r12;
-       unsigned long r13;
-       unsigned long r14;
-       unsigned long r15;
-       unsigned long r16;
-       unsigned long r17;
-       unsigned long r18;
-       unsigned long r19;
-       unsigned long r20;
-       unsigned long r21;
-       unsigned long r22;
-       unsigned long r23;
-       unsigned long r24;
-       unsigned long r25;
-       unsigned long r26;
-       unsigned long r27;
-       unsigned long r28;
-       unsigned long r29;
-       unsigned long r30;
-       unsigned long r31;
-       unsigned long sa0;
-       unsigned long lc0;
-       unsigned long sa1;
-       unsigned long lc1;
-       unsigned long m0;
-       unsigned long m1;
-       unsigned long usr;
-       unsigned long p3_0;
-       unsigned long gp;
-       unsigned long ugp;
-       unsigned long pc;
-       unsigned long cause;
-       unsigned long badva;
-       unsigned long pad1;  /* pad out to 48 words total */
-       unsigned long pad2;  /* pad out to 48 words total */
-       unsigned long pad3;  /* pad out to 48 words total */
-};
-
-#endif
index 2d95cbba3572cac44663978261d5ea3be6091284..ed08e6c6886d8774e4f892419b2eae25561bbaa9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vDSO implementation for Hexagon
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. 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
index cacda36ef5d5cd2ccb44fe6f843bb1de857b1387..9b0e9c50ceda4bc09e94c4376bfcec1746b7529b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 580462de5cca35eb2c0b1e011708d3322e844307..9a94de7969bb5e192f57bb9d5bc6ca877376f23c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hexagon VM page table entry definitions
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index baebb3da1d44160fc6f6f259886656e6f494b167..c31706c38631b75779b0f472667d5f01fe2c0936 100644 (file)
@@ -1,3 +1,15 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += kvm_para.h
+header-y += param.h
+header-y += ptrace.h
+header-y += registers.h
+header-y += setup.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += swab.h
+header-y += unistd.h
+header-y += user.h
diff --git a/arch/hexagon/include/uapi/asm/bitsperlong.h b/arch/hexagon/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..4a65815
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ASM_HEXAGON_BITSPERLONG_H
+#define __ASM_HEXAGON_BITSPERLONG_H
+
+#define __BITS_PER_LONG 32
+
+#include <asm-generic/bitsperlong.h>
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/byteorder.h b/arch/hexagon/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..e31f3f7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_BYTEORDER_H
+#define _ASM_BYTEORDER_H
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#endif
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _ASM_BYTEORDER_H */
diff --git a/arch/hexagon/include/uapi/asm/kvm_para.h b/arch/hexagon/include/uapi/asm/kvm_para.h
new file mode 100644 (file)
index 0000000..14fab8f
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/kvm_para.h>
diff --git a/arch/hexagon/include/uapi/asm/param.h b/arch/hexagon/include/uapi/asm/param.h
new file mode 100644 (file)
index 0000000..5cec8c0
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PARAM_H
+#define _ASM_PARAM_H
+
+#define EXEC_PAGESIZE  16384
+
+#include <asm-generic/param.h>
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/ptrace.h b/arch/hexagon/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..8ef7840
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Ptrace definitions for the Hexagon architecture
+ *
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_PTRACE_H
+#define _ASM_PTRACE_H
+
+#include <asm/registers.h>
+
+#define instruction_pointer(regs) pt_elr(regs)
+#define user_stack_pointer(regs) ((regs)->r29)
+
+#define profile_pc(regs) instruction_pointer(regs)
+
+/* kprobe-based event tracer support */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/registers.h b/arch/hexagon/include/uapi/asm/registers.h
new file mode 100644 (file)
index 0000000..c20406f
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Register definitions for the Hexagon architecture
+ */
+
+
+#ifndef _ASM_REGISTERS_H
+#define _ASM_REGISTERS_H
+
+#define SP r29
+
+#ifndef __ASSEMBLY__
+
+/*  See kernel/entry.S for further documentation.  */
+
+/*
+ * Entry code copies the event record out of guest registers into
+ * this structure (which is on the stack).
+ */
+
+struct hvm_event_record {
+       unsigned long vmel;     /* Event Linkage (return address) */
+       unsigned long vmest;    /* Event context - pre-event SSR values */
+       unsigned long vmpsp;    /* Previous stack pointer */
+       unsigned long vmbadva;  /* Bad virtual address for addressing events */
+};
+
+struct pt_regs {
+       long restart_r0;        /* R0 checkpoint for syscall restart */
+       long syscall_nr;        /* Only used in system calls */
+       union {
+               struct {
+                       unsigned long usr;
+                       unsigned long preds;
+               };
+               long long int predsusr;
+       };
+       union {
+               struct {
+                       unsigned long m0;
+                       unsigned long m1;
+               };
+               long long int m1m0;
+       };
+       union {
+               struct {
+                       unsigned long sa1;
+                       unsigned long lc1;
+               };
+               long long int lc1sa1;
+       };
+       union {
+               struct {
+                       unsigned long sa0;
+                       unsigned long lc0;
+               };
+               long long int lc0sa0;
+       };
+       union {
+               struct {
+                       unsigned long gp;
+                       unsigned long ugp;
+               };
+               long long int ugpgp;
+       };
+       /*
+       * Be extremely careful with rearranging these, if at all.  Some code
+       * assumes the 32 registers exist exactly like this in memory;
+       * e.g. kernel/ptrace.c
+       * e.g. kernel/signal.c (restore_sigcontext)
+       */
+       union {
+               struct {
+                       unsigned long r00;
+                       unsigned long r01;
+               };
+               long long int r0100;
+       };
+       union {
+               struct {
+                       unsigned long r02;
+                       unsigned long r03;
+               };
+               long long int r0302;
+       };
+       union {
+               struct {
+                       unsigned long r04;
+                       unsigned long r05;
+               };
+               long long int r0504;
+       };
+       union {
+               struct {
+                       unsigned long r06;
+                       unsigned long r07;
+               };
+               long long int r0706;
+       };
+       union {
+               struct {
+                       unsigned long r08;
+                       unsigned long r09;
+               };
+               long long int r0908;
+       };
+       union {
+              struct {
+                       unsigned long r10;
+                       unsigned long r11;
+              };
+              long long int r1110;
+       };
+       union {
+              struct {
+                       unsigned long r12;
+                       unsigned long r13;
+              };
+              long long int r1312;
+       };
+       union {
+              struct {
+                       unsigned long r14;
+                       unsigned long r15;
+              };
+              long long int r1514;
+       };
+       union {
+               struct {
+                       unsigned long r16;
+                       unsigned long r17;
+               };
+               long long int r1716;
+       };
+       union {
+               struct {
+                       unsigned long r18;
+                       unsigned long r19;
+               };
+               long long int r1918;
+       };
+       union {
+               struct {
+                       unsigned long r20;
+                       unsigned long r21;
+               };
+               long long int r2120;
+       };
+       union {
+               struct {
+                       unsigned long r22;
+                       unsigned long r23;
+               };
+               long long int r2322;
+       };
+       union {
+               struct {
+                       unsigned long r24;
+                       unsigned long r25;
+               };
+               long long int r2524;
+       };
+       union {
+               struct {
+                       unsigned long r26;
+                       unsigned long r27;
+               };
+               long long int r2726;
+       };
+       union {
+               struct {
+                       unsigned long r28;
+                       unsigned long r29;
+              };
+              long long int r2928;
+       };
+       union {
+               struct {
+                       unsigned long r30;
+                       unsigned long r31;
+               };
+               long long int r3130;
+       };
+       /* VM dispatch pushes event record onto stack - we can build on it */
+       struct hvm_event_record hvmer;
+};
+
+/* Defines to conveniently access the values  */
+
+/*
+ * As of the VM spec 0.5, these registers are now set/retrieved via a
+ * VM call.  On the in-bound side, we just fetch the values
+ * at the entry points and stuff them into the old record in pt_regs.
+ * However, on the outbound side, probably at VM rte, we set the
+ * registers back.
+ */
+
+#define pt_elr(regs) ((regs)->hvmer.vmel)
+#define pt_set_elr(regs, val) ((regs)->hvmer.vmel = (val))
+#define pt_cause(regs) ((regs)->hvmer.vmest & (HVM_VMEST_CAUSE_MSK))
+#define user_mode(regs) \
+       (((regs)->hvmer.vmest & (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT)) != 0)
+#define ints_enabled(regs) \
+       (((regs)->hvmer.vmest & (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)) != 0)
+#define pt_psp(regs) ((regs)->hvmer.vmpsp)
+#define pt_badva(regs) ((regs)->hvmer.vmbadva)
+
+#define pt_set_rte_sp(regs, sp) do {\
+       pt_psp(regs) = (sp);\
+       (regs)->SP = (unsigned long) &((regs)->hvmer);\
+       } while (0)
+
+#define pt_set_kmode(regs) \
+       (regs)->hvmer.vmest = (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#define pt_set_usermode(regs) \
+       (regs)->hvmer.vmest = (HVM_VMEST_UM_MSK << HVM_VMEST_UM_SFT) \
+                           | (HVM_VMEST_IE_MSK << HVM_VMEST_IE_SFT)
+
+#endif  /*  ifndef __ASSEMBLY  */
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/setup.h b/arch/hexagon/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..e48285e
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SETUP_H
+#define _ASM_SETUP_H
+
+#include <linux/init.h>
+#include <asm-generic/setup.h>
+
+extern char external_cmdline_buffer;
+
+void __init setup_arch_memory(void);
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/sigcontext.h b/arch/hexagon/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..b6ba536
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
+
+#include <asm/user.h>
+
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+       struct user_regs_struct sc_regs;
+} __aligned(8);
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/signal.h b/arch/hexagon/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..9395568
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SIGNAL_H
+#define _ASM_SIGNAL_H
+
+extern unsigned long __rt_sigtramp_template[2];
+
+#include <asm-generic/signal.h>
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/swab.h b/arch/hexagon/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..9069e92
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+#define __SWAB_64_THRU_32__
+
+#endif
diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..81312d6
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Syscall support for Hexagon
+ *
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/*
+ *  The kernel pulls this unistd.h in three different ways:
+ *  1.  the "normal" way which gets all the __NR defines
+ *  2.  with __SYSCALL defined to produce function declarations
+ *  3.  with __SYSCALL defined to produce syscall table initialization
+ *  See also:  syscalltab.c
+ */
+
+#define sys_mmap2 sys_mmap_pgoff
+
+#include <asm-generic/unistd.h>
diff --git a/arch/hexagon/include/uapi/asm/user.h b/arch/hexagon/include/uapi/asm/user.h
new file mode 100644 (file)
index 0000000..cef13ee
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef HEXAGON_ASM_USER_H
+#define HEXAGON_ASM_USER_H
+
+/*
+ * Layout for registers passed in elf core dumps to userspace.
+ *
+ * Basically a rearranged subset of "pt_regs".
+ *
+ * Interested parties:  libc, gdb...
+ */
+
+struct user_regs_struct {
+       unsigned long r0;
+       unsigned long r1;
+       unsigned long r2;
+       unsigned long r3;
+       unsigned long r4;
+       unsigned long r5;
+       unsigned long r6;
+       unsigned long r7;
+       unsigned long r8;
+       unsigned long r9;
+       unsigned long r10;
+       unsigned long r11;
+       unsigned long r12;
+       unsigned long r13;
+       unsigned long r14;
+       unsigned long r15;
+       unsigned long r16;
+       unsigned long r17;
+       unsigned long r18;
+       unsigned long r19;
+       unsigned long r20;
+       unsigned long r21;
+       unsigned long r22;
+       unsigned long r23;
+       unsigned long r24;
+       unsigned long r25;
+       unsigned long r26;
+       unsigned long r27;
+       unsigned long r28;
+       unsigned long r29;
+       unsigned long r30;
+       unsigned long r31;
+       unsigned long sa0;
+       unsigned long lc0;
+       unsigned long sa1;
+       unsigned long lc1;
+       unsigned long m0;
+       unsigned long m1;
+       unsigned long usr;
+       unsigned long p3_0;
+       unsigned long gp;
+       unsigned long ugp;
+       unsigned long pc;
+       unsigned long cause;
+       unsigned long badva;
+       unsigned long pad1;  /* pad out to 48 words total */
+       unsigned long pad2;  /* pad out to 48 words total */
+       unsigned long pad3;  /* pad out to 48 words total */
+};
+
+#endif
index 89ffa514611f51754ef1ed3fe3c33e1149ac3f5b..2d5e84d3b00d69a738eb52e90388a184fb790d54 100644 (file)
@@ -5,7 +5,7 @@
  * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  * Copyright (C) 2000 MIPS Technologies, Inc.
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 2b48751aa5f75848c0e4d7674c412a479390ac5a..65c7bdcf565ef94b02882a30a6be129075cee511 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DMA implementation for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 8e6b819125a3e8f10760e2a6f9bef5c6a28431ec..d859402c73bac00251cfde0109ce6a42bab7bf72 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Early kernel startup code for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 7f1892471805c189e49798c513a468dc05a40086..32b1379d68772a7077929d6bb95f7ea09590458b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Export of symbols defined in assembly files and/or libgcc.
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index d4416a1a431ed77ee06aedf6de65bdc93e1a07ed..85883e1fdc12e950898239ba1f608934e5fe225f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * First-level interrupt controller model for Hexagon.
  *
- * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index fe4aa1bcca503fc5ad67c682f671065503b0cb9b..344645370646bfdb91ffa1e21c0a9a93e060ab52 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/hexagon/kernel/kgdb.c - Hexagon KGDB Support
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. 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
index 61a76bae3668e61be566c3dd4c08d2decac1f53b..477d07a5646c59691a9603dd9069ce3dac8eb1de 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Kernel module loader for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index af51de63b8359fface711d6b89424afc7f2d937d..9f6d7411b5747d87901e59733c1d1646ec72d631 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Process creation support for Hexagon
  *
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. 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
index 96c3b2c4dbaded2a24bb0c62a13a5f669637c90d..670b1b0bee63bf740e5979a28a12298b8b8084a8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Ptrace support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 4d72fc58e9b18f4e2ad804ddbf2681dfe4d4e1f0..6aeabc962b3b41348ea84e55970d4b2db67cd25d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 1202f78d25cb9ab8ca08f6ea339546424f20b497..94a38783500870f06945f993e0840fbc01b0cb75 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Arch related setup for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 1ea16bec7b91385ca9bb9de3563d44e0958546af..5047b8b879c02376f44c9b06114ce1facde7b013 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Signal support for Hexagon processor
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 149fbefc1a4d36988d6f5ce3422aaac57d029b60..8e095dffd070da9b57fa03ab67b93014013e7e0d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SMP support for Hexagon
  *
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. 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
index 11c597b2ac59ef2ac3b3c0e731170758d13b9081..f94918b449a8aa4258a5f04cc98c7b42b1b27fda 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Stacktrace support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 25a9bfe3445d941f3386e05dd8ae5c0c2ece0f95..319fa6494f58cd70c8823619fce09972e9846af3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hexagon system calls
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index c550f4177ab84f8e9875c784cab2a49b8902347c..7024b1ddc08a3f1519fb8ce347da44b7617d0a28 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * System call table for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 36ba641857112e1382579d16bd8badf1942115ae..9903fad997f3e2dc210b85905e832d268df31b5b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Time related functions for Hexagon architecture
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index ba4475184432b86245e8f6677fbc8cfad3ae2840..352f27e809fdde4bfb99a640f7656ad65eb9bb70 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * CPU topology for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 06c36c036b981edb77b2d66598281a50c8418080..18110a9056b02b0ec47150f5cd6915481102468e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index f08857d0715b87d3162d4fcd2fbadfad68df0e3b..a41eeb8eeaa1a7734e7d170ec679c1438e70adc9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Kernel traps/events for Hexagon processor
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 5d39f42f7085bb1fec3c44a101dceb3615c0cc2d..0bf5a87e4d0a9b7f5e57a2831fbb81118285549d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * vDSO implementation for Hexagon
  *
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. 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
index 5b99066cbc8d40d118ed2d688ee3b50b0cd4b721..cd71673ac25983cebe108f19a58efd656a523b03 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Event entry/exit for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 591fc1b68635e00b86bb2ba73134d2e71d5c0125..9b5a4a295a68ba1afbec0f636c58ed072e02a013 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Mostly IRQ support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index aebb35b6465e914531f081aeeeea0ebfe6e80e95..80967f2192b37aee002b0f05c0aff64cd5e02f16 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Initial page table for Linux kernel under Hexagon VM,
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 24d7fcac4ff262808b23beb83e3ee561eebf4b3e..9fb77b3f6cf2950391c0eedf980187ce3f357c85 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hexagon VM instruction support
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 0decf2f58e3202f8857d2147fe876e7817d2a3ec..62c6df91b3bb3f64523d5551082ce47db20b80ab 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Context switch support for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 97a4b50b00dfce0f2fff21473a40bfbc91517d10..620f42cc582a17180083058a001d3464b57ac907 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Event jump tables
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 071d3c30edfbe60da04634d33b0a0ec41a170ef1..14e793f6abbfff6a4313720710646826233be8ea 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Linker script for Hexagon kernel
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 93005522d52b1af1c15a47262519262986e50fde..8169f78a46a70f5bc0359b4fa006070772116d59 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Checksum functions for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 8ae47ba0e7057fe3c70897bd29ae49c1f374c1eb..885c9626d5e08b4a9472359419beba4bfbf8d972 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * I/O access functions for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 2101c339566524ea44b68947f21790674e6dac20..81c561c4b4d606ee7159f18742a2d5fe4c81b20d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  *
  *
  * This program is free software; you can redistribute it and/or modify
index 26d961439ab0c8de3d717a26c3f75c598c8f4c82..9341889ea3f67877e64819fdd43e26301838a2b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011, The Linux Foundation. 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
index c5cf6ee2758777de0d948b55eb315fe8cfd3d7af..fe14ccf285613c39f8801a8ca29389c5df6afa44 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Cache management functions for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 8eb1d4d61a3d55118c29b120890049a185853d08..7fc94f3e66425b8d3020e808420cda7b9b78ba58 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User memory copy functions for kernel
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index cb9740ed9e7dd867672e3fbf0b54beeb9f3c1570..0cfbcc09d1d942d47aa594b90f773de80a971372 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User memory copying routines for the Hexagon Kernel
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 08d7d7b23daa70f70e4f3edc75be620254cffdbd..254d8cc766bb9f7746425c83326ef2290e43d57c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index b57d741750b22225d9c20cf287306161e8ba4246..69ffcfd2879450de9fd16538be3d4acc7ee9e5f7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Memory subsystem initialization for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 3a37bc3b01163b02b3c96dcd21f4f0d69f465d5b..5905fd5f97f666fa9379c7860699fe9bf8807407 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * I/O remap functions for Hexagon
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index b175e2d42b895aaf3d27e62fc3a2c0fa3c52e8e9..19760a4611d97a7e7eed513d411436d3e1eae03b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 5c6a16c7c72ac9527e6858fd82f17428524fba5b..0eecb7a768fe0edd87ece9e8b9c55974ab9e74b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * User string length functions for kernel
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index e748108b47a7f7a8c93350137874eae96866a677..34127261c2b7124d4fc43e36ddb7bb84dcf7900b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 513b74cb397eb4dffab84d240367f2e71d8a4263..308ef0ce648baeb77ed933a6c30de55a94d96438 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Memory fault handling for Hexagon
  *
- * Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index c6ff415754615dd5be37bc032823c2b9e8dd0845..9647d00cb761002c3d4370df41785b740f6c980c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hexagon Virtual Machine TLB functions
  *
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2011, The Linux Foundation. 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
index 4a159da23633dbf359c9886513958ce49e842ce7..dd02f09b6eda6e2b41f1dd643a6ff550625a15e0 100644 (file)
@@ -1,3 +1,4 @@
 
 generic-y += clkdev.h
 generic-y += exec.h
+generic-y += kvm_para.h
diff --git a/arch/ia64/include/asm/kvm_para.h b/arch/ia64/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 47c00f9..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2007 Xiantao Zhang <xiantao.zhang@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- *
- */
-#ifndef __IA64_KVM_PARA_H
-#define __IA64_KVM_PARA_H
-
-#include <uapi/asm/kvm_para.h>
-
-
-static inline unsigned int kvm_arch_para_features(void)
-{
-       return 0;
-}
-
-static inline bool kvm_check_and_clear_guest_paused(void)
-{
-       return false;
-}
-
-#endif
index 30cafac937030ab7f174252949a05948a153b0ef..1b3f5eb5fcdb4566d66f5bd09f4d0b2ffb161926 100644 (file)
@@ -1,6 +1,8 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+generic-y += kvm_para.h
+
 header-y += auxvec.h
 header-y += bitsperlong.h
 header-y += break.h
diff --git a/arch/ia64/include/uapi/asm/kvm_para.h b/arch/ia64/include/uapi/asm/kvm_para.h
deleted file mode 100644 (file)
index e69de29..0000000
index 41fc28a4a18a2305763db7be6e0d51210671030e..23d6759bb57b8dd6af9a824e78ce7335dede1d80 100644 (file)
@@ -49,6 +49,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER       26
 #define SO_DETACH_FILTER       27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index acd5b68e887128e90f8e59530d77dc3985bf1e97..082e383c1b6f22dc8370fdac789489acbb04ffba 100644 (file)
@@ -637,7 +637,6 @@ mem_init (void)
 
        high_memory = __va(max_low_pfn * PAGE_SIZE);
 
-       reset_zone_present_pages();
        for_each_online_pgdat(pgdat)
                if (pgdat->bdata->node_bootmem_map)
                        totalram_pages += free_all_bootmem_node(pgdat);
index a15f40b527834256eababa34dd23d076cf003e2d..5e7088a26726cc0133ae3a6f166f3597832646a6 100644 (file)
@@ -40,6 +40,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index ecb540810ab3ace200ae66368d700d97b4abf0d2..88fa3ac86fae9af988331112cba87ff711eb3555 100644 (file)
@@ -1,5 +1,3 @@
-include include/asm-generic/Kbuild.asm
-header-y += cachectl.h
 
 generic-y += bitsperlong.h
 generic-y += clkdev.h
diff --git a/arch/m68k/include/asm/a.out.h b/arch/m68k/include/asm/a.out.h
deleted file mode 100644 (file)
index 3885fe4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __M68K_A_OUT_H__
-#define __M68K_A_OUT_H__
-
-struct exec
-{
-  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
-  unsigned a_text;             /* length of text, in bytes */
-  unsigned a_data;             /* length of data, in bytes */
-  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
-  unsigned a_syms;             /* length of symbol table data in file, in bytes */
-  unsigned a_entry;            /* start address */
-  unsigned a_trsize;           /* length of relocation info for text, in bytes */
-  unsigned a_drsize;           /* length of relocation info for data, in bytes */
-};
-
-#define N_TRSIZE(a)    ((a).a_trsize)
-#define N_DRSIZE(a)    ((a).a_drsize)
-#define N_SYMSIZE(a)   ((a).a_syms)
-
-#endif /* __M68K_A_OUT_H__ */
diff --git a/arch/m68k/include/asm/auxvec.h b/arch/m68k/include/asm/auxvec.h
deleted file mode 100644 (file)
index 844d6d5..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMm68k_AUXVEC_H
-#define __ASMm68k_AUXVEC_H
-
-#endif
diff --git a/arch/m68k/include/asm/byteorder.h b/arch/m68k/include/asm/byteorder.h
deleted file mode 100644 (file)
index 31b260a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _M68K_BYTEORDER_H
-#define _M68K_BYTEORDER_H
-
-#include <linux/byteorder/big_endian.h>
-
-#endif /* _M68K_BYTEORDER_H */
diff --git a/arch/m68k/include/asm/cachectl.h b/arch/m68k/include/asm/cachectl.h
deleted file mode 100644 (file)
index 525978e..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _M68K_CACHECTL_H
-#define _M68K_CACHECTL_H
-
-/* Definitions for the cacheflush system call.  */
-
-#define FLUSH_SCOPE_LINE    1  /* Flush a cache line */
-#define FLUSH_SCOPE_PAGE    2  /* Flush a page */
-#define FLUSH_SCOPE_ALL     3  /* Flush the whole cache -- superuser only */
-
-#define FLUSH_CACHE_DATA    1  /* Writeback and flush data cache */
-#define FLUSH_CACHE_INSN    2  /* Flush instruction cache */
-#define FLUSH_CACHE_BOTH    3  /* Flush both caches */
-
-#endif /* _M68K_CACHECTL_H */
diff --git a/arch/m68k/include/asm/fcntl.h b/arch/m68k/include/asm/fcntl.h
deleted file mode 100644 (file)
index 1c369b2..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef _M68K_FCNTL_H
-#define _M68K_FCNTL_H
-
-#define O_DIRECTORY    040000  /* must be a directory */
-#define O_NOFOLLOW     0100000 /* don't follow links */
-#define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
-#define O_LARGEFILE    0400000
-
-#include <asm-generic/fcntl.h>
-
-#endif /* _M68K_FCNTL_H */
diff --git a/arch/m68k/include/asm/ioctls.h b/arch/m68k/include/asm/ioctls.h
deleted file mode 100644 (file)
index 1332bb4..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __ARCH_M68K_IOCTLS_H__
-#define __ARCH_M68K_IOCTLS_H__
-
-#define FIOQSIZE       0x545E
-
-#include <asm-generic/ioctls.h>
-
-#endif /* __ARCH_M68K_IOCTLS_H__ */
diff --git a/arch/m68k/include/asm/msgbuf.h b/arch/m68k/include/asm/msgbuf.h
deleted file mode 100644 (file)
index 243cb79..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef _M68K_MSGBUF_H
-#define _M68K_MSGBUF_H
-
-/*
- * The msqid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-       struct ipc64_perm msg_perm;
-       __kernel_time_t msg_stime;      /* last msgsnd time */
-       unsigned long   __unused1;
-       __kernel_time_t msg_rtime;      /* last msgrcv time */
-       unsigned long   __unused2;
-       __kernel_time_t msg_ctime;      /* last change time */
-       unsigned long   __unused3;
-       unsigned long  msg_cbytes;      /* current number of bytes on queue */
-       unsigned long  msg_qnum;        /* number of messages in queue */
-       unsigned long  msg_qbytes;      /* max number of bytes on queue */
-       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
-       __kernel_pid_t msg_lrpid;       /* last receive pid */
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-#endif /* _M68K_MSGBUF_H */
diff --git a/arch/m68k/include/asm/param.h b/arch/m68k/include/asm/param.h
deleted file mode 100644 (file)
index 36265cc..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _M68K_PARAM_H
-#define _M68K_PARAM_H
-
-#ifdef __uClinux__
-#define EXEC_PAGESIZE  4096
-#else
-#define EXEC_PAGESIZE  8192
-#endif
-
-#include <asm-generic/param.h>
-
-#endif /* _M68K_PARAM_H */
diff --git a/arch/m68k/include/asm/poll.h b/arch/m68k/include/asm/poll.h
deleted file mode 100644 (file)
index f080fcd..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __m68k_POLL_H
-#define __m68k_POLL_H
-
-#define POLLWRNORM     POLLOUT
-#define POLLWRBAND     256
-
-#include <asm-generic/poll.h>
-
-#endif
diff --git a/arch/m68k/include/asm/posix_types.h b/arch/m68k/include/asm/posix_types.h
deleted file mode 100644 (file)
index cf4dbf7..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __ARCH_M68K_POSIX_TYPES_H
-#define __ARCH_M68K_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned short __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-typedef unsigned short __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-#define __kernel_uid_t __kernel_uid_t
-
-typedef unsigned short __kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif
index 5e08b597f012192e8a5f8cd4cc4d0a20690b485d..0f717045bddef4094584fe9c5be624e9ee2d4927 100644 (file)
@@ -1,82 +1,10 @@
 #ifndef _M68K_PTRACE_H
 #define _M68K_PTRACE_H
 
-#define PT_D1     0
-#define PT_D2     1
-#define PT_D3     2
-#define PT_D4     3
-#define PT_D5     4
-#define PT_D6     5
-#define PT_D7     6
-#define PT_A0     7
-#define PT_A1     8
-#define PT_A2     9
-#define PT_A3     10
-#define PT_A4     11
-#define PT_A5     12
-#define PT_A6     13
-#define PT_D0     14
-#define PT_USP    15
-#define PT_ORIG_D0 16
-#define PT_SR     17
-#define PT_PC     18
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-/* this struct defines the way the registers are stored on the
-   stack during a system call. */
-
-struct pt_regs {
-  long     d1;
-  long     d2;
-  long     d3;
-  long     d4;
-  long     d5;
-  long     a0;
-  long     a1;
-  long     a2;
-  long     d0;
-  long     orig_d0;
-  long     stkadj;
-#ifdef CONFIG_COLDFIRE
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-  unsigned short sr;
-  unsigned long  pc;
-#else
-  unsigned short sr;
-  unsigned long  pc;
-  unsigned format :  4; /* frame format specifier */
-  unsigned vector : 12; /* vector offset */
-#endif
-};
-
-/*
- * This is the extended stack used by signal handlers and the context
- * switcher: it's pushed after the normal "struct pt_regs".
- */
-struct switch_stack {
-       unsigned long  d6;
-       unsigned long  d7;
-       unsigned long  a3;
-       unsigned long  a4;
-       unsigned long  a5;
-       unsigned long  a6;
-       unsigned long  retpc;
-};
-
-/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
-#define PTRACE_GETREGS            12
-#define PTRACE_SETREGS            13
-#define PTRACE_GETFPREGS          14
-#define PTRACE_SETFPREGS          15
-
-#define PTRACE_GET_THREAD_AREA    25
-
-#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
-
-#ifdef __KERNEL__
-
 #ifndef PS_S
 #define PS_S  (0x2000)
 #define PS_M  (0x1000)
@@ -94,6 +22,5 @@ struct switch_stack {
 #define arch_has_block_step()  (1)
 #endif
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _M68K_PTRACE_H */
diff --git a/arch/m68k/include/asm/sembuf.h b/arch/m68k/include/asm/sembuf.h
deleted file mode 100644 (file)
index 2308052..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _M68K_SEMBUF_H
-#define _M68K_SEMBUF_H
-
-/*
- * The semid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-       __kernel_time_t sem_otime;              /* last semop time */
-       unsigned long   __unused1;
-       __kernel_time_t sem_ctime;              /* last change time */
-       unsigned long   __unused2;
-       unsigned long   sem_nsems;              /* no. of semaphores in array */
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _M68K_SEMBUF_H */
index 00c2c5397d37ee787eaeac0df751e220c3cefa26..65e78a2dad64a9840fdb96bdc898e8b848f52331 100644 (file)
 **   Redesign of the boot information structure; moved boot information
 **   structure to bootinfo.h
 */
-
 #ifndef _M68K_SETUP_H
 #define _M68K_SETUP_H
 
+#include <uapi/asm/setup.h>
 
 
-    /*
-     *  Linux/m68k Architectures
-     */
-
-#define MACH_AMIGA    1
-#define MACH_ATARI    2
-#define MACH_MAC      3
-#define MACH_APOLLO   4
-#define MACH_SUN3     5
-#define MACH_MVME147  6
-#define MACH_MVME16x  7
-#define MACH_BVME6000 8
-#define MACH_HP300    9
-#define MACH_Q40     10
-#define MACH_SUN3X   11
-#define MACH_M54XX   12
-
-#define COMMAND_LINE_SIZE 256
-
-#ifdef __KERNEL__
-
 #define CL_SIZE COMMAND_LINE_SIZE
 
 #ifndef __ASSEMBLY__
@@ -194,63 +173,6 @@ extern unsigned long m68k_machtype;
 #  define MACH_TYPE (m68k_machtype)
 #endif
 
-#endif /* __KERNEL__ */
-
-
-    /*
-     *  CPU, FPU and MMU types
-     *
-     *  Note: we may rely on the following equalities:
-     *
-     *      CPU_68020 == MMU_68851
-     *      CPU_68030 == MMU_68030
-     *      CPU_68040 == FPU_68040 == MMU_68040
-     *      CPU_68060 == FPU_68060 == MMU_68060
-     */
-
-#define CPUB_68020     0
-#define CPUB_68030     1
-#define CPUB_68040     2
-#define CPUB_68060     3
-#define CPUB_COLDFIRE  4
-
-#define CPU_68020      (1<<CPUB_68020)
-#define CPU_68030      (1<<CPUB_68030)
-#define CPU_68040      (1<<CPUB_68040)
-#define CPU_68060      (1<<CPUB_68060)
-#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
-
-#define FPUB_68881     0
-#define FPUB_68882     1
-#define FPUB_68040     2                       /* Internal FPU */
-#define FPUB_68060     3                       /* Internal FPU */
-#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
-#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
-
-#define FPU_68881      (1<<FPUB_68881)
-#define FPU_68882      (1<<FPUB_68882)
-#define FPU_68040      (1<<FPUB_68040)
-#define FPU_68060      (1<<FPUB_68060)
-#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
-#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
-
-#define MMUB_68851     0
-#define MMUB_68030     1                       /* Internal MMU */
-#define MMUB_68040     2                       /* Internal MMU */
-#define MMUB_68060     3                       /* Internal MMU */
-#define MMUB_APOLLO    4                       /* Custom Apollo */
-#define MMUB_SUN3      5                       /* Custom Sun-3 */
-#define MMUB_COLDFIRE  6                       /* Internal MMU */
-
-#define MMU_68851      (1<<MMUB_68851)
-#define MMU_68030      (1<<MMUB_68030)
-#define MMU_68040      (1<<MMUB_68040)
-#define MMU_68060      (1<<MMUB_68060)
-#define MMU_SUN3       (1<<MMUB_SUN3)
-#define MMU_APOLLO     (1<<MMUB_APOLLO)
-#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
-
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 extern unsigned long m68k_cputype;
@@ -385,6 +307,4 @@ extern int m68k_realnum_memory;             /* real # of memory blocks found */
 extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
 #endif
 
-#endif /* __KERNEL__ */
-
 #endif /* _M68K_SETUP_H */
diff --git a/arch/m68k/include/asm/shmbuf.h b/arch/m68k/include/asm/shmbuf.h
deleted file mode 100644 (file)
index f8928d6..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef _M68K_SHMBUF_H
-#define _M68K_SHMBUF_H
-
-/*
- * The shmid64_ds structure for m68k architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm;       /* operation perms */
-       size_t                  shm_segsz;      /* size of segment (bytes) */
-       __kernel_time_t         shm_atime;      /* last attach time */
-       unsigned long           __unused1;
-       __kernel_time_t         shm_dtime;      /* last detach time */
-       unsigned long           __unused2;
-       __kernel_time_t         shm_ctime;      /* last change time */
-       unsigned long           __unused3;
-       __kernel_pid_t          shm_cpid;       /* pid of creator */
-       __kernel_pid_t          shm_lpid;       /* pid of last operator */
-       unsigned long           shm_nattch;     /* no. of current attaches */
-       unsigned long           __unused4;
-       unsigned long           __unused5;
-};
-
-struct shminfo64 {
-       unsigned long   shmmax;
-       unsigned long   shmmin;
-       unsigned long   shmmni;
-       unsigned long   shmseg;
-       unsigned long   shmall;
-       unsigned long   __unused1;
-       unsigned long   __unused2;
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _M68K_SHMBUF_H */
diff --git a/arch/m68k/include/asm/sigcontext.h b/arch/m68k/include/asm/sigcontext.h
deleted file mode 100644 (file)
index 523db2a..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef _ASM_M68k_SIGCONTEXT_H
-#define _ASM_M68k_SIGCONTEXT_H
-
-struct sigcontext {
-       unsigned long  sc_mask;         /* old sigmask */
-       unsigned long  sc_usp;          /* old user stack pointer */
-       unsigned long  sc_d0;
-       unsigned long  sc_d1;
-       unsigned long  sc_a0;
-       unsigned long  sc_a1;
-#ifdef __uClinux__
-       unsigned long  sc_a5;
-#endif
-       unsigned short sc_sr;
-       unsigned long  sc_pc;
-       unsigned short sc_formatvec;
-#ifndef __uClinux__
-       unsigned long  sc_fpregs[2*3];  /* room for two fp registers */
-       unsigned long  sc_fpcntl[3];
-       unsigned char  sc_fpstate[216];
-#endif
-};
-
-#endif
index 60e88660169c4575f53bb26d429b095abfd04a4e..2df26b57c26ada5cf34d6c608f75ebd7460f2063 100644 (file)
@@ -1,12 +1,8 @@
 #ifndef _M68K_SIGNAL_H
 #define _M68K_SIGNAL_H
 
-#include <linux/types.h>
+#include <uapi/asm/signal.h>
 
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-#ifdef __KERNEL__
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -20,92 +16,6 @@ typedef struct {
        unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-#define NSIG           32
-typedef unsigned long sigset_t;
-
-#endif /* __KERNEL__ */
-
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/*
-#define SIGLOST                29
-*/
-#define SIGPWR         30
-#define SIGSYS         31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       32
-#define SIGRTMAX       _NSIG
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-#include <asm-generic/signal-defs.h>
-
-#ifdef __KERNEL__
 struct old_sigaction {
        __sighandler_t sa_handler;
        old_sigset_t sa_mask;
@@ -123,31 +33,6 @@ struct sigaction {
 struct k_sigaction {
        struct sigaction sa;
 };
-#else
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-       union {
-         __sighandler_t _sa_handler;
-         void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-       void __user *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 
 #ifndef CONFIG_CPU_HAS_NO_BITFIELDS
@@ -156,7 +41,7 @@ typedef struct sigaltstack {
 static inline void sigaddset(sigset_t *set, int _sig)
 {
        asm ("bfset %0{%1,#1}"
-               : "+od" (*set)
+               : "+o" (*set)
                : "id" ((_sig - 1) ^ 31)
                : "cc");
 }
@@ -164,7 +49,7 @@ static inline void sigaddset(sigset_t *set, int _sig)
 static inline void sigdelset(sigset_t *set, int _sig)
 {
        asm ("bfclr %0{%1,#1}"
-               : "+od" (*set)
+               : "+o" (*set)
                : "id" ((_sig - 1) ^ 31)
                : "cc");
 }
@@ -180,7 +65,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
        int ret;
        asm ("bfextu %1{%2,#1},%0"
                : "=d" (ret)
-               : "od" (*set), "id" ((_sig-1) ^ 31)
+               : "o" (*set), "id" ((_sig-1) ^ 31)
                : "cc");
        return ret;
 }
@@ -208,5 +93,4 @@ struct pt_regs;
 extern void ptrace_signal_deliver(struct pt_regs *regs, void *cookie);
 #endif /* __uClinux__ */
 
-#endif /* __KERNEL__ */
 #endif /* _M68K_SIGNAL_H */
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h
deleted file mode 100644 (file)
index d1be684..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(2) */
-#define SOL_SOCKET     1
-
-#define SO_DEBUG       1
-#define SO_REUSEADDR   2
-#define SO_TYPE                3
-#define SO_ERROR       4
-#define SO_DONTROUTE   5
-#define SO_BROADCAST   6
-#define SO_SNDBUF      7
-#define SO_RCVBUF      8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE   9
-#define SO_OOBINLINE   10
-#define SO_NO_CHECK    11
-#define SO_PRIORITY    12
-#define SO_LINGER      13
-#define SO_BSDCOMPAT   14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED    16
-#define SO_PEERCRED    17
-#define SO_RCVLOWAT    18
-#define SO_SNDLOWAT    19
-#define SO_RCVTIMEO    20
-#define SO_SNDTIMEO    21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION             22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
-#define SO_SECURITY_ENCRYPTION_NETWORK         24
-
-#define SO_BINDTODEVICE        25
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-
-#define SO_PEERNAME             28
-#define SO_TIMESTAMP           29
-#define SCM_TIMESTAMP          SO_TIMESTAMP
-
-#define SO_ACCEPTCONN          30
-
-#define SO_PEERSEC             31
-#define SO_PASSSEC             34
-#define SO_TIMESTAMPNS         35
-#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
-
-#define SO_MARK                        36
-
-#define SO_TIMESTAMPING                37
-#define SCM_TIMESTAMPING       SO_TIMESTAMPING
-
-#define SO_PROTOCOL            38
-#define SO_DOMAIN              39
-
-#define SO_RXQ_OVFL             40
-
-#define SO_WIFI_STATUS         41
-#define SCM_WIFI_STATUS                SO_WIFI_STATUS
-#define SO_PEEK_OFF            42
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS               43
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/m68k/include/asm/sockios.h b/arch/m68k/include/asm/sockios.h
deleted file mode 100644 (file)
index c04a239..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_M68K_SOCKIOS__
-#define __ARCH_M68K_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN      0x8901
-#define SIOCSPGRP      0x8902
-#define FIOGETOWN      0x8903
-#define SIOCGPGRP      0x8904
-#define SIOCATMARK     0x8905
-#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
-
-#endif /* __ARCH_M68K_SOCKIOS__ */
diff --git a/arch/m68k/include/asm/stat.h b/arch/m68k/include/asm/stat.h
deleted file mode 100644 (file)
index dd38bc2..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _M68K_STAT_H
-#define _M68K_STAT_H
-
-struct __old_kernel_stat {
-       unsigned short st_dev;
-       unsigned short st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned long  st_size;
-       unsigned long  st_atime;
-       unsigned long  st_mtime;
-       unsigned long  st_ctime;
-};
-
-struct stat {
-       unsigned short st_dev;
-       unsigned short __pad1;
-       unsigned long  st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned short __pad2;
-       unsigned long  st_size;
-       unsigned long  st_blksize;
-       unsigned long  st_blocks;
-       unsigned long  st_atime;
-       unsigned long  __unused1;
-       unsigned long  st_mtime;
-       unsigned long  __unused2;
-       unsigned long  st_ctime;
-       unsigned long  __unused3;
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- */
-struct stat64 {
-       unsigned long long      st_dev;
-       unsigned char   __pad1[2];
-
-#define STAT64_HAS_BROKEN_ST_INO       1
-       unsigned long   __st_ino;
-
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-
-       unsigned long   st_uid;
-       unsigned long   st_gid;
-
-       unsigned long long      st_rdev;
-       unsigned char   __pad3[2];
-
-       long long       st_size;
-       unsigned long   st_blksize;
-
-       unsigned long long      st_blocks;      /* Number 512-byte blocks allocated. */
-
-       unsigned long   st_atime;
-       unsigned long   st_atime_nsec;
-
-       unsigned long   st_mtime;
-       unsigned long   st_mtime_nsec;
-
-       unsigned long   st_ctime;
-       unsigned long   st_ctime_nsec;
-
-       unsigned long long      st_ino;
-};
-
-#endif /* _M68K_STAT_H */
diff --git a/arch/m68k/include/asm/swab.h b/arch/m68k/include/asm/swab.h
deleted file mode 100644 (file)
index b7b37a4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef _M68K_SWAB_H
-#define _M68K_SWAB_H
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-#define __SWAB_64_THRU_32__
-
-#if defined (__mcfisaaplus__) || defined (__mcfisac__)
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
-       __asm__("byterev %0" : "=d" (val) : "0" (val));
-       return val;
-}
-
-#define __arch_swab32 __arch_swab32
-#elif !defined(__mcoldfire__)
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
-{
-       __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val));
-       return val;
-}
-#define __arch_swab32 __arch_swab32
-#endif
-
-#endif /* _M68K_SWAB_H */
diff --git a/arch/m68k/include/asm/termbits.h b/arch/m68k/include/asm/termbits.h
deleted file mode 100644 (file)
index aea1e37..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __ARCH_M68K_TERMBITS_H__
-#define __ARCH_M68K_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char  cc_t;
-typedef unsigned int   speed_t;
-typedef unsigned int   tcflag_t;
-
-#define NCCS 19
-struct termios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-};
-
-struct termios2 {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-struct ktermios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK  0000020
-#define ISTRIP 0000040
-#define INLCR  0000100
-#define IGNCR  0000200
-#define ICRNL  0000400
-#define IUCLC  0001000
-#define IXON   0002000
-#define IXANY  0004000
-#define IXOFF  0010000
-#define IMAXBEL        0020000
-#define IUTF8  0040000
-
-/* c_oflag bits */
-#define OPOST  0000001
-#define OLCUC  0000002
-#define ONLCR  0000004
-#define OCRNL  0000010
-#define ONOCR  0000020
-#define ONLRET 0000040
-#define OFILL  0000100
-#define OFDEL  0000200
-#define NLDLY  0000400
-#define   NL0  0000000
-#define   NL1  0000400
-#define CRDLY  0003000
-#define   CR0  0000000
-#define   CR1  0001000
-#define   CR2  0002000
-#define   CR3  0003000
-#define TABDLY 0014000
-#define   TAB0 0000000
-#define   TAB1 0004000
-#define   TAB2 0010000
-#define   TAB3 0014000
-#define   XTABS        0014000
-#define BSDLY  0020000
-#define   BS0  0000000
-#define   BS1  0020000
-#define VTDLY  0040000
-#define   VT0  0000000
-#define   VT1  0040000
-#define FFDLY  0100000
-#define   FF0  0000000
-#define   FF1  0100000
-
-/* c_cflag bit meaning */
-#define CBAUD  0010017
-#define  B0    0000000         /* hang up */
-#define  B50   0000001
-#define  B75   0000002
-#define  B110  0000003
-#define  B134  0000004
-#define  B150  0000005
-#define  B200  0000006
-#define  B300  0000007
-#define  B600  0000010
-#define  B1200 0000011
-#define  B1800 0000012
-#define  B2400 0000013
-#define  B4800 0000014
-#define  B9600 0000015
-#define  B19200        0000016
-#define  B38400        0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE  0000060
-#define   CS5  0000000
-#define   CS6  0000020
-#define   CS7  0000040
-#define   CS8  0000060
-#define CSTOPB 0000100
-#define CREAD  0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL  0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define    BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD   002003600000          /* input baud rate */
-#define CMSPAR   010000000000          /* mark or space (stick) parity */
-#define CRTSCTS          020000000000          /* flow control */
-
-#define IBSHIFT        16                      /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-#define ISIG   0000001
-#define ICANON 0000002
-#define XCASE  0000004
-#define ECHO   0000010
-#define ECHOE  0000020
-#define ECHOK  0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL        0001000
-#define ECHOPRT        0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-#define EXTPROC        0200000
-
-
-/* tcflow() and TCXONC use these */
-#define        TCOOFF          0
-#define        TCOON           1
-#define        TCIOFF          2
-#define        TCION           3
-
-/* tcflush() and TCFLSH use these */
-#define        TCIFLUSH        0
-#define        TCOFLUSH        1
-#define        TCIOFLUSH       2
-
-/* tcsetattr uses these */
-#define        TCSANOW         0
-#define        TCSADRAIN       1
-#define        TCSAFLUSH       2
-
-#endif /* __ARCH_M68K_TERMBITS_H__ */
index 0823032e404572fe7bbeca5a639fddd0595248b2..ad8efb098663ee41a28487f385c84642c4f4bf0f 100644 (file)
@@ -1,27 +1,8 @@
 #ifndef _M68K_TERMIOS_H
 #define _M68K_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
+#include <uapi/asm/termios.h>
 
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-#ifdef __KERNEL__
 /*     intr=^C         quit=^|         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
        start=^Q        stop=^S         susp=^Z         eol=\0
@@ -29,27 +10,6 @@ struct termio {
        eol2=\0
 */
 #define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-#endif
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
 
 /*
  * Translate a "termio" structure into a "termios". Ugh.
@@ -87,6 +47,4 @@ struct termio {
 #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
 #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
-#endif /* __KERNEL__ */
-
 #endif /* _M68K_TERMIOS_H */
index c702ad71679195f501f540b7ed5b32108f920813..5fc7f7bec1c807ced0c300d5f6f4747cf781c024 100644 (file)
 #ifndef _ASM_M68K_UNISTD_H_
 #define _ASM_M68K_UNISTD_H_
 
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_chown              16
-/*#define __NR_break            17*/
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-/*#define __NR_stty             31*/
-/*#define __NR_gtty             32*/
-#define __NR_access             33
-#define __NR_nice               34
-/*#define __NR_ftime            35*/
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-/*#define __NR_prof             44*/
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-/*#define __NR_lock             53*/
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-/*#define __NR_mpx              56*/
-#define __NR_setpgid            57
-/*#define __NR_ulimit           58*/
-/*#define __NR_oldolduname      59*/
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-/*#define __NR_profil           98*/
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-/*#define __NR_ioperm          101*/
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-/*#define __NR_olduname                109*/
-/*#define __NR_iopl            110*/ /* not supported */
-#define __NR_vhangup           111
-/*#define __NR_idle            112*/ /* Obsolete */
-/*#define __NR_vm86            113*/ /* not supported */
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_cacheflush                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_getpagesize       166
-#define __NR_query_module      167
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl             172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread64           180
-#define __NR_pwrite64          181
-#define __NR_lchown            182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-#define __NR_getpmsg           188     /* some people actually want streams */
-#define __NR_putpmsg           189     /* some people actually want streams */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_chown32           198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_lchown32          212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-/* 218*/
-/* 219*/
-#define __NR_getdents64                220
-#define __NR_gettid            221
-#define __NR_tkill             222
-#define __NR_setxattr          223
-#define __NR_lsetxattr         224
-#define __NR_fsetxattr         225
-#define __NR_getxattr          226
-#define __NR_lgetxattr         227
-#define __NR_fgetxattr         228
-#define __NR_listxattr         229
-#define __NR_llistxattr                230
-#define __NR_flistxattr                231
-#define __NR_removexattr       232
-#define __NR_lremovexattr      233
-#define __NR_fremovexattr      234
-#define __NR_futex             235
-#define __NR_sendfile64                236
-#define __NR_mincore           237
-#define __NR_madvise           238
-#define __NR_fcntl64           239
-#define __NR_readahead         240
-#define __NR_io_setup          241
-#define __NR_io_destroy                242
-#define __NR_io_getevents      243
-#define __NR_io_submit         244
-#define __NR_io_cancel         245
-#define __NR_fadvise64         246
-#define __NR_exit_group                247
-#define __NR_lookup_dcookie    248
-#define __NR_epoll_create      249
-#define __NR_epoll_ctl         250
-#define __NR_epoll_wait                251
-#define __NR_remap_file_pages  252
-#define __NR_set_tid_address   253
-#define __NR_timer_create      254
-#define __NR_timer_settime     255
-#define __NR_timer_gettime     256
-#define __NR_timer_getoverrun  257
-#define __NR_timer_delete      258
-#define __NR_clock_settime     259
-#define __NR_clock_gettime     260
-#define __NR_clock_getres      261
-#define __NR_clock_nanosleep   262
-#define __NR_statfs64          263
-#define __NR_fstatfs64         264
-#define __NR_tgkill            265
-#define __NR_utimes            266
-#define __NR_fadvise64_64      267
-#define __NR_mbind             268
-#define __NR_get_mempolicy     269
-#define __NR_set_mempolicy     270
-#define __NR_mq_open           271
-#define __NR_mq_unlink         272
-#define __NR_mq_timedsend      273
-#define __NR_mq_timedreceive   274
-#define __NR_mq_notify         275
-#define __NR_mq_getsetattr     276
-#define __NR_waitid            277
-/*#define __NR_vserver         278*/
-#define __NR_add_key           279
-#define __NR_request_key       280
-#define __NR_keyctl            281
-#define __NR_ioprio_set                282
-#define __NR_ioprio_get                283
-#define __NR_inotify_init      284
-#define __NR_inotify_add_watch 285
-#define __NR_inotify_rm_watch  286
-#define __NR_migrate_pages     287
-#define __NR_openat            288
-#define __NR_mkdirat           289
-#define __NR_mknodat           290
-#define __NR_fchownat          291
-#define __NR_futimesat         292
-#define __NR_fstatat64         293
-#define __NR_unlinkat          294
-#define __NR_renameat          295
-#define __NR_linkat            296
-#define __NR_symlinkat         297
-#define __NR_readlinkat                298
-#define __NR_fchmodat          299
-#define __NR_faccessat         300
-#define __NR_pselect6          301
-#define __NR_ppoll             302
-#define __NR_unshare           303
-#define __NR_set_robust_list   304
-#define __NR_get_robust_list   305
-#define __NR_splice            306
-#define __NR_sync_file_range   307
-#define __NR_tee               308
-#define __NR_vmsplice          309
-#define __NR_move_pages                310
-#define __NR_sched_setaffinity 311
-#define __NR_sched_getaffinity 312
-#define __NR_kexec_load                313
-#define __NR_getcpu            314
-#define __NR_epoll_pwait       315
-#define __NR_utimensat         316
-#define __NR_signalfd          317
-#define __NR_timerfd_create    318
-#define __NR_eventfd           319
-#define __NR_fallocate         320
-#define __NR_timerfd_settime   321
-#define __NR_timerfd_gettime   322
-#define __NR_signalfd4         323
-#define __NR_eventfd2          324
-#define __NR_epoll_create1     325
-#define __NR_dup3              326
-#define __NR_pipe2             327
-#define __NR_inotify_init1     328
-#define __NR_preadv            329
-#define __NR_pwritev           330
-#define __NR_rt_tgsigqueueinfo 331
-#define __NR_perf_event_open   332
-#define __NR_get_thread_area   333
-#define __NR_set_thread_area   334
-#define __NR_atomic_cmpxchg_32 335
-#define __NR_atomic_barrier    336
-#define __NR_fanotify_init     337
-#define __NR_fanotify_mark     338
-#define __NR_prlimit64         339
-#define __NR_name_to_handle_at 340
-#define __NR_open_by_handle_at 341
-#define __NR_clock_adjtime     342
-#define __NR_syncfs            343
-#define __NR_setns             344
-#define __NR_process_vm_readv  345
-#define __NR_process_vm_writev 346
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 
-#define NR_syscalls            347
+#define NR_syscalls            348
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_M68K_UNISTD_H_ */
index baebb3da1d44160fc6f6f259886656e6f494b167..972bce120e1e94b8550408f788e0502ecd3d308f 100644 (file)
@@ -1,3 +1,26 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += a.out.h
+header-y += auxvec.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += fcntl.h
+header-y += ioctls.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += unistd.h
diff --git a/arch/m68k/include/uapi/asm/a.out.h b/arch/m68k/include/uapi/asm/a.out.h
new file mode 100644 (file)
index 0000000..3885fe4
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __M68K_A_OUT_H__
+#define __M68K_A_OUT_H__
+
+struct exec
+{
+  unsigned long a_info;                /* Use macros N_MAGIC, etc for access */
+  unsigned a_text;             /* length of text, in bytes */
+  unsigned a_data;             /* length of data, in bytes */
+  unsigned a_bss;              /* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;             /* length of symbol table data in file, in bytes */
+  unsigned a_entry;            /* start address */
+  unsigned a_trsize;           /* length of relocation info for text, in bytes */
+  unsigned a_drsize;           /* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)    ((a).a_trsize)
+#define N_DRSIZE(a)    ((a).a_drsize)
+#define N_SYMSIZE(a)   ((a).a_syms)
+
+#endif /* __M68K_A_OUT_H__ */
diff --git a/arch/m68k/include/uapi/asm/auxvec.h b/arch/m68k/include/uapi/asm/auxvec.h
new file mode 100644 (file)
index 0000000..844d6d5
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __ASMm68k_AUXVEC_H
+#define __ASMm68k_AUXVEC_H
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/byteorder.h b/arch/m68k/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..31b260a
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _M68K_BYTEORDER_H
+#define _M68K_BYTEORDER_H
+
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _M68K_BYTEORDER_H */
diff --git a/arch/m68k/include/uapi/asm/cachectl.h b/arch/m68k/include/uapi/asm/cachectl.h
new file mode 100644 (file)
index 0000000..525978e
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _M68K_CACHECTL_H
+#define _M68K_CACHECTL_H
+
+/* Definitions for the cacheflush system call.  */
+
+#define FLUSH_SCOPE_LINE    1  /* Flush a cache line */
+#define FLUSH_SCOPE_PAGE    2  /* Flush a page */
+#define FLUSH_SCOPE_ALL     3  /* Flush the whole cache -- superuser only */
+
+#define FLUSH_CACHE_DATA    1  /* Writeback and flush data cache */
+#define FLUSH_CACHE_INSN    2  /* Flush instruction cache */
+#define FLUSH_CACHE_BOTH    3  /* Flush both caches */
+
+#endif /* _M68K_CACHECTL_H */
diff --git a/arch/m68k/include/uapi/asm/fcntl.h b/arch/m68k/include/uapi/asm/fcntl.h
new file mode 100644 (file)
index 0000000..1c369b2
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef _M68K_FCNTL_H
+#define _M68K_FCNTL_H
+
+#define O_DIRECTORY    040000  /* must be a directory */
+#define O_NOFOLLOW     0100000 /* don't follow links */
+#define O_DIRECT       0200000 /* direct disk access hint - currently ignored */
+#define O_LARGEFILE    0400000
+
+#include <asm-generic/fcntl.h>
+
+#endif /* _M68K_FCNTL_H */
diff --git a/arch/m68k/include/uapi/asm/ioctls.h b/arch/m68k/include/uapi/asm/ioctls.h
new file mode 100644 (file)
index 0000000..1332bb4
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __ARCH_M68K_IOCTLS_H__
+#define __ARCH_M68K_IOCTLS_H__
+
+#define FIOQSIZE       0x545E
+
+#include <asm-generic/ioctls.h>
+
+#endif /* __ARCH_M68K_IOCTLS_H__ */
diff --git a/arch/m68k/include/uapi/asm/msgbuf.h b/arch/m68k/include/uapi/asm/msgbuf.h
new file mode 100644 (file)
index 0000000..243cb79
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef _M68K_MSGBUF_H
+#define _M68K_MSGBUF_H
+
+/*
+ * The msqid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned long   __unused1;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned long   __unused2;
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned long   __unused3;
+       unsigned long  msg_cbytes;      /* current number of bytes on queue */
+       unsigned long  msg_qnum;        /* number of messages in queue */
+       unsigned long  msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+#endif /* _M68K_MSGBUF_H */
diff --git a/arch/m68k/include/uapi/asm/param.h b/arch/m68k/include/uapi/asm/param.h
new file mode 100644 (file)
index 0000000..36265cc
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _M68K_PARAM_H
+#define _M68K_PARAM_H
+
+#ifdef __uClinux__
+#define EXEC_PAGESIZE  4096
+#else
+#define EXEC_PAGESIZE  8192
+#endif
+
+#include <asm-generic/param.h>
+
+#endif /* _M68K_PARAM_H */
diff --git a/arch/m68k/include/uapi/asm/poll.h b/arch/m68k/include/uapi/asm/poll.h
new file mode 100644 (file)
index 0000000..f080fcd
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __m68k_POLL_H
+#define __m68k_POLL_H
+
+#define POLLWRNORM     POLLOUT
+#define POLLWRBAND     256
+
+#include <asm-generic/poll.h>
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/posix_types.h b/arch/m68k/include/uapi/asm/posix_types.h
new file mode 100644 (file)
index 0000000..cf4dbf7
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ARCH_M68K_POSIX_TYPES_H
+#define __ARCH_M68K_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+#define __kernel_uid_t __kernel_uid_t
+
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/ptrace.h b/arch/m68k/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..caf92fd
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef _UAPI_M68K_PTRACE_H
+#define _UAPI_M68K_PTRACE_H
+
+#define PT_D1     0
+#define PT_D2     1
+#define PT_D3     2
+#define PT_D4     3
+#define PT_D5     4
+#define PT_D6     5
+#define PT_D7     6
+#define PT_A0     7
+#define PT_A1     8
+#define PT_A2     9
+#define PT_A3     10
+#define PT_A4     11
+#define PT_A5     12
+#define PT_A6     13
+#define PT_D0     14
+#define PT_USP    15
+#define PT_ORIG_D0 16
+#define PT_SR     17
+#define PT_PC     18
+
+#ifndef __ASSEMBLY__
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. */
+
+struct pt_regs {
+  long     d1;
+  long     d2;
+  long     d3;
+  long     d4;
+  long     d5;
+  long     a0;
+  long     a1;
+  long     a2;
+  long     d0;
+  long     orig_d0;
+  long     stkadj;
+#ifdef CONFIG_COLDFIRE
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+  unsigned short sr;
+  unsigned long  pc;
+#else
+  unsigned short sr;
+  unsigned long  pc;
+  unsigned format :  4; /* frame format specifier */
+  unsigned vector : 12; /* vector offset */
+#endif
+};
+
+/*
+ * This is the extended stack used by signal handlers and the context
+ * switcher: it's pushed after the normal "struct pt_regs".
+ */
+struct switch_stack {
+       unsigned long  d6;
+       unsigned long  d7;
+       unsigned long  a3;
+       unsigned long  a4;
+       unsigned long  a5;
+       unsigned long  a6;
+       unsigned long  retpc;
+};
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+#define PTRACE_GETFPREGS          14
+#define PTRACE_SETFPREGS          15
+
+#define PTRACE_GET_THREAD_AREA    25
+
+#define PTRACE_SINGLEBLOCK     33      /* resume execution until next branch */
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_M68K_PTRACE_H */
diff --git a/arch/m68k/include/uapi/asm/sembuf.h b/arch/m68k/include/uapi/asm/sembuf.h
new file mode 100644 (file)
index 0000000..2308052
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _M68K_SEMBUF_H
+#define _M68K_SEMBUF_H
+
+/*
+ * The semid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+       __kernel_time_t sem_otime;              /* last semop time */
+       unsigned long   __unused1;
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned long   __unused2;
+       unsigned long   sem_nsems;              /* no. of semaphores in array */
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _M68K_SEMBUF_H */
diff --git a/arch/m68k/include/uapi/asm/setup.h b/arch/m68k/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..85579bf
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+** asm/setup.h -- Definition of the Linux/m68k setup information
+**
+** Copyright 1992 by Greg Harp
+**
+** This file is subject to the terms and conditions of the GNU General Public
+** License.  See the file COPYING in the main directory of this archive
+** for more details.
+**
+** Created 09/29/92 by Greg Harp
+**
+** 5/2/94 Roman Hodek:
+**   Added bi_atari part of the machine dependent union bi_un; for now it
+**   contains just a model field to distinguish between TT and Falcon.
+** 26/7/96 Roman Zippel:
+**   Renamed to setup.h; added some useful macros to allow gcc some
+**   optimizations if possible.
+** 5/10/96 Geert Uytterhoeven:
+**   Redesign of the boot information structure; moved boot information
+**   structure to bootinfo.h
+*/
+
+#ifndef _UAPI_M68K_SETUP_H
+#define _UAPI_M68K_SETUP_H
+
+
+
+    /*
+     *  Linux/m68k Architectures
+     */
+
+#define MACH_AMIGA    1
+#define MACH_ATARI    2
+#define MACH_MAC      3
+#define MACH_APOLLO   4
+#define MACH_SUN3     5
+#define MACH_MVME147  6
+#define MACH_MVME16x  7
+#define MACH_BVME6000 8
+#define MACH_HP300    9
+#define MACH_Q40     10
+#define MACH_SUN3X   11
+#define MACH_M54XX   12
+
+#define COMMAND_LINE_SIZE 256
+
+
+
+    /*
+     *  CPU, FPU and MMU types
+     *
+     *  Note: we may rely on the following equalities:
+     *
+     *      CPU_68020 == MMU_68851
+     *      CPU_68030 == MMU_68030
+     *      CPU_68040 == FPU_68040 == MMU_68040
+     *      CPU_68060 == FPU_68060 == MMU_68060
+     */
+
+#define CPUB_68020     0
+#define CPUB_68030     1
+#define CPUB_68040     2
+#define CPUB_68060     3
+#define CPUB_COLDFIRE  4
+
+#define CPU_68020      (1<<CPUB_68020)
+#define CPU_68030      (1<<CPUB_68030)
+#define CPU_68040      (1<<CPUB_68040)
+#define CPU_68060      (1<<CPUB_68060)
+#define CPU_COLDFIRE   (1<<CPUB_COLDFIRE)
+
+#define FPUB_68881     0
+#define FPUB_68882     1
+#define FPUB_68040     2                       /* Internal FPU */
+#define FPUB_68060     3                       /* Internal FPU */
+#define FPUB_SUNFPA    4                       /* Sun-3 FPA */
+#define FPUB_COLDFIRE  5                       /* ColdFire FPU */
+
+#define FPU_68881      (1<<FPUB_68881)
+#define FPU_68882      (1<<FPUB_68882)
+#define FPU_68040      (1<<FPUB_68040)
+#define FPU_68060      (1<<FPUB_68060)
+#define FPU_SUNFPA     (1<<FPUB_SUNFPA)
+#define FPU_COLDFIRE   (1<<FPUB_COLDFIRE)
+
+#define MMUB_68851     0
+#define MMUB_68030     1                       /* Internal MMU */
+#define MMUB_68040     2                       /* Internal MMU */
+#define MMUB_68060     3                       /* Internal MMU */
+#define MMUB_APOLLO    4                       /* Custom Apollo */
+#define MMUB_SUN3      5                       /* Custom Sun-3 */
+#define MMUB_COLDFIRE  6                       /* Internal MMU */
+
+#define MMU_68851      (1<<MMUB_68851)
+#define MMU_68030      (1<<MMUB_68030)
+#define MMU_68040      (1<<MMUB_68040)
+#define MMU_68060      (1<<MMUB_68060)
+#define MMU_SUN3       (1<<MMUB_SUN3)
+#define MMU_APOLLO     (1<<MMUB_APOLLO)
+#define MMU_COLDFIRE   (1<<MMUB_COLDFIRE)
+
+
+#endif /* _UAPI_M68K_SETUP_H */
diff --git a/arch/m68k/include/uapi/asm/shmbuf.h b/arch/m68k/include/uapi/asm/shmbuf.h
new file mode 100644 (file)
index 0000000..f8928d6
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef _M68K_SHMBUF_H
+#define _M68K_SHMBUF_H
+
+/*
+ * The shmid64_ds structure for m68k architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+
+struct shminfo64 {
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _M68K_SHMBUF_H */
diff --git a/arch/m68k/include/uapi/asm/sigcontext.h b/arch/m68k/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..523db2a
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _ASM_M68k_SIGCONTEXT_H
+#define _ASM_M68k_SIGCONTEXT_H
+
+struct sigcontext {
+       unsigned long  sc_mask;         /* old sigmask */
+       unsigned long  sc_usp;          /* old user stack pointer */
+       unsigned long  sc_d0;
+       unsigned long  sc_d1;
+       unsigned long  sc_a0;
+       unsigned long  sc_a1;
+#ifdef __uClinux__
+       unsigned long  sc_a5;
+#endif
+       unsigned short sc_sr;
+       unsigned long  sc_pc;
+       unsigned short sc_formatvec;
+#ifndef __uClinux__
+       unsigned long  sc_fpregs[2*3];  /* room for two fp registers */
+       unsigned long  sc_fpcntl[3];
+       unsigned char  sc_fpstate[216];
+#endif
+};
+
+#endif
diff --git a/arch/m68k/include/uapi/asm/signal.h b/arch/m68k/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..2b450f3
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef _UAPI_M68K_SIGNAL_H
+#define _UAPI_M68K_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG           32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/*
+#define SIGLOST                29
+*/
+#define SIGPWR         30
+#define SIGSYS         31
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#define SIGRTMAX       _NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP   0x00000001
+#define SA_NOCLDWAIT   0x00000002
+#define SA_SIGINFO     0x00000004
+#define SA_ONSTACK     0x08000000
+#define SA_RESTART     0x10000000
+#define SA_NODEFER     0x40000000
+#define SA_RESETHAND   0x80000000
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#include <asm-generic/signal-defs.h>
+
+#ifndef __KERNEL__
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+       union {
+         __sighandler_t _sa_handler;
+         void (*_sa_sigaction)(int, struct siginfo *, void *);
+       } _u;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+       void __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* _UAPI_M68K_SIGNAL_H */
diff --git a/arch/m68k/include/uapi/asm/socket.h b/arch/m68k/include/uapi/asm/socket.h
new file mode 100644 (file)
index 0000000..285da3b
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockopt(2) */
+#define SOL_SOCKET     1
+
+#define SO_DEBUG       1
+#define SO_REUSEADDR   2
+#define SO_TYPE                3
+#define SO_ERROR       4
+#define SO_DONTROUTE   5
+#define SO_BROADCAST   6
+#define SO_SNDBUF      7
+#define SO_RCVBUF      8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_KEEPALIVE   9
+#define SO_OOBINLINE   10
+#define SO_NO_CHECK    11
+#define SO_PRIORITY    12
+#define SO_LINGER      13
+#define SO_BSDCOMPAT   14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED    16
+#define SO_PEERCRED    17
+#define SO_RCVLOWAT    18
+#define SO_SNDLOWAT    19
+#define SO_RCVTIMEO    20
+#define SO_SNDTIMEO    21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION             22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
+#define SO_SECURITY_ENCRYPTION_NETWORK         24
+
+#define SO_BINDTODEVICE        25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
+
+#define SO_PEERNAME             28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
+
+#define SO_ACCEPTCONN          30
+
+#define SO_PEERSEC             31
+#define SO_PASSSEC             34
+#define SO_TIMESTAMPNS         35
+#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
+
+#define SO_MARK                        36
+
+#define SO_TIMESTAMPING                37
+#define SCM_TIMESTAMPING       SO_TIMESTAMPING
+
+#define SO_PROTOCOL            38
+#define SO_DOMAIN              39
+
+#define SO_RXQ_OVFL             40
+
+#define SO_WIFI_STATUS         41
+#define SCM_WIFI_STATUS                SO_WIFI_STATUS
+#define SO_PEEK_OFF            42
+
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
+#endif /* _ASM_SOCKET_H */
diff --git a/arch/m68k/include/uapi/asm/sockios.h b/arch/m68k/include/uapi/asm/sockios.h
new file mode 100644 (file)
index 0000000..c04a239
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ARCH_M68K_SOCKIOS__
+#define __ARCH_M68K_SOCKIOS__
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN      0x8901
+#define SIOCSPGRP      0x8902
+#define FIOGETOWN      0x8903
+#define SIOCGPGRP      0x8904
+#define SIOCATMARK     0x8905
+#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
+#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
+
+#endif /* __ARCH_M68K_SOCKIOS__ */
diff --git a/arch/m68k/include/uapi/asm/stat.h b/arch/m68k/include/uapi/asm/stat.h
new file mode 100644 (file)
index 0000000..dd38bc2
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _M68K_STAT_H
+#define _M68K_STAT_H
+
+struct __old_kernel_stat {
+       unsigned short st_dev;
+       unsigned short st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned long  st_size;
+       unsigned long  st_atime;
+       unsigned long  st_mtime;
+       unsigned long  st_ctime;
+};
+
+struct stat {
+       unsigned short st_dev;
+       unsigned short __pad1;
+       unsigned long  st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned short __pad2;
+       unsigned long  st_size;
+       unsigned long  st_blksize;
+       unsigned long  st_blocks;
+       unsigned long  st_atime;
+       unsigned long  __unused1;
+       unsigned long  st_mtime;
+       unsigned long  __unused2;
+       unsigned long  st_ctime;
+       unsigned long  __unused3;
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+       unsigned long long      st_dev;
+       unsigned char   __pad1[2];
+
+#define STAT64_HAS_BROKEN_ST_INO       1
+       unsigned long   __st_ino;
+
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+
+       unsigned long   st_uid;
+       unsigned long   st_gid;
+
+       unsigned long long      st_rdev;
+       unsigned char   __pad3[2];
+
+       long long       st_size;
+       unsigned long   st_blksize;
+
+       unsigned long long      st_blocks;      /* Number 512-byte blocks allocated. */
+
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+
+       unsigned long   st_mtime;
+       unsigned long   st_mtime_nsec;
+
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;
+
+       unsigned long long      st_ino;
+};
+
+#endif /* _M68K_STAT_H */
diff --git a/arch/m68k/include/uapi/asm/swab.h b/arch/m68k/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..b7b37a4
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef _M68K_SWAB_H
+#define _M68K_SWAB_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#define __SWAB_64_THRU_32__
+
+#if defined (__mcfisaaplus__) || defined (__mcfisac__)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+       __asm__("byterev %0" : "=d" (val) : "0" (val));
+       return val;
+}
+
+#define __arch_swab32 __arch_swab32
+#elif !defined(__mcoldfire__)
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 val)
+{
+       __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val));
+       return val;
+}
+#define __arch_swab32 __arch_swab32
+#endif
+
+#endif /* _M68K_SWAB_H */
diff --git a/arch/m68k/include/uapi/asm/termbits.h b/arch/m68k/include/uapi/asm/termbits.h
new file mode 100644 (file)
index 0000000..aea1e37
--- /dev/null
@@ -0,0 +1,201 @@
+#ifndef __ARCH_M68K_TERMBITS_H__
+#define __ARCH_M68K_TERMBITS_H__
+
+#include <linux/posix_types.h>
+
+typedef unsigned char  cc_t;
+typedef unsigned int   speed_t;
+typedef unsigned int   tcflag_t;
+
+#define NCCS 19
+struct termios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+};
+
+struct termios2 {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+
+/* c_iflag bits */
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK  0000020
+#define ISTRIP 0000040
+#define INLCR  0000100
+#define IGNCR  0000200
+#define ICRNL  0000400
+#define IUCLC  0001000
+#define IXON   0002000
+#define IXANY  0004000
+#define IXOFF  0010000
+#define IMAXBEL        0020000
+#define IUTF8  0040000
+
+/* c_oflag bits */
+#define OPOST  0000001
+#define OLCUC  0000002
+#define ONLCR  0000004
+#define OCRNL  0000010
+#define ONOCR  0000020
+#define ONLRET 0000040
+#define OFILL  0000100
+#define OFDEL  0000200
+#define NLDLY  0000400
+#define   NL0  0000000
+#define   NL1  0000400
+#define CRDLY  0003000
+#define   CR0  0000000
+#define   CR1  0001000
+#define   CR2  0002000
+#define   CR3  0003000
+#define TABDLY 0014000
+#define   TAB0 0000000
+#define   TAB1 0004000
+#define   TAB2 0010000
+#define   TAB3 0014000
+#define   XTABS        0014000
+#define BSDLY  0020000
+#define   BS0  0000000
+#define   BS1  0020000
+#define VTDLY  0040000
+#define   VT0  0000000
+#define   VT1  0040000
+#define FFDLY  0100000
+#define   FF0  0000000
+#define   FF1  0100000
+
+/* c_cflag bit meaning */
+#define CBAUD  0010017
+#define  B0    0000000         /* hang up */
+#define  B50   0000001
+#define  B75   0000002
+#define  B110  0000003
+#define  B134  0000004
+#define  B150  0000005
+#define  B200  0000006
+#define  B300  0000007
+#define  B600  0000010
+#define  B1200 0000011
+#define  B1800 0000012
+#define  B2400 0000013
+#define  B4800 0000014
+#define  B9600 0000015
+#define  B19200        0000016
+#define  B38400        0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE  0000060
+#define   CS5  0000000
+#define   CS6  0000020
+#define   CS7  0000040
+#define   CS8  0000060
+#define CSTOPB 0000100
+#define CREAD  0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL  0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define    BOTHER 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD   002003600000          /* input baud rate */
+#define CMSPAR   010000000000          /* mark or space (stick) parity */
+#define CRTSCTS          020000000000          /* flow control */
+
+#define IBSHIFT        16                      /* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+#define ISIG   0000001
+#define ICANON 0000002
+#define XCASE  0000004
+#define ECHO   0000010
+#define ECHOE  0000020
+#define ECHOK  0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL        0001000
+#define ECHOPRT        0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+#define EXTPROC        0200000
+
+
+/* tcflow() and TCXONC use these */
+#define        TCOOFF          0
+#define        TCOON           1
+#define        TCIOFF          2
+#define        TCION           3
+
+/* tcflush() and TCFLSH use these */
+#define        TCIFLUSH        0
+#define        TCOFLUSH        1
+#define        TCIOFLUSH       2
+
+/* tcsetattr uses these */
+#define        TCSANOW         0
+#define        TCSADRAIN       1
+#define        TCSAFLUSH       2
+
+#endif /* __ARCH_M68K_TERMBITS_H__ */
diff --git a/arch/m68k/include/uapi/asm/termios.h b/arch/m68k/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..ce2142c
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef _UAPI_M68K_TERMIOS_H
+#define _UAPI_M68K_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_M68K_TERMIOS_H */
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..b94bfbf
--- /dev/null
@@ -0,0 +1,357 @@
+#ifndef _UAPI_ASM_M68K_UNISTD_H_
+#define _UAPI_ASM_M68K_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall     0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_chown              16
+/*#define __NR_break            17*/
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+/*#define __NR_stty             31*/
+/*#define __NR_gtty             32*/
+#define __NR_access             33
+#define __NR_nice               34
+/*#define __NR_ftime            35*/
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+/*#define __NR_prof             44*/
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+/*#define __NR_lock             53*/
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+/*#define __NR_mpx              56*/
+#define __NR_setpgid            57
+/*#define __NR_ulimit           58*/
+/*#define __NR_oldolduname      59*/
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+#define __NR_select             82
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+/*#define __NR_profil           98*/
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+/*#define __NR_ioperm          101*/
+#define __NR_socketcall                102
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+/*#define __NR_olduname                109*/
+/*#define __NR_iopl            110*/ /* not supported */
+#define __NR_vhangup           111
+/*#define __NR_idle            112*/ /* Obsolete */
+/*#define __NR_vm86            113*/ /* not supported */
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_cacheflush                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+#define __NR_create_module     127
+#define __NR_init_module       128
+#define __NR_delete_module     129
+#define __NR_get_kernel_syms   130
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+/*#define __NR_afs_syscall     137*/ /* Syscall for Andrew File System */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+#define __NR_getpagesize       166
+#define __NR_query_module      167
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl             172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread64           180
+#define __NR_pwrite64          181
+#define __NR_lchown            182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+#define __NR_getpmsg           188     /* some people actually want streams */
+#define __NR_putpmsg           189     /* some people actually want streams */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_chown32           198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_lchown32          212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+/* 218*/
+/* 219*/
+#define __NR_getdents64                220
+#define __NR_gettid            221
+#define __NR_tkill             222
+#define __NR_setxattr          223
+#define __NR_lsetxattr         224
+#define __NR_fsetxattr         225
+#define __NR_getxattr          226
+#define __NR_lgetxattr         227
+#define __NR_fgetxattr         228
+#define __NR_listxattr         229
+#define __NR_llistxattr                230
+#define __NR_flistxattr                231
+#define __NR_removexattr       232
+#define __NR_lremovexattr      233
+#define __NR_fremovexattr      234
+#define __NR_futex             235
+#define __NR_sendfile64                236
+#define __NR_mincore           237
+#define __NR_madvise           238
+#define __NR_fcntl64           239
+#define __NR_readahead         240
+#define __NR_io_setup          241
+#define __NR_io_destroy                242
+#define __NR_io_getevents      243
+#define __NR_io_submit         244
+#define __NR_io_cancel         245
+#define __NR_fadvise64         246
+#define __NR_exit_group                247
+#define __NR_lookup_dcookie    248
+#define __NR_epoll_create      249
+#define __NR_epoll_ctl         250
+#define __NR_epoll_wait                251
+#define __NR_remap_file_pages  252
+#define __NR_set_tid_address   253
+#define __NR_timer_create      254
+#define __NR_timer_settime     255
+#define __NR_timer_gettime     256
+#define __NR_timer_getoverrun  257
+#define __NR_timer_delete      258
+#define __NR_clock_settime     259
+#define __NR_clock_gettime     260
+#define __NR_clock_getres      261
+#define __NR_clock_nanosleep   262
+#define __NR_statfs64          263
+#define __NR_fstatfs64         264
+#define __NR_tgkill            265
+#define __NR_utimes            266
+#define __NR_fadvise64_64      267
+#define __NR_mbind             268
+#define __NR_get_mempolicy     269
+#define __NR_set_mempolicy     270
+#define __NR_mq_open           271
+#define __NR_mq_unlink         272
+#define __NR_mq_timedsend      273
+#define __NR_mq_timedreceive   274
+#define __NR_mq_notify         275
+#define __NR_mq_getsetattr     276
+#define __NR_waitid            277
+/*#define __NR_vserver         278*/
+#define __NR_add_key           279
+#define __NR_request_key       280
+#define __NR_keyctl            281
+#define __NR_ioprio_set                282
+#define __NR_ioprio_get                283
+#define __NR_inotify_init      284
+#define __NR_inotify_add_watch 285
+#define __NR_inotify_rm_watch  286
+#define __NR_migrate_pages     287
+#define __NR_openat            288
+#define __NR_mkdirat           289
+#define __NR_mknodat           290
+#define __NR_fchownat          291
+#define __NR_futimesat         292
+#define __NR_fstatat64         293
+#define __NR_unlinkat          294
+#define __NR_renameat          295
+#define __NR_linkat            296
+#define __NR_symlinkat         297
+#define __NR_readlinkat                298
+#define __NR_fchmodat          299
+#define __NR_faccessat         300
+#define __NR_pselect6          301
+#define __NR_ppoll             302
+#define __NR_unshare           303
+#define __NR_set_robust_list   304
+#define __NR_get_robust_list   305
+#define __NR_splice            306
+#define __NR_sync_file_range   307
+#define __NR_tee               308
+#define __NR_vmsplice          309
+#define __NR_move_pages                310
+#define __NR_sched_setaffinity 311
+#define __NR_sched_getaffinity 312
+#define __NR_kexec_load                313
+#define __NR_getcpu            314
+#define __NR_epoll_pwait       315
+#define __NR_utimensat         316
+#define __NR_signalfd          317
+#define __NR_timerfd_create    318
+#define __NR_eventfd           319
+#define __NR_fallocate         320
+#define __NR_timerfd_settime   321
+#define __NR_timerfd_gettime   322
+#define __NR_signalfd4         323
+#define __NR_eventfd2          324
+#define __NR_epoll_create1     325
+#define __NR_dup3              326
+#define __NR_pipe2             327
+#define __NR_inotify_init1     328
+#define __NR_preadv            329
+#define __NR_pwritev           330
+#define __NR_rt_tgsigqueueinfo 331
+#define __NR_perf_event_open   332
+#define __NR_get_thread_area   333
+#define __NR_set_thread_area   334
+#define __NR_atomic_cmpxchg_32 335
+#define __NR_atomic_barrier    336
+#define __NR_fanotify_init     337
+#define __NR_fanotify_mark     338
+#define __NR_prlimit64         339
+#define __NR_name_to_handle_at 340
+#define __NR_open_by_handle_at 341
+#define __NR_clock_adjtime     342
+#define __NR_syncfs            343
+#define __NR_setns             344
+#define __NR_process_vm_readv  345
+#define __NR_process_vm_writev 346
+#define __NR_kcmp              347
+
+#endif /* _UAPI_ASM_M68K_UNISTD_H_ */
index ce827b376110a6a815b4ccece0a066e5ad66cc59..4fc2e29b771b51eb2e2189a4c050c5e05510bc2b 100644 (file)
@@ -367,4 +367,5 @@ ENTRY(sys_call_table)
        .long sys_setns
        .long sys_process_vm_readv      /* 345 */
        .long sys_process_vm_writev
+       .long sys_kcmp
 
index d38246e33ddb9f1eacb7f885f809db54057c5203..9f883bf769530d18c880416850060cd738bb0fa8 100644 (file)
@@ -30,6 +30,7 @@
  * measurement, and debugging facilities.
  */
 
+#include <linux/irqflags.h>
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-l2c.h>
 #include <asm/octeon/cvmx-spinlock.h>
index 7cf80ca2c1d2117c239ba574406c6814ecb91961..f9f5307434c276a35624f5c137333867e2357794 100644 (file)
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/irqflags.h>
 
 #include <asm/bcache.h>
 
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..533053d12cede054a47d225534b1a4ec34b07986 100644 (file)
@@ -0,0 +1 @@
+# MIPS headers
index 82ad35ce2b45d975705e90a90db8cf82b7189255..46ac73abd5ee950b2bd14e57ad07d1b08ff7e010 100644 (file)
@@ -14,7 +14,6 @@
 #endif
 
 #include <linux/compiler.h>
-#include <linux/irqflags.h>
 #include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/byteorder.h>             /* sigh ... */
 #define smp_mb__before_clear_bit()     smp_mb__before_llsc()
 #define smp_mb__after_clear_bit()      smp_llsc_mb()
 
+
+/*
+ * These are the "slower" versions of the functions and are in bitops.c.
+ * These functions call raw_local_irq_{save,restore}().
+ */
+void __mips_set_bit(unsigned long nr, volatile unsigned long *addr);
+void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr);
+void __mips_change_bit(unsigned long nr, volatile unsigned long *addr);
+int __mips_test_and_set_bit(unsigned long nr,
+                           volatile unsigned long *addr);
+int __mips_test_and_set_bit_lock(unsigned long nr,
+                                volatile unsigned long *addr);
+int __mips_test_and_clear_bit(unsigned long nr,
+                             volatile unsigned long *addr);
+int __mips_test_and_change_bit(unsigned long nr,
+                              volatile unsigned long *addr);
+
+
 /*
  * set_bit - Atomically set a bit in memory
  * @nr: the bit to set
@@ -57,7 +74,7 @@
 static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -92,17 +109,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (1UL << bit));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_set_bit(nr, addr);
 }
 
 /*
@@ -118,7 +126,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -153,17 +161,8 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (~(1UL << bit)));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a &= ~mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_clear_bit(nr, addr);
 }
 
 /*
@@ -191,7 +190,7 @@ static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *ad
  */
 static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -220,17 +219,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (1UL << bit));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a ^= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_change_bit(nr, addr);
 }
 
 /*
@@ -244,7 +234,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 static inline int test_and_set_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -281,18 +271,8 @@ static inline int test_and_set_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_set_bit(nr, addr);
 
        smp_llsc_mb();
 
@@ -310,7 +290,7 @@ static inline int test_and_set_bit(unsigned long nr,
 static inline int test_and_set_bit_lock(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -345,18 +325,8 @@ static inline int test_and_set_bit_lock(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_set_bit_lock(nr, addr);
 
        smp_llsc_mb();
 
@@ -373,7 +343,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 static inline int test_and_clear_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -428,18 +398,8 @@ static inline int test_and_clear_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a &= ~mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_clear_bit(nr, addr);
 
        smp_llsc_mb();
 
@@ -457,7 +417,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 static inline int test_and_change_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -494,18 +454,8 @@ static inline int test_and_change_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a ^= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_change_bit(nr, addr);
 
        smp_llsc_mb();
 
index 58277e0e9cd4075e001f79e48fcaaf928dd53064..3c5d1464b7bde4d93f5d4345fbedd31ccda7e47a 100644 (file)
@@ -290,7 +290,7 @@ struct compat_shmid64_ds {
 
 static inline int is_compat_task(void)
 {
-       return test_thread_flag(TIF_32BIT);
+       return test_thread_flag(TIF_32BIT_ADDR);
 }
 
 #endif /* _ASM_COMPAT_H */
index e7cd78277c2314cee30aec8d078d2e9cd3a8e69e..dc0a5f77a35c8d9a6c09567e61e54b7e349b55ae 100644 (file)
@@ -13,9 +13,9 @@
 
 #include <linux/param.h>
 
-extern void __delay(unsigned int loops);
-extern void __ndelay(unsigned int ns);
-extern void __udelay(unsigned int us);
+extern void __delay(unsigned long loops);
+extern void __ndelay(unsigned long ns);
+extern void __udelay(unsigned long us);
 
 #define ndelay(ns) __ndelay(ns)
 #define udelay(us) __udelay(us)
index 29d9c23c20c72d87f847f28772666448cdd2711a..ff2e0345e0132744eb57fcfc12969c950bc97bf0 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/irqflags.h>
 
 #include <asm/addrspace.h>
 #include <asm/bug.h>
index 309cbcd6909cd808b92941e53deea0e3e3a5a756..9f3384c789d7bfdff5511706b0dffc3d2962c96c 100644 (file)
 #include <linux/compiler.h>
 #include <asm/hazards.h>
 
-__asm__(
-       "       .macro  arch_local_irq_enable                           \n"
-       "       .set    push                                            \n"
-       "       .set    reorder                                         \n"
-       "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
-       "       ori     $1, 0x400                                       \n"
-       "       xori    $1, 0x400                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
-       "       ei                                                      \n"
-#else
-       "       mfc0    $1,$12                                          \n"
-       "       ori     $1,0x1f                                         \n"
-       "       xori    $1,0x1e                                         \n"
-       "       mtc0    $1,$12                                          \n"
-#endif
-       "       irq_enable_hazard                                       \n"
-       "       .set    pop                                             \n"
-       "       .endm");
+#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC)
 
-extern void smtc_ipi_replay(void);
-
-static inline void arch_local_irq_enable(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-       /*
-        * SMTC kernel needs to do a software replay of queued
-        * IPIs, at the cost of call overhead on each local_irq_enable()
-        */
-       smtc_ipi_replay();
-#endif
-       __asm__ __volatile__(
-               "arch_local_irq_enable"
-               : /* no outputs */
-               : /* no inputs */
-               : "memory");
-}
-
-
-/*
- * For cli() we have to insert nops to make sure that the new value
- * has actually arrived in the status register before the end of this
- * macro.
- * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
- * no nops at all.
- */
-/*
- * For TX49, operating only IE bit is not enough.
- *
- * If mfc0 $12 follows store and the mfc0 is last instruction of a
- * page and fetching the next instruction causes TLB miss, the result
- * of the mfc0 might wrongly contain EXL bit.
- *
- * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
- *
- * Workaround: mask EXL bit of the result or place a nop before mfc0.
- */
 __asm__(
        "       .macro  arch_local_irq_disable\n"
        "       .set    push                                            \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    $1, $2, 1                                       \n"
-       "       ori     $1, 0x400                                       \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
        "       di                                                      \n"
-#else
-       "       mfc0    $1,$12                                          \n"
-       "       ori     $1,0x1f                                         \n"
-       "       xori    $1,0x1f                                         \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1,$12                                          \n"
-#endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
@@ -106,46 +36,14 @@ static inline void arch_local_irq_disable(void)
                : "memory");
 }
 
-__asm__(
-       "       .macro  arch_local_save_flags flags                     \n"
-       "       .set    push                                            \n"
-       "       .set    reorder                                         \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    \\flags, $2, 1                                  \n"
-#else
-       "       mfc0    \\flags, $12                                    \n"
-#endif
-       "       .set    pop                                             \n"
-       "       .endm                                                   \n");
-
-static inline unsigned long arch_local_save_flags(void)
-{
-       unsigned long flags;
-       asm volatile("arch_local_save_flags %0" : "=r" (flags));
-       return flags;
-}
 
 __asm__(
        "       .macro  arch_local_irq_save result                      \n"
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    \\result, $2, 1                                 \n"
-       "       ori     $1, \\result, 0x400                             \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-       "       andi    \\result, \\result, 0x400                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
        "       di      \\result                                        \n"
        "       andi    \\result, 1                                     \n"
-#else
-       "       mfc0    \\result, $12                                   \n"
-       "       ori     $1, \\result, 0x1f                              \n"
-       "       xori    $1, 0x1f                                        \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $12                                         \n"
-#endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
@@ -160,61 +58,37 @@ static inline unsigned long arch_local_irq_save(void)
        return flags;
 }
 
+
 __asm__(
        "       .macro  arch_local_irq_restore flags                    \n"
        "       .set    push                                            \n"
        "       .set    noreorder                                       \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "mfc0   $1, $2, 1                                               \n"
-       "andi   \\flags, 0x400                                          \n"
-       "ori    $1, 0x400                                               \n"
-       "xori   $1, 0x400                                               \n"
-       "or     \\flags, $1                                             \n"
-       "mtc0   \\flags, $2, 1                                          \n"
-#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_IRQ_CPU)
        /*
         * Slow, but doesn't suffer from a relatively unlikely race
         * condition we're having since days 1.
         */
        "       beqz    \\flags, 1f                                     \n"
-       "        di                                                     \n"
+       "       di                                                      \n"
        "       ei                                                      \n"
        "1:                                                             \n"
-#elif defined(CONFIG_CPU_MIPSR2)
+#else
        /*
         * Fast, dangerous.  Life is fun, life is good.
         */
        "       mfc0    $1, $12                                         \n"
        "       ins     $1, \\flags, 0, 1                               \n"
        "       mtc0    $1, $12                                         \n"
-#else
-       "       mfc0    $1, $12                                         \n"
-       "       andi    \\flags, 1                                      \n"
-       "       ori     $1, 0x1f                                        \n"
-       "       xori    $1, 0x1f                                        \n"
-       "       or      \\flags, $1                                     \n"
-       "       mtc0    \\flags, $12                                    \n"
 #endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
 
-
 static inline void arch_local_irq_restore(unsigned long flags)
 {
        unsigned long __tmp1;
 
-#ifdef CONFIG_MIPS_MT_SMTC
-       /*
-        * SMTC kernel needs to do a software replay of queued
-        * IPIs, at the cost of branch and call overhead on each
-        * local_irq_restore()
-        */
-       if (unlikely(!(flags & 0x0400)))
-               smtc_ipi_replay();
-#endif
-
        __asm__ __volatile__(
                "arch_local_irq_restore\t%0"
                : "=r" (__tmp1)
@@ -232,6 +106,75 @@ static inline void __arch_local_irq_restore(unsigned long flags)
                : "0" (flags)
                : "memory");
 }
+#else
+/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
+void arch_local_irq_disable(void);
+unsigned long arch_local_irq_save(void);
+void arch_local_irq_restore(unsigned long flags);
+void __arch_local_irq_restore(unsigned long flags);
+#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */
+
+
+__asm__(
+       "       .macro  arch_local_irq_enable                           \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
+       "       ori     $1, 0x400                                       \n"
+       "       xori    $1, 0x400                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       "       ei                                                      \n"
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1e                                         \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_enable_hazard                                       \n"
+       "       .set    pop                                             \n"
+       "       .endm");
+
+extern void smtc_ipi_replay(void);
+
+static inline void arch_local_irq_enable(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC kernel needs to do a software replay of queued
+        * IPIs, at the cost of call overhead on each local_irq_enable()
+        */
+       smtc_ipi_replay();
+#endif
+       __asm__ __volatile__(
+               "arch_local_irq_enable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+}
+
+
+__asm__(
+       "       .macro  arch_local_save_flags flags                     \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\flags, $2, 1                                  \n"
+#else
+       "       mfc0    \\flags, $12                                    \n"
+#endif
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("arch_local_save_flags %0" : "=r" (flags));
+       return flags;
+}
+
 
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
@@ -245,7 +188,7 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 #endif
 }
 
-#endif
+#endif /* #ifndef __ASSEMBLY__ */
 
 /*
  * Do the CPU's IRQ-state tracing from assembly code.
index c26e182500799b7ba6cf97b2ef540f6feb82b6c8..f5b521d5a67d744e3f250c5a99e5023c77deaee0 100644 (file)
@@ -9,6 +9,7 @@
 #ifndef _ASM_PGTABLE_64_H
 #define _ASM_PGTABLE_64_H
 
+#include <linux/compiler.h>
 #include <linux/linkage.h>
 
 #include <asm/addrspace.h>
@@ -172,7 +173,19 @@ static inline int pmd_none(pmd_t pmd)
        return pmd_val(pmd) == (unsigned long) invalid_pte_table;
 }
 
-#define pmd_bad(pmd)           (pmd_val(pmd) & ~PAGE_MASK)
+static inline int pmd_bad(pmd_t pmd)
+{
+#ifdef CONFIG_HUGETLB_PAGE
+       /* pmd_huge(pmd) but inline */
+       if (unlikely(pmd_val(pmd) & _PAGE_HUGE))
+               return 0;
+#endif
+
+       if (unlikely(pmd_val(pmd) & ~PAGE_MASK))
+               return 1;
+
+       return 0;
+}
 
 static inline int pmd_present(pmd_t pmd)
 {
index 8debe9e917549097d09f5083489714605066a1cc..18806a52061c3c6869ed03c101ccabe740b64ac8 100644 (file)
@@ -112,12 +112,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define TIF_LOAD_WATCH         25      /* If set, load watch registers */
 #define TIF_SYSCALL_TRACE      31      /* syscall trace active */
 
-#ifdef CONFIG_MIPS32_O32
-#define TIF_32BIT TIF_32BIT_REGS
-#elif defined(CONFIG_MIPS32_N32)
-#define TIF_32BIT _TIF_32BIT_ADDR
-#endif /* CONFIG_MIPS32_O32 */
-
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
index c5ed59549cb878c211146c8ac86c8eaff354c525..17307ab90474271e4c77f9d48bfb775f2049db74 100644 (file)
@@ -63,6 +63,7 @@ To add: #define SO_REUSEPORT 0x0200   /* Allow local address and port reuse.  */
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME             28
 #define SO_TIMESTAMP           29
index b9fe3ade028987f67a97b29e1192ef8768d72c17..8eb715bb1ea871f0141c0508a55a18f755257d5f 100644 (file)
@@ -14,6 +14,9 @@
  */
 
 #ifndef __MIPS_JZ4740_SERIAL_H__
+#define __MIPS_JZ4740_SERIAL_H__
+
+struct uart_port;
 
 void jz4740_serial_out(struct uart_port *p, int offset, int value);
 
index a53f8ec37aac68beef41b905b88cf1fe92e805d9..290dc6a1d7a344413e36f00fdacfa86e9d1bcbe3 100644 (file)
@@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", };
 void __init add_memory_region(phys_t start, phys_t size, long type)
 {
        int x = boot_mem_map.nr_map;
-       struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
+       int i;
 
        /* Sanity check */
        if (start + size < start) {
@@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
        }
 
        /*
-        * Try to merge with previous entry if any.  This is far less than
-        * perfect but is sufficient for most real world cases.
+        * Try to merge with existing entry, if any.
         */
-       if (x && prev->addr + prev->size == start && prev->type == type) {
-               prev->size += size;
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               struct boot_mem_map_entry *entry = boot_mem_map.map + i;
+               unsigned long top;
+
+               if (entry->type != type)
+                       continue;
+
+               if (start + size < entry->addr)
+                       continue;                       /* no overlap */
+
+               if (entry->addr + entry->size < start)
+                       continue;                       /* no overlap */
+
+               top = max(entry->addr + entry->size, start + size);
+               entry->addr = min(entry->addr, start);
+               entry->size = top - entry->addr;
+
                return;
        }
 
-       if (x == BOOT_MEM_MAP_MAX) {
+       if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) {
                pr_err("Ooops! Too many entries in the memory map!\n");
                return;
        }
index afc379ca375301f7e916a4fd46447239ad478a38..06cd0c610f4475a3cfc03f6907e00542117fe2ba 100644 (file)
@@ -97,7 +97,7 @@ static void cmp_init_secondary(void)
 
        /* Enable per-cpu interrupts: platform specific */
 
-       c->core = (read_c0_ebase() >> 1) & 0xff;
+       c->core = (read_c0_ebase() >> 1) & 0x1ff;
 #if defined(CONFIG_MIPS_MT_SMP) || defined(CONFIG_MIPS_MT_SMTC)
        c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE;
 #endif
index c4a82e841c7309d1659ceeac4e708e6796ee8c2c..eeddc58802e11a57595ee7d123e0538577af0c67 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y  += csum_partial.o delay.o memcpy.o memset.o \
-          strlen_user.o strncpy_user.o strnlen_user.o uncached.o
+lib-y  += bitops.o csum_partial.o delay.o memcpy.o memset.o \
+          mips-atomic.o strlen_user.o strncpy_user.o \
+          strnlen_user.o uncached.o
 
 obj-y                  += iomap.o
 obj-$(CONFIG_PCI)      += iomap-pci.o
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c
new file mode 100644 (file)
index 0000000..239a9c9
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * 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-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
+ */
+#include <linux/bitops.h>
+#include <linux/irqflags.h>
+#include <linux/export.h>
+
+
+/**
+ * __mips_set_bit - Atomically set a bit in memory.  This is called by
+ * set_bit() if it cannot find a faster solution.
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+void __mips_set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_set_bit);
+
+
+/**
+ * __mips_clear_bit - Clears a bit in memory.  This is called by clear_bit() if
+ * it cannot find a faster solution.
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ */
+void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a &= ~mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_clear_bit);
+
+
+/**
+ * __mips_change_bit - Toggle a bit in memory.  This is called by change_bit()
+ * if it cannot find a faster solution.
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ */
+void __mips_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a ^= mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_change_bit);
+
+
+/**
+ * __mips_test_and_set_bit - Set a bit and return its old value.  This is
+ * called by test_and_set_bit() if it cannot find a faster solution.
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+int __mips_test_and_set_bit(unsigned long nr,
+                           volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_set_bit);
+
+
+/**
+ * __mips_test_and_set_bit_lock - Set a bit and return its old value.  This is
+ * called by test_and_set_bit_lock() if it cannot find a faster solution.
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+int __mips_test_and_set_bit_lock(unsigned long nr,
+                                volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_set_bit_lock);
+
+
+/**
+ * __mips_test_and_clear_bit - Clear a bit and return its old value.  This is
+ * called by test_and_clear_bit() if it cannot find a faster solution.
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a &= ~mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_clear_bit);
+
+
+/**
+ * __mips_test_and_change_bit - Change a bit and return its old value.  This is
+ * called by test_and_change_bit() if it cannot find a faster solution.
+ * @nr: Bit to change
+ * @addr: Address to count from
+ */
+int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a ^= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_change_bit);
index 5995969e8c42b4c4b0d6a1f44005104429c50479..dc81ca8dc0dd4b0ccd81ae2edc78b059aa8fd016 100644 (file)
 #include <asm/compiler.h>
 #include <asm/war.h>
 
-inline void __delay(unsigned int loops)
+void __delay(unsigned long loops)
 {
        __asm__ __volatile__ (
        "       .set    noreorder                               \n"
        "       .align  3                                       \n"
        "1:     bnez    %0, 1b                                  \n"
+#if __SIZEOF_LONG__ == 4
        "       subu    %0, 1                                   \n"
+#else
+       "       dsubu   %0, 1                                   \n"
+#endif
        "       .set    reorder                                 \n"
        : "=r" (loops)
        : "0" (loops));
index 3f69725556afb3fc78d5ac3bab04be6176e28017..a99c1d3fc56769dc91f58ce64e117e0eb8533b44 100644 (file)
@@ -50,8 +50,9 @@ static void dump_tlb(int first, int last)
 {
        unsigned long s_entryhi, entryhi, asid;
        unsigned long long entrylo0, entrylo1;
-       unsigned int s_index, pagemask, c0, c1, i;
+       unsigned int s_index, s_pagemask, pagemask, c0, c1, i;
 
+       s_pagemask = read_c0_pagemask();
        s_entryhi = read_c0_entryhi();
        s_index = read_c0_index();
        asid = s_entryhi & 0xff;
@@ -103,6 +104,7 @@ static void dump_tlb(int first, int last)
 
        write_c0_entryhi(s_entryhi);
        write_c0_index(s_index);
+       write_c0_pagemask(s_pagemask);
 }
 
 void dump_tlb_all(void)
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c
new file mode 100644 (file)
index 0000000..cd160be
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * 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, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#include <asm/irqflags.h>
+#include <asm/hazards.h>
+#include <linux/compiler.h>
+#include <linux/preempt.h>
+#include <linux/export.h>
+
+#if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC)
+
+/*
+ * For cli() we have to insert nops to make sure that the new value
+ * has actually arrived in the status register before the end of this
+ * macro.
+ * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
+ * no nops at all.
+ */
+/*
+ * For TX49, operating only IE bit is not enough.
+ *
+ * If mfc0 $12 follows store and the mfc0 is last instruction of a
+ * page and fetching the next instruction causes TLB miss, the result
+ * of the mfc0 might wrongly contain EXL bit.
+ *
+ * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
+ *
+ * Workaround: mask EXL bit of the result or place a nop before mfc0.
+ */
+__asm__(
+       "       .macro  arch_local_irq_disable\n"
+       "       .set    push                                            \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1                                       \n"
+       "       ori     $1, 0x400                                       \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1f                                         \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace void arch_local_irq_disable(void)
+{
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_disable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(arch_local_irq_disable);
+
+
+__asm__(
+       "       .macro  arch_local_irq_save result                      \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\result, $2, 1                                 \n"
+       "       ori     $1, \\result, 0x400                             \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+       "       andi    \\result, \\result, 0x400                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    \\result, $12                                   \n"
+       "       ori     $1, \\result, 0x1f                              \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $12                                         \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       preempt_disable();
+       asm volatile("arch_local_irq_save\t%0"
+                    : "=r" (flags)
+                    : /* no inputs */
+                    : "memory");
+       preempt_enable();
+       return flags;
+}
+EXPORT_SYMBOL(arch_local_irq_save);
+
+
+__asm__(
+       "       .macro  arch_local_irq_restore flags                    \n"
+       "       .set    push                                            \n"
+       "       .set    noreorder                                       \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "mfc0   $1, $2, 1                                               \n"
+       "andi   \\flags, 0x400                                          \n"
+       "ori    $1, 0x400                                               \n"
+       "xori   $1, 0x400                                               \n"
+       "or     \\flags, $1                                             \n"
+       "mtc0   \\flags, $2, 1                                          \n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+       /* see irqflags.h for inline function */
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    $1, $12                                         \n"
+       "       andi    \\flags, 1                                      \n"
+       "       ori     $1, 0x1f                                        \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       or      \\flags, $1                                     \n"
+       "       mtc0    \\flags, $12                                    \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace void arch_local_irq_restore(unsigned long flags)
+{
+       unsigned long __tmp1;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC kernel needs to do a software replay of queued
+        * IPIs, at the cost of branch and call overhead on each
+        * local_irq_restore()
+        */
+       if (unlikely(!(flags & 0x0400)))
+               smtc_ipi_replay();
+#endif
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_restore\t%0"
+               : "=r" (__tmp1)
+               : "0" (flags)
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(arch_local_irq_restore);
+
+
+notrace void __arch_local_irq_restore(unsigned long flags)
+{
+       unsigned long __tmp1;
+
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_restore\t%0"
+               : "=r" (__tmp1)
+               : "0" (flags)
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(__arch_local_irq_restore);
+
+#endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */
index 87b9cfcc30ff9ee44a982ae40982073e3eb5b855..4b9b935a070e0c4d0160f2c259c3dc553c40b35e 100644 (file)
@@ -320,6 +320,7 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte)
                        tlb_write_random();
                else
                        tlb_write_indexed();
+               tlbw_use_hazard();
                write_c0_pagemask(PM_DEFAULT_MASK);
        } else
 #endif
index 658a520364ce76979191defd64c56a1da88899fb..2833dcb67b5adeaf838536580728176bbc715a77 100644 (file)
@@ -148,8 +148,8 @@ enum label_id {
        label_leave,
        label_vmalloc,
        label_vmalloc_done,
-       label_tlbw_hazard,
-       label_split,
+       label_tlbw_hazard_0,
+       label_split = label_tlbw_hazard_0 + 8,
        label_tlbl_goaround1,
        label_tlbl_goaround2,
        label_nopage_tlbl,
@@ -167,7 +167,7 @@ UASM_L_LA(_second_part)
 UASM_L_LA(_leave)
 UASM_L_LA(_vmalloc)
 UASM_L_LA(_vmalloc_done)
-UASM_L_LA(_tlbw_hazard)
+/* _tlbw_hazard_x is handled differently.  */
 UASM_L_LA(_split)
 UASM_L_LA(_tlbl_goaround1)
 UASM_L_LA(_tlbl_goaround2)
@@ -181,6 +181,30 @@ UASM_L_LA(_large_segbits_fault)
 UASM_L_LA(_tlb_huge_update)
 #endif
 
+static int __cpuinitdata hazard_instance;
+
+static void uasm_bgezl_hazard(u32 **p, struct uasm_reloc **r, int instance)
+{
+       switch (instance) {
+       case 0 ... 7:
+               uasm_il_bgezl(p, r, 0, label_tlbw_hazard_0 + instance);
+               return;
+       default:
+               BUG();
+       }
+}
+
+static void uasm_bgezl_label(struct uasm_label **l, u32 **p, int instance)
+{
+       switch (instance) {
+       case 0 ... 7:
+               uasm_build_label(l, *p, label_tlbw_hazard_0 + instance);
+               break;
+       default:
+               BUG();
+       }
+}
+
 /*
  * For debug purposes.
  */
@@ -478,21 +502,28 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
                 * This branch uses up a mtc0 hazard nop slot and saves
                 * two nops after the tlbw instruction.
                 */
-               uasm_il_bgezl(p, r, 0, label_tlbw_hazard);
+               uasm_bgezl_hazard(p, r, hazard_instance);
                tlbw(p);
-               uasm_l_tlbw_hazard(l, *p);
+               uasm_bgezl_label(l, p, hazard_instance);
+               hazard_instance++;
                uasm_i_nop(p);
                break;
 
        case CPU_R4600:
        case CPU_R4700:
-       case CPU_R5000:
-       case CPU_R5000A:
                uasm_i_nop(p);
                tlbw(p);
                uasm_i_nop(p);
                break;
 
+       case CPU_R5000:
+       case CPU_R5000A:
+       case CPU_NEVADA:
+               uasm_i_nop(p); /* QED specifies 2 nops hazard */
+               uasm_i_nop(p); /* QED specifies 2 nops hazard */
+               tlbw(p);
+               break;
+
        case CPU_R4300:
        case CPU_5KC:
        case CPU_TX49XX:
@@ -526,17 +557,6 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
                tlbw(p);
                break;
 
-       case CPU_NEVADA:
-               uasm_i_nop(p); /* QED specifies 2 nops hazard */
-               /*
-                * This branch uses up a mtc0 hazard nop slot and saves
-                * a nop after the tlbw instruction.
-                */
-               uasm_il_bgezl(p, r, 0, label_tlbw_hazard);
-               tlbw(p);
-               uasm_l_tlbw_hazard(l, *p);
-               break;
-
        case CPU_RM7000:
                uasm_i_nop(p);
                uasm_i_nop(p);
index 80562b81f0f2a2036fbf0a28781601b420c5d872..74732177851c31843add1f2259dab3233932726a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
+#include <asm/mips-boards/maltaint.h>
 #include <mtd/mtd-abi.h>
 
 #define SMC_PORT(base, int)                                            \
@@ -48,7 +49,7 @@ static struct plat_serial8250_port uart8250_data[] = {
        SMC_PORT(0x2F8, 3),
        {
                .mapbase        = 0x1f000900,   /* The CBUS UART */
-               .irq            = MIPS_CPU_IRQ_BASE + 2,
+               .irq            = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
                .uartclk        = 3686400,      /* Twice the usual clk! */
                .iotype         = UPIO_MEM32,
                .flags          = CBUS_UART_FLAGS,
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ae5704fa77ad6d15e8de4623ca6465f24f2341b9 100644 (file)
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
index 820463a484b8dbc5b21ee627822297d4a33bf91f..af5366bbfe62727b09e2d47474e78a7483bb3a13 100644 (file)
@@ -40,6 +40,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index 458371a1565aa2fdcbaa75e27ab398d8741019a9..bac8debecffb067ca8b550e0773a3c7c204d1e0b 100644 (file)
@@ -1,6 +1,5 @@
-include include/asm-generic/Kbuild.asm
 
-header-y += pdc.h
-generic-y += clkdev.h
-generic-y += word-at-a-time.h
-generic-y += exec.h
+generic-y += word-at-a-time.h auxvec.h user.h cputime.h emergency-restart.h \
+         segment.h topology.h vga.h device.h percpu.h hw_irq.h mutex.h \
+         div64.h irq_regs.h kdebug.h kvm_para.h local64.h local.h param.h \
+         poll.h xor.h clkdev.h exec.h
diff --git a/arch/parisc/include/asm/auxvec.h b/arch/parisc/include/asm/auxvec.h
deleted file mode 100644 (file)
index 9c3ac4b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __ASMPARISC_AUXVEC_H
-#define __ASMPARISC_AUXVEC_H
-
-#endif
diff --git a/arch/parisc/include/asm/bitsperlong.h b/arch/parisc/include/asm/bitsperlong.h
deleted file mode 100644 (file)
index 75196b4..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __ASM_PARISC_BITSPERLONG_H
-#define __ASM_PARISC_BITSPERLONG_H
-
-/*
- * using CONFIG_* outside of __KERNEL__ is wrong,
- * __LP64__ was also removed from headers, so what
- * is the right approach on parisc?
- *     -arnd
- */
-#if (defined(__KERNEL__) && defined(CONFIG_64BIT)) || defined (__LP64__)
-#define __BITS_PER_LONG 64
-#define SHIFT_PER_LONG 6
-#else
-#define __BITS_PER_LONG 32
-#define SHIFT_PER_LONG 5
-#endif
-
-#include <asm-generic/bitsperlong.h>
-
-#endif /* __ASM_PARISC_BITSPERLONG_H */
diff --git a/arch/parisc/include/asm/byteorder.h b/arch/parisc/include/asm/byteorder.h
deleted file mode 100644 (file)
index 58af2c5..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PARISC_BYTEORDER_H
-#define _PARISC_BYTEORDER_H
-
-#include <linux/byteorder/big_endian.h>
-
-#endif /* _PARISC_BYTEORDER_H */
diff --git a/arch/parisc/include/asm/compat_signal.h b/arch/parisc/include/asm/compat_signal.h
deleted file mode 100644 (file)
index 6ad02c3..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-/* Use generic */
-#include <asm-generic/compat_signal.h>
diff --git a/arch/parisc/include/asm/cputime.h b/arch/parisc/include/asm/cputime.h
deleted file mode 100644 (file)
index dcdf2fb..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PARISC_CPUTIME_H
-#define __PARISC_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __PARISC_CPUTIME_H */
diff --git a/arch/parisc/include/asm/device.h b/arch/parisc/include/asm/device.h
deleted file mode 100644 (file)
index d8f9872..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/parisc/include/asm/div64.h b/arch/parisc/include/asm/div64.h
deleted file mode 100644 (file)
index 6cd978c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/div64.h>
diff --git a/arch/parisc/include/asm/emergency-restart.h b/arch/parisc/include/asm/emergency-restart.h
deleted file mode 100644 (file)
index 108d8c4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/parisc/include/asm/errno.h b/arch/parisc/include/asm/errno.h
deleted file mode 100644 (file)
index 135ad60..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-#ifndef _PARISC_ERRNO_H
-#define _PARISC_ERRNO_H
-
-#include <asm-generic/errno-base.h>
-
-#define        ENOMSG          35      /* No message of desired type */
-#define        EIDRM           36      /* Identifier removed */
-#define        ECHRNG          37      /* Channel number out of range */
-#define        EL2NSYNC        38      /* Level 2 not synchronized */
-#define        EL3HLT          39      /* Level 3 halted */
-#define        EL3RST          40      /* Level 3 reset */
-#define        ELNRNG          41      /* Link number out of range */
-#define        EUNATCH         42      /* Protocol driver not attached */
-#define        ENOCSI          43      /* No CSI structure available */
-#define        EL2HLT          44      /* Level 2 halted */
-#define        EDEADLK         45      /* Resource deadlock would occur */
-#define        EDEADLOCK       EDEADLK
-#define        ENOLCK          46      /* No record locks available */
-#define        EILSEQ          47      /* Illegal byte sequence */
-
-#define        ENONET          50      /* Machine is not on the network */
-#define        ENODATA         51      /* No data available */
-#define        ETIME           52      /* Timer expired */
-#define        ENOSR           53      /* Out of streams resources */
-#define        ENOSTR          54      /* Device not a stream */
-#define        ENOPKG          55      /* Package not installed */
-
-#define        ENOLINK         57      /* Link has been severed */
-#define        EADV            58      /* Advertise error */
-#define        ESRMNT          59      /* Srmount error */
-#define        ECOMM           60      /* Communication error on send */
-#define        EPROTO          61      /* Protocol error */
-
-#define        EMULTIHOP       64      /* Multihop attempted */
-
-#define        EDOTDOT         66      /* RFS specific error */
-#define        EBADMSG         67      /* Not a data message */
-#define        EUSERS          68      /* Too many users */
-#define        EDQUOT          69      /* Quota exceeded */
-#define        ESTALE          70      /* Stale NFS file handle */
-#define        EREMOTE         71      /* Object is remote */
-#define        EOVERFLOW       72      /* Value too large for defined data type */
-
-/* these errnos are defined by Linux but not HPUX. */
-
-#define        EBADE           160     /* Invalid exchange */
-#define        EBADR           161     /* Invalid request descriptor */
-#define        EXFULL          162     /* Exchange full */
-#define        ENOANO          163     /* No anode */
-#define        EBADRQC         164     /* Invalid request code */
-#define        EBADSLT         165     /* Invalid slot */
-#define        EBFONT          166     /* Bad font file format */
-#define        ENOTUNIQ        167     /* Name not unique on network */
-#define        EBADFD          168     /* File descriptor in bad state */
-#define        EREMCHG         169     /* Remote address changed */
-#define        ELIBACC         170     /* Can not access a needed shared library */
-#define        ELIBBAD         171     /* Accessing a corrupted shared library */
-#define        ELIBSCN         172     /* .lib section in a.out corrupted */
-#define        ELIBMAX         173     /* Attempting to link in too many shared libraries */
-#define        ELIBEXEC        174     /* Cannot exec a shared library directly */
-#define        ERESTART        175     /* Interrupted system call should be restarted */
-#define        ESTRPIPE        176     /* Streams pipe error */
-#define        EUCLEAN         177     /* Structure needs cleaning */
-#define        ENOTNAM         178     /* Not a XENIX named type file */
-#define        ENAVAIL         179     /* No XENIX semaphores available */
-#define        EISNAM          180     /* Is a named type file */
-#define        EREMOTEIO       181     /* Remote I/O error */
-#define        ENOMEDIUM       182     /* No medium found */
-#define        EMEDIUMTYPE     183     /* Wrong medium type */
-#define        ENOKEY          184     /* Required key not available */
-#define        EKEYEXPIRED     185     /* Key has expired */
-#define        EKEYREVOKED     186     /* Key has been revoked */
-#define        EKEYREJECTED    187     /* Key was rejected by service */
-
-/* We now return you to your regularly scheduled HPUX. */
-
-#define ENOSYM         215     /* symbol does not exist in executable */
-#define        ENOTSOCK        216     /* Socket operation on non-socket */
-#define        EDESTADDRREQ    217     /* Destination address required */
-#define        EMSGSIZE        218     /* Message too long */
-#define        EPROTOTYPE      219     /* Protocol wrong type for socket */
-#define        ENOPROTOOPT     220     /* Protocol not available */
-#define        EPROTONOSUPPORT 221     /* Protocol not supported */
-#define        ESOCKTNOSUPPORT 222     /* Socket type not supported */
-#define        EOPNOTSUPP      223     /* Operation not supported on transport endpoint */
-#define        EPFNOSUPPORT    224     /* Protocol family not supported */
-#define        EAFNOSUPPORT    225     /* Address family not supported by protocol */
-#define        EADDRINUSE      226     /* Address already in use */
-#define        EADDRNOTAVAIL   227     /* Cannot assign requested address */
-#define        ENETDOWN        228     /* Network is down */
-#define        ENETUNREACH     229     /* Network is unreachable */
-#define        ENETRESET       230     /* Network dropped connection because of reset */
-#define        ECONNABORTED    231     /* Software caused connection abort */
-#define        ECONNRESET      232     /* Connection reset by peer */
-#define        ENOBUFS         233     /* No buffer space available */
-#define        EISCONN         234     /* Transport endpoint is already connected */
-#define        ENOTCONN        235     /* Transport endpoint is not connected */
-#define        ESHUTDOWN       236     /* Cannot send after transport endpoint shutdown */
-#define        ETOOMANYREFS    237     /* Too many references: cannot splice */
-#define EREFUSED       ECONNREFUSED    /* for HP's NFS apparently */
-#define        ETIMEDOUT       238     /* Connection timed out */
-#define        ECONNREFUSED    239     /* Connection refused */
-#define EREMOTERELEASE 240     /* Remote peer released connection */
-#define        EHOSTDOWN       241     /* Host is down */
-#define        EHOSTUNREACH    242     /* No route to host */
-
-#define        EALREADY        244     /* Operation already in progress */
-#define        EINPROGRESS     245     /* Operation now in progress */
-#define        EWOULDBLOCK     246     /* Operation would block (Linux returns EAGAIN) */
-#define        ENOTEMPTY       247     /* Directory not empty */
-#define        ENAMETOOLONG    248     /* File name too long */
-#define        ELOOP           249     /* Too many symbolic links encountered */
-#define        ENOSYS          251     /* Function not implemented */
-
-#define ENOTSUP                252     /* Function not implemented (POSIX.4 / HPUX) */
-#define ECANCELLED     253     /* aio request was canceled before complete (POSIX.4 / HPUX) */
-#define ECANCELED      ECANCELLED      /* SuSv3 and Solaris wants one 'L' */
-
-/* for robust mutexes */
-#define EOWNERDEAD     254     /* Owner died */
-#define ENOTRECOVERABLE        255     /* State not recoverable */
-
-#define        ERFKILL         256     /* Operation not possible due to RF-kill */
-
-#define EHWPOISON      257     /* Memory page has hardware error */
-
-#endif
diff --git a/arch/parisc/include/asm/fcntl.h b/arch/parisc/include/asm/fcntl.h
deleted file mode 100644 (file)
index 0304b92..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _PARISC_FCNTL_H
-#define _PARISC_FCNTL_H
-
-#define O_APPEND       000000010
-#define O_BLKSEEK      000000100 /* HPUX only */
-#define O_CREAT                000000400 /* not fcntl */
-#define O_EXCL         000002000 /* not fcntl */
-#define O_LARGEFILE    000004000
-#define __O_SYNC       000100000
-#define O_SYNC         (__O_SYNC|O_DSYNC)
-#define O_NONBLOCK     000200004 /* HPUX has separate NDELAY & NONBLOCK */
-#define O_NOCTTY       000400000 /* not fcntl */
-#define O_DSYNC                001000000 /* HPUX only */
-#define O_RSYNC                002000000 /* HPUX only */
-#define O_NOATIME      004000000
-#define O_CLOEXEC      010000000 /* set close_on_exec */
-
-#define O_DIRECTORY    000010000 /* must be a directory */
-#define O_NOFOLLOW     000000200 /* don't follow links */
-#define O_INVISIBLE    004000000 /* invisible I/O, for DMAPI/XDSM */
-
-#define O_PATH         020000000
-
-#define F_GETLK64      8
-#define F_SETLK64      9
-#define F_SETLKW64     10
-
-#define F_GETOWN       11      /*  for sockets. */
-#define F_SETOWN       12      /*  for sockets. */
-#define F_SETSIG       13      /*  for sockets. */
-#define F_GETSIG       14      /*  for sockets. */
-
-/* for posix fcntl() and lockf() */
-#define F_RDLCK                01
-#define F_WRLCK                02
-#define F_UNLCK                03
-
-#include <asm-generic/fcntl.h>
-
-#endif
diff --git a/arch/parisc/include/asm/hw_irq.h b/arch/parisc/include/asm/hw_irq.h
deleted file mode 100644 (file)
index 6707f7d..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef _ASM_HW_IRQ_H
-#define _ASM_HW_IRQ_H
-
-/*
- *     linux/include/asm/hw_irq.h
- */
-
-#endif
diff --git a/arch/parisc/include/asm/ioctl.h b/arch/parisc/include/asm/ioctl.h
deleted file mode 100644 (file)
index ec8efa0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *    Linux/PA-RISC Project (http://www.parisc-linux.org/)
- *    Copyright (C) 1999,2003 Matthew Wilcox < willy at debian . org >
- *    portions from "linux/ioctl.h for Linux" by H.H. Bergman.
- *
- *    This program is free software; you can redistribute it and/or modify
- *    it under the terms of the GNU General Public License as published by
- *    the Free Software Foundation; either version 2 of the License, or
- *    (at your option) any later version.
- *
- *    This program is distributed in the hope that it will be useful,
- *    but WITHOUT ANY WARRANTY; without even the implied warranty of
- *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *    GNU General Public License for more details.
- *
- *    You should have received a copy of the GNU General Public License
- *    along with this program; if not, write to the Free Software
- *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#ifndef _ASM_PARISC_IOCTL_H
-#define _ASM_PARISC_IOCTL_H
-
-/* ioctl command encoding: 32 bits total, command in lower 16 bits,
- * size of the parameter structure in the lower 14 bits of the
- * upper 16 bits.
- * Encoding the size of the parameter structure in the ioctl request
- * is useful for catching programs compiled with old versions
- * and to avoid overwriting user space outside the user buffer area.
- * The highest 2 bits are reserved for indicating the ``access mode''.
- * NOTE: This limits the max parameter size to 16kB -1 !
- */
-
-/*
- * Direction bits.
- */
-#define _IOC_NONE      0U
-#define _IOC_WRITE     2U
-#define _IOC_READ      1U
-
-#include <asm-generic/ioctl.h>
-
-#endif /* _ASM_PARISC_IOCTL_H */
diff --git a/arch/parisc/include/asm/ioctls.h b/arch/parisc/include/asm/ioctls.h
deleted file mode 100644 (file)
index 054ec06..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-#ifndef __ARCH_PARISC_IOCTLS_H__
-#define __ARCH_PARISC_IOCTLS_H__
-
-#include <asm/ioctl.h>
-
-/* 0x54 is just a magic number to make these relatively unique ('T') */
-
-#define TCGETS         _IOR('T', 16, struct termios) /* TCGETATTR */
-#define TCSETS         _IOW('T', 17, struct termios) /* TCSETATTR */
-#define TCSETSW                _IOW('T', 18, struct termios) /* TCSETATTRD */
-#define TCSETSF                _IOW('T', 19, struct termios) /* TCSETATTRF */
-#define TCGETA         _IOR('T', 1, struct termio)
-#define TCSETA         _IOW('T', 2, struct termio)
-#define TCSETAW                _IOW('T', 3, struct termio)
-#define TCSETAF                _IOW('T', 4, struct termio)
-#define TCSBRK         _IO('T', 5)
-#define TCXONC         _IO('T', 6)
-#define TCFLSH         _IO('T', 7)
-#define TIOCEXCL       0x540C
-#define TIOCNXCL       0x540D
-#define TIOCSCTTY      0x540E
-#define TIOCGPGRP      _IOR('T', 30, int)
-#define TIOCSPGRP      _IOW('T', 29, int)
-#define TIOCOUTQ       0x5411
-#define TIOCSTI                0x5412
-#define TIOCGWINSZ     0x5413
-#define TIOCSWINSZ     0x5414
-#define TIOCMGET       0x5415
-#define TIOCMBIS       0x5416
-#define TIOCMBIC       0x5417
-#define TIOCMSET       0x5418
-#define TIOCGSOFTCAR   0x5419
-#define TIOCSSOFTCAR   0x541A
-#define FIONREAD       0x541B
-#define TIOCINQ                FIONREAD
-#define TIOCLINUX      0x541C
-#define TIOCCONS       0x541D
-#define TIOCGSERIAL    0x541E
-#define TIOCSSERIAL    0x541F
-#define TIOCPKT                0x5420
-#define FIONBIO                0x5421
-#define TIOCNOTTY      0x5422
-#define TIOCSETD       0x5423
-#define TIOCGETD       0x5424
-#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK       0x5427  /* BSD compatibility */
-#define TIOCCBRK       0x5428  /* BSD compatibility */
-#define TIOCGSID       _IOR('T', 20, int) /* Return the session ID of FD */
-#define TCGETS2                _IOR('T',0x2A, struct termios2)
-#define TCSETS2                _IOW('T',0x2B, struct termios2)
-#define TCSETSW2       _IOW('T',0x2C, struct termios2)
-#define TCSETSF2       _IOW('T',0x2D, struct termios2)
-#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCGDEV       _IOR('T',0x32, int)  /* Get primary device node of /dev/console */
-#define TIOCSIG                _IOW('T',0x36, int)  /* Generate signal on Pty slave */
-#define TIOCVHANGUP    0x5437
-
-#define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
-#define FIOCLEX                0x5451
-#define FIOASYNC       0x5452
-#define TIOCSERCONFIG  0x5453
-#define TIOCSERGWILD   0x5454
-#define TIOCSERSWILD   0x5455
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
-#define TIOCSERGETLSR   0x5459 /* Get line status register */
-#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
-#define TIOCSERSETMULTI 0x545B /* Set multiport config */
-
-#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-#define FIOQSIZE       0x5460  /* Get exact space used by quota */
-
-#define TIOCSTART      0x5461
-#define TIOCSTOP       0x5462
-#define TIOCSLTC       0x5462
-
-/* Used for packet mode */
-#define TIOCPKT_DATA            0
-#define TIOCPKT_FLUSHREAD       1
-#define TIOCPKT_FLUSHWRITE      2
-#define TIOCPKT_STOP            4
-#define TIOCPKT_START           8
-#define TIOCPKT_NOSTOP         16
-#define TIOCPKT_DOSTOP         32
-#define TIOCPKT_IOCTL          64
-
-#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
-
-#endif /* _ASM_PARISC_IOCTLS_H */
diff --git a/arch/parisc/include/asm/ipcbuf.h b/arch/parisc/include/asm/ipcbuf.h
deleted file mode 100644 (file)
index bd956c4..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef __PARISC_IPCBUF_H__
-#define __PARISC_IPCBUF_H__
-
-/*
- * The ipc64_perm structure for PA-RISC is almost identical to
- * kern_ipc_perm as we have always had 32-bit UIDs and GIDs in the kernel.
- * 'seq' has been changed from long to int so that it's the same size
- * on 64-bit kernels as on 32-bit ones.
- */
-
-struct ipc64_perm
-{
-       key_t           key;
-       uid_t           uid;
-       gid_t           gid;
-       uid_t           cuid;
-       gid_t           cgid;
-       unsigned short int      __pad1;
-       mode_t          mode;
-       unsigned short int      __pad2;
-       unsigned short int      seq;
-       unsigned int    __pad3;
-       unsigned long long int __unused1;
-       unsigned long long int __unused2;
-};
-
-#endif /* __PARISC_IPCBUF_H__ */
diff --git a/arch/parisc/include/asm/irq_regs.h b/arch/parisc/include/asm/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
diff --git a/arch/parisc/include/asm/kdebug.h b/arch/parisc/include/asm/kdebug.h
deleted file mode 100644 (file)
index 6ece1b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/parisc/include/asm/kvm_para.h b/arch/parisc/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/parisc/include/asm/local.h b/arch/parisc/include/asm/local.h
deleted file mode 100644 (file)
index c11c530..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local.h>
diff --git a/arch/parisc/include/asm/local64.h b/arch/parisc/include/asm/local64.h
deleted file mode 100644 (file)
index 36c93b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/parisc/include/asm/mman.h b/arch/parisc/include/asm/mman.h
deleted file mode 100644 (file)
index 12219eb..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef __PARISC_MMAN_H__
-#define __PARISC_MMAN_H__
-
-#define PROT_READ      0x1             /* page can be read */
-#define PROT_WRITE     0x2             /* page can be written */
-#define PROT_EXEC      0x4             /* page can be executed */
-#define PROT_SEM       0x8             /* page may be used for atomic ops */
-#define PROT_NONE      0x0             /* page can not be accessed */
-#define PROT_GROWSDOWN 0x01000000      /* mprotect flag: extend change to start of growsdown vma */
-#define PROT_GROWSUP   0x02000000      /* mprotect flag: extend change to end of growsup vma */
-
-#define MAP_SHARED     0x01            /* Share changes */
-#define MAP_PRIVATE    0x02            /* Changes are private */
-#define MAP_TYPE       0x03            /* Mask for type of mapping */
-#define MAP_FIXED      0x04            /* Interpret addr exactly */
-#define MAP_ANONYMOUS  0x10            /* don't use a file */
-
-#define MAP_DENYWRITE  0x0800          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
-#define MAP_LOCKED     0x2000          /* pages are locked */
-#define MAP_NORESERVE  0x4000          /* don't check for reservations */
-#define MAP_GROWSDOWN  0x8000          /* stack-like segment */
-#define MAP_POPULATE   0x10000         /* populate (prefault) pagetables */
-#define MAP_NONBLOCK   0x20000         /* do not block on IO */
-#define MAP_STACK      0x40000         /* give out an address that is best suited for process/thread stacks */
-#define MAP_HUGETLB    0x80000         /* create a huge page mapping */
-
-#define MS_SYNC                1               /* synchronous memory sync */
-#define MS_ASYNC       2               /* sync memory asynchronously */
-#define MS_INVALIDATE  4               /* invalidate the caches */
-
-#define MCL_CURRENT    1               /* lock all current mappings */
-#define MCL_FUTURE     2               /* lock all future mappings */
-
-#define MADV_NORMAL     0               /* no further special treatment */
-#define MADV_RANDOM     1               /* expect random page references */
-#define MADV_SEQUENTIAL 2               /* expect sequential page references */
-#define MADV_WILLNEED   3               /* will need these pages */
-#define MADV_DONTNEED   4               /* don't need these pages */
-#define MADV_SPACEAVAIL 5               /* insure that resources are reserved */
-#define MADV_VPS_PURGE  6               /* Purge pages from VM page cache */
-#define MADV_VPS_INHERIT 7              /* Inherit parents page size */
-
-/* common/generic parameters */
-#define MADV_REMOVE    9               /* remove these pages & resources */
-#define MADV_DONTFORK  10              /* don't inherit across fork */
-#define MADV_DOFORK    11              /* do inherit across fork */
-
-/* The range 12-64 is reserved for page size specification. */
-#define MADV_4K_PAGES   12              /* Use 4K pages  */
-#define MADV_16K_PAGES  14              /* Use 16K pages */
-#define MADV_64K_PAGES  16              /* Use 64K pages */
-#define MADV_256K_PAGES 18              /* Use 256K pages */
-#define MADV_1M_PAGES   20              /* Use 1 Megabyte pages */
-#define MADV_4M_PAGES   22              /* Use 4 Megabyte pages */
-#define MADV_16M_PAGES  24              /* Use 16 Megabyte pages */
-#define MADV_64M_PAGES  26              /* Use 64 Megabyte pages */
-
-#define MADV_MERGEABLE   65            /* KSM may merge identical pages */
-#define MADV_UNMERGEABLE 66            /* KSM may not merge identical pages */
-
-#define MADV_HUGEPAGE  67              /* Worth backing with hugepages */
-#define MADV_NOHUGEPAGE        68              /* Not worth backing with hugepages */
-
-#define MADV_DONTDUMP   69             /* Explicity exclude from the core dump,
-                                          overrides the coredump filter bits */
-#define MADV_DODUMP    70              /* Clear the MADV_NODUMP flag */
-
-/* compatibility flags */
-#define MAP_FILE       0
-#define MAP_VARIABLE   0
-
-#endif /* __PARISC_MMAN_H__ */
diff --git a/arch/parisc/include/asm/msgbuf.h b/arch/parisc/include/asm/msgbuf.h
deleted file mode 100644 (file)
index fe88f26..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-#ifndef _PARISC_MSGBUF_H
-#define _PARISC_MSGBUF_H
-
-/* 
- * The msqid64_ds structure for parisc architecture, copied from sparc.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct msqid64_ds {
-       struct ipc64_perm msg_perm;
-#ifndef CONFIG_64BIT
-       unsigned int   __pad1;
-#endif
-       __kernel_time_t msg_stime;      /* last msgsnd time */
-#ifndef CONFIG_64BIT
-       unsigned int   __pad2;
-#endif
-       __kernel_time_t msg_rtime;      /* last msgrcv time */
-#ifndef CONFIG_64BIT
-       unsigned int   __pad3;
-#endif
-       __kernel_time_t msg_ctime;      /* last change time */
-       unsigned int  msg_cbytes;       /* current number of bytes on queue */
-       unsigned int  msg_qnum; /* number of messages in queue */
-       unsigned int  msg_qbytes;       /* max number of bytes on queue */
-       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
-       __kernel_pid_t msg_lrpid;       /* last receive pid */
-       unsigned int  __unused1;
-       unsigned int  __unused2;
-};
-
-#endif /* _PARISC_MSGBUF_H */
diff --git a/arch/parisc/include/asm/mutex.h b/arch/parisc/include/asm/mutex.h
deleted file mode 100644 (file)
index 458c1f7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- * 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/parisc/include/asm/param.h b/arch/parisc/include/asm/param.h
deleted file mode 100644 (file)
index 965d454..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/param.h>
index 7f0f2d23059d3f1acbb1990c04016025446643d2..7eb616e4bf8aee7cc2e89b8b05b11ed9dc76228f 100644 (file)
 #ifndef _PARISC_PDC_H
 #define _PARISC_PDC_H
 
-/*
- *     PDC return values ...
- *     All PDC calls return a subset of these errors. 
- */
-
-#define PDC_WARN                 3     /* Call completed with a warning */
-#define PDC_REQ_ERR_1            2     /* See above                     */
-#define PDC_REQ_ERR_0            1     /* Call would generate a requestor error */
-#define PDC_OK                   0     /* Call completed successfully  */
-#define PDC_BAD_PROC            -1     /* Called non-existent procedure*/
-#define PDC_BAD_OPTION          -2     /* Called with non-existent option */
-#define PDC_ERROR               -3     /* Call could not complete without an error */
-#define PDC_NE_MOD              -5     /* Module not found             */
-#define PDC_NE_CELL_MOD                 -7     /* Cell module not found        */
-#define PDC_INVALID_ARG                -10     /* Called with an invalid argument */
-#define PDC_BUS_POW_WARN       -12     /* Call could not complete in allowed power budget */
-#define PDC_NOT_NARROW         -17     /* Narrow mode not supported    */
-
-/*
- *     PDC entry points...
- */
-
-#define PDC_POW_FAIL   1               /* perform a power-fail         */
-#define PDC_POW_FAIL_PREPARE   0       /* prepare for powerfail        */
-
-#define PDC_CHASSIS    2               /* PDC-chassis functions        */
-#define PDC_CHASSIS_DISP       0       /* update chassis display       */
-#define PDC_CHASSIS_WARN       1       /* return chassis warnings      */
-#define PDC_CHASSIS_DISPWARN   2       /* update&return chassis status */
-#define PDC_RETURN_CHASSIS_INFO 128    /* HVERSION dependent: return chassis LED/LCD info  */
-
-#define PDC_PIM         3               /* Get PIM data                 */
-#define PDC_PIM_HPMC            0       /* Transfer HPMC data           */
-#define PDC_PIM_RETURN_SIZE     1       /* Get Max buffer needed for PIM*/
-#define PDC_PIM_LPMC            2       /* Transfer HPMC data           */
-#define PDC_PIM_SOFT_BOOT       3       /* Transfer Soft Boot data      */
-#define PDC_PIM_TOC             4       /* Transfer TOC data            */
-
-#define PDC_MODEL      4               /* PDC model information call   */
-#define PDC_MODEL_INFO         0       /* returns information          */
-#define PDC_MODEL_BOOTID       1       /* set the BOOT_ID              */
-#define PDC_MODEL_VERSIONS     2       /* returns cpu-internal versions*/
-#define PDC_MODEL_SYSMODEL     3       /* return system model info     */
-#define PDC_MODEL_ENSPEC       4       /* enable specific option       */
-#define PDC_MODEL_DISPEC       5       /* disable specific option      */
-#define PDC_MODEL_CPU_ID       6       /* returns cpu-id (only newer machines!) */
-#define PDC_MODEL_CAPABILITIES 7       /* returns OS32/OS64-flags      */
-/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */
-#define  PDC_MODEL_OS64                        (1 << 0)
-#define  PDC_MODEL_OS32                        (1 << 1)
-#define  PDC_MODEL_IOPDIR_FDC          (1 << 2)
-#define  PDC_MODEL_NVA_MASK            (3 << 4)
-#define  PDC_MODEL_NVA_SUPPORTED       (0 << 4)
-#define  PDC_MODEL_NVA_SLOW            (1 << 4)
-#define  PDC_MODEL_NVA_UNSUPPORTED     (3 << 4)
-#define PDC_MODEL_GET_BOOT__OP 8       /* returns boot test options    */
-#define PDC_MODEL_SET_BOOT__OP 9       /* set boot test options        */
-
-#define PA89_INSTRUCTION_SET   0x4     /* capatibilies returned        */
-#define PA90_INSTRUCTION_SET   0x8
-
-#define PDC_CACHE      5               /* return/set cache (& TLB) info*/
-#define PDC_CACHE_INFO         0       /* returns information          */
-#define PDC_CACHE_SET_COH      1       /* set coherence state          */
-#define PDC_CACHE_RET_SPID     2       /* returns space-ID bits        */
-
-#define PDC_HPA                6               /* return HPA of processor      */
-#define PDC_HPA_PROCESSOR      0
-#define PDC_HPA_MODULES                1
-
-#define PDC_COPROC     7               /* Co-Processor (usually FP unit(s)) */
-#define PDC_COPROC_CFG         0       /* Co-Processor Cfg (FP unit(s) enabled?) */
-
-#define PDC_IODC       8               /* talk to IODC                 */
-#define PDC_IODC_READ          0       /* read IODC entry point        */
-/*      PDC_IODC_RI_                    * INDEX parameter of PDC_IODC_READ */
-#define PDC_IODC_RI_DATA_BYTES 0       /* IODC Data Bytes              */
-/*                             1, 2       obsolete - HVERSION dependent*/
-#define PDC_IODC_RI_INIT       3       /* Initialize module            */
-#define PDC_IODC_RI_IO         4       /* Module input/output          */
-#define PDC_IODC_RI_SPA                5       /* Module input/output          */
-#define PDC_IODC_RI_CONFIG     6       /* Module input/output          */
-/*                             7         obsolete - HVERSION dependent */
-#define PDC_IODC_RI_TEST       8       /* Module input/output          */
-#define PDC_IODC_RI_TLB                9       /* Module input/output          */
-#define PDC_IODC_NINIT         2       /* non-destructive init         */
-#define PDC_IODC_DINIT         3       /* destructive init             */
-#define PDC_IODC_MEMERR                4       /* check for memory errors      */
-#define PDC_IODC_INDEX_DATA    0       /* get first 16 bytes from mod IODC */
-#define PDC_IODC_BUS_ERROR     -4      /* bus error return value       */
-#define PDC_IODC_INVALID_INDEX -5      /* invalid index return value   */
-#define PDC_IODC_COUNT         -6      /* count is too small           */
-
-#define PDC_TOD                9               /* time-of-day clock (TOD)      */
-#define PDC_TOD_READ           0       /* read TOD                     */
-#define PDC_TOD_WRITE          1       /* write TOD                    */
-
-
-#define PDC_STABLE     10              /* stable storage (sprockets)   */
-#define PDC_STABLE_READ                0
-#define PDC_STABLE_WRITE       1
-#define PDC_STABLE_RETURN_SIZE 2
-#define PDC_STABLE_VERIFY_CONTENTS 3
-#define PDC_STABLE_INITIALIZE  4
-
-#define PDC_NVOLATILE  11              /* often not implemented        */
-
-#define PDC_ADD_VALID  12              /* Memory validation PDC call   */
-#define PDC_ADD_VALID_VERIFY   0       /* Make PDC_ADD_VALID verify region */
-
-#define PDC_INSTR      15              /* get instr to invoke PDCE_CHECK() */
-
-#define PDC_PROC       16              /* (sprockets)                  */
-
-#define PDC_CONFIG     16              /* (sprockets)                  */
-#define PDC_CONFIG_DECONFIG    0
-#define PDC_CONFIG_DRECONFIG   1
-#define PDC_CONFIG_DRETURN_CONFIG 2
-
-#define PDC_BLOCK_TLB  18              /* manage hardware block-TLB    */
-#define PDC_BTLB_INFO          0       /* returns parameter            */
-#define PDC_BTLB_INSERT                1       /* insert BTLB entry            */
-#define PDC_BTLB_PURGE         2       /* purge BTLB entries           */
-#define PDC_BTLB_PURGE_ALL     3       /* purge all BTLB entries       */
-
-#define PDC_TLB                19              /* manage hardware TLB miss handling */
-#define PDC_TLB_INFO           0       /* returns parameter            */
-#define PDC_TLB_SETUP          1       /* set up miss handling         */
-
-#define PDC_MEM                20              /* Manage memory                */
-#define PDC_MEM_MEMINFO                0
-#define PDC_MEM_ADD_PAGE       1
-#define PDC_MEM_CLEAR_PDT      2
-#define PDC_MEM_READ_PDT       3
-#define PDC_MEM_RESET_CLEAR    4
-#define PDC_MEM_GOODMEM                5
-#define PDC_MEM_TABLE          128     /* Non contig mem map (sprockets) */
-#define PDC_MEM_RETURN_ADDRESS_TABLE   PDC_MEM_TABLE
-#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE  131
-#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES       132
-#define PDC_MEM_GET_PHYSICAL_LOCATION_FROM_MEMORY_ADDRESS 133
-
-#define PDC_MEM_RET_SBE_REPLACED       5       /* PDC_MEM return values */
-#define PDC_MEM_RET_DUPLICATE_ENTRY    4
-#define PDC_MEM_RET_BUF_SIZE_SMALL     1
-#define PDC_MEM_RET_PDT_FULL           -11
-#define PDC_MEM_RET_INVALID_PHYSICAL_LOCATION ~0ULL
-
-#define PDC_PSW                21              /* Get/Set default System Mask  */
-#define PDC_PSW_MASK           0       /* Return mask                  */
-#define PDC_PSW_GET_DEFAULTS   1       /* Return defaults              */
-#define PDC_PSW_SET_DEFAULTS   2       /* Set default                  */
-#define PDC_PSW_ENDIAN_BIT     1       /* set for big endian           */
-#define PDC_PSW_WIDE_BIT       2       /* set for wide mode            */ 
-
-#define PDC_SYSTEM_MAP 22              /* find system modules          */
-#define PDC_FIND_MODULE        0
-#define PDC_FIND_ADDRESS       1
-#define PDC_TRANSLATE_PATH     2
-
-#define PDC_SOFT_POWER 23              /* soft power switch            */
-#define PDC_SOFT_POWER_INFO    0       /* return info about the soft power switch */
-#define PDC_SOFT_POWER_ENABLE  1       /* enable/disable soft power switch */
-
-
-/* HVERSION dependent */
-
-/* The PDC_MEM_MAP calls */
-#define PDC_MEM_MAP    128             /* on s700: return page info    */
-#define PDC_MEM_MAP_HPA                0       /* returns hpa of a module      */
-
-#define PDC_EEPROM     129             /* EEPROM access                */
-#define PDC_EEPROM_READ_WORD   0
-#define PDC_EEPROM_WRITE_WORD  1
-#define PDC_EEPROM_READ_BYTE   2
-#define PDC_EEPROM_WRITE_BYTE  3
-#define PDC_EEPROM_EEPROM_PASSWORD -1000
-
-#define PDC_NVM                130             /* NVM (non-volatile memory) access */
-#define PDC_NVM_READ_WORD      0
-#define PDC_NVM_WRITE_WORD     1
-#define PDC_NVM_READ_BYTE      2
-#define PDC_NVM_WRITE_BYTE     3
-
-#define PDC_SEED_ERROR 132             /* (sprockets)                  */
-
-#define PDC_IO         135             /* log error info, reset IO system */
-#define PDC_IO_READ_AND_CLEAR_ERRORS   0
-#define PDC_IO_RESET                   1
-#define PDC_IO_RESET_DEVICES           2
-/* sets bits 6&7 (little endian) of the HcControl Register */
-#define PDC_IO_USB_SUSPEND     0xC000000000000000
-#define PDC_IO_EEPROM_IO_ERR_TABLE_FULL        -5      /* return value */
-#define PDC_IO_NO_SUSPEND              -6      /* return value */
-
-#define PDC_BROADCAST_RESET 136                /* reset all processors         */
-#define PDC_DO_RESET           0       /* option: perform a broadcast reset */
-#define PDC_DO_FIRM_TEST_RESET 1       /* Do broadcast reset with bitmap */
-#define PDC_BR_RECONFIGURATION 2       /* reset w/reconfiguration      */
-#define PDC_FIRM_TEST_MAGIC    0xab9ec36fUL    /* for this reboot only */
-
-#define PDC_LAN_STATION_ID 138         /* Hversion dependent mechanism for */
-#define PDC_LAN_STATION_ID_READ        0       /* getting the lan station address  */
-
-#define        PDC_LAN_STATION_ID_SIZE 6
-
-#define PDC_CHECK_RANGES 139           /* (sprockets)                  */
-
-#define PDC_NV_SECTIONS        141             /* (sprockets)                  */
-
-#define PDC_PERFORMANCE        142             /* performance monitoring       */
-
-#define PDC_SYSTEM_INFO        143             /* system information           */
-#define PDC_SYSINFO_RETURN_INFO_SIZE   0
-#define PDC_SYSINFO_RRETURN_SYS_INFO   1
-#define PDC_SYSINFO_RRETURN_ERRORS     2
-#define PDC_SYSINFO_RRETURN_WARNINGS   3
-#define PDC_SYSINFO_RETURN_REVISIONS   4
-#define PDC_SYSINFO_RRETURN_DIAGNOSE   5
-#define PDC_SYSINFO_RRETURN_HV_DIAGNOSE        1005
-
-#define PDC_RDR                144             /* (sprockets)                  */
-#define PDC_RDR_READ_BUFFER    0
-#define PDC_RDR_READ_SINGLE    1
-#define PDC_RDR_WRITE_SINGLE   2
-
-#define PDC_INTRIGUE   145             /* (sprockets)                  */
-#define PDC_INTRIGUE_WRITE_BUFFER       0
-#define PDC_INTRIGUE_GET_SCRATCH_BUFSIZE 1
-#define PDC_INTRIGUE_START_CPU_COUNTERS         2
-#define PDC_INTRIGUE_STOP_CPU_COUNTERS  3
-
-#define PDC_STI                146             /* STI access                   */
-/* same as PDC_PCI_XXX values (see below) */
-
-/* Legacy PDC definitions for same stuff */
-#define PDC_PCI_INDEX  147
-#define PDC_PCI_INTERFACE_INFO         0
-#define PDC_PCI_SLOT_INFO              1
-#define PDC_PCI_INFLIGHT_BYTES         2
-#define PDC_PCI_READ_CONFIG            3
-#define PDC_PCI_WRITE_CONFIG           4
-#define PDC_PCI_READ_PCI_IO            5
-#define PDC_PCI_WRITE_PCI_IO           6
-#define PDC_PCI_READ_CONFIG_DELAY      7
-#define PDC_PCI_UPDATE_CONFIG_DELAY    8
-#define PDC_PCI_PCI_PATH_TO_PCI_HPA    9
-#define PDC_PCI_PCI_HPA_TO_PCI_PATH    10
-#define PDC_PCI_PCI_PATH_TO_PCI_BUS    11
-#define PDC_PCI_PCI_RESERVED           12
-#define PDC_PCI_PCI_INT_ROUTE_SIZE     13
-#define PDC_PCI_GET_INT_TBL_SIZE       PDC_PCI_PCI_INT_ROUTE_SIZE
-#define PDC_PCI_PCI_INT_ROUTE          14
-#define PDC_PCI_GET_INT_TBL            PDC_PCI_PCI_INT_ROUTE 
-#define PDC_PCI_READ_MON_TYPE          15
-#define PDC_PCI_WRITE_MON_TYPE         16
-
-
-/* Get SCSI Interface Card info:  SDTR, SCSI ID, mode (SE vs LVD) */
-#define PDC_INITIATOR  163
-#define PDC_GET_INITIATOR      0
-#define PDC_SET_INITIATOR      1
-#define PDC_DELETE_INITIATOR   2
-#define PDC_RETURN_TABLE_SIZE  3
-#define PDC_RETURN_TABLE       4
-
-#define PDC_LINK       165             /* (sprockets)                  */
-#define PDC_LINK_PCI_ENTRY_POINTS      0  /* list (Arg1) = 0 */
-#define PDC_LINK_USB_ENTRY_POINTS      1  /* list (Arg1) = 1 */
-
-/* cl_class
- * page 3-33 of IO-Firmware ARS
- * IODC ENTRY_INIT(Search first) RET[1]
- */
-#define        CL_NULL         0       /* invalid */
-#define        CL_RANDOM       1       /* random access (as disk) */
-#define        CL_SEQU         2       /* sequential access (as tape) */
-#define        CL_DUPLEX       7       /* full-duplex point-to-point (RS-232, Net) */
-#define        CL_KEYBD        8       /* half-duplex console (HIL Keyboard) */
-#define        CL_DISPL        9       /* half-duplex console (display) */
-#define        CL_FC           10      /* FiberChannel access media */
-
-/* IODC ENTRY_INIT() */
-#define ENTRY_INIT_SRCH_FRST   2
-#define ENTRY_INIT_SRCH_NEXT   3
-#define ENTRY_INIT_MOD_DEV     4
-#define ENTRY_INIT_DEV         5
-#define ENTRY_INIT_MOD         6
-#define ENTRY_INIT_MSG         9
-
-/* IODC ENTRY_IO() */
-#define ENTRY_IO_BOOTIN                0
-#define ENTRY_IO_BOOTOUT       1
-#define ENTRY_IO_CIN           2
-#define ENTRY_IO_COUT          3
-#define ENTRY_IO_CLOSE         4
-#define ENTRY_IO_GETMSG                9
-#define ENTRY_IO_BBLOCK_IN     16
-#define ENTRY_IO_BBLOCK_OUT    17
-
-/* IODC ENTRY_SPA() */
-
-/* IODC ENTRY_CONFIG() */
-
-/* IODC ENTRY_TEST() */
-
-/* IODC ENTRY_TLB() */
-
-/* constants for OS (NVM...) */
-#define OS_ID_NONE             0       /* Undefined OS ID      */
-#define OS_ID_HPUX             1       /* HP-UX OS             */
-#define OS_ID_MPEXL            2       /* MPE XL OS            */
-#define OS_ID_OSF              3       /* OSF OS               */
-#define OS_ID_HPRT             4       /* HP-RT OS             */
-#define OS_ID_NOVEL            5       /* NOVELL OS            */
-#define OS_ID_LINUX            6       /* Linux                */
-
-
-/* constants for PDC_CHASSIS */
-#define OSTAT_OFF              0
-#define OSTAT_FLT              1 
-#define OSTAT_TEST             2
-#define OSTAT_INIT             3
-#define OSTAT_SHUT             4
-#define OSTAT_WARN             5
-#define OSTAT_RUN              6
-#define OSTAT_ON               7
-
-/* Page Zero constant offsets used by the HPMC handler */
-#define BOOT_CONSOLE_HPA_OFFSET  0x3c0
-#define BOOT_CONSOLE_SPA_OFFSET  0x3c4
-#define BOOT_CONSOLE_PATH_OFFSET 0x3a8
-
-/* size of the pdc_result buffer for firmware.c */
-#define NUM_PDC_RESULT 32
+#include <uapi/asm/pdc.h>
 
 #if !defined(__ASSEMBLY__)
 
-#include <linux/types.h>
-
-#ifdef __KERNEL__
-
 extern int pdc_type;
 
 /* Values for pdc_type */
@@ -673,88 +335,5 @@ static inline char * os_id_to_string(u16 os_id) {
        }
 }
 
-#endif /* __KERNEL__ */
-
-/* flags of the device_path */
-#define        PF_AUTOBOOT     0x80
-#define        PF_AUTOSEARCH   0x40
-#define        PF_TIMER        0x0F
-
-struct device_path {           /* page 1-69 */
-       unsigned char flags;    /* flags see above! */
-       unsigned char bc[6];    /* bus converter routing info */
-       unsigned char mod;
-       unsigned int  layers[6];/* device-specific layer-info */
-} __attribute__((aligned(8))) ;
-
-struct pz_device {
-       struct  device_path dp; /* see above */
-       /* struct       iomod *hpa; */
-       unsigned int hpa;       /* HPA base address */
-       /* char *spa; */
-       unsigned int spa;       /* SPA base address */
-       /* int  (*iodc_io)(struct iomod*, ...); */
-       unsigned int iodc_io;   /* device entry point */
-       short   pad;            /* reserved */
-       unsigned short cl_class;/* see below */
-} __attribute__((aligned(8))) ;
-
-struct zeropage {
-       /* [0x000] initialize vectors (VEC) */
-       unsigned int    vec_special;            /* must be zero */
-       /* int  (*vec_pow_fail)(void);*/
-       unsigned int    vec_pow_fail; /* power failure handler */
-       /* int  (*vec_toc)(void); */
-       unsigned int    vec_toc;
-       unsigned int    vec_toclen;
-       /* int  (*vec_rendz)(void); */
-       unsigned int vec_rendz;
-       int     vec_pow_fail_flen;
-       int     vec_pad[10];            
-       
-       /* [0x040] reserved processor dependent */
-       int     pad0[112];
-
-       /* [0x200] reserved */
-       int     pad1[84];
-
-       /* [0x350] memory configuration (MC) */
-       int     memc_cont;              /* contiguous mem size (bytes) */
-       int     memc_phsize;            /* physical memory size */
-       int     memc_adsize;            /* additional mem size, bytes of SPA space used by PDC */
-       unsigned int mem_pdc_hi;        /* used for 64-bit */
-
-       /* [0x360] various parameters for the boot-CPU */
-       /* unsigned int *mem_booterr[8]; */
-       unsigned int mem_booterr[8];    /* ptr to boot errors */
-       unsigned int mem_free;          /* first location, where OS can be loaded */
-       /* struct iomod *mem_hpa; */
-       unsigned int mem_hpa;           /* HPA of the boot-CPU */
-       /* int (*mem_pdc)(int, ...); */
-       unsigned int mem_pdc;           /* PDC entry point */
-       unsigned int mem_10msec;        /* number of clock ticks in 10msec */
-
-       /* [0x390] initial memory module (IMM) */
-       /* struct iomod *imm_hpa; */
-       unsigned int imm_hpa;           /* HPA of the IMM */
-       int     imm_soft_boot;          /* 0 = was hard boot, 1 = was soft boot */
-       unsigned int    imm_spa_size;           /* SPA size of the IMM in bytes */
-       unsigned int    imm_max_mem;            /* bytes of mem in IMM */
-
-       /* [0x3A0] boot console, display device and keyboard */
-       struct pz_device mem_cons;      /* description of console device */
-       struct pz_device mem_boot;      /* description of boot device */
-       struct pz_device mem_kbd;       /* description of keyboard device */
-
-       /* [0x430] reserved */
-       int     pad430[116];
-
-       /* [0x600] processor dependent */
-       __u32   pad600[1];
-       __u32   proc_sti;               /* pointer to STI ROM */
-       __u32   pad608[126];
-};
-
 #endif /* !defined(__ASSEMBLY__) */
-
 #endif /* _PARISC_PDC_H */
diff --git a/arch/parisc/include/asm/percpu.h b/arch/parisc/include/asm/percpu.h
deleted file mode 100644 (file)
index a0dcd19..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _PARISC_PERCPU_H
-#define _PARISC_PERCPU_H
-
-#include <asm-generic/percpu.h>
-
-#endif 
-
diff --git a/arch/parisc/include/asm/poll.h b/arch/parisc/include/asm/poll.h
deleted file mode 100644 (file)
index c98509d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/poll.h>
diff --git a/arch/parisc/include/asm/posix_types.h b/arch/parisc/include/asm/posix_types.h
deleted file mode 100644 (file)
index b934425..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __ARCH_PARISC_POSIX_TYPES_H
-#define __ARCH_PARISC_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned short         __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-
-typedef unsigned short         __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-
-typedef int                    __kernel_suseconds_t;
-#define __kernel_suseconds_t __kernel_suseconds_t
-
-typedef long long              __kernel_off64_t;
-typedef unsigned long long     __kernel_ino64_t;
-
-#include <asm-generic/posix_types.h>
-
-#endif
index 250ae35aa06220d7b4a3072ac447d0b14271eee6..a2db278a5def69c4a6ac4745c3685e45600df156 100644 (file)
@@ -1,49 +1,11 @@
-#ifndef _PARISC_PTRACE_H
-#define _PARISC_PTRACE_H
-
 /* written by Philipp Rumpf, Copyright (C) 1999 SuSE GmbH Nuernberg
 ** Copyright (C) 2000 Grant Grundler, Hewlett-Packard
 */
+#ifndef _PARISC_PTRACE_H
+#define _PARISC_PTRACE_H
 
-#include <linux/types.h>
-
-/* This struct defines the way the registers are stored on the 
- * stack during a system call.
- *
- * N.B. gdb/strace care about the size and offsets within this
- * structure. If you change things, you may break object compatibility
- * for those applications.
- */
-
-struct pt_regs {
-       unsigned long gr[32];   /* PSW is in gr[0] */
-       __u64 fr[32];
-       unsigned long sr[ 8];
-       unsigned long iasq[2];
-       unsigned long iaoq[2];
-       unsigned long cr27;
-       unsigned long pad0;     /* available for other uses */
-       unsigned long orig_r28;
-       unsigned long ksp;
-       unsigned long kpc;
-       unsigned long sar;      /* CR11 */
-       unsigned long iir;      /* CR19 */
-       unsigned long isr;      /* CR20 */
-       unsigned long ior;      /* CR21 */
-       unsigned long ipsw;     /* CR22 */
-};
-
-/*
- * The numbers chosen here are somewhat arbitrary but absolutely MUST
- * not overlap with any of the number assigned in <linux/ptrace.h>.
- *
- * These ones are taken from IA-64 on the assumption that theirs are
- * the most correct (and we also want to support PTRACE_SINGLEBLOCK
- * since we have taken branch traps too)
- */
-#define PTRACE_SINGLEBLOCK     12      /* resume execution until next branch */
+#include <uapi/asm/ptrace.h>
 
-#ifdef __KERNEL__
 
 #define task_regs(task) ((struct pt_regs *) ((char *)(task) + TASK_REGS))
 
@@ -58,6 +20,4 @@ struct pt_regs {
 unsigned long profile_pc(struct pt_regs *);
 
 
-#endif /* __KERNEL__ */
-
 #endif
diff --git a/arch/parisc/include/asm/real.h b/arch/parisc/include/asm/real.h
deleted file mode 100644 (file)
index 82acb25..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#ifndef _PARISC_REAL_H
-#define _PARISC_REAL_H
-
-
-#endif
diff --git a/arch/parisc/include/asm/resource.h b/arch/parisc/include/asm/resource.h
deleted file mode 100644 (file)
index 8b06343..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _ASM_PARISC_RESOURCE_H
-#define _ASM_PARISC_RESOURCE_H
-
-#define _STK_LIM_MAX   10 * _STK_LIM
-#include <asm-generic/resource.h>
-
-#endif
diff --git a/arch/parisc/include/asm/segment.h b/arch/parisc/include/asm/segment.h
deleted file mode 100644 (file)
index 26794dd..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PARISC_SEGMENT_H
-#define __PARISC_SEGMENT_H
-
-/* Only here because we have some old header files that expect it.. */
-
-#endif
diff --git a/arch/parisc/include/asm/sembuf.h b/arch/parisc/include/asm/sembuf.h
deleted file mode 100644 (file)
index 1e59ffd..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef _PARISC_SEMBUF_H
-#define _PARISC_SEMBUF_H
-
-/* 
- * The semid64_ds structure for parisc architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct semid64_ds {
-       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-#ifndef CONFIG_64BIT
-       unsigned int    __pad1;
-#endif
-       __kernel_time_t sem_otime;              /* last semop time */
-#ifndef CONFIG_64BIT
-       unsigned int    __pad2;
-#endif
-       __kernel_time_t sem_ctime;              /* last change time */
-       unsigned int    sem_nsems;              /* no. of semaphores in array */
-       unsigned int    __unused1;
-       unsigned int    __unused2;
-};
-
-#endif /* _PARISC_SEMBUF_H */
diff --git a/arch/parisc/include/asm/setup.h b/arch/parisc/include/asm/setup.h
deleted file mode 100644 (file)
index 7da2e5b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PARISC_SETUP_H
-#define _PARISC_SETUP_H
-
-#define COMMAND_LINE_SIZE      1024
-
-#endif /* _PARISC_SETUP_H */
diff --git a/arch/parisc/include/asm/shmbuf.h b/arch/parisc/include/asm/shmbuf.h
deleted file mode 100644 (file)
index 0a3eada..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef _PARISC_SHMBUF_H
-#define _PARISC_SHMBUF_H
-
-/* 
- * The shmid64_ds structure for parisc architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- */
-
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm;       /* operation perms */
-#ifndef CONFIG_64BIT
-       unsigned int            __pad1;
-#endif
-       __kernel_time_t         shm_atime;      /* last attach time */
-#ifndef CONFIG_64BIT
-       unsigned int            __pad2;
-#endif
-       __kernel_time_t         shm_dtime;      /* last detach time */
-#ifndef CONFIG_64BIT
-       unsigned int            __pad3;
-#endif
-       __kernel_time_t         shm_ctime;      /* last change time */
-#ifndef CONFIG_64BIT
-       unsigned int            __pad4;
-#endif
-       size_t                  shm_segsz;      /* size of segment (bytes) */
-       __kernel_pid_t          shm_cpid;       /* pid of creator */
-       __kernel_pid_t          shm_lpid;       /* pid of last operator */
-       unsigned int            shm_nattch;     /* no. of current attaches */
-       unsigned int            __unused1;
-       unsigned int            __unused2;
-};
-
-#ifdef CONFIG_64BIT
-/* The 'unsigned int' (formerly 'unsigned long') data types below will
- * ensure that a 32-bit app calling shmctl(*,IPC_INFO,*) will work on
- * a wide kernel, but if some of these values are meant to contain pointers
- * they may need to be 'long long' instead. -PB XXX FIXME
- */
-#endif
-struct shminfo64 {
-       unsigned int    shmmax;
-       unsigned int    shmmin;
-       unsigned int    shmmni;
-       unsigned int    shmseg;
-       unsigned int    shmall;
-       unsigned int    __unused1;
-       unsigned int    __unused2;
-       unsigned int    __unused3;
-       unsigned int    __unused4;
-};
-
-#endif /* _PARISC_SHMBUF_H */
diff --git a/arch/parisc/include/asm/sigcontext.h b/arch/parisc/include/asm/sigcontext.h
deleted file mode 100644 (file)
index 27ef31b..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef _ASMPARISC_SIGCONTEXT_H
-#define _ASMPARISC_SIGCONTEXT_H
-
-#define PARISC_SC_FLAG_ONSTACK 1<<0
-#define PARISC_SC_FLAG_IN_SYSCALL 1<<1
-
-/* We will add more stuff here as it becomes necessary, until we know
-   it works. */
-struct sigcontext {
-       unsigned long sc_flags;
-
-       unsigned long sc_gr[32]; /* PSW in sc_gr[0] */
-       unsigned long long sc_fr[32]; /* FIXME, do we need other state info? */
-       unsigned long sc_iasq[2];
-       unsigned long sc_iaoq[2];
-       unsigned long sc_sar; /* cr11 */
-};
-
-
-#endif
diff --git a/arch/parisc/include/asm/siginfo.h b/arch/parisc/include/asm/siginfo.h
deleted file mode 100644 (file)
index d703472..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _PARISC_SIGINFO_H
-#define _PARISC_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#undef NSIGTRAP
-#define NSIGTRAP       4
-
-#endif
index c20356375d1d5630f07d98ed27212b6e5d08a257..21abf4fc169a3086123327a6528dd302498a1b8b 100644 (file)
 #ifndef _ASM_PARISC_SIGNAL_H
 #define _ASM_PARISC_SIGNAL_H
 
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGEMT          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGBUS         10
-#define SIGSEGV                11
-#define SIGSYS         12 /* Linux doesn't use this */
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGUSR1                16
-#define SIGUSR2                17
-#define SIGCHLD                18
-#define SIGPWR         19
-#define SIGVTALRM      20
-#define SIGPROF                21
-#define SIGIO          22
-#define SIGPOLL                SIGIO
-#define SIGWINCH       23
-#define SIGSTOP                24
-#define SIGTSTP                25
-#define SIGCONT                26
-#define SIGTTIN                27
-#define SIGTTOU                28
-#define SIGURG         29
-#define SIGLOST                30 /* Linux doesn't use this either */
-#define        SIGUNUSED       31
-#define SIGRESERVE     SIGUNUSED
+#include <uapi/asm/signal.h>
 
-#define SIGXCPU                33
-#define SIGXFSZ                34
-#define SIGSTKFLT      36
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       37
-#define SIGRTMAX       _NSIG /* it's 44 under HP/UX */
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_ONSTACK     0x00000001
-#define SA_RESETHAND   0x00000004
-#define SA_NOCLDSTOP   0x00000008
-#define SA_SIGINFO     0x00000010
-#define SA_NODEFER     0x00000020
-#define SA_RESTART     0x00000040
-#define SA_NOCLDWAIT   0x00000080
-#define _SA_SIGGFAULT  0x00000100 /* HPUX */
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-#define SA_RESTORER    0x04000000 /* obsolete -- ignored */
-
-/* 
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
-
-#ifdef __KERNEL__
 
 #define _NSIG          64
 /* bits-per-word, where word apparently means 'long' not 'int' */
 #define _NSIG_BPW      BITS_PER_LONG
 #define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
 
-#endif /* __KERNEL__ */
-
-#define SIG_BLOCK          0   /* for blocking signals */
-#define SIG_UNBLOCK        1   /* for unblocking signals */
-#define SIG_SETMASK        2   /* for setting the signal mask */
-
-#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
-#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
-#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
-
 # ifndef __ASSEMBLY__
-
-#  include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-
-/* Type of a signal handler.  */
 #ifdef CONFIG_64BIT
-/* function pointers on 64-bit parisc are pointers to little structs and the
- * compiler doesn't support code which changes or tests the address of
- * the function in the little struct.  This is really ugly -PB
- */
-typedef char __user *__sighandler_t;
 #else
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
 #endif
 
-typedef struct sigaltstack {
-       void __user *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
-
 /* Most things should be clean enough to redefine this at will, if care
    is taken to make libc match.  */
 
@@ -148,6 +38,5 @@ struct k_sigaction {
 
 #include <asm/sigcontext.h>
 
-#endif /* __KERNEL__ */
 #endif /* !__ASSEMBLY */
 #endif /* _ASM_PARISC_SIGNAL_H */
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h
deleted file mode 100644 (file)
index 1b52c2c..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#ifndef _ASM_SOCKET_H
-#define _ASM_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockopt(2) */
-#define SOL_SOCKET     0xffff
-
-#define SO_DEBUG       0x0001
-#define SO_REUSEADDR   0x0004
-#define SO_KEEPALIVE   0x0008
-#define SO_DONTROUTE   0x0010
-#define SO_BROADCAST   0x0020
-#define SO_LINGER      0x0080
-#define SO_OOBINLINE   0x0100
-/* To add :#define SO_REUSEPORT 0x0200 */
-#define SO_SNDBUF      0x1001
-#define SO_RCVBUF      0x1002
-#define SO_SNDBUFFORCE 0x100a
-#define SO_RCVBUFFORCE 0x100b
-#define SO_SNDLOWAT    0x1003
-#define SO_RCVLOWAT    0x1004
-#define SO_SNDTIMEO    0x1005
-#define SO_RCVTIMEO    0x1006
-#define SO_ERROR       0x1007
-#define SO_TYPE                0x1008
-#define SO_PROTOCOL    0x1028
-#define SO_DOMAIN      0x1029
-#define SO_PEERNAME    0x2000
-
-#define SO_NO_CHECK    0x400b
-#define SO_PRIORITY    0x400c
-#define SO_BSDCOMPAT   0x400e
-#define SO_PASSCRED    0x4010
-#define SO_PEERCRED    0x4011
-#define SO_TIMESTAMP   0x4012
-#define SCM_TIMESTAMP  SO_TIMESTAMP
-#define SO_TIMESTAMPNS 0x4013
-#define SCM_TIMESTAMPNS        SO_TIMESTAMPNS
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-#define SO_SECURITY_AUTHENTICATION             0x4016
-#define SO_SECURITY_ENCRYPTION_TRANSPORT       0x4017
-#define SO_SECURITY_ENCRYPTION_NETWORK         0x4018
-
-#define SO_BINDTODEVICE        0x4019
-
-/* Socket filtering */
-#define SO_ATTACH_FILTER        0x401a
-#define SO_DETACH_FILTER        0x401b
-
-#define SO_ACCEPTCONN          0x401c
-
-#define SO_PEERSEC             0x401d
-#define SO_PASSSEC             0x401e
-
-#define SO_MARK                        0x401f
-
-#define SO_TIMESTAMPING                0x4020
-#define SCM_TIMESTAMPING       SO_TIMESTAMPING
-
-#define SO_RXQ_OVFL             0x4021
-
-#define SO_WIFI_STATUS         0x4022
-#define SCM_WIFI_STATUS                SO_WIFI_STATUS
-#define SO_PEEK_OFF            0x4023
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS               0x4024
-
-
-/* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
- * have to define SOCK_NONBLOCK to a different value here.
- */
-#define SOCK_NONBLOCK   0x40000000
-
-#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/asm/sockios.h b/arch/parisc/include/asm/sockios.h
deleted file mode 100644 (file)
index dabfbc7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef __ARCH_PARISC_SOCKIOS__
-#define __ARCH_PARISC_SOCKIOS__
-
-/* Socket-level I/O control calls. */
-#define FIOSETOWN      0x8901
-#define SIOCSPGRP      0x8902
-#define FIOGETOWN      0x8903
-#define SIOCGPGRP      0x8904
-#define SIOCATMARK     0x8905
-#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
-
-#endif
diff --git a/arch/parisc/include/asm/stat.h b/arch/parisc/include/asm/stat.h
deleted file mode 100644 (file)
index d76fbda..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-#ifndef _PARISC_STAT_H
-#define _PARISC_STAT_H
-
-#include <linux/types.h>
-
-struct stat {
-       unsigned int    st_dev;         /* dev_t is 32 bits on parisc */
-       ino_t           st_ino;         /* 32 bits */
-       mode_t          st_mode;        /* 16 bits */
-       unsigned short  st_nlink;       /* 16 bits */
-       unsigned short  st_reserved1;   /* old st_uid */
-       unsigned short  st_reserved2;   /* old st_gid */
-       unsigned int    st_rdev;
-       off_t           st_size;
-       time_t          st_atime;
-       unsigned int    st_atime_nsec;
-       time_t          st_mtime;
-       unsigned int    st_mtime_nsec;
-       time_t          st_ctime;
-       unsigned int    st_ctime_nsec;
-       int             st_blksize;
-       int             st_blocks;
-       unsigned int    __unused1;      /* ACL stuff */
-       unsigned int    __unused2;      /* network */
-       ino_t           __unused3;      /* network */
-       unsigned int    __unused4;      /* cnodes */
-       unsigned short  __unused5;      /* netsite */
-       short           st_fstype;
-       unsigned int    st_realdev;
-       unsigned short  st_basemode;
-       unsigned short  st_spareshort;
-       uid_t           st_uid;
-       gid_t           st_gid;
-       unsigned int    st_spare4[3];
-};
-
-#define STAT_HAVE_NSEC
-
-typedef __kernel_off64_t       off64_t;
-
-struct hpux_stat64 {
-       unsigned int    st_dev;         /* dev_t is 32 bits on parisc */
-       ino_t           st_ino;         /* 32 bits */
-       mode_t          st_mode;        /* 16 bits */
-       unsigned short  st_nlink;       /* 16 bits */
-       unsigned short  st_reserved1;   /* old st_uid */
-       unsigned short  st_reserved2;   /* old st_gid */
-       unsigned int    st_rdev;
-       off64_t         st_size;
-       time_t          st_atime;
-       unsigned int    st_spare1;
-       time_t          st_mtime;
-       unsigned int    st_spare2;
-       time_t          st_ctime;
-       unsigned int    st_spare3;
-       int             st_blksize;
-       __u64           st_blocks;
-       unsigned int    __unused1;      /* ACL stuff */
-       unsigned int    __unused2;      /* network */
-       ino_t           __unused3;      /* network */
-       unsigned int    __unused4;      /* cnodes */
-       unsigned short  __unused5;      /* netsite */
-       short           st_fstype;
-       unsigned int    st_realdev;
-       unsigned short  st_basemode;
-       unsigned short  st_spareshort;
-       uid_t           st_uid;
-       gid_t           st_gid;
-       unsigned int    st_spare4[3];
-};
-
-/* This is the struct that 32-bit userspace applications are expecting.
- * How 64-bit apps are going to be compiled, I have no idea.  But at least
- * this way, we don't have a wrapper in the kernel.
- */
-struct stat64 {
-       unsigned long long      st_dev;
-       unsigned int            __pad1;
-
-       unsigned int            __st_ino;       /* Not actually filled in */
-       unsigned int            st_mode;
-       unsigned int            st_nlink;
-       unsigned int            st_uid;
-       unsigned int            st_gid;
-       unsigned long long      st_rdev;
-       unsigned int            __pad2;
-       signed long long        st_size;
-       signed int              st_blksize;
-
-       signed long long        st_blocks;
-       signed int              st_atime;
-       unsigned int            st_atime_nsec;
-       signed int              st_mtime;
-       unsigned int            st_mtime_nsec;
-       signed int              st_ctime;
-       unsigned int            st_ctime_nsec;
-       unsigned long long      st_ino;
-};
-
-#endif
diff --git a/arch/parisc/include/asm/statfs.h b/arch/parisc/include/asm/statfs.h
deleted file mode 100644 (file)
index 324bea9..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef _PARISC_STATFS_H
-#define _PARISC_STATFS_H
-
-#define __statfs_word long
-#include <asm-generic/statfs.h>
-
-#endif
diff --git a/arch/parisc/include/asm/swab.h b/arch/parisc/include/asm/swab.h
deleted file mode 100644 (file)
index e78403b..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef _PARISC_SWAB_H
-#define _PARISC_SWAB_H
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-#define __SWAB_64_THRU_32__
-
-static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
-{
-       __asm__("dep %0, 15, 8, %0\n\t"         /* deposit 00ab -> 0bab */
-               "shd %%r0, %0, 8, %0"           /* shift 000000ab -> 00ba */
-               : "=r" (x)
-               : "0" (x));
-       return x;
-}
-#define __arch_swab16 __arch_swab16
-
-static inline __attribute_const__ __u32 __arch_swab24(__u32 x)
-{
-       __asm__("shd %0, %0, 8, %0\n\t"         /* shift xabcxabc -> cxab */
-               "dep %0, 15, 8, %0\n\t"         /* deposit cxab -> cbab */
-               "shd %%r0, %0, 8, %0"           /* shift 0000cbab -> 0cba */
-               : "=r" (x)
-               : "0" (x));
-       return x;
-}
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
-{
-       unsigned int temp;
-       __asm__("shd %0, %0, 16, %1\n\t"        /* shift abcdabcd -> cdab */
-               "dep %1, 15, 8, %1\n\t"         /* deposit cdab -> cbab */
-               "shd %0, %1, 8, %0"             /* shift abcdcbab -> dcba */
-               : "=r" (x), "=&r" (temp)
-               : "0" (x));
-       return x;
-}
-#define __arch_swab32 __arch_swab32
-
-#if BITS_PER_LONG > 32
-/*
-** From "PA-RISC 2.0 Architecture", HP Professional Books.
-** See Appendix I page 8 , "Endian Byte Swapping".
-**
-** Pretty cool algorithm: (* == zero'd bits)
-**      PERMH   01234567 -> 67452301 into %0
-**      HSHL    67452301 -> 7*5*3*1* into %1
-**      HSHR    67452301 -> *6*4*2*0 into %0
-**      OR      %0 | %1  -> 76543210 into %0 (all done!)
-*/
-static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
-{
-       __u64 temp;
-       __asm__("permh,3210 %0, %0\n\t"
-               "hshl %0, 8, %1\n\t"
-               "hshr,u %0, 8, %0\n\t"
-               "or %1, %0, %0"
-               : "=r" (x), "=&r" (temp)
-               : "0" (x));
-       return x;
-}
-#define __arch_swab64 __arch_swab64
-#endif /* BITS_PER_LONG > 32 */
-
-#endif /* _PARISC_SWAB_H */
diff --git a/arch/parisc/include/asm/termbits.h b/arch/parisc/include/asm/termbits.h
deleted file mode 100644 (file)
index d1ab921..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef __ARCH_PARISC_TERMBITS_H__
-#define __ARCH_PARISC_TERMBITS_H__
-
-#include <linux/posix_types.h>
-
-typedef unsigned char  cc_t;
-typedef unsigned int   speed_t;
-typedef unsigned int   tcflag_t;
-
-#define NCCS 19
-struct termios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-};
-
-struct termios2 {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-struct ktermios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-/* c_cc characters */
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-
-/* c_iflag bits */
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK  0000020
-#define ISTRIP 0000040
-#define INLCR  0000100
-#define IGNCR  0000200
-#define ICRNL  0000400
-#define IUCLC  0001000
-#define IXON   0002000
-#define IXANY  0004000
-#define IXOFF  0010000
-#define IMAXBEL        0040000
-#define IUTF8  0100000
-
-/* c_oflag bits */
-#define OPOST  0000001
-#define OLCUC  0000002
-#define ONLCR  0000004
-#define OCRNL  0000010
-#define ONOCR  0000020
-#define ONLRET 0000040
-#define OFILL  0000100
-#define OFDEL  0000200
-#define NLDLY  0000400
-#define   NL0  0000000
-#define   NL1  0000400
-#define CRDLY  0003000
-#define   CR0  0000000
-#define   CR1  0001000
-#define   CR2  0002000
-#define   CR3  0003000
-#define TABDLY 0014000
-#define   TAB0 0000000
-#define   TAB1 0004000
-#define   TAB2 0010000
-#define   TAB3 0014000
-#define   XTABS        0014000
-#define BSDLY  0020000
-#define   BS0  0000000
-#define   BS1  0020000
-#define VTDLY  0040000
-#define   VT0  0000000
-#define   VT1  0040000
-#define FFDLY  0100000
-#define   FF0  0000000
-#define   FF1  0100000
-
-/* c_cflag bit meaning */
-#define CBAUD   0010017
-#define  B0     0000000         /* hang up */
-#define  B50    0000001
-#define  B75    0000002
-#define  B110   0000003
-#define  B134   0000004
-#define  B150   0000005
-#define  B200   0000006
-#define  B300   0000007
-#define  B600   0000010
-#define  B1200  0000011
-#define  B1800  0000012
-#define  B2400  0000013
-#define  B4800  0000014
-#define  B9600  0000015
-#define  B19200 0000016
-#define  B38400 0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE   0000060
-#define   CS5   0000000
-#define   CS6   0000020
-#define   CS7   0000040
-#define   CS8   0000060
-#define CSTOPB  0000100
-#define CREAD   0000200
-#define PARENB  0000400
-#define PARODD  0001000
-#define HUPCL   0002000
-#define CLOCAL  0004000
-#define CBAUDEX 0010000
-#define    BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD    002003600000         /* input baud rate */
-#define CMSPAR    010000000000          /* mark or space (stick) parity */
-#define CRTSCTS   020000000000          /* flow control */
-
-#define IBSHIFT        16              /* Shift from CBAUD to CIBAUD */
-
-
-/* c_lflag bits */
-#define ISIG    0000001
-#define ICANON  0000002
-#define XCASE   0000004
-#define ECHO    0000010
-#define ECHOE   0000020
-#define ECHOK   0000040
-#define ECHONL  0000100
-#define NOFLSH  0000200
-#define TOSTOP  0000400
-#define ECHOCTL 0001000
-#define ECHOPRT 0002000
-#define ECHOKE  0004000
-#define FLUSHO  0010000
-#define PENDIN  0040000
-#define IEXTEN  0100000
-#define EXTPROC        0200000
-
-/* tcflow() and TCXONC use these */
-#define        TCOOFF          0
-#define        TCOON           1
-#define        TCIOFF          2
-#define        TCION           3
-
-/* tcflush() and TCFLSH use these */
-#define        TCIFLUSH        0
-#define        TCOFLUSH        1
-#define        TCIOFLUSH       2
-
-/* tcsetattr uses these */
-#define        TCSANOW         0
-#define        TCSADRAIN       1
-#define        TCSAFLUSH       2
-
-#endif
index a2a57a4548af7bd6d7c745a54d755d6a8fa0418e..9bbc0c8974ea90fc6fc6b68c4614936007512952 100644 (file)
@@ -1,45 +1,8 @@
 #ifndef _PARISC_TERMIOS_H
 #define _PARISC_TERMIOS_H
 
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
+#include <uapi/asm/termios.h>
 
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-/* modem lines */
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
 
 /*     intr=^C         quit=^\         erase=del       kill=^U
        eof=^D          vtime=\0        vmin=\1         sxtc=\0
@@ -85,6 +48,4 @@ struct termio {
 #define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
 #define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
 
-#endif /* __KERNEL__ */
-
 #endif /* _PARISC_TERMIOS_H */
diff --git a/arch/parisc/include/asm/topology.h b/arch/parisc/include/asm/topology.h
deleted file mode 100644 (file)
index d8133eb..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_PARISC_TOPOLOGY_H
-#define _ASM_PARISC_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _ASM_PARISC_TOPOLOGY_H */
diff --git a/arch/parisc/include/asm/types.h b/arch/parisc/include/asm/types.h
deleted file mode 100644 (file)
index 8866f9b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _PARISC_TYPES_H
-#define _PARISC_TYPES_H
-
-#include <asm-generic/int-ll64.h>
-
-#endif
index d61de64f990af771e6d56a41beda7473f062060f..541639c3f60717487015518a5336475346ff5639 100644 (file)
@@ -1,840 +1,8 @@
 #ifndef _ASM_PARISC_UNISTD_H_
 #define _ASM_PARISC_UNISTD_H_
 
-/*
- * This file contains the system call numbers.
- */
-
-/*
- *   HP-UX system calls get their native numbers for binary compatibility.
- */
-
-#define __NR_HPUX_exit                    1
-#define __NR_HPUX_fork                    2
-#define __NR_HPUX_read                    3
-#define __NR_HPUX_write                   4
-#define __NR_HPUX_open                    5
-#define __NR_HPUX_close                   6
-#define __NR_HPUX_wait                    7
-#define __NR_HPUX_creat                   8
-#define __NR_HPUX_link                    9
-#define __NR_HPUX_unlink                 10
-#define __NR_HPUX_execv                  11
-#define __NR_HPUX_chdir                  12
-#define __NR_HPUX_time                   13
-#define __NR_HPUX_mknod                  14
-#define __NR_HPUX_chmod                  15
-#define __NR_HPUX_chown                  16
-#define __NR_HPUX_break                  17
-#define __NR_HPUX_lchmod                 18
-#define __NR_HPUX_lseek                  19
-#define __NR_HPUX_getpid                 20
-#define __NR_HPUX_mount                  21
-#define __NR_HPUX_umount                 22
-#define __NR_HPUX_setuid                 23
-#define __NR_HPUX_getuid                 24
-#define __NR_HPUX_stime                  25
-#define __NR_HPUX_ptrace                 26
-#define __NR_HPUX_alarm                  27
-#define __NR_HPUX_oldfstat               28
-#define __NR_HPUX_pause                  29
-#define __NR_HPUX_utime                  30
-#define __NR_HPUX_stty                   31
-#define __NR_HPUX_gtty                   32
-#define __NR_HPUX_access                 33
-#define __NR_HPUX_nice                   34
-#define __NR_HPUX_ftime                  35
-#define __NR_HPUX_sync                   36
-#define __NR_HPUX_kill                   37
-#define __NR_HPUX_stat                   38
-#define __NR_HPUX_setpgrp3               39
-#define __NR_HPUX_lstat                  40
-#define __NR_HPUX_dup                    41
-#define __NR_HPUX_pipe                   42
-#define __NR_HPUX_times                  43
-#define __NR_HPUX_profil                 44
-#define __NR_HPUX_ki_call                45
-#define __NR_HPUX_setgid                 46
-#define __NR_HPUX_getgid                 47
-#define __NR_HPUX_sigsys                 48
-#define __NR_HPUX_reserved1              49
-#define __NR_HPUX_reserved2              50
-#define __NR_HPUX_acct                   51
-#define __NR_HPUX_set_userthreadid       52
-#define __NR_HPUX_oldlock                53
-#define __NR_HPUX_ioctl                  54
-#define __NR_HPUX_reboot                 55
-#define __NR_HPUX_symlink                56
-#define __NR_HPUX_utssys                 57
-#define __NR_HPUX_readlink               58
-#define __NR_HPUX_execve                 59
-#define __NR_HPUX_umask                  60
-#define __NR_HPUX_chroot                 61
-#define __NR_HPUX_fcntl                  62
-#define __NR_HPUX_ulimit                 63
-#define __NR_HPUX_getpagesize            64
-#define __NR_HPUX_mremap                 65
-#define __NR_HPUX_vfork                  66
-#define __NR_HPUX_vread                  67
-#define __NR_HPUX_vwrite                 68
-#define __NR_HPUX_sbrk                   69
-#define __NR_HPUX_sstk                   70
-#define __NR_HPUX_mmap                   71
-#define __NR_HPUX_vadvise                72
-#define __NR_HPUX_munmap                 73
-#define __NR_HPUX_mprotect               74
-#define __NR_HPUX_madvise                75
-#define __NR_HPUX_vhangup                76
-#define __NR_HPUX_swapoff                77
-#define __NR_HPUX_mincore                78
-#define __NR_HPUX_getgroups              79
-#define __NR_HPUX_setgroups              80
-#define __NR_HPUX_getpgrp2               81
-#define __NR_HPUX_setpgrp2               82
-#define __NR_HPUX_setitimer              83
-#define __NR_HPUX_wait3                  84
-#define __NR_HPUX_swapon                 85
-#define __NR_HPUX_getitimer              86
-#define __NR_HPUX_gethostname42          87
-#define __NR_HPUX_sethostname42          88
-#define __NR_HPUX_getdtablesize          89
-#define __NR_HPUX_dup2                   90
-#define __NR_HPUX_getdopt                91
-#define __NR_HPUX_fstat                  92
-#define __NR_HPUX_select                 93
-#define __NR_HPUX_setdopt                94
-#define __NR_HPUX_fsync                  95
-#define __NR_HPUX_setpriority            96
-#define __NR_HPUX_socket_old             97
-#define __NR_HPUX_connect_old            98
-#define __NR_HPUX_accept_old             99
-#define __NR_HPUX_getpriority           100
-#define __NR_HPUX_send_old              101
-#define __NR_HPUX_recv_old              102
-#define __NR_HPUX_socketaddr_old        103
-#define __NR_HPUX_bind_old              104
-#define __NR_HPUX_setsockopt_old        105
-#define __NR_HPUX_listen_old            106
-#define __NR_HPUX_vtimes_old            107
-#define __NR_HPUX_sigvector             108
-#define __NR_HPUX_sigblock              109
-#define __NR_HPUX_siggetmask            110
-#define __NR_HPUX_sigpause              111
-#define __NR_HPUX_sigstack              112
-#define __NR_HPUX_recvmsg_old           113
-#define __NR_HPUX_sendmsg_old           114
-#define __NR_HPUX_vtrace_old            115
-#define __NR_HPUX_gettimeofday          116
-#define __NR_HPUX_getrusage             117
-#define __NR_HPUX_getsockopt_old        118
-#define __NR_HPUX_resuba_old            119
-#define __NR_HPUX_readv                 120
-#define __NR_HPUX_writev                121
-#define __NR_HPUX_settimeofday          122
-#define __NR_HPUX_fchown                123
-#define __NR_HPUX_fchmod                124
-#define __NR_HPUX_recvfrom_old          125
-#define __NR_HPUX_setresuid             126
-#define __NR_HPUX_setresgid             127
-#define __NR_HPUX_rename                128
-#define __NR_HPUX_truncate              129
-#define __NR_HPUX_ftruncate             130
-#define __NR_HPUX_flock_old             131
-#define __NR_HPUX_sysconf               132
-#define __NR_HPUX_sendto_old            133
-#define __NR_HPUX_shutdown_old          134
-#define __NR_HPUX_socketpair_old        135
-#define __NR_HPUX_mkdir                 136
-#define __NR_HPUX_rmdir                 137
-#define __NR_HPUX_utimes_old            138
-#define __NR_HPUX_sigcleanup_old        139
-#define __NR_HPUX_setcore               140
-#define __NR_HPUX_getpeername_old       141
-#define __NR_HPUX_gethostid             142
-#define __NR_HPUX_sethostid             143
-#define __NR_HPUX_getrlimit             144
-#define __NR_HPUX_setrlimit             145
-#define __NR_HPUX_killpg_old            146
-#define __NR_HPUX_cachectl              147
-#define __NR_HPUX_quotactl              148
-#define __NR_HPUX_get_sysinfo           149
-#define __NR_HPUX_getsockname_old       150
-#define __NR_HPUX_privgrp               151
-#define __NR_HPUX_rtprio                152
-#define __NR_HPUX_plock                 153
-#define __NR_HPUX_reserved3             154
-#define __NR_HPUX_lockf                 155
-#define __NR_HPUX_semget                156
-#define __NR_HPUX_osemctl               157
-#define __NR_HPUX_semop                 158
-#define __NR_HPUX_msgget                159
-#define __NR_HPUX_omsgctl               160
-#define __NR_HPUX_msgsnd                161
-#define __NR_HPUX_msgrecv               162
-#define __NR_HPUX_shmget                163
-#define __NR_HPUX_oshmctl               164
-#define __NR_HPUX_shmat                 165
-#define __NR_HPUX_shmdt                 166
-#define __NR_HPUX_m68020_advise         167
-/* [168,189] are for Discless/DUX */
-#define __NR_HPUX_csp                   168
-#define __NR_HPUX_cluster               169
-#define __NR_HPUX_mkrnod                170
-#define __NR_HPUX_test                  171
-#define __NR_HPUX_unsp_open             172
-#define __NR_HPUX_reserved4             173
-#define __NR_HPUX_getcontext_old        174
-#define __NR_HPUX_osetcontext           175
-#define __NR_HPUX_bigio                 176
-#define __NR_HPUX_pipenode              177
-#define __NR_HPUX_lsync                 178
-#define __NR_HPUX_getmachineid          179
-#define __NR_HPUX_cnodeid               180
-#define __NR_HPUX_cnodes                181
-#define __NR_HPUX_swapclients           182
-#define __NR_HPUX_rmt_process           183
-#define __NR_HPUX_dskless_stats         184
-#define __NR_HPUX_sigprocmask           185
-#define __NR_HPUX_sigpending            186
-#define __NR_HPUX_sigsuspend            187
-#define __NR_HPUX_sigaction             188
-#define __NR_HPUX_reserved5             189
-#define __NR_HPUX_nfssvc                190
-#define __NR_HPUX_getfh                 191
-#define __NR_HPUX_getdomainname         192
-#define __NR_HPUX_setdomainname         193
-#define __NR_HPUX_async_daemon          194
-#define __NR_HPUX_getdirentries         195
-#define __NR_HPUX_statfs                196
-#define __NR_HPUX_fstatfs               197
-#define __NR_HPUX_vfsmount              198
-#define __NR_HPUX_reserved6             199
-#define __NR_HPUX_waitpid               200
-/* 201 - 223 missing */
-#define __NR_HPUX_sigsetreturn          224
-#define __NR_HPUX_sigsetstatemask       225
-/* 226 missing */
-#define __NR_HPUX_cs                    227
-#define __NR_HPUX_cds                   228
-#define __NR_HPUX_set_no_trunc          229
-#define __NR_HPUX_pathconf              230
-#define __NR_HPUX_fpathconf             231
-/* 232, 233 missing */
-#define __NR_HPUX_nfs_fcntl             234
-#define __NR_HPUX_ogetacl               235
-#define __NR_HPUX_ofgetacl              236
-#define __NR_HPUX_osetacl               237
-#define __NR_HPUX_ofsetacl              238
-#define __NR_HPUX_pstat                 239
-#define __NR_HPUX_getaudid              240
-#define __NR_HPUX_setaudid              241
-#define __NR_HPUX_getaudproc            242
-#define __NR_HPUX_setaudproc            243
-#define __NR_HPUX_getevent              244
-#define __NR_HPUX_setevent              245
-#define __NR_HPUX_audwrite              246
-#define __NR_HPUX_audswitch             247
-#define __NR_HPUX_audctl                248
-#define __NR_HPUX_ogetaccess            249
-#define __NR_HPUX_fsctl                 250
-/* 251 - 258 missing */
-#define __NR_HPUX_swapfs                259
-#define __NR_HPUX_fss                   260
-/* 261 - 266 missing */
-#define __NR_HPUX_tsync                 267
-#define __NR_HPUX_getnumfds             268
-#define __NR_HPUX_poll                  269
-#define __NR_HPUX_getmsg                270
-#define __NR_HPUX_putmsg                271
-#define __NR_HPUX_fchdir                272
-#define __NR_HPUX_getmount_cnt          273
-#define __NR_HPUX_getmount_entry        274
-#define __NR_HPUX_accept                275
-#define __NR_HPUX_bind                  276
-#define __NR_HPUX_connect               277
-#define __NR_HPUX_getpeername           278
-#define __NR_HPUX_getsockname           279
-#define __NR_HPUX_getsockopt            280
-#define __NR_HPUX_listen                281
-#define __NR_HPUX_recv                  282
-#define __NR_HPUX_recvfrom              283
-#define __NR_HPUX_recvmsg               284
-#define __NR_HPUX_send                  285
-#define __NR_HPUX_sendmsg               286
-#define __NR_HPUX_sendto                287
-#define __NR_HPUX_setsockopt            288
-#define __NR_HPUX_shutdown              289
-#define __NR_HPUX_socket                290
-#define __NR_HPUX_socketpair            291
-#define __NR_HPUX_proc_open             292
-#define __NR_HPUX_proc_close            293
-#define __NR_HPUX_proc_send             294
-#define __NR_HPUX_proc_recv             295
-#define __NR_HPUX_proc_sendrecv         296
-#define __NR_HPUX_proc_syscall          297
-/* 298 - 311 missing */
-#define __NR_HPUX_semctl                312
-#define __NR_HPUX_msgctl                313
-#define __NR_HPUX_shmctl                314
-#define __NR_HPUX_mpctl                 315
-#define __NR_HPUX_exportfs              316
-#define __NR_HPUX_getpmsg               317
-#define __NR_HPUX_putpmsg               318
-/* 319 missing */
-#define __NR_HPUX_msync                 320
-#define __NR_HPUX_msleep                321
-#define __NR_HPUX_mwakeup               322
-#define __NR_HPUX_msem_init             323
-#define __NR_HPUX_msem_remove           324
-#define __NR_HPUX_adjtime               325
-#define __NR_HPUX_kload                 326
-#define __NR_HPUX_fattach               327
-#define __NR_HPUX_fdetach               328
-#define __NR_HPUX_serialize             329
-#define __NR_HPUX_statvfs               330
-#define __NR_HPUX_fstatvfs              331
-#define __NR_HPUX_lchown                332
-#define __NR_HPUX_getsid                333
-#define __NR_HPUX_sysfs                 334
-/* 335, 336 missing */
-#define __NR_HPUX_sched_setparam        337
-#define __NR_HPUX_sched_getparam        338
-#define __NR_HPUX_sched_setscheduler    339
-#define __NR_HPUX_sched_getscheduler    340
-#define __NR_HPUX_sched_yield           341
-#define __NR_HPUX_sched_get_priority_max 342
-#define __NR_HPUX_sched_get_priority_min 343
-#define __NR_HPUX_sched_rr_get_interval 344
-#define __NR_HPUX_clock_settime         345
-#define __NR_HPUX_clock_gettime         346
-#define __NR_HPUX_clock_getres          347
-#define __NR_HPUX_timer_create          348
-#define __NR_HPUX_timer_delete          349
-#define __NR_HPUX_timer_settime         350
-#define __NR_HPUX_timer_gettime         351
-#define __NR_HPUX_timer_getoverrun      352
-#define __NR_HPUX_nanosleep             353
-#define __NR_HPUX_toolbox               354
-/* 355 missing */
-#define __NR_HPUX_getdents              356
-#define __NR_HPUX_getcontext            357
-#define __NR_HPUX_sysinfo               358
-#define __NR_HPUX_fcntl64               359
-#define __NR_HPUX_ftruncate64           360
-#define __NR_HPUX_fstat64               361
-#define __NR_HPUX_getdirentries64       362
-#define __NR_HPUX_getrlimit64           363
-#define __NR_HPUX_lockf64               364
-#define __NR_HPUX_lseek64               365
-#define __NR_HPUX_lstat64               366
-#define __NR_HPUX_mmap64                367
-#define __NR_HPUX_setrlimit64           368
-#define __NR_HPUX_stat64                369
-#define __NR_HPUX_truncate64            370
-#define __NR_HPUX_ulimit64              371
-#define __NR_HPUX_pread                 372
-#define __NR_HPUX_preadv                373
-#define __NR_HPUX_pwrite                374
-#define __NR_HPUX_pwritev               375
-#define __NR_HPUX_pread64               376
-#define __NR_HPUX_preadv64              377
-#define __NR_HPUX_pwrite64              378
-#define __NR_HPUX_pwritev64             379
-#define __NR_HPUX_setcontext            380
-#define __NR_HPUX_sigaltstack           381
-#define __NR_HPUX_waitid                382
-#define __NR_HPUX_setpgrp               383
-#define __NR_HPUX_recvmsg2              384
-#define __NR_HPUX_sendmsg2              385
-#define __NR_HPUX_socket2               386
-#define __NR_HPUX_socketpair2           387
-#define __NR_HPUX_setregid              388
-#define __NR_HPUX_lwp_create            389
-#define __NR_HPUX_lwp_terminate         390
-#define __NR_HPUX_lwp_wait              391
-#define __NR_HPUX_lwp_suspend           392
-#define __NR_HPUX_lwp_resume            393
-/* 394 missing */
-#define __NR_HPUX_lwp_abort_syscall     395
-#define __NR_HPUX_lwp_info              396
-#define __NR_HPUX_lwp_kill              397
-#define __NR_HPUX_ksleep                398
-#define __NR_HPUX_kwakeup               399
-/* 400 missing */
-#define __NR_HPUX_pstat_getlwp          401
-#define __NR_HPUX_lwp_exit              402
-#define __NR_HPUX_lwp_continue          403
-#define __NR_HPUX_getacl                404
-#define __NR_HPUX_fgetacl               405
-#define __NR_HPUX_setacl                406
-#define __NR_HPUX_fsetacl               407
-#define __NR_HPUX_getaccess             408
-#define __NR_HPUX_lwp_mutex_init        409
-#define __NR_HPUX_lwp_mutex_lock_sys    410
-#define __NR_HPUX_lwp_mutex_unlock      411
-#define __NR_HPUX_lwp_cond_init         412
-#define __NR_HPUX_lwp_cond_signal       413
-#define __NR_HPUX_lwp_cond_broadcast    414
-#define __NR_HPUX_lwp_cond_wait_sys     415
-#define __NR_HPUX_lwp_getscheduler      416
-#define __NR_HPUX_lwp_setscheduler      417
-#define __NR_HPUX_lwp_getstate          418
-#define __NR_HPUX_lwp_setstate          419
-#define __NR_HPUX_lwp_detach            420
-#define __NR_HPUX_mlock                 421
-#define __NR_HPUX_munlock               422
-#define __NR_HPUX_mlockall              423
-#define __NR_HPUX_munlockall            424
-#define __NR_HPUX_shm_open              425
-#define __NR_HPUX_shm_unlink            426
-#define __NR_HPUX_sigqueue              427
-#define __NR_HPUX_sigwaitinfo           428
-#define __NR_HPUX_sigtimedwait          429
-#define __NR_HPUX_sigwait               430
-#define __NR_HPUX_aio_read              431
-#define __NR_HPUX_aio_write             432
-#define __NR_HPUX_lio_listio            433
-#define __NR_HPUX_aio_error             434
-#define __NR_HPUX_aio_return            435
-#define __NR_HPUX_aio_cancel            436
-#define __NR_HPUX_aio_suspend           437
-#define __NR_HPUX_aio_fsync             438
-#define __NR_HPUX_mq_open               439
-#define __NR_HPUX_mq_close              440
-#define __NR_HPUX_mq_unlink             441
-#define __NR_HPUX_mq_send               442
-#define __NR_HPUX_mq_receive            443
-#define __NR_HPUX_mq_notify             444
-#define __NR_HPUX_mq_setattr            445
-#define __NR_HPUX_mq_getattr            446
-#define __NR_HPUX_ksem_open             447
-#define __NR_HPUX_ksem_unlink           448
-#define __NR_HPUX_ksem_close            449
-#define __NR_HPUX_ksem_post             450
-#define __NR_HPUX_ksem_wait             451
-#define __NR_HPUX_ksem_read             452
-#define __NR_HPUX_ksem_trywait          453
-#define __NR_HPUX_lwp_rwlock_init       454
-#define __NR_HPUX_lwp_rwlock_destroy    455
-#define __NR_HPUX_lwp_rwlock_rdlock_sys 456
-#define __NR_HPUX_lwp_rwlock_wrlock_sys 457
-#define __NR_HPUX_lwp_rwlock_tryrdlock  458
-#define __NR_HPUX_lwp_rwlock_trywrlock  459
-#define __NR_HPUX_lwp_rwlock_unlock     460
-#define __NR_HPUX_ttrace                461
-#define __NR_HPUX_ttrace_wait           462
-#define __NR_HPUX_lf_wire_mem           463
-#define __NR_HPUX_lf_unwire_mem         464
-#define __NR_HPUX_lf_send_pin_map       465
-#define __NR_HPUX_lf_free_buf           466
-#define __NR_HPUX_lf_wait_nq            467
-#define __NR_HPUX_lf_wakeup_conn_q      468
-#define __NR_HPUX_lf_unused             469
-#define __NR_HPUX_lwp_sema_init         470
-#define __NR_HPUX_lwp_sema_post         471
-#define __NR_HPUX_lwp_sema_wait         472
-#define __NR_HPUX_lwp_sema_trywait      473
-#define __NR_HPUX_lwp_sema_destroy      474
-#define __NR_HPUX_statvfs64             475
-#define __NR_HPUX_fstatvfs64            476
-#define __NR_HPUX_msh_register          477
-#define __NR_HPUX_ptrace64              478
-#define __NR_HPUX_sendfile              479
-#define __NR_HPUX_sendpath              480
-#define __NR_HPUX_sendfile64            481
-#define __NR_HPUX_sendpath64            482
-#define __NR_HPUX_modload               483
-#define __NR_HPUX_moduload              484
-#define __NR_HPUX_modpath               485
-#define __NR_HPUX_getksym               486
-#define __NR_HPUX_modadm                487
-#define __NR_HPUX_modstat               488
-#define __NR_HPUX_lwp_detached_exit     489
-#define __NR_HPUX_crashconf             490
-#define __NR_HPUX_siginhibit            491
-#define __NR_HPUX_sigenable             492
-#define __NR_HPUX_spuctl                493
-#define __NR_HPUX_zerokernelsum         494
-#define __NR_HPUX_nfs_kstat             495
-#define __NR_HPUX_aio_read64            496
-#define __NR_HPUX_aio_write64           497
-#define __NR_HPUX_aio_error64           498
-#define __NR_HPUX_aio_return64          499
-#define __NR_HPUX_aio_cancel64          500
-#define __NR_HPUX_aio_suspend64         501
-#define __NR_HPUX_aio_fsync64           502
-#define __NR_HPUX_lio_listio64          503
-#define __NR_HPUX_recv2                 504
-#define __NR_HPUX_recvfrom2             505
-#define __NR_HPUX_send2                 506
-#define __NR_HPUX_sendto2               507
-#define __NR_HPUX_acl                   508
-#define __NR_HPUX___cnx_p2p_ctl         509
-#define __NR_HPUX___cnx_gsched_ctl      510
-#define __NR_HPUX___cnx_pmon_ctl        511
-
-#define __NR_HPUX_syscalls             512
-
-/*
- * Linux system call numbers.
- *
- * Cary Coutant says that we should just use another syscall gateway
- * page to avoid clashing with the HPUX space, and I think he's right:
- * it will would keep a branch out of our syscall entry path, at the
- * very least.  If we decide to change it later, we can ``just'' tweak
- * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be
- * 1024 or something.  Oh, and recompile libc. =)
- *
- * 64-bit HPUX binaries get the syscall gateway address passed in a register
- * from the kernel at startup, which seems a sane strategy.
- */
-
-#define __NR_Linux                0
-#define __NR_restart_syscall      (__NR_Linux + 0)
-#define __NR_exit                 (__NR_Linux + 1)
-#define __NR_fork                 (__NR_Linux + 2)
-#define __NR_read                 (__NR_Linux + 3)
-#define __NR_write                (__NR_Linux + 4)
-#define __NR_open                 (__NR_Linux + 5)
-#define __NR_close                (__NR_Linux + 6)
-#define __NR_waitpid              (__NR_Linux + 7)
-#define __NR_creat                (__NR_Linux + 8)
-#define __NR_link                 (__NR_Linux + 9)
-#define __NR_unlink              (__NR_Linux + 10)
-#define __NR_execve              (__NR_Linux + 11)
-#define __NR_chdir               (__NR_Linux + 12)
-#define __NR_time                (__NR_Linux + 13)
-#define __NR_mknod               (__NR_Linux + 14)
-#define __NR_chmod               (__NR_Linux + 15)
-#define __NR_lchown              (__NR_Linux + 16)
-#define __NR_socket              (__NR_Linux + 17)
-#define __NR_stat                (__NR_Linux + 18)
-#define __NR_lseek               (__NR_Linux + 19)
-#define __NR_getpid              (__NR_Linux + 20)
-#define __NR_mount               (__NR_Linux + 21)
-#define __NR_bind                (__NR_Linux + 22)
-#define __NR_setuid              (__NR_Linux + 23)
-#define __NR_getuid              (__NR_Linux + 24)
-#define __NR_stime               (__NR_Linux + 25)
-#define __NR_ptrace              (__NR_Linux + 26)
-#define __NR_alarm               (__NR_Linux + 27)
-#define __NR_fstat               (__NR_Linux + 28)
-#define __NR_pause               (__NR_Linux + 29)
-#define __NR_utime               (__NR_Linux + 30)
-#define __NR_connect             (__NR_Linux + 31)
-#define __NR_listen              (__NR_Linux + 32)
-#define __NR_access              (__NR_Linux + 33)
-#define __NR_nice                (__NR_Linux + 34)
-#define __NR_accept              (__NR_Linux + 35)
-#define __NR_sync                (__NR_Linux + 36)
-#define __NR_kill                (__NR_Linux + 37)
-#define __NR_rename              (__NR_Linux + 38)
-#define __NR_mkdir               (__NR_Linux + 39)
-#define __NR_rmdir               (__NR_Linux + 40)
-#define __NR_dup                 (__NR_Linux + 41)
-#define __NR_pipe                (__NR_Linux + 42)
-#define __NR_times               (__NR_Linux + 43)
-#define __NR_getsockname         (__NR_Linux + 44)
-#define __NR_brk                 (__NR_Linux + 45)
-#define __NR_setgid              (__NR_Linux + 46)
-#define __NR_getgid              (__NR_Linux + 47)
-#define __NR_signal              (__NR_Linux + 48)
-#define __NR_geteuid             (__NR_Linux + 49)
-#define __NR_getegid             (__NR_Linux + 50)
-#define __NR_acct                (__NR_Linux + 51)
-#define __NR_umount2             (__NR_Linux + 52)
-#define __NR_getpeername         (__NR_Linux + 53)
-#define __NR_ioctl               (__NR_Linux + 54)
-#define __NR_fcntl               (__NR_Linux + 55)
-#define __NR_socketpair          (__NR_Linux + 56)
-#define __NR_setpgid             (__NR_Linux + 57)
-#define __NR_send                (__NR_Linux + 58)
-#define __NR_uname               (__NR_Linux + 59)
-#define __NR_umask               (__NR_Linux + 60)
-#define __NR_chroot              (__NR_Linux + 61)
-#define __NR_ustat               (__NR_Linux + 62)
-#define __NR_dup2                (__NR_Linux + 63)
-#define __NR_getppid             (__NR_Linux + 64)
-#define __NR_getpgrp             (__NR_Linux + 65)
-#define __NR_setsid              (__NR_Linux + 66)
-#define __NR_pivot_root          (__NR_Linux + 67)
-#define __NR_sgetmask            (__NR_Linux + 68)
-#define __NR_ssetmask            (__NR_Linux + 69)
-#define __NR_setreuid            (__NR_Linux + 70)
-#define __NR_setregid            (__NR_Linux + 71)
-#define __NR_mincore             (__NR_Linux + 72)
-#define __NR_sigpending          (__NR_Linux + 73)
-#define __NR_sethostname         (__NR_Linux + 74)
-#define __NR_setrlimit           (__NR_Linux + 75)
-#define __NR_getrlimit           (__NR_Linux + 76)
-#define __NR_getrusage           (__NR_Linux + 77)
-#define __NR_gettimeofday        (__NR_Linux + 78)
-#define __NR_settimeofday        (__NR_Linux + 79)
-#define __NR_getgroups           (__NR_Linux + 80)
-#define __NR_setgroups           (__NR_Linux + 81)
-#define __NR_sendto              (__NR_Linux + 82)
-#define __NR_symlink             (__NR_Linux + 83)
-#define __NR_lstat               (__NR_Linux + 84)
-#define __NR_readlink            (__NR_Linux + 85)
-#define __NR_uselib              (__NR_Linux + 86)
-#define __NR_swapon              (__NR_Linux + 87)
-#define __NR_reboot              (__NR_Linux + 88)
-#define __NR_mmap2             (__NR_Linux + 89)
-#define __NR_mmap                (__NR_Linux + 90)
-#define __NR_munmap              (__NR_Linux + 91)
-#define __NR_truncate            (__NR_Linux + 92)
-#define __NR_ftruncate           (__NR_Linux + 93)
-#define __NR_fchmod              (__NR_Linux + 94)
-#define __NR_fchown              (__NR_Linux + 95)
-#define __NR_getpriority         (__NR_Linux + 96)
-#define __NR_setpriority         (__NR_Linux + 97)
-#define __NR_recv                (__NR_Linux + 98)
-#define __NR_statfs              (__NR_Linux + 99)
-#define __NR_fstatfs            (__NR_Linux + 100)
-#define __NR_stat64           (__NR_Linux + 101)
-/* #define __NR_socketcall         (__NR_Linux + 102) */
-#define __NR_syslog             (__NR_Linux + 103)
-#define __NR_setitimer          (__NR_Linux + 104)
-#define __NR_getitimer          (__NR_Linux + 105)
-#define __NR_capget             (__NR_Linux + 106)
-#define __NR_capset             (__NR_Linux + 107)
-#define __NR_pread64            (__NR_Linux + 108)
-#define __NR_pwrite64           (__NR_Linux + 109)
-#define __NR_getcwd             (__NR_Linux + 110)
-#define __NR_vhangup            (__NR_Linux + 111)
-#define __NR_fstat64            (__NR_Linux + 112)
-#define __NR_vfork              (__NR_Linux + 113)
-#define __NR_wait4              (__NR_Linux + 114)
-#define __NR_swapoff            (__NR_Linux + 115)
-#define __NR_sysinfo            (__NR_Linux + 116)
-#define __NR_shutdown           (__NR_Linux + 117)
-#define __NR_fsync              (__NR_Linux + 118)
-#define __NR_madvise            (__NR_Linux + 119)
-#define __NR_clone              (__NR_Linux + 120)
-#define __NR_setdomainname      (__NR_Linux + 121)
-#define __NR_sendfile           (__NR_Linux + 122)
-#define __NR_recvfrom           (__NR_Linux + 123)
-#define __NR_adjtimex           (__NR_Linux + 124)
-#define __NR_mprotect           (__NR_Linux + 125)
-#define __NR_sigprocmask        (__NR_Linux + 126)
-#define __NR_create_module      (__NR_Linux + 127)
-#define __NR_init_module        (__NR_Linux + 128)
-#define __NR_delete_module      (__NR_Linux + 129)
-#define __NR_get_kernel_syms    (__NR_Linux + 130)
-#define __NR_quotactl           (__NR_Linux + 131)
-#define __NR_getpgid            (__NR_Linux + 132)
-#define __NR_fchdir             (__NR_Linux + 133)
-#define __NR_bdflush            (__NR_Linux + 134)
-#define __NR_sysfs              (__NR_Linux + 135)
-#define __NR_personality        (__NR_Linux + 136)
-#define __NR_afs_syscall        (__NR_Linux + 137) /* Syscall for Andrew File System */
-#define __NR_setfsuid           (__NR_Linux + 138)
-#define __NR_setfsgid           (__NR_Linux + 139)
-#define __NR__llseek            (__NR_Linux + 140)
-#define __NR_getdents           (__NR_Linux + 141)
-#define __NR__newselect         (__NR_Linux + 142)
-#define __NR_flock              (__NR_Linux + 143)
-#define __NR_msync              (__NR_Linux + 144)
-#define __NR_readv              (__NR_Linux + 145)
-#define __NR_writev             (__NR_Linux + 146)
-#define __NR_getsid             (__NR_Linux + 147)
-#define __NR_fdatasync          (__NR_Linux + 148)
-#define __NR__sysctl            (__NR_Linux + 149)
-#define __NR_mlock              (__NR_Linux + 150)
-#define __NR_munlock            (__NR_Linux + 151)
-#define __NR_mlockall           (__NR_Linux + 152)
-#define __NR_munlockall         (__NR_Linux + 153)
-#define __NR_sched_setparam             (__NR_Linux + 154)
-#define __NR_sched_getparam             (__NR_Linux + 155)
-#define __NR_sched_setscheduler         (__NR_Linux + 156)
-#define __NR_sched_getscheduler         (__NR_Linux + 157)
-#define __NR_sched_yield                (__NR_Linux + 158)
-#define __NR_sched_get_priority_max     (__NR_Linux + 159)
-#define __NR_sched_get_priority_min     (__NR_Linux + 160)
-#define __NR_sched_rr_get_interval      (__NR_Linux + 161)
-#define __NR_nanosleep          (__NR_Linux + 162)
-#define __NR_mremap             (__NR_Linux + 163)
-#define __NR_setresuid          (__NR_Linux + 164)
-#define __NR_getresuid          (__NR_Linux + 165)
-#define __NR_sigaltstack        (__NR_Linux + 166)
-#define __NR_query_module       (__NR_Linux + 167)
-#define __NR_poll               (__NR_Linux + 168)
-#define __NR_nfsservctl         (__NR_Linux + 169)
-#define __NR_setresgid          (__NR_Linux + 170)
-#define __NR_getresgid          (__NR_Linux + 171)
-#define __NR_prctl              (__NR_Linux + 172)
-#define __NR_rt_sigreturn       (__NR_Linux + 173)
-#define __NR_rt_sigaction       (__NR_Linux + 174)
-#define __NR_rt_sigprocmask     (__NR_Linux + 175)
-#define __NR_rt_sigpending      (__NR_Linux + 176)
-#define __NR_rt_sigtimedwait    (__NR_Linux + 177)
-#define __NR_rt_sigqueueinfo    (__NR_Linux + 178)
-#define __NR_rt_sigsuspend      (__NR_Linux + 179)
-#define __NR_chown              (__NR_Linux + 180)
-#define __NR_setsockopt         (__NR_Linux + 181)
-#define __NR_getsockopt         (__NR_Linux + 182)
-#define __NR_sendmsg            (__NR_Linux + 183)
-#define __NR_recvmsg            (__NR_Linux + 184)
-#define __NR_semop              (__NR_Linux + 185)
-#define __NR_semget             (__NR_Linux + 186)
-#define __NR_semctl             (__NR_Linux + 187)
-#define __NR_msgsnd             (__NR_Linux + 188)
-#define __NR_msgrcv             (__NR_Linux + 189)
-#define __NR_msgget             (__NR_Linux + 190)
-#define __NR_msgctl             (__NR_Linux + 191)
-#define __NR_shmat              (__NR_Linux + 192)
-#define __NR_shmdt              (__NR_Linux + 193)
-#define __NR_shmget             (__NR_Linux + 194)
-#define __NR_shmctl             (__NR_Linux + 195)
-
-#define __NR_getpmsg           (__NR_Linux + 196) /* Somebody *wants* streams? */
-#define __NR_putpmsg           (__NR_Linux + 197)
-
-#define __NR_lstat64            (__NR_Linux + 198)
-#define __NR_truncate64         (__NR_Linux + 199)
-#define __NR_ftruncate64        (__NR_Linux + 200)
-#define __NR_getdents64         (__NR_Linux + 201)
-#define __NR_fcntl64            (__NR_Linux + 202)
-#define __NR_attrctl            (__NR_Linux + 203)
-#define __NR_acl_get            (__NR_Linux + 204)
-#define __NR_acl_set            (__NR_Linux + 205)
-#define __NR_gettid             (__NR_Linux + 206)
-#define __NR_readahead          (__NR_Linux + 207)
-#define __NR_tkill              (__NR_Linux + 208)
-#define __NR_sendfile64         (__NR_Linux + 209)
-#define __NR_futex              (__NR_Linux + 210)
-#define __NR_sched_setaffinity  (__NR_Linux + 211)
-#define __NR_sched_getaffinity  (__NR_Linux + 212)
-#define __NR_set_thread_area    (__NR_Linux + 213)
-#define __NR_get_thread_area    (__NR_Linux + 214)
-#define __NR_io_setup           (__NR_Linux + 215)
-#define __NR_io_destroy         (__NR_Linux + 216)
-#define __NR_io_getevents       (__NR_Linux + 217)
-#define __NR_io_submit          (__NR_Linux + 218)
-#define __NR_io_cancel          (__NR_Linux + 219)
-#define __NR_alloc_hugepages    (__NR_Linux + 220)
-#define __NR_free_hugepages     (__NR_Linux + 221)
-#define __NR_exit_group         (__NR_Linux + 222)
-#define __NR_lookup_dcookie     (__NR_Linux + 223)
-#define __NR_epoll_create       (__NR_Linux + 224)
-#define __NR_epoll_ctl          (__NR_Linux + 225)
-#define __NR_epoll_wait         (__NR_Linux + 226)
-#define __NR_remap_file_pages   (__NR_Linux + 227)
-#define __NR_semtimedop         (__NR_Linux + 228)
-#define __NR_mq_open            (__NR_Linux + 229)
-#define __NR_mq_unlink          (__NR_Linux + 230)
-#define __NR_mq_timedsend       (__NR_Linux + 231)
-#define __NR_mq_timedreceive    (__NR_Linux + 232)
-#define __NR_mq_notify          (__NR_Linux + 233)
-#define __NR_mq_getsetattr      (__NR_Linux + 234)
-#define __NR_waitid            (__NR_Linux + 235)
-#define __NR_fadvise64_64      (__NR_Linux + 236)
-#define __NR_set_tid_address   (__NR_Linux + 237)
-#define __NR_setxattr          (__NR_Linux + 238)
-#define __NR_lsetxattr         (__NR_Linux + 239)
-#define __NR_fsetxattr         (__NR_Linux + 240)
-#define __NR_getxattr          (__NR_Linux + 241)
-#define __NR_lgetxattr         (__NR_Linux + 242)
-#define __NR_fgetxattr         (__NR_Linux + 243)
-#define __NR_listxattr         (__NR_Linux + 244)
-#define __NR_llistxattr                (__NR_Linux + 245)
-#define __NR_flistxattr                (__NR_Linux + 246)
-#define __NR_removexattr       (__NR_Linux + 247)
-#define __NR_lremovexattr      (__NR_Linux + 248)
-#define __NR_fremovexattr      (__NR_Linux + 249)
-#define __NR_timer_create      (__NR_Linux + 250)
-#define __NR_timer_settime     (__NR_Linux + 251)
-#define __NR_timer_gettime     (__NR_Linux + 252)
-#define __NR_timer_getoverrun  (__NR_Linux + 253)
-#define __NR_timer_delete      (__NR_Linux + 254)
-#define __NR_clock_settime     (__NR_Linux + 255)
-#define __NR_clock_gettime     (__NR_Linux + 256)
-#define __NR_clock_getres      (__NR_Linux + 257)
-#define __NR_clock_nanosleep   (__NR_Linux + 258)
-#define __NR_tgkill            (__NR_Linux + 259)
-#define __NR_mbind             (__NR_Linux + 260)
-#define __NR_get_mempolicy     (__NR_Linux + 261)
-#define __NR_set_mempolicy     (__NR_Linux + 262)
-#define __NR_vserver           (__NR_Linux + 263)
-#define __NR_add_key           (__NR_Linux + 264)
-#define __NR_request_key       (__NR_Linux + 265)
-#define __NR_keyctl            (__NR_Linux + 266)
-#define __NR_ioprio_set                (__NR_Linux + 267)
-#define __NR_ioprio_get                (__NR_Linux + 268)
-#define __NR_inotify_init      (__NR_Linux + 269)
-#define __NR_inotify_add_watch (__NR_Linux + 270)
-#define __NR_inotify_rm_watch  (__NR_Linux + 271)
-#define __NR_migrate_pages     (__NR_Linux + 272)
-#define __NR_pselect6          (__NR_Linux + 273)
-#define __NR_ppoll             (__NR_Linux + 274)
-#define __NR_openat            (__NR_Linux + 275)
-#define __NR_mkdirat           (__NR_Linux + 276)
-#define __NR_mknodat           (__NR_Linux + 277)
-#define __NR_fchownat          (__NR_Linux + 278)
-#define __NR_futimesat         (__NR_Linux + 279)
-#define __NR_fstatat64         (__NR_Linux + 280)
-#define __NR_unlinkat          (__NR_Linux + 281)
-#define __NR_renameat          (__NR_Linux + 282)
-#define __NR_linkat            (__NR_Linux + 283)
-#define __NR_symlinkat         (__NR_Linux + 284)
-#define __NR_readlinkat                (__NR_Linux + 285)
-#define __NR_fchmodat          (__NR_Linux + 286)
-#define __NR_faccessat         (__NR_Linux + 287)
-#define __NR_unshare           (__NR_Linux + 288)
-#define __NR_set_robust_list   (__NR_Linux + 289)
-#define __NR_get_robust_list   (__NR_Linux + 290)
-#define __NR_splice            (__NR_Linux + 291)
-#define __NR_sync_file_range   (__NR_Linux + 292)
-#define __NR_tee               (__NR_Linux + 293)
-#define __NR_vmsplice          (__NR_Linux + 294)
-#define __NR_move_pages                (__NR_Linux + 295)
-#define __NR_getcpu            (__NR_Linux + 296)
-#define __NR_epoll_pwait       (__NR_Linux + 297)
-#define __NR_statfs64          (__NR_Linux + 298)
-#define __NR_fstatfs64         (__NR_Linux + 299)
-#define __NR_kexec_load                (__NR_Linux + 300)
-#define __NR_utimensat         (__NR_Linux + 301)
-#define __NR_signalfd          (__NR_Linux + 302)
-#define __NR_timerfd           (__NR_Linux + 303)
-#define __NR_eventfd           (__NR_Linux + 304)
-#define __NR_fallocate         (__NR_Linux + 305)
-#define __NR_timerfd_create    (__NR_Linux + 306)
-#define __NR_timerfd_settime   (__NR_Linux + 307)
-#define __NR_timerfd_gettime   (__NR_Linux + 308)
-#define __NR_signalfd4         (__NR_Linux + 309)
-#define __NR_eventfd2          (__NR_Linux + 310)
-#define __NR_epoll_create1     (__NR_Linux + 311)
-#define __NR_dup3              (__NR_Linux + 312)
-#define __NR_pipe2             (__NR_Linux + 313)
-#define __NR_inotify_init1     (__NR_Linux + 314)
-#define __NR_preadv            (__NR_Linux + 315)
-#define __NR_pwritev           (__NR_Linux + 316)
-#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317)
-#define __NR_perf_event_open   (__NR_Linux + 318)
-#define __NR_recvmmsg          (__NR_Linux + 319)
-#define __NR_accept4           (__NR_Linux + 320)
-#define __NR_prlimit64         (__NR_Linux + 321)
-#define __NR_fanotify_init     (__NR_Linux + 322)
-#define __NR_fanotify_mark     (__NR_Linux + 323)
-#define __NR_clock_adjtime     (__NR_Linux + 324)
-#define __NR_name_to_handle_at (__NR_Linux + 325)
-#define __NR_open_by_handle_at (__NR_Linux + 326)
-#define __NR_syncfs            (__NR_Linux + 327)
-#define __NR_setns             (__NR_Linux + 328)
-#define __NR_sendmmsg          (__NR_Linux + 329)
-
-#define __NR_Linux_syscalls    (__NR_sendmmsg + 1)
-
-
-#define __IGNORE_select                /* newselect */
-#define __IGNORE_fadvise64     /* fadvise64_64 */
-#define __IGNORE_utimes                /* utime */
-
-
-#define HPUX_GATEWAY_ADDR       0xC0000004
-#define LINUX_GATEWAY_ADDR      0x100
+#include <uapi/asm/unistd.h>
 
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #define SYS_ify(syscall_name)   __NR_##syscall_name
@@ -1008,5 +176,4 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)      \
  */
 #define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#endif /* __KERNEL__ */
 #endif /* _ASM_PARISC_UNISTD_H_ */
diff --git a/arch/parisc/include/asm/user.h b/arch/parisc/include/asm/user.h
deleted file mode 100644 (file)
index 8022475..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-/* This file should not exist, but lots of generic code still includes
-   it. It's a hangover from old a.out days and the traditional core
-   dump format.  We are ELF-only, and so are our core dumps.  If we
-   need to support HP/UX core format then we'll do it here
-   eventually. */
diff --git a/arch/parisc/include/asm/vga.h b/arch/parisc/include/asm/vga.h
deleted file mode 100644 (file)
index 171399a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __ASM_PARISC_VGA_H__
-#define __ASM_PARISC_VGA_H__
-
-/* nothing */
-
-#endif /* __ASM_PARISC_VGA_H__ */
diff --git a/arch/parisc/include/asm/xor.h b/arch/parisc/include/asm/xor.h
deleted file mode 100644 (file)
index c82eb12..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/xor.h>
index baebb3da1d44160fc6f6f259886656e6f494b167..a580642555b6f0e7f087ade117ce062cb303d429 100644 (file)
@@ -1,3 +1,31 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += bitsperlong.h
+header-y += byteorder.h
+header-y += errno.h
+header-y += fcntl.h
+header-y += ioctl.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += pdc.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += resource.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += siginfo.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += statfs.h
+header-y += swab.h
+header-y += termbits.h
+header-y += termios.h
+header-y += types.h
+header-y += unistd.h
diff --git a/arch/parisc/include/uapi/asm/bitsperlong.h b/arch/parisc/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..75196b4
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_PARISC_BITSPERLONG_H
+#define __ASM_PARISC_BITSPERLONG_H
+
+/*
+ * using CONFIG_* outside of __KERNEL__ is wrong,
+ * __LP64__ was also removed from headers, so what
+ * is the right approach on parisc?
+ *     -arnd
+ */
+#if (defined(__KERNEL__) && defined(CONFIG_64BIT)) || defined (__LP64__)
+#define __BITS_PER_LONG 64
+#define SHIFT_PER_LONG 6
+#else
+#define __BITS_PER_LONG 32
+#define SHIFT_PER_LONG 5
+#endif
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* __ASM_PARISC_BITSPERLONG_H */
diff --git a/arch/parisc/include/uapi/asm/byteorder.h b/arch/parisc/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..58af2c5
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _PARISC_BYTEORDER_H
+#define _PARISC_BYTEORDER_H
+
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _PARISC_BYTEORDER_H */
diff --git a/arch/parisc/include/uapi/asm/errno.h b/arch/parisc/include/uapi/asm/errno.h
new file mode 100644 (file)
index 0000000..135ad60
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef _PARISC_ERRNO_H
+#define _PARISC_ERRNO_H
+
+#include <asm-generic/errno-base.h>
+
+#define        ENOMSG          35      /* No message of desired type */
+#define        EIDRM           36      /* Identifier removed */
+#define        ECHRNG          37      /* Channel number out of range */
+#define        EL2NSYNC        38      /* Level 2 not synchronized */
+#define        EL3HLT          39      /* Level 3 halted */
+#define        EL3RST          40      /* Level 3 reset */
+#define        ELNRNG          41      /* Link number out of range */
+#define        EUNATCH         42      /* Protocol driver not attached */
+#define        ENOCSI          43      /* No CSI structure available */
+#define        EL2HLT          44      /* Level 2 halted */
+#define        EDEADLK         45      /* Resource deadlock would occur */
+#define        EDEADLOCK       EDEADLK
+#define        ENOLCK          46      /* No record locks available */
+#define        EILSEQ          47      /* Illegal byte sequence */
+
+#define        ENONET          50      /* Machine is not on the network */
+#define        ENODATA         51      /* No data available */
+#define        ETIME           52      /* Timer expired */
+#define        ENOSR           53      /* Out of streams resources */
+#define        ENOSTR          54      /* Device not a stream */
+#define        ENOPKG          55      /* Package not installed */
+
+#define        ENOLINK         57      /* Link has been severed */
+#define        EADV            58      /* Advertise error */
+#define        ESRMNT          59      /* Srmount error */
+#define        ECOMM           60      /* Communication error on send */
+#define        EPROTO          61      /* Protocol error */
+
+#define        EMULTIHOP       64      /* Multihop attempted */
+
+#define        EDOTDOT         66      /* RFS specific error */
+#define        EBADMSG         67      /* Not a data message */
+#define        EUSERS          68      /* Too many users */
+#define        EDQUOT          69      /* Quota exceeded */
+#define        ESTALE          70      /* Stale NFS file handle */
+#define        EREMOTE         71      /* Object is remote */
+#define        EOVERFLOW       72      /* Value too large for defined data type */
+
+/* these errnos are defined by Linux but not HPUX. */
+
+#define        EBADE           160     /* Invalid exchange */
+#define        EBADR           161     /* Invalid request descriptor */
+#define        EXFULL          162     /* Exchange full */
+#define        ENOANO          163     /* No anode */
+#define        EBADRQC         164     /* Invalid request code */
+#define        EBADSLT         165     /* Invalid slot */
+#define        EBFONT          166     /* Bad font file format */
+#define        ENOTUNIQ        167     /* Name not unique on network */
+#define        EBADFD          168     /* File descriptor in bad state */
+#define        EREMCHG         169     /* Remote address changed */
+#define        ELIBACC         170     /* Can not access a needed shared library */
+#define        ELIBBAD         171     /* Accessing a corrupted shared library */
+#define        ELIBSCN         172     /* .lib section in a.out corrupted */
+#define        ELIBMAX         173     /* Attempting to link in too many shared libraries */
+#define        ELIBEXEC        174     /* Cannot exec a shared library directly */
+#define        ERESTART        175     /* Interrupted system call should be restarted */
+#define        ESTRPIPE        176     /* Streams pipe error */
+#define        EUCLEAN         177     /* Structure needs cleaning */
+#define        ENOTNAM         178     /* Not a XENIX named type file */
+#define        ENAVAIL         179     /* No XENIX semaphores available */
+#define        EISNAM          180     /* Is a named type file */
+#define        EREMOTEIO       181     /* Remote I/O error */
+#define        ENOMEDIUM       182     /* No medium found */
+#define        EMEDIUMTYPE     183     /* Wrong medium type */
+#define        ENOKEY          184     /* Required key not available */
+#define        EKEYEXPIRED     185     /* Key has expired */
+#define        EKEYREVOKED     186     /* Key has been revoked */
+#define        EKEYREJECTED    187     /* Key was rejected by service */
+
+/* We now return you to your regularly scheduled HPUX. */
+
+#define ENOSYM         215     /* symbol does not exist in executable */
+#define        ENOTSOCK        216     /* Socket operation on non-socket */
+#define        EDESTADDRREQ    217     /* Destination address required */
+#define        EMSGSIZE        218     /* Message too long */
+#define        EPROTOTYPE      219     /* Protocol wrong type for socket */
+#define        ENOPROTOOPT     220     /* Protocol not available */
+#define        EPROTONOSUPPORT 221     /* Protocol not supported */
+#define        ESOCKTNOSUPPORT 222     /* Socket type not supported */
+#define        EOPNOTSUPP      223     /* Operation not supported on transport endpoint */
+#define        EPFNOSUPPORT    224     /* Protocol family not supported */
+#define        EAFNOSUPPORT    225     /* Address family not supported by protocol */
+#define        EADDRINUSE      226     /* Address already in use */
+#define        EADDRNOTAVAIL   227     /* Cannot assign requested address */
+#define        ENETDOWN        228     /* Network is down */
+#define        ENETUNREACH     229     /* Network is unreachable */
+#define        ENETRESET       230     /* Network dropped connection because of reset */
+#define        ECONNABORTED    231     /* Software caused connection abort */
+#define        ECONNRESET      232     /* Connection reset by peer */
+#define        ENOBUFS         233     /* No buffer space available */
+#define        EISCONN         234     /* Transport endpoint is already connected */
+#define        ENOTCONN        235     /* Transport endpoint is not connected */
+#define        ESHUTDOWN       236     /* Cannot send after transport endpoint shutdown */
+#define        ETOOMANYREFS    237     /* Too many references: cannot splice */
+#define EREFUSED       ECONNREFUSED    /* for HP's NFS apparently */
+#define        ETIMEDOUT       238     /* Connection timed out */
+#define        ECONNREFUSED    239     /* Connection refused */
+#define EREMOTERELEASE 240     /* Remote peer released connection */
+#define        EHOSTDOWN       241     /* Host is down */
+#define        EHOSTUNREACH    242     /* No route to host */
+
+#define        EALREADY        244     /* Operation already in progress */
+#define        EINPROGRESS     245     /* Operation now in progress */
+#define        EWOULDBLOCK     246     /* Operation would block (Linux returns EAGAIN) */
+#define        ENOTEMPTY       247     /* Directory not empty */
+#define        ENAMETOOLONG    248     /* File name too long */
+#define        ELOOP           249     /* Too many symbolic links encountered */
+#define        ENOSYS          251     /* Function not implemented */
+
+#define ENOTSUP                252     /* Function not implemented (POSIX.4 / HPUX) */
+#define ECANCELLED     253     /* aio request was canceled before complete (POSIX.4 / HPUX) */
+#define ECANCELED      ECANCELLED      /* SuSv3 and Solaris wants one 'L' */
+
+/* for robust mutexes */
+#define EOWNERDEAD     254     /* Owner died */
+#define ENOTRECOVERABLE        255     /* State not recoverable */
+
+#define        ERFKILL         256     /* Operation not possible due to RF-kill */
+
+#define EHWPOISON      257     /* Memory page has hardware error */
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h
new file mode 100644 (file)
index 0000000..0304b92
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef _PARISC_FCNTL_H
+#define _PARISC_FCNTL_H
+
+#define O_APPEND       000000010
+#define O_BLKSEEK      000000100 /* HPUX only */
+#define O_CREAT                000000400 /* not fcntl */
+#define O_EXCL         000002000 /* not fcntl */
+#define O_LARGEFILE    000004000
+#define __O_SYNC       000100000
+#define O_SYNC         (__O_SYNC|O_DSYNC)
+#define O_NONBLOCK     000200004 /* HPUX has separate NDELAY & NONBLOCK */
+#define O_NOCTTY       000400000 /* not fcntl */
+#define O_DSYNC                001000000 /* HPUX only */
+#define O_RSYNC                002000000 /* HPUX only */
+#define O_NOATIME      004000000
+#define O_CLOEXEC      010000000 /* set close_on_exec */
+
+#define O_DIRECTORY    000010000 /* must be a directory */
+#define O_NOFOLLOW     000000200 /* don't follow links */
+#define O_INVISIBLE    004000000 /* invisible I/O, for DMAPI/XDSM */
+
+#define O_PATH         020000000
+
+#define F_GETLK64      8
+#define F_SETLK64      9
+#define F_SETLKW64     10
+
+#define F_GETOWN       11      /*  for sockets. */
+#define F_SETOWN       12      /*  for sockets. */
+#define F_SETSIG       13      /*  for sockets. */
+#define F_GETSIG       14      /*  for sockets. */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK                01
+#define F_WRLCK                02
+#define F_UNLCK                03
+
+#include <asm-generic/fcntl.h>
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/ioctl.h b/arch/parisc/include/uapi/asm/ioctl.h
new file mode 100644 (file)
index 0000000..ec8efa0
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ *    Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *    Copyright (C) 1999,2003 Matthew Wilcox < willy at debian . org >
+ *    portions from "linux/ioctl.h for Linux" by H.H. Bergman.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _ASM_PARISC_IOCTL_H
+#define _ASM_PARISC_IOCTL_H
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE      0U
+#define _IOC_WRITE     2U
+#define _IOC_READ      1U
+
+#include <asm-generic/ioctl.h>
+
+#endif /* _ASM_PARISC_IOCTL_H */
diff --git a/arch/parisc/include/uapi/asm/ioctls.h b/arch/parisc/include/uapi/asm/ioctls.h
new file mode 100644 (file)
index 0000000..054ec06
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef __ARCH_PARISC_IOCTLS_H__
+#define __ARCH_PARISC_IOCTLS_H__
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS         _IOR('T', 16, struct termios) /* TCGETATTR */
+#define TCSETS         _IOW('T', 17, struct termios) /* TCSETATTR */
+#define TCSETSW                _IOW('T', 18, struct termios) /* TCSETATTRD */
+#define TCSETSF                _IOW('T', 19, struct termios) /* TCSETATTRF */
+#define TCGETA         _IOR('T', 1, struct termio)
+#define TCSETA         _IOW('T', 2, struct termio)
+#define TCSETAW                _IOW('T', 3, struct termio)
+#define TCSETAF                _IOW('T', 4, struct termio)
+#define TCSBRK         _IO('T', 5)
+#define TCXONC         _IO('T', 6)
+#define TCFLSH         _IO('T', 7)
+#define TIOCEXCL       0x540C
+#define TIOCNXCL       0x540D
+#define TIOCSCTTY      0x540E
+#define TIOCGPGRP      _IOR('T', 30, int)
+#define TIOCSPGRP      _IOW('T', 29, int)
+#define TIOCOUTQ       0x5411
+#define TIOCSTI                0x5412
+#define TIOCGWINSZ     0x5413
+#define TIOCSWINSZ     0x5414
+#define TIOCMGET       0x5415
+#define TIOCMBIS       0x5416
+#define TIOCMBIC       0x5417
+#define TIOCMSET       0x5418
+#define TIOCGSOFTCAR   0x5419
+#define TIOCSSOFTCAR   0x541A
+#define FIONREAD       0x541B
+#define TIOCINQ                FIONREAD
+#define TIOCLINUX      0x541C
+#define TIOCCONS       0x541D
+#define TIOCGSERIAL    0x541E
+#define TIOCSSERIAL    0x541F
+#define TIOCPKT                0x5420
+#define FIONBIO                0x5421
+#define TIOCNOTTY      0x5422
+#define TIOCSETD       0x5423
+#define TIOCGETD       0x5424
+#define TCSBRKP                0x5425  /* Needed for POSIX tcsendbreak() */
+#define TIOCSBRK       0x5427  /* BSD compatibility */
+#define TIOCCBRK       0x5428  /* BSD compatibility */
+#define TIOCGSID       _IOR('T', 20, int) /* Return the session ID of FD */
+#define TCGETS2                _IOR('T',0x2A, struct termios2)
+#define TCSETS2                _IOW('T',0x2B, struct termios2)
+#define TCSETSW2       _IOW('T',0x2C, struct termios2)
+#define TCSETSF2       _IOW('T',0x2D, struct termios2)
+#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV       _IOR('T',0x32, int)  /* Get primary device node of /dev/console */
+#define TIOCSIG                _IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP    0x5437
+
+#define FIONCLEX       0x5450  /* these numbers need to be adjusted. */
+#define FIOCLEX                0x5451
+#define FIOASYNC       0x5452
+#define TIOCSERCONFIG  0x5453
+#define TIOCSERGWILD   0x5454
+#define TIOCSERSWILD   0x5455
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT     0x545C  /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
+#define FIOQSIZE       0x5460  /* Get exact space used by quota */
+
+#define TIOCSTART      0x5461
+#define TIOCSTOP       0x5462
+#define TIOCSLTC       0x5462
+
+/* Used for packet mode */
+#define TIOCPKT_DATA            0
+#define TIOCPKT_FLUSHREAD       1
+#define TIOCPKT_FLUSHWRITE      2
+#define TIOCPKT_STOP            4
+#define TIOCPKT_START           8
+#define TIOCPKT_NOSTOP         16
+#define TIOCPKT_DOSTOP         32
+#define TIOCPKT_IOCTL          64
+
+#define TIOCSER_TEMT    0x01   /* Transmitter physically empty */
+
+#endif /* _ASM_PARISC_IOCTLS_H */
diff --git a/arch/parisc/include/uapi/asm/ipcbuf.h b/arch/parisc/include/uapi/asm/ipcbuf.h
new file mode 100644 (file)
index 0000000..bd956c4
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __PARISC_IPCBUF_H__
+#define __PARISC_IPCBUF_H__
+
+/*
+ * The ipc64_perm structure for PA-RISC is almost identical to
+ * kern_ipc_perm as we have always had 32-bit UIDs and GIDs in the kernel.
+ * 'seq' has been changed from long to int so that it's the same size
+ * on 64-bit kernels as on 32-bit ones.
+ */
+
+struct ipc64_perm
+{
+       key_t           key;
+       uid_t           uid;
+       gid_t           gid;
+       uid_t           cuid;
+       gid_t           cgid;
+       unsigned short int      __pad1;
+       mode_t          mode;
+       unsigned short int      __pad2;
+       unsigned short int      seq;
+       unsigned int    __pad3;
+       unsigned long long int __unused1;
+       unsigned long long int __unused2;
+};
+
+#endif /* __PARISC_IPCBUF_H__ */
diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h
new file mode 100644 (file)
index 0000000..12219eb
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef __PARISC_MMAN_H__
+#define __PARISC_MMAN_H__
+
+#define PROT_READ      0x1             /* page can be read */
+#define PROT_WRITE     0x2             /* page can be written */
+#define PROT_EXEC      0x4             /* page can be executed */
+#define PROT_SEM       0x8             /* page may be used for atomic ops */
+#define PROT_NONE      0x0             /* page can not be accessed */
+#define PROT_GROWSDOWN 0x01000000      /* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP   0x02000000      /* mprotect flag: extend change to end of growsup vma */
+
+#define MAP_SHARED     0x01            /* Share changes */
+#define MAP_PRIVATE    0x02            /* Changes are private */
+#define MAP_TYPE       0x03            /* Mask for type of mapping */
+#define MAP_FIXED      0x04            /* Interpret addr exactly */
+#define MAP_ANONYMOUS  0x10            /* don't use a file */
+
+#define MAP_DENYWRITE  0x0800          /* ETXTBSY */
+#define MAP_EXECUTABLE 0x1000          /* mark it as an executable */
+#define MAP_LOCKED     0x2000          /* pages are locked */
+#define MAP_NORESERVE  0x4000          /* don't check for reservations */
+#define MAP_GROWSDOWN  0x8000          /* stack-like segment */
+#define MAP_POPULATE   0x10000         /* populate (prefault) pagetables */
+#define MAP_NONBLOCK   0x20000         /* do not block on IO */
+#define MAP_STACK      0x40000         /* give out an address that is best suited for process/thread stacks */
+#define MAP_HUGETLB    0x80000         /* create a huge page mapping */
+
+#define MS_SYNC                1               /* synchronous memory sync */
+#define MS_ASYNC       2               /* sync memory asynchronously */
+#define MS_INVALIDATE  4               /* invalidate the caches */
+
+#define MCL_CURRENT    1               /* lock all current mappings */
+#define MCL_FUTURE     2               /* lock all future mappings */
+
+#define MADV_NORMAL     0               /* no further special treatment */
+#define MADV_RANDOM     1               /* expect random page references */
+#define MADV_SEQUENTIAL 2               /* expect sequential page references */
+#define MADV_WILLNEED   3               /* will need these pages */
+#define MADV_DONTNEED   4               /* don't need these pages */
+#define MADV_SPACEAVAIL 5               /* insure that resources are reserved */
+#define MADV_VPS_PURGE  6               /* Purge pages from VM page cache */
+#define MADV_VPS_INHERIT 7              /* Inherit parents page size */
+
+/* common/generic parameters */
+#define MADV_REMOVE    9               /* remove these pages & resources */
+#define MADV_DONTFORK  10              /* don't inherit across fork */
+#define MADV_DOFORK    11              /* do inherit across fork */
+
+/* The range 12-64 is reserved for page size specification. */
+#define MADV_4K_PAGES   12              /* Use 4K pages  */
+#define MADV_16K_PAGES  14              /* Use 16K pages */
+#define MADV_64K_PAGES  16              /* Use 64K pages */
+#define MADV_256K_PAGES 18              /* Use 256K pages */
+#define MADV_1M_PAGES   20              /* Use 1 Megabyte pages */
+#define MADV_4M_PAGES   22              /* Use 4 Megabyte pages */
+#define MADV_16M_PAGES  24              /* Use 16 Megabyte pages */
+#define MADV_64M_PAGES  26              /* Use 64 Megabyte pages */
+
+#define MADV_MERGEABLE   65            /* KSM may merge identical pages */
+#define MADV_UNMERGEABLE 66            /* KSM may not merge identical pages */
+
+#define MADV_HUGEPAGE  67              /* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE        68              /* Not worth backing with hugepages */
+
+#define MADV_DONTDUMP   69             /* Explicity exclude from the core dump,
+                                          overrides the coredump filter bits */
+#define MADV_DODUMP    70              /* Clear the MADV_NODUMP flag */
+
+/* compatibility flags */
+#define MAP_FILE       0
+#define MAP_VARIABLE   0
+
+#endif /* __PARISC_MMAN_H__ */
diff --git a/arch/parisc/include/uapi/asm/msgbuf.h b/arch/parisc/include/uapi/asm/msgbuf.h
new file mode 100644 (file)
index 0000000..fe88f26
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _PARISC_MSGBUF_H
+#define _PARISC_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for parisc architecture, copied from sparc.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+#ifndef CONFIG_64BIT
+       unsigned int   __pad1;
+#endif
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+#ifndef CONFIG_64BIT
+       unsigned int   __pad2;
+#endif
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+#ifndef CONFIG_64BIT
+       unsigned int   __pad3;
+#endif
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned int  msg_cbytes;       /* current number of bytes on queue */
+       unsigned int  msg_qnum; /* number of messages in queue */
+       unsigned int  msg_qbytes;       /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned int  __unused1;
+       unsigned int  __unused2;
+};
+
+#endif /* _PARISC_MSGBUF_H */
diff --git a/arch/parisc/include/uapi/asm/pdc.h b/arch/parisc/include/uapi/asm/pdc.h
new file mode 100644 (file)
index 0000000..702498f
--- /dev/null
@@ -0,0 +1,427 @@
+#ifndef _UAPI_PARISC_PDC_H
+#define _UAPI_PARISC_PDC_H
+
+/*
+ *     PDC return values ...
+ *     All PDC calls return a subset of these errors. 
+ */
+
+#define PDC_WARN                 3     /* Call completed with a warning */
+#define PDC_REQ_ERR_1            2     /* See above                     */
+#define PDC_REQ_ERR_0            1     /* Call would generate a requestor error */
+#define PDC_OK                   0     /* Call completed successfully  */
+#define PDC_BAD_PROC            -1     /* Called non-existent procedure*/
+#define PDC_BAD_OPTION          -2     /* Called with non-existent option */
+#define PDC_ERROR               -3     /* Call could not complete without an error */
+#define PDC_NE_MOD              -5     /* Module not found             */
+#define PDC_NE_CELL_MOD                 -7     /* Cell module not found        */
+#define PDC_INVALID_ARG                -10     /* Called with an invalid argument */
+#define PDC_BUS_POW_WARN       -12     /* Call could not complete in allowed power budget */
+#define PDC_NOT_NARROW         -17     /* Narrow mode not supported    */
+
+/*
+ *     PDC entry points...
+ */
+
+#define PDC_POW_FAIL   1               /* perform a power-fail         */
+#define PDC_POW_FAIL_PREPARE   0       /* prepare for powerfail        */
+
+#define PDC_CHASSIS    2               /* PDC-chassis functions        */
+#define PDC_CHASSIS_DISP       0       /* update chassis display       */
+#define PDC_CHASSIS_WARN       1       /* return chassis warnings      */
+#define PDC_CHASSIS_DISPWARN   2       /* update&return chassis status */
+#define PDC_RETURN_CHASSIS_INFO 128    /* HVERSION dependent: return chassis LED/LCD info  */
+
+#define PDC_PIM         3               /* Get PIM data                 */
+#define PDC_PIM_HPMC            0       /* Transfer HPMC data           */
+#define PDC_PIM_RETURN_SIZE     1       /* Get Max buffer needed for PIM*/
+#define PDC_PIM_LPMC            2       /* Transfer HPMC data           */
+#define PDC_PIM_SOFT_BOOT       3       /* Transfer Soft Boot data      */
+#define PDC_PIM_TOC             4       /* Transfer TOC data            */
+
+#define PDC_MODEL      4               /* PDC model information call   */
+#define PDC_MODEL_INFO         0       /* returns information          */
+#define PDC_MODEL_BOOTID       1       /* set the BOOT_ID              */
+#define PDC_MODEL_VERSIONS     2       /* returns cpu-internal versions*/
+#define PDC_MODEL_SYSMODEL     3       /* return system model info     */
+#define PDC_MODEL_ENSPEC       4       /* enable specific option       */
+#define PDC_MODEL_DISPEC       5       /* disable specific option      */
+#define PDC_MODEL_CPU_ID       6       /* returns cpu-id (only newer machines!) */
+#define PDC_MODEL_CAPABILITIES 7       /* returns OS32/OS64-flags      */
+/* Values for PDC_MODEL_CAPABILITIES non-equivalent virtual aliasing support */
+#define  PDC_MODEL_OS64                        (1 << 0)
+#define  PDC_MODEL_OS32                        (1 << 1)
+#define  PDC_MODEL_IOPDIR_FDC          (1 << 2)
+#define  PDC_MODEL_NVA_MASK            (3 << 4)
+#define  PDC_MODEL_NVA_SUPPORTED       (0 << 4)
+#define  PDC_MODEL_NVA_SLOW            (1 << 4)
+#define  PDC_MODEL_NVA_UNSUPPORTED     (3 << 4)
+#define PDC_MODEL_GET_BOOT__OP 8       /* returns boot test options    */
+#define PDC_MODEL_SET_BOOT__OP 9       /* set boot test options        */
+
+#define PA89_INSTRUCTION_SET   0x4     /* capatibilies returned        */
+#define PA90_INSTRUCTION_SET   0x8
+
+#define PDC_CACHE      5               /* return/set cache (& TLB) info*/
+#define PDC_CACHE_INFO         0       /* returns information          */
+#define PDC_CACHE_SET_COH      1       /* set coherence state          */
+#define PDC_CACHE_RET_SPID     2       /* returns space-ID bits        */
+
+#define PDC_HPA                6               /* return HPA of processor      */
+#define PDC_HPA_PROCESSOR      0
+#define PDC_HPA_MODULES                1
+
+#define PDC_COPROC     7               /* Co-Processor (usually FP unit(s)) */
+#define PDC_COPROC_CFG         0       /* Co-Processor Cfg (FP unit(s) enabled?) */
+
+#define PDC_IODC       8               /* talk to IODC                 */
+#define PDC_IODC_READ          0       /* read IODC entry point        */
+/*      PDC_IODC_RI_                    * INDEX parameter of PDC_IODC_READ */
+#define PDC_IODC_RI_DATA_BYTES 0       /* IODC Data Bytes              */
+/*                             1, 2       obsolete - HVERSION dependent*/
+#define PDC_IODC_RI_INIT       3       /* Initialize module            */
+#define PDC_IODC_RI_IO         4       /* Module input/output          */
+#define PDC_IODC_RI_SPA                5       /* Module input/output          */
+#define PDC_IODC_RI_CONFIG     6       /* Module input/output          */
+/*                             7         obsolete - HVERSION dependent */
+#define PDC_IODC_RI_TEST       8       /* Module input/output          */
+#define PDC_IODC_RI_TLB                9       /* Module input/output          */
+#define PDC_IODC_NINIT         2       /* non-destructive init         */
+#define PDC_IODC_DINIT         3       /* destructive init             */
+#define PDC_IODC_MEMERR                4       /* check for memory errors      */
+#define PDC_IODC_INDEX_DATA    0       /* get first 16 bytes from mod IODC */
+#define PDC_IODC_BUS_ERROR     -4      /* bus error return value       */
+#define PDC_IODC_INVALID_INDEX -5      /* invalid index return value   */
+#define PDC_IODC_COUNT         -6      /* count is too small           */
+
+#define PDC_TOD                9               /* time-of-day clock (TOD)      */
+#define PDC_TOD_READ           0       /* read TOD                     */
+#define PDC_TOD_WRITE          1       /* write TOD                    */
+
+
+#define PDC_STABLE     10              /* stable storage (sprockets)   */
+#define PDC_STABLE_READ                0
+#define PDC_STABLE_WRITE       1
+#define PDC_STABLE_RETURN_SIZE 2
+#define PDC_STABLE_VERIFY_CONTENTS 3
+#define PDC_STABLE_INITIALIZE  4
+
+#define PDC_NVOLATILE  11              /* often not implemented        */
+
+#define PDC_ADD_VALID  12              /* Memory validation PDC call   */
+#define PDC_ADD_VALID_VERIFY   0       /* Make PDC_ADD_VALID verify region */
+
+#define PDC_INSTR      15              /* get instr to invoke PDCE_CHECK() */
+
+#define PDC_PROC       16              /* (sprockets)                  */
+
+#define PDC_CONFIG     16              /* (sprockets)                  */
+#define PDC_CONFIG_DECONFIG    0
+#define PDC_CONFIG_DRECONFIG   1
+#define PDC_CONFIG_DRETURN_CONFIG 2
+
+#define PDC_BLOCK_TLB  18              /* manage hardware block-TLB    */
+#define PDC_BTLB_INFO          0       /* returns parameter            */
+#define PDC_BTLB_INSERT                1       /* insert BTLB entry            */
+#define PDC_BTLB_PURGE         2       /* purge BTLB entries           */
+#define PDC_BTLB_PURGE_ALL     3       /* purge all BTLB entries       */
+
+#define PDC_TLB                19              /* manage hardware TLB miss handling */
+#define PDC_TLB_INFO           0       /* returns parameter            */
+#define PDC_TLB_SETUP          1       /* set up miss handling         */
+
+#define PDC_MEM                20              /* Manage memory                */
+#define PDC_MEM_MEMINFO                0
+#define PDC_MEM_ADD_PAGE       1
+#define PDC_MEM_CLEAR_PDT      2
+#define PDC_MEM_READ_PDT       3
+#define PDC_MEM_RESET_CLEAR    4
+#define PDC_MEM_GOODMEM                5
+#define PDC_MEM_TABLE          128     /* Non contig mem map (sprockets) */
+#define PDC_MEM_RETURN_ADDRESS_TABLE   PDC_MEM_TABLE
+#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE  131
+#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES       132
+#define PDC_MEM_GET_PHYSICAL_LOCATION_FROM_MEMORY_ADDRESS 133
+
+#define PDC_MEM_RET_SBE_REPLACED       5       /* PDC_MEM return values */
+#define PDC_MEM_RET_DUPLICATE_ENTRY    4
+#define PDC_MEM_RET_BUF_SIZE_SMALL     1
+#define PDC_MEM_RET_PDT_FULL           -11
+#define PDC_MEM_RET_INVALID_PHYSICAL_LOCATION ~0ULL
+
+#define PDC_PSW                21              /* Get/Set default System Mask  */
+#define PDC_PSW_MASK           0       /* Return mask                  */
+#define PDC_PSW_GET_DEFAULTS   1       /* Return defaults              */
+#define PDC_PSW_SET_DEFAULTS   2       /* Set default                  */
+#define PDC_PSW_ENDIAN_BIT     1       /* set for big endian           */
+#define PDC_PSW_WIDE_BIT       2       /* set for wide mode            */ 
+
+#define PDC_SYSTEM_MAP 22              /* find system modules          */
+#define PDC_FIND_MODULE        0
+#define PDC_FIND_ADDRESS       1
+#define PDC_TRANSLATE_PATH     2
+
+#define PDC_SOFT_POWER 23              /* soft power switch            */
+#define PDC_SOFT_POWER_INFO    0       /* return info about the soft power switch */
+#define PDC_SOFT_POWER_ENABLE  1       /* enable/disable soft power switch */
+
+
+/* HVERSION dependent */
+
+/* The PDC_MEM_MAP calls */
+#define PDC_MEM_MAP    128             /* on s700: return page info    */
+#define PDC_MEM_MAP_HPA                0       /* returns hpa of a module      */
+
+#define PDC_EEPROM     129             /* EEPROM access                */
+#define PDC_EEPROM_READ_WORD   0
+#define PDC_EEPROM_WRITE_WORD  1
+#define PDC_EEPROM_READ_BYTE   2
+#define PDC_EEPROM_WRITE_BYTE  3
+#define PDC_EEPROM_EEPROM_PASSWORD -1000
+
+#define PDC_NVM                130             /* NVM (non-volatile memory) access */
+#define PDC_NVM_READ_WORD      0
+#define PDC_NVM_WRITE_WORD     1
+#define PDC_NVM_READ_BYTE      2
+#define PDC_NVM_WRITE_BYTE     3
+
+#define PDC_SEED_ERROR 132             /* (sprockets)                  */
+
+#define PDC_IO         135             /* log error info, reset IO system */
+#define PDC_IO_READ_AND_CLEAR_ERRORS   0
+#define PDC_IO_RESET                   1
+#define PDC_IO_RESET_DEVICES           2
+/* sets bits 6&7 (little endian) of the HcControl Register */
+#define PDC_IO_USB_SUSPEND     0xC000000000000000
+#define PDC_IO_EEPROM_IO_ERR_TABLE_FULL        -5      /* return value */
+#define PDC_IO_NO_SUSPEND              -6      /* return value */
+
+#define PDC_BROADCAST_RESET 136                /* reset all processors         */
+#define PDC_DO_RESET           0       /* option: perform a broadcast reset */
+#define PDC_DO_FIRM_TEST_RESET 1       /* Do broadcast reset with bitmap */
+#define PDC_BR_RECONFIGURATION 2       /* reset w/reconfiguration      */
+#define PDC_FIRM_TEST_MAGIC    0xab9ec36fUL    /* for this reboot only */
+
+#define PDC_LAN_STATION_ID 138         /* Hversion dependent mechanism for */
+#define PDC_LAN_STATION_ID_READ        0       /* getting the lan station address  */
+
+#define        PDC_LAN_STATION_ID_SIZE 6
+
+#define PDC_CHECK_RANGES 139           /* (sprockets)                  */
+
+#define PDC_NV_SECTIONS        141             /* (sprockets)                  */
+
+#define PDC_PERFORMANCE        142             /* performance monitoring       */
+
+#define PDC_SYSTEM_INFO        143             /* system information           */
+#define PDC_SYSINFO_RETURN_INFO_SIZE   0
+#define PDC_SYSINFO_RRETURN_SYS_INFO   1
+#define PDC_SYSINFO_RRETURN_ERRORS     2
+#define PDC_SYSINFO_RRETURN_WARNINGS   3
+#define PDC_SYSINFO_RETURN_REVISIONS   4
+#define PDC_SYSINFO_RRETURN_DIAGNOSE   5
+#define PDC_SYSINFO_RRETURN_HV_DIAGNOSE        1005
+
+#define PDC_RDR                144             /* (sprockets)                  */
+#define PDC_RDR_READ_BUFFER    0
+#define PDC_RDR_READ_SINGLE    1
+#define PDC_RDR_WRITE_SINGLE   2
+
+#define PDC_INTRIGUE   145             /* (sprockets)                  */
+#define PDC_INTRIGUE_WRITE_BUFFER       0
+#define PDC_INTRIGUE_GET_SCRATCH_BUFSIZE 1
+#define PDC_INTRIGUE_START_CPU_COUNTERS         2
+#define PDC_INTRIGUE_STOP_CPU_COUNTERS  3
+
+#define PDC_STI                146             /* STI access                   */
+/* same as PDC_PCI_XXX values (see below) */
+
+/* Legacy PDC definitions for same stuff */
+#define PDC_PCI_INDEX  147
+#define PDC_PCI_INTERFACE_INFO         0
+#define PDC_PCI_SLOT_INFO              1
+#define PDC_PCI_INFLIGHT_BYTES         2
+#define PDC_PCI_READ_CONFIG            3
+#define PDC_PCI_WRITE_CONFIG           4
+#define PDC_PCI_READ_PCI_IO            5
+#define PDC_PCI_WRITE_PCI_IO           6
+#define PDC_PCI_READ_CONFIG_DELAY      7
+#define PDC_PCI_UPDATE_CONFIG_DELAY    8
+#define PDC_PCI_PCI_PATH_TO_PCI_HPA    9
+#define PDC_PCI_PCI_HPA_TO_PCI_PATH    10
+#define PDC_PCI_PCI_PATH_TO_PCI_BUS    11
+#define PDC_PCI_PCI_RESERVED           12
+#define PDC_PCI_PCI_INT_ROUTE_SIZE     13
+#define PDC_PCI_GET_INT_TBL_SIZE       PDC_PCI_PCI_INT_ROUTE_SIZE
+#define PDC_PCI_PCI_INT_ROUTE          14
+#define PDC_PCI_GET_INT_TBL            PDC_PCI_PCI_INT_ROUTE 
+#define PDC_PCI_READ_MON_TYPE          15
+#define PDC_PCI_WRITE_MON_TYPE         16
+
+
+/* Get SCSI Interface Card info:  SDTR, SCSI ID, mode (SE vs LVD) */
+#define PDC_INITIATOR  163
+#define PDC_GET_INITIATOR      0
+#define PDC_SET_INITIATOR      1
+#define PDC_DELETE_INITIATOR   2
+#define PDC_RETURN_TABLE_SIZE  3
+#define PDC_RETURN_TABLE       4
+
+#define PDC_LINK       165             /* (sprockets)                  */
+#define PDC_LINK_PCI_ENTRY_POINTS      0  /* list (Arg1) = 0 */
+#define PDC_LINK_USB_ENTRY_POINTS      1  /* list (Arg1) = 1 */
+
+/* cl_class
+ * page 3-33 of IO-Firmware ARS
+ * IODC ENTRY_INIT(Search first) RET[1]
+ */
+#define        CL_NULL         0       /* invalid */
+#define        CL_RANDOM       1       /* random access (as disk) */
+#define        CL_SEQU         2       /* sequential access (as tape) */
+#define        CL_DUPLEX       7       /* full-duplex point-to-point (RS-232, Net) */
+#define        CL_KEYBD        8       /* half-duplex console (HIL Keyboard) */
+#define        CL_DISPL        9       /* half-duplex console (display) */
+#define        CL_FC           10      /* FiberChannel access media */
+
+/* IODC ENTRY_INIT() */
+#define ENTRY_INIT_SRCH_FRST   2
+#define ENTRY_INIT_SRCH_NEXT   3
+#define ENTRY_INIT_MOD_DEV     4
+#define ENTRY_INIT_DEV         5
+#define ENTRY_INIT_MOD         6
+#define ENTRY_INIT_MSG         9
+
+/* IODC ENTRY_IO() */
+#define ENTRY_IO_BOOTIN                0
+#define ENTRY_IO_BOOTOUT       1
+#define ENTRY_IO_CIN           2
+#define ENTRY_IO_COUT          3
+#define ENTRY_IO_CLOSE         4
+#define ENTRY_IO_GETMSG                9
+#define ENTRY_IO_BBLOCK_IN     16
+#define ENTRY_IO_BBLOCK_OUT    17
+
+/* IODC ENTRY_SPA() */
+
+/* IODC ENTRY_CONFIG() */
+
+/* IODC ENTRY_TEST() */
+
+/* IODC ENTRY_TLB() */
+
+/* constants for OS (NVM...) */
+#define OS_ID_NONE             0       /* Undefined OS ID      */
+#define OS_ID_HPUX             1       /* HP-UX OS             */
+#define OS_ID_MPEXL            2       /* MPE XL OS            */
+#define OS_ID_OSF              3       /* OSF OS               */
+#define OS_ID_HPRT             4       /* HP-RT OS             */
+#define OS_ID_NOVEL            5       /* NOVELL OS            */
+#define OS_ID_LINUX            6       /* Linux                */
+
+
+/* constants for PDC_CHASSIS */
+#define OSTAT_OFF              0
+#define OSTAT_FLT              1 
+#define OSTAT_TEST             2
+#define OSTAT_INIT             3
+#define OSTAT_SHUT             4
+#define OSTAT_WARN             5
+#define OSTAT_RUN              6
+#define OSTAT_ON               7
+
+/* Page Zero constant offsets used by the HPMC handler */
+#define BOOT_CONSOLE_HPA_OFFSET  0x3c0
+#define BOOT_CONSOLE_SPA_OFFSET  0x3c4
+#define BOOT_CONSOLE_PATH_OFFSET 0x3a8
+
+/* size of the pdc_result buffer for firmware.c */
+#define NUM_PDC_RESULT 32
+
+#if !defined(__ASSEMBLY__)
+
+#include <linux/types.h>
+
+
+/* flags of the device_path */
+#define        PF_AUTOBOOT     0x80
+#define        PF_AUTOSEARCH   0x40
+#define        PF_TIMER        0x0F
+
+struct device_path {           /* page 1-69 */
+       unsigned char flags;    /* flags see above! */
+       unsigned char bc[6];    /* bus converter routing info */
+       unsigned char mod;
+       unsigned int  layers[6];/* device-specific layer-info */
+} __attribute__((aligned(8))) ;
+
+struct pz_device {
+       struct  device_path dp; /* see above */
+       /* struct       iomod *hpa; */
+       unsigned int hpa;       /* HPA base address */
+       /* char *spa; */
+       unsigned int spa;       /* SPA base address */
+       /* int  (*iodc_io)(struct iomod*, ...); */
+       unsigned int iodc_io;   /* device entry point */
+       short   pad;            /* reserved */
+       unsigned short cl_class;/* see below */
+} __attribute__((aligned(8))) ;
+
+struct zeropage {
+       /* [0x000] initialize vectors (VEC) */
+       unsigned int    vec_special;            /* must be zero */
+       /* int  (*vec_pow_fail)(void);*/
+       unsigned int    vec_pow_fail; /* power failure handler */
+       /* int  (*vec_toc)(void); */
+       unsigned int    vec_toc;
+       unsigned int    vec_toclen;
+       /* int  (*vec_rendz)(void); */
+       unsigned int vec_rendz;
+       int     vec_pow_fail_flen;
+       int     vec_pad[10];            
+       
+       /* [0x040] reserved processor dependent */
+       int     pad0[112];
+
+       /* [0x200] reserved */
+       int     pad1[84];
+
+       /* [0x350] memory configuration (MC) */
+       int     memc_cont;              /* contiguous mem size (bytes) */
+       int     memc_phsize;            /* physical memory size */
+       int     memc_adsize;            /* additional mem size, bytes of SPA space used by PDC */
+       unsigned int mem_pdc_hi;        /* used for 64-bit */
+
+       /* [0x360] various parameters for the boot-CPU */
+       /* unsigned int *mem_booterr[8]; */
+       unsigned int mem_booterr[8];    /* ptr to boot errors */
+       unsigned int mem_free;          /* first location, where OS can be loaded */
+       /* struct iomod *mem_hpa; */
+       unsigned int mem_hpa;           /* HPA of the boot-CPU */
+       /* int (*mem_pdc)(int, ...); */
+       unsigned int mem_pdc;           /* PDC entry point */
+       unsigned int mem_10msec;        /* number of clock ticks in 10msec */
+
+       /* [0x390] initial memory module (IMM) */
+       /* struct iomod *imm_hpa; */
+       unsigned int imm_hpa;           /* HPA of the IMM */
+       int     imm_soft_boot;          /* 0 = was hard boot, 1 = was soft boot */
+       unsigned int    imm_spa_size;           /* SPA size of the IMM in bytes */
+       unsigned int    imm_max_mem;            /* bytes of mem in IMM */
+
+       /* [0x3A0] boot console, display device and keyboard */
+       struct pz_device mem_cons;      /* description of console device */
+       struct pz_device mem_boot;      /* description of boot device */
+       struct pz_device mem_kbd;       /* description of keyboard device */
+
+       /* [0x430] reserved */
+       int     pad430[116];
+
+       /* [0x600] processor dependent */
+       __u32   pad600[1];
+       __u32   proc_sti;               /* pointer to STI ROM */
+       __u32   pad608[126];
+};
+
+#endif /* !defined(__ASSEMBLY__) */
+
+#endif /* _UAPI_PARISC_PDC_H */
diff --git a/arch/parisc/include/uapi/asm/posix_types.h b/arch/parisc/include/uapi/asm/posix_types.h
new file mode 100644 (file)
index 0000000..b934425
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef __ARCH_PARISC_POSIX_TYPES_H
+#define __ARCH_PARISC_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short         __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+
+typedef unsigned short         __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef int                    __kernel_suseconds_t;
+#define __kernel_suseconds_t __kernel_suseconds_t
+
+typedef long long              __kernel_off64_t;
+typedef unsigned long long     __kernel_ino64_t;
+
+#include <asm-generic/posix_types.h>
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/ptrace.h b/arch/parisc/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..c4fa6c8
--- /dev/null
@@ -0,0 +1,47 @@
+/* written by Philipp Rumpf, Copyright (C) 1999 SuSE GmbH Nuernberg
+** Copyright (C) 2000 Grant Grundler, Hewlett-Packard
+*/
+#ifndef _UAPI_PARISC_PTRACE_H
+#define _UAPI_PARISC_PTRACE_H
+
+
+#include <linux/types.h>
+
+/* This struct defines the way the registers are stored on the 
+ * stack during a system call.
+ *
+ * N.B. gdb/strace care about the size and offsets within this
+ * structure. If you change things, you may break object compatibility
+ * for those applications.
+ */
+
+struct pt_regs {
+       unsigned long gr[32];   /* PSW is in gr[0] */
+       __u64 fr[32];
+       unsigned long sr[ 8];
+       unsigned long iasq[2];
+       unsigned long iaoq[2];
+       unsigned long cr27;
+       unsigned long pad0;     /* available for other uses */
+       unsigned long orig_r28;
+       unsigned long ksp;
+       unsigned long kpc;
+       unsigned long sar;      /* CR11 */
+       unsigned long iir;      /* CR19 */
+       unsigned long isr;      /* CR20 */
+       unsigned long ior;      /* CR21 */
+       unsigned long ipsw;     /* CR22 */
+};
+
+/*
+ * The numbers chosen here are somewhat arbitrary but absolutely MUST
+ * not overlap with any of the number assigned in <linux/ptrace.h>.
+ *
+ * These ones are taken from IA-64 on the assumption that theirs are
+ * the most correct (and we also want to support PTRACE_SINGLEBLOCK
+ * since we have taken branch traps too)
+ */
+#define PTRACE_SINGLEBLOCK     12      /* resume execution until next branch */
+
+
+#endif /* _UAPI_PARISC_PTRACE_H */
diff --git a/arch/parisc/include/uapi/asm/resource.h b/arch/parisc/include/uapi/asm/resource.h
new file mode 100644 (file)
index 0000000..8b06343
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _ASM_PARISC_RESOURCE_H
+#define _ASM_PARISC_RESOURCE_H
+
+#define _STK_LIM_MAX   10 * _STK_LIM
+#include <asm-generic/resource.h>
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/sembuf.h b/arch/parisc/include/uapi/asm/sembuf.h
new file mode 100644 (file)
index 0000000..1e59ffd
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef _PARISC_SEMBUF_H
+#define _PARISC_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for parisc architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+#ifndef CONFIG_64BIT
+       unsigned int    __pad1;
+#endif
+       __kernel_time_t sem_otime;              /* last semop time */
+#ifndef CONFIG_64BIT
+       unsigned int    __pad2;
+#endif
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned int    sem_nsems;              /* no. of semaphores in array */
+       unsigned int    __unused1;
+       unsigned int    __unused2;
+};
+
+#endif /* _PARISC_SEMBUF_H */
diff --git a/arch/parisc/include/uapi/asm/setup.h b/arch/parisc/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..7da2e5b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _PARISC_SETUP_H
+#define _PARISC_SETUP_H
+
+#define COMMAND_LINE_SIZE      1024
+
+#endif /* _PARISC_SETUP_H */
diff --git a/arch/parisc/include/uapi/asm/shmbuf.h b/arch/parisc/include/uapi/asm/shmbuf.h
new file mode 100644 (file)
index 0000000..0a3eada
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _PARISC_SHMBUF_H
+#define _PARISC_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for parisc architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+#ifndef CONFIG_64BIT
+       unsigned int            __pad1;
+#endif
+       __kernel_time_t         shm_atime;      /* last attach time */
+#ifndef CONFIG_64BIT
+       unsigned int            __pad2;
+#endif
+       __kernel_time_t         shm_dtime;      /* last detach time */
+#ifndef CONFIG_64BIT
+       unsigned int            __pad3;
+#endif
+       __kernel_time_t         shm_ctime;      /* last change time */
+#ifndef CONFIG_64BIT
+       unsigned int            __pad4;
+#endif
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned int            shm_nattch;     /* no. of current attaches */
+       unsigned int            __unused1;
+       unsigned int            __unused2;
+};
+
+#ifdef CONFIG_64BIT
+/* The 'unsigned int' (formerly 'unsigned long') data types below will
+ * ensure that a 32-bit app calling shmctl(*,IPC_INFO,*) will work on
+ * a wide kernel, but if some of these values are meant to contain pointers
+ * they may need to be 'long long' instead. -PB XXX FIXME
+ */
+#endif
+struct shminfo64 {
+       unsigned int    shmmax;
+       unsigned int    shmmin;
+       unsigned int    shmmni;
+       unsigned int    shmseg;
+       unsigned int    shmall;
+       unsigned int    __unused1;
+       unsigned int    __unused2;
+       unsigned int    __unused3;
+       unsigned int    __unused4;
+};
+
+#endif /* _PARISC_SHMBUF_H */
diff --git a/arch/parisc/include/uapi/asm/sigcontext.h b/arch/parisc/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..27ef31b
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _ASMPARISC_SIGCONTEXT_H
+#define _ASMPARISC_SIGCONTEXT_H
+
+#define PARISC_SC_FLAG_ONSTACK 1<<0
+#define PARISC_SC_FLAG_IN_SYSCALL 1<<1
+
+/* We will add more stuff here as it becomes necessary, until we know
+   it works. */
+struct sigcontext {
+       unsigned long sc_flags;
+
+       unsigned long sc_gr[32]; /* PSW in sc_gr[0] */
+       unsigned long long sc_fr[32]; /* FIXME, do we need other state info? */
+       unsigned long sc_iasq[2];
+       unsigned long sc_iaoq[2];
+       unsigned long sc_sar; /* cr11 */
+};
+
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/siginfo.h b/arch/parisc/include/uapi/asm/siginfo.h
new file mode 100644 (file)
index 0000000..d703472
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _PARISC_SIGINFO_H
+#define _PARISC_SIGINFO_H
+
+#include <asm-generic/siginfo.h>
+
+#undef NSIGTRAP
+#define NSIGTRAP       4
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..b1ddaa2
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef _UAPI_ASM_PARISC_SIGNAL_H
+#define _UAPI_ASM_PARISC_SIGNAL_H
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGEMT          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGBUS         10
+#define SIGSEGV                11
+#define SIGSYS         12 /* Linux doesn't use this */
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGUSR1                16
+#define SIGUSR2                17
+#define SIGCHLD                18
+#define SIGPWR         19
+#define SIGVTALRM      20
+#define SIGPROF                21
+#define SIGIO          22
+#define SIGPOLL                SIGIO
+#define SIGWINCH       23
+#define SIGSTOP                24
+#define SIGTSTP                25
+#define SIGCONT                26
+#define SIGTTIN                27
+#define SIGTTOU                28
+#define SIGURG         29
+#define SIGLOST                30 /* Linux doesn't use this either */
+#define        SIGUNUSED       31
+#define SIGRESERVE     SIGUNUSED
+
+#define SIGXCPU                33
+#define SIGXFSZ                34
+#define SIGSTKFLT      36
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       37
+#define SIGRTMAX       _NSIG /* it's 44 under HP/UX */
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_ONSTACK     0x00000001
+#define SA_RESETHAND   0x00000004
+#define SA_NOCLDSTOP   0x00000008
+#define SA_SIGINFO     0x00000010
+#define SA_NODEFER     0x00000020
+#define SA_RESTART     0x00000040
+#define SA_NOCLDWAIT   0x00000080
+#define _SA_SIGGFAULT  0x00000100 /* HPUX */
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+#define SA_RESTORER    0x04000000 /* obsolete -- ignored */
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+
+#define SIG_BLOCK          0   /* for blocking signals */
+#define SIG_UNBLOCK        1   /* for unblocking signals */
+#define SIG_SETMASK        2   /* for setting the signal mask */
+
+#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
+#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
+#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+
+# ifndef __ASSEMBLY__
+
+#  include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+/* Type of a signal handler.  */
+#ifdef CONFIG_64BIT
+/* function pointers on 64-bit parisc are pointers to little structs and the
+ * compiler doesn't support code which changes or tests the address of
+ * the function in the little struct.  This is really ugly -PB
+ */
+typedef char __user *__sighandler_t;
+#else
+typedef void __signalfn_t(int);
+typedef __signalfn_t __user *__sighandler_t;
+#endif
+
+typedef struct sigaltstack {
+       void __user *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* !__ASSEMBLY */
+#endif /* _UAPI_ASM_PARISC_SIGNAL_H */
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
new file mode 100644 (file)
index 0000000..d9ff473
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockopt(2) */
+#define SOL_SOCKET     0xffff
+
+#define SO_DEBUG       0x0001
+#define SO_REUSEADDR   0x0004
+#define SO_KEEPALIVE   0x0008
+#define SO_DONTROUTE   0x0010
+#define SO_BROADCAST   0x0020
+#define SO_LINGER      0x0080
+#define SO_OOBINLINE   0x0100
+/* To add :#define SO_REUSEPORT 0x0200 */
+#define SO_SNDBUF      0x1001
+#define SO_RCVBUF      0x1002
+#define SO_SNDBUFFORCE 0x100a
+#define SO_RCVBUFFORCE 0x100b
+#define SO_SNDLOWAT    0x1003
+#define SO_RCVLOWAT    0x1004
+#define SO_SNDTIMEO    0x1005
+#define SO_RCVTIMEO    0x1006
+#define SO_ERROR       0x1007
+#define SO_TYPE                0x1008
+#define SO_PROTOCOL    0x1028
+#define SO_DOMAIN      0x1029
+#define SO_PEERNAME    0x2000
+
+#define SO_NO_CHECK    0x400b
+#define SO_PRIORITY    0x400c
+#define SO_BSDCOMPAT   0x400e
+#define SO_PASSCRED    0x4010
+#define SO_PEERCRED    0x4011
+#define SO_TIMESTAMP   0x4012
+#define SCM_TIMESTAMP  SO_TIMESTAMP
+#define SO_TIMESTAMPNS 0x4013
+#define SCM_TIMESTAMPNS        SO_TIMESTAMPNS
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION             0x4016
+#define SO_SECURITY_ENCRYPTION_TRANSPORT       0x4017
+#define SO_SECURITY_ENCRYPTION_NETWORK         0x4018
+
+#define SO_BINDTODEVICE        0x4019
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        0x401a
+#define SO_DETACH_FILTER        0x401b
+#define SO_GET_FILTER          SO_ATTACH_FILTER
+
+#define SO_ACCEPTCONN          0x401c
+
+#define SO_PEERSEC             0x401d
+#define SO_PASSSEC             0x401e
+
+#define SO_MARK                        0x401f
+
+#define SO_TIMESTAMPING                0x4020
+#define SCM_TIMESTAMPING       SO_TIMESTAMPING
+
+#define SO_RXQ_OVFL             0x4021
+
+#define SO_WIFI_STATUS         0x4022
+#define SCM_WIFI_STATUS                SO_WIFI_STATUS
+#define SO_PEEK_OFF            0x4023
+
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               0x4024
+
+
+/* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
+ * have to define SOCK_NONBLOCK to a different value here.
+ */
+#define SOCK_NONBLOCK   0x40000000
+
+#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/uapi/asm/sockios.h b/arch/parisc/include/uapi/asm/sockios.h
new file mode 100644 (file)
index 0000000..dabfbc7
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __ARCH_PARISC_SOCKIOS__
+#define __ARCH_PARISC_SOCKIOS__
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN      0x8901
+#define SIOCSPGRP      0x8902
+#define FIOGETOWN      0x8903
+#define SIOCGPGRP      0x8904
+#define SIOCATMARK     0x8905
+#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
+#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/stat.h b/arch/parisc/include/uapi/asm/stat.h
new file mode 100644 (file)
index 0000000..d76fbda
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef _PARISC_STAT_H
+#define _PARISC_STAT_H
+
+#include <linux/types.h>
+
+struct stat {
+       unsigned int    st_dev;         /* dev_t is 32 bits on parisc */
+       ino_t           st_ino;         /* 32 bits */
+       mode_t          st_mode;        /* 16 bits */
+       unsigned short  st_nlink;       /* 16 bits */
+       unsigned short  st_reserved1;   /* old st_uid */
+       unsigned short  st_reserved2;   /* old st_gid */
+       unsigned int    st_rdev;
+       off_t           st_size;
+       time_t          st_atime;
+       unsigned int    st_atime_nsec;
+       time_t          st_mtime;
+       unsigned int    st_mtime_nsec;
+       time_t          st_ctime;
+       unsigned int    st_ctime_nsec;
+       int             st_blksize;
+       int             st_blocks;
+       unsigned int    __unused1;      /* ACL stuff */
+       unsigned int    __unused2;      /* network */
+       ino_t           __unused3;      /* network */
+       unsigned int    __unused4;      /* cnodes */
+       unsigned short  __unused5;      /* netsite */
+       short           st_fstype;
+       unsigned int    st_realdev;
+       unsigned short  st_basemode;
+       unsigned short  st_spareshort;
+       uid_t           st_uid;
+       gid_t           st_gid;
+       unsigned int    st_spare4[3];
+};
+
+#define STAT_HAVE_NSEC
+
+typedef __kernel_off64_t       off64_t;
+
+struct hpux_stat64 {
+       unsigned int    st_dev;         /* dev_t is 32 bits on parisc */
+       ino_t           st_ino;         /* 32 bits */
+       mode_t          st_mode;        /* 16 bits */
+       unsigned short  st_nlink;       /* 16 bits */
+       unsigned short  st_reserved1;   /* old st_uid */
+       unsigned short  st_reserved2;   /* old st_gid */
+       unsigned int    st_rdev;
+       off64_t         st_size;
+       time_t          st_atime;
+       unsigned int    st_spare1;
+       time_t          st_mtime;
+       unsigned int    st_spare2;
+       time_t          st_ctime;
+       unsigned int    st_spare3;
+       int             st_blksize;
+       __u64           st_blocks;
+       unsigned int    __unused1;      /* ACL stuff */
+       unsigned int    __unused2;      /* network */
+       ino_t           __unused3;      /* network */
+       unsigned int    __unused4;      /* cnodes */
+       unsigned short  __unused5;      /* netsite */
+       short           st_fstype;
+       unsigned int    st_realdev;
+       unsigned short  st_basemode;
+       unsigned short  st_spareshort;
+       uid_t           st_uid;
+       gid_t           st_gid;
+       unsigned int    st_spare4[3];
+};
+
+/* This is the struct that 32-bit userspace applications are expecting.
+ * How 64-bit apps are going to be compiled, I have no idea.  But at least
+ * this way, we don't have a wrapper in the kernel.
+ */
+struct stat64 {
+       unsigned long long      st_dev;
+       unsigned int            __pad1;
+
+       unsigned int            __st_ino;       /* Not actually filled in */
+       unsigned int            st_mode;
+       unsigned int            st_nlink;
+       unsigned int            st_uid;
+       unsigned int            st_gid;
+       unsigned long long      st_rdev;
+       unsigned int            __pad2;
+       signed long long        st_size;
+       signed int              st_blksize;
+
+       signed long long        st_blocks;
+       signed int              st_atime;
+       unsigned int            st_atime_nsec;
+       signed int              st_mtime;
+       unsigned int            st_mtime_nsec;
+       signed int              st_ctime;
+       unsigned int            st_ctime_nsec;
+       unsigned long long      st_ino;
+};
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/statfs.h b/arch/parisc/include/uapi/asm/statfs.h
new file mode 100644 (file)
index 0000000..324bea9
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef _PARISC_STATFS_H
+#define _PARISC_STATFS_H
+
+#define __statfs_word long
+#include <asm-generic/statfs.h>
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/swab.h b/arch/parisc/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..e78403b
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef _PARISC_SWAB_H
+#define _PARISC_SWAB_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#define __SWAB_64_THRU_32__
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
+{
+       __asm__("dep %0, 15, 8, %0\n\t"         /* deposit 00ab -> 0bab */
+               "shd %%r0, %0, 8, %0"           /* shift 000000ab -> 00ba */
+               : "=r" (x)
+               : "0" (x));
+       return x;
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __attribute_const__ __u32 __arch_swab24(__u32 x)
+{
+       __asm__("shd %0, %0, 8, %0\n\t"         /* shift xabcxabc -> cxab */
+               "dep %0, 15, 8, %0\n\t"         /* deposit cxab -> cbab */
+               "shd %%r0, %0, 8, %0"           /* shift 0000cbab -> 0cba */
+               : "=r" (x)
+               : "0" (x));
+       return x;
+}
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+       unsigned int temp;
+       __asm__("shd %0, %0, 16, %1\n\t"        /* shift abcdabcd -> cdab */
+               "dep %1, 15, 8, %1\n\t"         /* deposit cdab -> cbab */
+               "shd %0, %1, 8, %0"             /* shift abcdcbab -> dcba */
+               : "=r" (x), "=&r" (temp)
+               : "0" (x));
+       return x;
+}
+#define __arch_swab32 __arch_swab32
+
+#if BITS_PER_LONG > 32
+/*
+** From "PA-RISC 2.0 Architecture", HP Professional Books.
+** See Appendix I page 8 , "Endian Byte Swapping".
+**
+** Pretty cool algorithm: (* == zero'd bits)
+**      PERMH   01234567 -> 67452301 into %0
+**      HSHL    67452301 -> 7*5*3*1* into %1
+**      HSHR    67452301 -> *6*4*2*0 into %0
+**      OR      %0 | %1  -> 76543210 into %0 (all done!)
+*/
+static inline __attribute_const__ __u64 __arch_swab64(__u64 x)
+{
+       __u64 temp;
+       __asm__("permh,3210 %0, %0\n\t"
+               "hshl %0, 8, %1\n\t"
+               "hshr,u %0, 8, %0\n\t"
+               "or %1, %0, %0"
+               : "=r" (x), "=&r" (temp)
+               : "0" (x));
+       return x;
+}
+#define __arch_swab64 __arch_swab64
+#endif /* BITS_PER_LONG > 32 */
+
+#endif /* _PARISC_SWAB_H */
diff --git a/arch/parisc/include/uapi/asm/termbits.h b/arch/parisc/include/uapi/asm/termbits.h
new file mode 100644 (file)
index 0000000..d1ab921
--- /dev/null
@@ -0,0 +1,201 @@
+#ifndef __ARCH_PARISC_TERMBITS_H__
+#define __ARCH_PARISC_TERMBITS_H__
+
+#include <linux/posix_types.h>
+
+typedef unsigned char  cc_t;
+typedef unsigned int   speed_t;
+typedef unsigned int   tcflag_t;
+
+#define NCCS 19
+struct termios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+};
+
+struct termios2 {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+
+/* c_iflag bits */
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK  0000020
+#define ISTRIP 0000040
+#define INLCR  0000100
+#define IGNCR  0000200
+#define ICRNL  0000400
+#define IUCLC  0001000
+#define IXON   0002000
+#define IXANY  0004000
+#define IXOFF  0010000
+#define IMAXBEL        0040000
+#define IUTF8  0100000
+
+/* c_oflag bits */
+#define OPOST  0000001
+#define OLCUC  0000002
+#define ONLCR  0000004
+#define OCRNL  0000010
+#define ONOCR  0000020
+#define ONLRET 0000040
+#define OFILL  0000100
+#define OFDEL  0000200
+#define NLDLY  0000400
+#define   NL0  0000000
+#define   NL1  0000400
+#define CRDLY  0003000
+#define   CR0  0000000
+#define   CR1  0001000
+#define   CR2  0002000
+#define   CR3  0003000
+#define TABDLY 0014000
+#define   TAB0 0000000
+#define   TAB1 0004000
+#define   TAB2 0010000
+#define   TAB3 0014000
+#define   XTABS        0014000
+#define BSDLY  0020000
+#define   BS0  0000000
+#define   BS1  0020000
+#define VTDLY  0040000
+#define   VT0  0000000
+#define   VT1  0040000
+#define FFDLY  0100000
+#define   FF0  0000000
+#define   FF1  0100000
+
+/* c_cflag bit meaning */
+#define CBAUD   0010017
+#define  B0     0000000         /* hang up */
+#define  B50    0000001
+#define  B75    0000002
+#define  B110   0000003
+#define  B134   0000004
+#define  B150   0000005
+#define  B200   0000006
+#define  B300   0000007
+#define  B600   0000010
+#define  B1200  0000011
+#define  B1800  0000012
+#define  B2400  0000013
+#define  B4800  0000014
+#define  B9600  0000015
+#define  B19200 0000016
+#define  B38400 0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE   0000060
+#define   CS5   0000000
+#define   CS6   0000020
+#define   CS7   0000040
+#define   CS8   0000060
+#define CSTOPB  0000100
+#define CREAD   0000200
+#define PARENB  0000400
+#define PARODD  0001000
+#define HUPCL   0002000
+#define CLOCAL  0004000
+#define CBAUDEX 0010000
+#define    BOTHER 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD    002003600000         /* input baud rate */
+#define CMSPAR    010000000000          /* mark or space (stick) parity */
+#define CRTSCTS   020000000000          /* flow control */
+
+#define IBSHIFT        16              /* Shift from CBAUD to CIBAUD */
+
+
+/* c_lflag bits */
+#define ISIG    0000001
+#define ICANON  0000002
+#define XCASE   0000004
+#define ECHO    0000010
+#define ECHOE   0000020
+#define ECHOK   0000040
+#define ECHONL  0000100
+#define NOFLSH  0000200
+#define TOSTOP  0000400
+#define ECHOCTL 0001000
+#define ECHOPRT 0002000
+#define ECHOKE  0004000
+#define FLUSHO  0010000
+#define PENDIN  0040000
+#define IEXTEN  0100000
+#define EXTPROC        0200000
+
+/* tcflow() and TCXONC use these */
+#define        TCOOFF          0
+#define        TCOON           1
+#define        TCIOFF          2
+#define        TCION           3
+
+/* tcflush() and TCFLSH use these */
+#define        TCIFLUSH        0
+#define        TCOFLUSH        1
+#define        TCIOFLUSH       2
+
+/* tcsetattr uses these */
+#define        TCSANOW         0
+#define        TCSADRAIN       1
+#define        TCSAFLUSH       2
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/termios.h b/arch/parisc/include/uapi/asm/termios.h
new file mode 100644 (file)
index 0000000..f337739
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _UAPI_PARISC_TERMIOS_H
+#define _UAPI_PARISC_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+       unsigned short ws_row;
+       unsigned short ws_col;
+       unsigned short ws_xpixel;
+       unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+       unsigned short c_iflag;         /* input mode flags */
+       unsigned short c_oflag;         /* output mode flags */
+       unsigned short c_cflag;         /* control mode flags */
+       unsigned short c_lflag;         /* local mode flags */
+       unsigned char c_line;           /* line discipline */
+       unsigned char c_cc[NCC];        /* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE       0x001
+#define TIOCM_DTR      0x002
+#define TIOCM_RTS      0x004
+#define TIOCM_ST       0x008
+#define TIOCM_SR       0x010
+#define TIOCM_CTS      0x020
+#define TIOCM_CAR      0x040
+#define TIOCM_RNG      0x080
+#define TIOCM_DSR      0x100
+#define TIOCM_CD       TIOCM_CAR
+#define TIOCM_RI       TIOCM_RNG
+#define TIOCM_OUT1     0x2000
+#define TIOCM_OUT2     0x4000
+#define TIOCM_LOOP     0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+
+#endif /* _UAPI_PARISC_TERMIOS_H */
diff --git a/arch/parisc/include/uapi/asm/types.h b/arch/parisc/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..8866f9b
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _PARISC_TYPES_H
+#define _PARISC_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+#endif
diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..e178f30
--- /dev/null
@@ -0,0 +1,837 @@
+#ifndef _UAPI_ASM_PARISC_UNISTD_H_
+#define _UAPI_ASM_PARISC_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+/*
+ *   HP-UX system calls get their native numbers for binary compatibility.
+ */
+
+#define __NR_HPUX_exit                    1
+#define __NR_HPUX_fork                    2
+#define __NR_HPUX_read                    3
+#define __NR_HPUX_write                   4
+#define __NR_HPUX_open                    5
+#define __NR_HPUX_close                   6
+#define __NR_HPUX_wait                    7
+#define __NR_HPUX_creat                   8
+#define __NR_HPUX_link                    9
+#define __NR_HPUX_unlink                 10
+#define __NR_HPUX_execv                  11
+#define __NR_HPUX_chdir                  12
+#define __NR_HPUX_time                   13
+#define __NR_HPUX_mknod                  14
+#define __NR_HPUX_chmod                  15
+#define __NR_HPUX_chown                  16
+#define __NR_HPUX_break                  17
+#define __NR_HPUX_lchmod                 18
+#define __NR_HPUX_lseek                  19
+#define __NR_HPUX_getpid                 20
+#define __NR_HPUX_mount                  21
+#define __NR_HPUX_umount                 22
+#define __NR_HPUX_setuid                 23
+#define __NR_HPUX_getuid                 24
+#define __NR_HPUX_stime                  25
+#define __NR_HPUX_ptrace                 26
+#define __NR_HPUX_alarm                  27
+#define __NR_HPUX_oldfstat               28
+#define __NR_HPUX_pause                  29
+#define __NR_HPUX_utime                  30
+#define __NR_HPUX_stty                   31
+#define __NR_HPUX_gtty                   32
+#define __NR_HPUX_access                 33
+#define __NR_HPUX_nice                   34
+#define __NR_HPUX_ftime                  35
+#define __NR_HPUX_sync                   36
+#define __NR_HPUX_kill                   37
+#define __NR_HPUX_stat                   38
+#define __NR_HPUX_setpgrp3               39
+#define __NR_HPUX_lstat                  40
+#define __NR_HPUX_dup                    41
+#define __NR_HPUX_pipe                   42
+#define __NR_HPUX_times                  43
+#define __NR_HPUX_profil                 44
+#define __NR_HPUX_ki_call                45
+#define __NR_HPUX_setgid                 46
+#define __NR_HPUX_getgid                 47
+#define __NR_HPUX_sigsys                 48
+#define __NR_HPUX_reserved1              49
+#define __NR_HPUX_reserved2              50
+#define __NR_HPUX_acct                   51
+#define __NR_HPUX_set_userthreadid       52
+#define __NR_HPUX_oldlock                53
+#define __NR_HPUX_ioctl                  54
+#define __NR_HPUX_reboot                 55
+#define __NR_HPUX_symlink                56
+#define __NR_HPUX_utssys                 57
+#define __NR_HPUX_readlink               58
+#define __NR_HPUX_execve                 59
+#define __NR_HPUX_umask                  60
+#define __NR_HPUX_chroot                 61
+#define __NR_HPUX_fcntl                  62
+#define __NR_HPUX_ulimit                 63
+#define __NR_HPUX_getpagesize            64
+#define __NR_HPUX_mremap                 65
+#define __NR_HPUX_vfork                  66
+#define __NR_HPUX_vread                  67
+#define __NR_HPUX_vwrite                 68
+#define __NR_HPUX_sbrk                   69
+#define __NR_HPUX_sstk                   70
+#define __NR_HPUX_mmap                   71
+#define __NR_HPUX_vadvise                72
+#define __NR_HPUX_munmap                 73
+#define __NR_HPUX_mprotect               74
+#define __NR_HPUX_madvise                75
+#define __NR_HPUX_vhangup                76
+#define __NR_HPUX_swapoff                77
+#define __NR_HPUX_mincore                78
+#define __NR_HPUX_getgroups              79
+#define __NR_HPUX_setgroups              80
+#define __NR_HPUX_getpgrp2               81
+#define __NR_HPUX_setpgrp2               82
+#define __NR_HPUX_setitimer              83
+#define __NR_HPUX_wait3                  84
+#define __NR_HPUX_swapon                 85
+#define __NR_HPUX_getitimer              86
+#define __NR_HPUX_gethostname42          87
+#define __NR_HPUX_sethostname42          88
+#define __NR_HPUX_getdtablesize          89
+#define __NR_HPUX_dup2                   90
+#define __NR_HPUX_getdopt                91
+#define __NR_HPUX_fstat                  92
+#define __NR_HPUX_select                 93
+#define __NR_HPUX_setdopt                94
+#define __NR_HPUX_fsync                  95
+#define __NR_HPUX_setpriority            96
+#define __NR_HPUX_socket_old             97
+#define __NR_HPUX_connect_old            98
+#define __NR_HPUX_accept_old             99
+#define __NR_HPUX_getpriority           100
+#define __NR_HPUX_send_old              101
+#define __NR_HPUX_recv_old              102
+#define __NR_HPUX_socketaddr_old        103
+#define __NR_HPUX_bind_old              104
+#define __NR_HPUX_setsockopt_old        105
+#define __NR_HPUX_listen_old            106
+#define __NR_HPUX_vtimes_old            107
+#define __NR_HPUX_sigvector             108
+#define __NR_HPUX_sigblock              109
+#define __NR_HPUX_siggetmask            110
+#define __NR_HPUX_sigpause              111
+#define __NR_HPUX_sigstack              112
+#define __NR_HPUX_recvmsg_old           113
+#define __NR_HPUX_sendmsg_old           114
+#define __NR_HPUX_vtrace_old            115
+#define __NR_HPUX_gettimeofday          116
+#define __NR_HPUX_getrusage             117
+#define __NR_HPUX_getsockopt_old        118
+#define __NR_HPUX_resuba_old            119
+#define __NR_HPUX_readv                 120
+#define __NR_HPUX_writev                121
+#define __NR_HPUX_settimeofday          122
+#define __NR_HPUX_fchown                123
+#define __NR_HPUX_fchmod                124
+#define __NR_HPUX_recvfrom_old          125
+#define __NR_HPUX_setresuid             126
+#define __NR_HPUX_setresgid             127
+#define __NR_HPUX_rename                128
+#define __NR_HPUX_truncate              129
+#define __NR_HPUX_ftruncate             130
+#define __NR_HPUX_flock_old             131
+#define __NR_HPUX_sysconf               132
+#define __NR_HPUX_sendto_old            133
+#define __NR_HPUX_shutdown_old          134
+#define __NR_HPUX_socketpair_old        135
+#define __NR_HPUX_mkdir                 136
+#define __NR_HPUX_rmdir                 137
+#define __NR_HPUX_utimes_old            138
+#define __NR_HPUX_sigcleanup_old        139
+#define __NR_HPUX_setcore               140
+#define __NR_HPUX_getpeername_old       141
+#define __NR_HPUX_gethostid             142
+#define __NR_HPUX_sethostid             143
+#define __NR_HPUX_getrlimit             144
+#define __NR_HPUX_setrlimit             145
+#define __NR_HPUX_killpg_old            146
+#define __NR_HPUX_cachectl              147
+#define __NR_HPUX_quotactl              148
+#define __NR_HPUX_get_sysinfo           149
+#define __NR_HPUX_getsockname_old       150
+#define __NR_HPUX_privgrp               151
+#define __NR_HPUX_rtprio                152
+#define __NR_HPUX_plock                 153
+#define __NR_HPUX_reserved3             154
+#define __NR_HPUX_lockf                 155
+#define __NR_HPUX_semget                156
+#define __NR_HPUX_osemctl               157
+#define __NR_HPUX_semop                 158
+#define __NR_HPUX_msgget                159
+#define __NR_HPUX_omsgctl               160
+#define __NR_HPUX_msgsnd                161
+#define __NR_HPUX_msgrecv               162
+#define __NR_HPUX_shmget                163
+#define __NR_HPUX_oshmctl               164
+#define __NR_HPUX_shmat                 165
+#define __NR_HPUX_shmdt                 166
+#define __NR_HPUX_m68020_advise         167
+/* [168,189] are for Discless/DUX */
+#define __NR_HPUX_csp                   168
+#define __NR_HPUX_cluster               169
+#define __NR_HPUX_mkrnod                170
+#define __NR_HPUX_test                  171
+#define __NR_HPUX_unsp_open             172
+#define __NR_HPUX_reserved4             173
+#define __NR_HPUX_getcontext_old        174
+#define __NR_HPUX_osetcontext           175
+#define __NR_HPUX_bigio                 176
+#define __NR_HPUX_pipenode              177
+#define __NR_HPUX_lsync                 178
+#define __NR_HPUX_getmachineid          179
+#define __NR_HPUX_cnodeid               180
+#define __NR_HPUX_cnodes                181
+#define __NR_HPUX_swapclients           182
+#define __NR_HPUX_rmt_process           183
+#define __NR_HPUX_dskless_stats         184
+#define __NR_HPUX_sigprocmask           185
+#define __NR_HPUX_sigpending            186
+#define __NR_HPUX_sigsuspend            187
+#define __NR_HPUX_sigaction             188
+#define __NR_HPUX_reserved5             189
+#define __NR_HPUX_nfssvc                190
+#define __NR_HPUX_getfh                 191
+#define __NR_HPUX_getdomainname         192
+#define __NR_HPUX_setdomainname         193
+#define __NR_HPUX_async_daemon          194
+#define __NR_HPUX_getdirentries         195
+#define __NR_HPUX_statfs                196
+#define __NR_HPUX_fstatfs               197
+#define __NR_HPUX_vfsmount              198
+#define __NR_HPUX_reserved6             199
+#define __NR_HPUX_waitpid               200
+/* 201 - 223 missing */
+#define __NR_HPUX_sigsetreturn          224
+#define __NR_HPUX_sigsetstatemask       225
+/* 226 missing */
+#define __NR_HPUX_cs                    227
+#define __NR_HPUX_cds                   228
+#define __NR_HPUX_set_no_trunc          229
+#define __NR_HPUX_pathconf              230
+#define __NR_HPUX_fpathconf             231
+/* 232, 233 missing */
+#define __NR_HPUX_nfs_fcntl             234
+#define __NR_HPUX_ogetacl               235
+#define __NR_HPUX_ofgetacl              236
+#define __NR_HPUX_osetacl               237
+#define __NR_HPUX_ofsetacl              238
+#define __NR_HPUX_pstat                 239
+#define __NR_HPUX_getaudid              240
+#define __NR_HPUX_setaudid              241
+#define __NR_HPUX_getaudproc            242
+#define __NR_HPUX_setaudproc            243
+#define __NR_HPUX_getevent              244
+#define __NR_HPUX_setevent              245
+#define __NR_HPUX_audwrite              246
+#define __NR_HPUX_audswitch             247
+#define __NR_HPUX_audctl                248
+#define __NR_HPUX_ogetaccess            249
+#define __NR_HPUX_fsctl                 250
+/* 251 - 258 missing */
+#define __NR_HPUX_swapfs                259
+#define __NR_HPUX_fss                   260
+/* 261 - 266 missing */
+#define __NR_HPUX_tsync                 267
+#define __NR_HPUX_getnumfds             268
+#define __NR_HPUX_poll                  269
+#define __NR_HPUX_getmsg                270
+#define __NR_HPUX_putmsg                271
+#define __NR_HPUX_fchdir                272
+#define __NR_HPUX_getmount_cnt          273
+#define __NR_HPUX_getmount_entry        274
+#define __NR_HPUX_accept                275
+#define __NR_HPUX_bind                  276
+#define __NR_HPUX_connect               277
+#define __NR_HPUX_getpeername           278
+#define __NR_HPUX_getsockname           279
+#define __NR_HPUX_getsockopt            280
+#define __NR_HPUX_listen                281
+#define __NR_HPUX_recv                  282
+#define __NR_HPUX_recvfrom              283
+#define __NR_HPUX_recvmsg               284
+#define __NR_HPUX_send                  285
+#define __NR_HPUX_sendmsg               286
+#define __NR_HPUX_sendto                287
+#define __NR_HPUX_setsockopt            288
+#define __NR_HPUX_shutdown              289
+#define __NR_HPUX_socket                290
+#define __NR_HPUX_socketpair            291
+#define __NR_HPUX_proc_open             292
+#define __NR_HPUX_proc_close            293
+#define __NR_HPUX_proc_send             294
+#define __NR_HPUX_proc_recv             295
+#define __NR_HPUX_proc_sendrecv         296
+#define __NR_HPUX_proc_syscall          297
+/* 298 - 311 missing */
+#define __NR_HPUX_semctl                312
+#define __NR_HPUX_msgctl                313
+#define __NR_HPUX_shmctl                314
+#define __NR_HPUX_mpctl                 315
+#define __NR_HPUX_exportfs              316
+#define __NR_HPUX_getpmsg               317
+#define __NR_HPUX_putpmsg               318
+/* 319 missing */
+#define __NR_HPUX_msync                 320
+#define __NR_HPUX_msleep                321
+#define __NR_HPUX_mwakeup               322
+#define __NR_HPUX_msem_init             323
+#define __NR_HPUX_msem_remove           324
+#define __NR_HPUX_adjtime               325
+#define __NR_HPUX_kload                 326
+#define __NR_HPUX_fattach               327
+#define __NR_HPUX_fdetach               328
+#define __NR_HPUX_serialize             329
+#define __NR_HPUX_statvfs               330
+#define __NR_HPUX_fstatvfs              331
+#define __NR_HPUX_lchown                332
+#define __NR_HPUX_getsid                333
+#define __NR_HPUX_sysfs                 334
+/* 335, 336 missing */
+#define __NR_HPUX_sched_setparam        337
+#define __NR_HPUX_sched_getparam        338
+#define __NR_HPUX_sched_setscheduler    339
+#define __NR_HPUX_sched_getscheduler    340
+#define __NR_HPUX_sched_yield           341
+#define __NR_HPUX_sched_get_priority_max 342
+#define __NR_HPUX_sched_get_priority_min 343
+#define __NR_HPUX_sched_rr_get_interval 344
+#define __NR_HPUX_clock_settime         345
+#define __NR_HPUX_clock_gettime         346
+#define __NR_HPUX_clock_getres          347
+#define __NR_HPUX_timer_create          348
+#define __NR_HPUX_timer_delete          349
+#define __NR_HPUX_timer_settime         350
+#define __NR_HPUX_timer_gettime         351
+#define __NR_HPUX_timer_getoverrun      352
+#define __NR_HPUX_nanosleep             353
+#define __NR_HPUX_toolbox               354
+/* 355 missing */
+#define __NR_HPUX_getdents              356
+#define __NR_HPUX_getcontext            357
+#define __NR_HPUX_sysinfo               358
+#define __NR_HPUX_fcntl64               359
+#define __NR_HPUX_ftruncate64           360
+#define __NR_HPUX_fstat64               361
+#define __NR_HPUX_getdirentries64       362
+#define __NR_HPUX_getrlimit64           363
+#define __NR_HPUX_lockf64               364
+#define __NR_HPUX_lseek64               365
+#define __NR_HPUX_lstat64               366
+#define __NR_HPUX_mmap64                367
+#define __NR_HPUX_setrlimit64           368
+#define __NR_HPUX_stat64                369
+#define __NR_HPUX_truncate64            370
+#define __NR_HPUX_ulimit64              371
+#define __NR_HPUX_pread                 372
+#define __NR_HPUX_preadv                373
+#define __NR_HPUX_pwrite                374
+#define __NR_HPUX_pwritev               375
+#define __NR_HPUX_pread64               376
+#define __NR_HPUX_preadv64              377
+#define __NR_HPUX_pwrite64              378
+#define __NR_HPUX_pwritev64             379
+#define __NR_HPUX_setcontext            380
+#define __NR_HPUX_sigaltstack           381
+#define __NR_HPUX_waitid                382
+#define __NR_HPUX_setpgrp               383
+#define __NR_HPUX_recvmsg2              384
+#define __NR_HPUX_sendmsg2              385
+#define __NR_HPUX_socket2               386
+#define __NR_HPUX_socketpair2           387
+#define __NR_HPUX_setregid              388
+#define __NR_HPUX_lwp_create            389
+#define __NR_HPUX_lwp_terminate         390
+#define __NR_HPUX_lwp_wait              391
+#define __NR_HPUX_lwp_suspend           392
+#define __NR_HPUX_lwp_resume            393
+/* 394 missing */
+#define __NR_HPUX_lwp_abort_syscall     395
+#define __NR_HPUX_lwp_info              396
+#define __NR_HPUX_lwp_kill              397
+#define __NR_HPUX_ksleep                398
+#define __NR_HPUX_kwakeup               399
+/* 400 missing */
+#define __NR_HPUX_pstat_getlwp          401
+#define __NR_HPUX_lwp_exit              402
+#define __NR_HPUX_lwp_continue          403
+#define __NR_HPUX_getacl                404
+#define __NR_HPUX_fgetacl               405
+#define __NR_HPUX_setacl                406
+#define __NR_HPUX_fsetacl               407
+#define __NR_HPUX_getaccess             408
+#define __NR_HPUX_lwp_mutex_init        409
+#define __NR_HPUX_lwp_mutex_lock_sys    410
+#define __NR_HPUX_lwp_mutex_unlock      411
+#define __NR_HPUX_lwp_cond_init         412
+#define __NR_HPUX_lwp_cond_signal       413
+#define __NR_HPUX_lwp_cond_broadcast    414
+#define __NR_HPUX_lwp_cond_wait_sys     415
+#define __NR_HPUX_lwp_getscheduler      416
+#define __NR_HPUX_lwp_setscheduler      417
+#define __NR_HPUX_lwp_getstate          418
+#define __NR_HPUX_lwp_setstate          419
+#define __NR_HPUX_lwp_detach            420
+#define __NR_HPUX_mlock                 421
+#define __NR_HPUX_munlock               422
+#define __NR_HPUX_mlockall              423
+#define __NR_HPUX_munlockall            424
+#define __NR_HPUX_shm_open              425
+#define __NR_HPUX_shm_unlink            426
+#define __NR_HPUX_sigqueue              427
+#define __NR_HPUX_sigwaitinfo           428
+#define __NR_HPUX_sigtimedwait          429
+#define __NR_HPUX_sigwait               430
+#define __NR_HPUX_aio_read              431
+#define __NR_HPUX_aio_write             432
+#define __NR_HPUX_lio_listio            433
+#define __NR_HPUX_aio_error             434
+#define __NR_HPUX_aio_return            435
+#define __NR_HPUX_aio_cancel            436
+#define __NR_HPUX_aio_suspend           437
+#define __NR_HPUX_aio_fsync             438
+#define __NR_HPUX_mq_open               439
+#define __NR_HPUX_mq_close              440
+#define __NR_HPUX_mq_unlink             441
+#define __NR_HPUX_mq_send               442
+#define __NR_HPUX_mq_receive            443
+#define __NR_HPUX_mq_notify             444
+#define __NR_HPUX_mq_setattr            445
+#define __NR_HPUX_mq_getattr            446
+#define __NR_HPUX_ksem_open             447
+#define __NR_HPUX_ksem_unlink           448
+#define __NR_HPUX_ksem_close            449
+#define __NR_HPUX_ksem_post             450
+#define __NR_HPUX_ksem_wait             451
+#define __NR_HPUX_ksem_read             452
+#define __NR_HPUX_ksem_trywait          453
+#define __NR_HPUX_lwp_rwlock_init       454
+#define __NR_HPUX_lwp_rwlock_destroy    455
+#define __NR_HPUX_lwp_rwlock_rdlock_sys 456
+#define __NR_HPUX_lwp_rwlock_wrlock_sys 457
+#define __NR_HPUX_lwp_rwlock_tryrdlock  458
+#define __NR_HPUX_lwp_rwlock_trywrlock  459
+#define __NR_HPUX_lwp_rwlock_unlock     460
+#define __NR_HPUX_ttrace                461
+#define __NR_HPUX_ttrace_wait           462
+#define __NR_HPUX_lf_wire_mem           463
+#define __NR_HPUX_lf_unwire_mem         464
+#define __NR_HPUX_lf_send_pin_map       465
+#define __NR_HPUX_lf_free_buf           466
+#define __NR_HPUX_lf_wait_nq            467
+#define __NR_HPUX_lf_wakeup_conn_q      468
+#define __NR_HPUX_lf_unused             469
+#define __NR_HPUX_lwp_sema_init         470
+#define __NR_HPUX_lwp_sema_post         471
+#define __NR_HPUX_lwp_sema_wait         472
+#define __NR_HPUX_lwp_sema_trywait      473
+#define __NR_HPUX_lwp_sema_destroy      474
+#define __NR_HPUX_statvfs64             475
+#define __NR_HPUX_fstatvfs64            476
+#define __NR_HPUX_msh_register          477
+#define __NR_HPUX_ptrace64              478
+#define __NR_HPUX_sendfile              479
+#define __NR_HPUX_sendpath              480
+#define __NR_HPUX_sendfile64            481
+#define __NR_HPUX_sendpath64            482
+#define __NR_HPUX_modload               483
+#define __NR_HPUX_moduload              484
+#define __NR_HPUX_modpath               485
+#define __NR_HPUX_getksym               486
+#define __NR_HPUX_modadm                487
+#define __NR_HPUX_modstat               488
+#define __NR_HPUX_lwp_detached_exit     489
+#define __NR_HPUX_crashconf             490
+#define __NR_HPUX_siginhibit            491
+#define __NR_HPUX_sigenable             492
+#define __NR_HPUX_spuctl                493
+#define __NR_HPUX_zerokernelsum         494
+#define __NR_HPUX_nfs_kstat             495
+#define __NR_HPUX_aio_read64            496
+#define __NR_HPUX_aio_write64           497
+#define __NR_HPUX_aio_error64           498
+#define __NR_HPUX_aio_return64          499
+#define __NR_HPUX_aio_cancel64          500
+#define __NR_HPUX_aio_suspend64         501
+#define __NR_HPUX_aio_fsync64           502
+#define __NR_HPUX_lio_listio64          503
+#define __NR_HPUX_recv2                 504
+#define __NR_HPUX_recvfrom2             505
+#define __NR_HPUX_send2                 506
+#define __NR_HPUX_sendto2               507
+#define __NR_HPUX_acl                   508
+#define __NR_HPUX___cnx_p2p_ctl         509
+#define __NR_HPUX___cnx_gsched_ctl      510
+#define __NR_HPUX___cnx_pmon_ctl        511
+
+#define __NR_HPUX_syscalls             512
+
+/*
+ * Linux system call numbers.
+ *
+ * Cary Coutant says that we should just use another syscall gateway
+ * page to avoid clashing with the HPUX space, and I think he's right:
+ * it will would keep a branch out of our syscall entry path, at the
+ * very least.  If we decide to change it later, we can ``just'' tweak
+ * the LINUX_GATEWAY_ADDR define at the bottom and make __NR_Linux be
+ * 1024 or something.  Oh, and recompile libc. =)
+ *
+ * 64-bit HPUX binaries get the syscall gateway address passed in a register
+ * from the kernel at startup, which seems a sane strategy.
+ */
+
+#define __NR_Linux                0
+#define __NR_restart_syscall      (__NR_Linux + 0)
+#define __NR_exit                 (__NR_Linux + 1)
+#define __NR_fork                 (__NR_Linux + 2)
+#define __NR_read                 (__NR_Linux + 3)
+#define __NR_write                (__NR_Linux + 4)
+#define __NR_open                 (__NR_Linux + 5)
+#define __NR_close                (__NR_Linux + 6)
+#define __NR_waitpid              (__NR_Linux + 7)
+#define __NR_creat                (__NR_Linux + 8)
+#define __NR_link                 (__NR_Linux + 9)
+#define __NR_unlink              (__NR_Linux + 10)
+#define __NR_execve              (__NR_Linux + 11)
+#define __NR_chdir               (__NR_Linux + 12)
+#define __NR_time                (__NR_Linux + 13)
+#define __NR_mknod               (__NR_Linux + 14)
+#define __NR_chmod               (__NR_Linux + 15)
+#define __NR_lchown              (__NR_Linux + 16)
+#define __NR_socket              (__NR_Linux + 17)
+#define __NR_stat                (__NR_Linux + 18)
+#define __NR_lseek               (__NR_Linux + 19)
+#define __NR_getpid              (__NR_Linux + 20)
+#define __NR_mount               (__NR_Linux + 21)
+#define __NR_bind                (__NR_Linux + 22)
+#define __NR_setuid              (__NR_Linux + 23)
+#define __NR_getuid              (__NR_Linux + 24)
+#define __NR_stime               (__NR_Linux + 25)
+#define __NR_ptrace              (__NR_Linux + 26)
+#define __NR_alarm               (__NR_Linux + 27)
+#define __NR_fstat               (__NR_Linux + 28)
+#define __NR_pause               (__NR_Linux + 29)
+#define __NR_utime               (__NR_Linux + 30)
+#define __NR_connect             (__NR_Linux + 31)
+#define __NR_listen              (__NR_Linux + 32)
+#define __NR_access              (__NR_Linux + 33)
+#define __NR_nice                (__NR_Linux + 34)
+#define __NR_accept              (__NR_Linux + 35)
+#define __NR_sync                (__NR_Linux + 36)
+#define __NR_kill                (__NR_Linux + 37)
+#define __NR_rename              (__NR_Linux + 38)
+#define __NR_mkdir               (__NR_Linux + 39)
+#define __NR_rmdir               (__NR_Linux + 40)
+#define __NR_dup                 (__NR_Linux + 41)
+#define __NR_pipe                (__NR_Linux + 42)
+#define __NR_times               (__NR_Linux + 43)
+#define __NR_getsockname         (__NR_Linux + 44)
+#define __NR_brk                 (__NR_Linux + 45)
+#define __NR_setgid              (__NR_Linux + 46)
+#define __NR_getgid              (__NR_Linux + 47)
+#define __NR_signal              (__NR_Linux + 48)
+#define __NR_geteuid             (__NR_Linux + 49)
+#define __NR_getegid             (__NR_Linux + 50)
+#define __NR_acct                (__NR_Linux + 51)
+#define __NR_umount2             (__NR_Linux + 52)
+#define __NR_getpeername         (__NR_Linux + 53)
+#define __NR_ioctl               (__NR_Linux + 54)
+#define __NR_fcntl               (__NR_Linux + 55)
+#define __NR_socketpair          (__NR_Linux + 56)
+#define __NR_setpgid             (__NR_Linux + 57)
+#define __NR_send                (__NR_Linux + 58)
+#define __NR_uname               (__NR_Linux + 59)
+#define __NR_umask               (__NR_Linux + 60)
+#define __NR_chroot              (__NR_Linux + 61)
+#define __NR_ustat               (__NR_Linux + 62)
+#define __NR_dup2                (__NR_Linux + 63)
+#define __NR_getppid             (__NR_Linux + 64)
+#define __NR_getpgrp             (__NR_Linux + 65)
+#define __NR_setsid              (__NR_Linux + 66)
+#define __NR_pivot_root          (__NR_Linux + 67)
+#define __NR_sgetmask            (__NR_Linux + 68)
+#define __NR_ssetmask            (__NR_Linux + 69)
+#define __NR_setreuid            (__NR_Linux + 70)
+#define __NR_setregid            (__NR_Linux + 71)
+#define __NR_mincore             (__NR_Linux + 72)
+#define __NR_sigpending          (__NR_Linux + 73)
+#define __NR_sethostname         (__NR_Linux + 74)
+#define __NR_setrlimit           (__NR_Linux + 75)
+#define __NR_getrlimit           (__NR_Linux + 76)
+#define __NR_getrusage           (__NR_Linux + 77)
+#define __NR_gettimeofday        (__NR_Linux + 78)
+#define __NR_settimeofday        (__NR_Linux + 79)
+#define __NR_getgroups           (__NR_Linux + 80)
+#define __NR_setgroups           (__NR_Linux + 81)
+#define __NR_sendto              (__NR_Linux + 82)
+#define __NR_symlink             (__NR_Linux + 83)
+#define __NR_lstat               (__NR_Linux + 84)
+#define __NR_readlink            (__NR_Linux + 85)
+#define __NR_uselib              (__NR_Linux + 86)
+#define __NR_swapon              (__NR_Linux + 87)
+#define __NR_reboot              (__NR_Linux + 88)
+#define __NR_mmap2             (__NR_Linux + 89)
+#define __NR_mmap                (__NR_Linux + 90)
+#define __NR_munmap              (__NR_Linux + 91)
+#define __NR_truncate            (__NR_Linux + 92)
+#define __NR_ftruncate           (__NR_Linux + 93)
+#define __NR_fchmod              (__NR_Linux + 94)
+#define __NR_fchown              (__NR_Linux + 95)
+#define __NR_getpriority         (__NR_Linux + 96)
+#define __NR_setpriority         (__NR_Linux + 97)
+#define __NR_recv                (__NR_Linux + 98)
+#define __NR_statfs              (__NR_Linux + 99)
+#define __NR_fstatfs            (__NR_Linux + 100)
+#define __NR_stat64           (__NR_Linux + 101)
+/* #define __NR_socketcall         (__NR_Linux + 102) */
+#define __NR_syslog             (__NR_Linux + 103)
+#define __NR_setitimer          (__NR_Linux + 104)
+#define __NR_getitimer          (__NR_Linux + 105)
+#define __NR_capget             (__NR_Linux + 106)
+#define __NR_capset             (__NR_Linux + 107)
+#define __NR_pread64            (__NR_Linux + 108)
+#define __NR_pwrite64           (__NR_Linux + 109)
+#define __NR_getcwd             (__NR_Linux + 110)
+#define __NR_vhangup            (__NR_Linux + 111)
+#define __NR_fstat64            (__NR_Linux + 112)
+#define __NR_vfork              (__NR_Linux + 113)
+#define __NR_wait4              (__NR_Linux + 114)
+#define __NR_swapoff            (__NR_Linux + 115)
+#define __NR_sysinfo            (__NR_Linux + 116)
+#define __NR_shutdown           (__NR_Linux + 117)
+#define __NR_fsync              (__NR_Linux + 118)
+#define __NR_madvise            (__NR_Linux + 119)
+#define __NR_clone              (__NR_Linux + 120)
+#define __NR_setdomainname      (__NR_Linux + 121)
+#define __NR_sendfile           (__NR_Linux + 122)
+#define __NR_recvfrom           (__NR_Linux + 123)
+#define __NR_adjtimex           (__NR_Linux + 124)
+#define __NR_mprotect           (__NR_Linux + 125)
+#define __NR_sigprocmask        (__NR_Linux + 126)
+#define __NR_create_module      (__NR_Linux + 127)
+#define __NR_init_module        (__NR_Linux + 128)
+#define __NR_delete_module      (__NR_Linux + 129)
+#define __NR_get_kernel_syms    (__NR_Linux + 130)
+#define __NR_quotactl           (__NR_Linux + 131)
+#define __NR_getpgid            (__NR_Linux + 132)
+#define __NR_fchdir             (__NR_Linux + 133)
+#define __NR_bdflush            (__NR_Linux + 134)
+#define __NR_sysfs              (__NR_Linux + 135)
+#define __NR_personality        (__NR_Linux + 136)
+#define __NR_afs_syscall        (__NR_Linux + 137) /* Syscall for Andrew File System */
+#define __NR_setfsuid           (__NR_Linux + 138)
+#define __NR_setfsgid           (__NR_Linux + 139)
+#define __NR__llseek            (__NR_Linux + 140)
+#define __NR_getdents           (__NR_Linux + 141)
+#define __NR__newselect         (__NR_Linux + 142)
+#define __NR_flock              (__NR_Linux + 143)
+#define __NR_msync              (__NR_Linux + 144)
+#define __NR_readv              (__NR_Linux + 145)
+#define __NR_writev             (__NR_Linux + 146)
+#define __NR_getsid             (__NR_Linux + 147)
+#define __NR_fdatasync          (__NR_Linux + 148)
+#define __NR__sysctl            (__NR_Linux + 149)
+#define __NR_mlock              (__NR_Linux + 150)
+#define __NR_munlock            (__NR_Linux + 151)
+#define __NR_mlockall           (__NR_Linux + 152)
+#define __NR_munlockall         (__NR_Linux + 153)
+#define __NR_sched_setparam             (__NR_Linux + 154)
+#define __NR_sched_getparam             (__NR_Linux + 155)
+#define __NR_sched_setscheduler         (__NR_Linux + 156)
+#define __NR_sched_getscheduler         (__NR_Linux + 157)
+#define __NR_sched_yield                (__NR_Linux + 158)
+#define __NR_sched_get_priority_max     (__NR_Linux + 159)
+#define __NR_sched_get_priority_min     (__NR_Linux + 160)
+#define __NR_sched_rr_get_interval      (__NR_Linux + 161)
+#define __NR_nanosleep          (__NR_Linux + 162)
+#define __NR_mremap             (__NR_Linux + 163)
+#define __NR_setresuid          (__NR_Linux + 164)
+#define __NR_getresuid          (__NR_Linux + 165)
+#define __NR_sigaltstack        (__NR_Linux + 166)
+#define __NR_query_module       (__NR_Linux + 167)
+#define __NR_poll               (__NR_Linux + 168)
+#define __NR_nfsservctl         (__NR_Linux + 169)
+#define __NR_setresgid          (__NR_Linux + 170)
+#define __NR_getresgid          (__NR_Linux + 171)
+#define __NR_prctl              (__NR_Linux + 172)
+#define __NR_rt_sigreturn       (__NR_Linux + 173)
+#define __NR_rt_sigaction       (__NR_Linux + 174)
+#define __NR_rt_sigprocmask     (__NR_Linux + 175)
+#define __NR_rt_sigpending      (__NR_Linux + 176)
+#define __NR_rt_sigtimedwait    (__NR_Linux + 177)
+#define __NR_rt_sigqueueinfo    (__NR_Linux + 178)
+#define __NR_rt_sigsuspend      (__NR_Linux + 179)
+#define __NR_chown              (__NR_Linux + 180)
+#define __NR_setsockopt         (__NR_Linux + 181)
+#define __NR_getsockopt         (__NR_Linux + 182)
+#define __NR_sendmsg            (__NR_Linux + 183)
+#define __NR_recvmsg            (__NR_Linux + 184)
+#define __NR_semop              (__NR_Linux + 185)
+#define __NR_semget             (__NR_Linux + 186)
+#define __NR_semctl             (__NR_Linux + 187)
+#define __NR_msgsnd             (__NR_Linux + 188)
+#define __NR_msgrcv             (__NR_Linux + 189)
+#define __NR_msgget             (__NR_Linux + 190)
+#define __NR_msgctl             (__NR_Linux + 191)
+#define __NR_shmat              (__NR_Linux + 192)
+#define __NR_shmdt              (__NR_Linux + 193)
+#define __NR_shmget             (__NR_Linux + 194)
+#define __NR_shmctl             (__NR_Linux + 195)
+
+#define __NR_getpmsg           (__NR_Linux + 196) /* Somebody *wants* streams? */
+#define __NR_putpmsg           (__NR_Linux + 197)
+
+#define __NR_lstat64            (__NR_Linux + 198)
+#define __NR_truncate64         (__NR_Linux + 199)
+#define __NR_ftruncate64        (__NR_Linux + 200)
+#define __NR_getdents64         (__NR_Linux + 201)
+#define __NR_fcntl64            (__NR_Linux + 202)
+#define __NR_attrctl            (__NR_Linux + 203)
+#define __NR_acl_get            (__NR_Linux + 204)
+#define __NR_acl_set            (__NR_Linux + 205)
+#define __NR_gettid             (__NR_Linux + 206)
+#define __NR_readahead          (__NR_Linux + 207)
+#define __NR_tkill              (__NR_Linux + 208)
+#define __NR_sendfile64         (__NR_Linux + 209)
+#define __NR_futex              (__NR_Linux + 210)
+#define __NR_sched_setaffinity  (__NR_Linux + 211)
+#define __NR_sched_getaffinity  (__NR_Linux + 212)
+#define __NR_set_thread_area    (__NR_Linux + 213)
+#define __NR_get_thread_area    (__NR_Linux + 214)
+#define __NR_io_setup           (__NR_Linux + 215)
+#define __NR_io_destroy         (__NR_Linux + 216)
+#define __NR_io_getevents       (__NR_Linux + 217)
+#define __NR_io_submit          (__NR_Linux + 218)
+#define __NR_io_cancel          (__NR_Linux + 219)
+#define __NR_alloc_hugepages    (__NR_Linux + 220)
+#define __NR_free_hugepages     (__NR_Linux + 221)
+#define __NR_exit_group         (__NR_Linux + 222)
+#define __NR_lookup_dcookie     (__NR_Linux + 223)
+#define __NR_epoll_create       (__NR_Linux + 224)
+#define __NR_epoll_ctl          (__NR_Linux + 225)
+#define __NR_epoll_wait         (__NR_Linux + 226)
+#define __NR_remap_file_pages   (__NR_Linux + 227)
+#define __NR_semtimedop         (__NR_Linux + 228)
+#define __NR_mq_open            (__NR_Linux + 229)
+#define __NR_mq_unlink          (__NR_Linux + 230)
+#define __NR_mq_timedsend       (__NR_Linux + 231)
+#define __NR_mq_timedreceive    (__NR_Linux + 232)
+#define __NR_mq_notify          (__NR_Linux + 233)
+#define __NR_mq_getsetattr      (__NR_Linux + 234)
+#define __NR_waitid            (__NR_Linux + 235)
+#define __NR_fadvise64_64      (__NR_Linux + 236)
+#define __NR_set_tid_address   (__NR_Linux + 237)
+#define __NR_setxattr          (__NR_Linux + 238)
+#define __NR_lsetxattr         (__NR_Linux + 239)
+#define __NR_fsetxattr         (__NR_Linux + 240)
+#define __NR_getxattr          (__NR_Linux + 241)
+#define __NR_lgetxattr         (__NR_Linux + 242)
+#define __NR_fgetxattr         (__NR_Linux + 243)
+#define __NR_listxattr         (__NR_Linux + 244)
+#define __NR_llistxattr                (__NR_Linux + 245)
+#define __NR_flistxattr                (__NR_Linux + 246)
+#define __NR_removexattr       (__NR_Linux + 247)
+#define __NR_lremovexattr      (__NR_Linux + 248)
+#define __NR_fremovexattr      (__NR_Linux + 249)
+#define __NR_timer_create      (__NR_Linux + 250)
+#define __NR_timer_settime     (__NR_Linux + 251)
+#define __NR_timer_gettime     (__NR_Linux + 252)
+#define __NR_timer_getoverrun  (__NR_Linux + 253)
+#define __NR_timer_delete      (__NR_Linux + 254)
+#define __NR_clock_settime     (__NR_Linux + 255)
+#define __NR_clock_gettime     (__NR_Linux + 256)
+#define __NR_clock_getres      (__NR_Linux + 257)
+#define __NR_clock_nanosleep   (__NR_Linux + 258)
+#define __NR_tgkill            (__NR_Linux + 259)
+#define __NR_mbind             (__NR_Linux + 260)
+#define __NR_get_mempolicy     (__NR_Linux + 261)
+#define __NR_set_mempolicy     (__NR_Linux + 262)
+#define __NR_vserver           (__NR_Linux + 263)
+#define __NR_add_key           (__NR_Linux + 264)
+#define __NR_request_key       (__NR_Linux + 265)
+#define __NR_keyctl            (__NR_Linux + 266)
+#define __NR_ioprio_set                (__NR_Linux + 267)
+#define __NR_ioprio_get                (__NR_Linux + 268)
+#define __NR_inotify_init      (__NR_Linux + 269)
+#define __NR_inotify_add_watch (__NR_Linux + 270)
+#define __NR_inotify_rm_watch  (__NR_Linux + 271)
+#define __NR_migrate_pages     (__NR_Linux + 272)
+#define __NR_pselect6          (__NR_Linux + 273)
+#define __NR_ppoll             (__NR_Linux + 274)
+#define __NR_openat            (__NR_Linux + 275)
+#define __NR_mkdirat           (__NR_Linux + 276)
+#define __NR_mknodat           (__NR_Linux + 277)
+#define __NR_fchownat          (__NR_Linux + 278)
+#define __NR_futimesat         (__NR_Linux + 279)
+#define __NR_fstatat64         (__NR_Linux + 280)
+#define __NR_unlinkat          (__NR_Linux + 281)
+#define __NR_renameat          (__NR_Linux + 282)
+#define __NR_linkat            (__NR_Linux + 283)
+#define __NR_symlinkat         (__NR_Linux + 284)
+#define __NR_readlinkat                (__NR_Linux + 285)
+#define __NR_fchmodat          (__NR_Linux + 286)
+#define __NR_faccessat         (__NR_Linux + 287)
+#define __NR_unshare           (__NR_Linux + 288)
+#define __NR_set_robust_list   (__NR_Linux + 289)
+#define __NR_get_robust_list   (__NR_Linux + 290)
+#define __NR_splice            (__NR_Linux + 291)
+#define __NR_sync_file_range   (__NR_Linux + 292)
+#define __NR_tee               (__NR_Linux + 293)
+#define __NR_vmsplice          (__NR_Linux + 294)
+#define __NR_move_pages                (__NR_Linux + 295)
+#define __NR_getcpu            (__NR_Linux + 296)
+#define __NR_epoll_pwait       (__NR_Linux + 297)
+#define __NR_statfs64          (__NR_Linux + 298)
+#define __NR_fstatfs64         (__NR_Linux + 299)
+#define __NR_kexec_load                (__NR_Linux + 300)
+#define __NR_utimensat         (__NR_Linux + 301)
+#define __NR_signalfd          (__NR_Linux + 302)
+#define __NR_timerfd           (__NR_Linux + 303)
+#define __NR_eventfd           (__NR_Linux + 304)
+#define __NR_fallocate         (__NR_Linux + 305)
+#define __NR_timerfd_create    (__NR_Linux + 306)
+#define __NR_timerfd_settime   (__NR_Linux + 307)
+#define __NR_timerfd_gettime   (__NR_Linux + 308)
+#define __NR_signalfd4         (__NR_Linux + 309)
+#define __NR_eventfd2          (__NR_Linux + 310)
+#define __NR_epoll_create1     (__NR_Linux + 311)
+#define __NR_dup3              (__NR_Linux + 312)
+#define __NR_pipe2             (__NR_Linux + 313)
+#define __NR_inotify_init1     (__NR_Linux + 314)
+#define __NR_preadv            (__NR_Linux + 315)
+#define __NR_pwritev           (__NR_Linux + 316)
+#define __NR_rt_tgsigqueueinfo (__NR_Linux + 317)
+#define __NR_perf_event_open   (__NR_Linux + 318)
+#define __NR_recvmmsg          (__NR_Linux + 319)
+#define __NR_accept4           (__NR_Linux + 320)
+#define __NR_prlimit64         (__NR_Linux + 321)
+#define __NR_fanotify_init     (__NR_Linux + 322)
+#define __NR_fanotify_mark     (__NR_Linux + 323)
+#define __NR_clock_adjtime     (__NR_Linux + 324)
+#define __NR_name_to_handle_at (__NR_Linux + 325)
+#define __NR_open_by_handle_at (__NR_Linux + 326)
+#define __NR_syncfs            (__NR_Linux + 327)
+#define __NR_setns             (__NR_Linux + 328)
+#define __NR_sendmmsg          (__NR_Linux + 329)
+
+#define __NR_Linux_syscalls    (__NR_sendmmsg + 1)
+
+
+#define __IGNORE_select                /* newselect */
+#define __IGNORE_fadvise64     /* fadvise64_64 */
+#define __IGNORE_utimes                /* utime */
+
+
+#define HPUX_GATEWAY_ADDR       0xC0000004
+#define LINUX_GATEWAY_ADDR      0x100
+
+#endif /* _UAPI_ASM_PARISC_UNISTD_H_ */
index fd49aeda9eb8b0c4fef656e3dc00228c59251b99..5dede04f2f3ead372752fdbaaafceca5708b6902 100644 (file)
@@ -65,7 +65,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
 {
        compat_sigset_t s;
 
-       if (sz != sizeof *set) panic("put_sigset32()");
+       if (sz != sizeof *set)
+               return -EINVAL;
        sigset_64to32(&s, set);
 
        return copy_to_user(up, &s, sizeof s);
@@ -77,7 +78,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
        compat_sigset_t s;
        int r;
 
-       if (sz != sizeof *set) panic("put_sigset32()");
+       if (sz != sizeof *set)
+               return -EINVAL;
 
        if ((r = copy_from_user(&s, up, sz)) == 0) {
                sigset_32to64(set, &s);
index 7426e40699bdbf08575d0b69722e6594a1535076..f76c10863c6266c5a4fe6a3fbbe22d022a11e8c2 100644 (file)
@@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping,
        struct vm_area_struct *vma;
        int offset = mapping ? get_offset(mapping) : 0;
 
+       offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000;
+
        addr = DCACHE_ALIGN(addr - offset) + offset;
 
        for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
index 7ab286ab5300accb706fb72a2e343153cae85d18..39ed65a44c5fac5fc996b2d5ec25effbbf9853fa 100644 (file)
                        interrupts = <2 7 0>;
                };
 
+               sclpc@3c00 {
+                       compatible = "fsl,mpc5200-lpbfifo";
+                       reg = <0x3c00 0x60>;
+                       interrupts = <2 23 0>;
+               };
+
                i2c@3d00 {
                        #address-cells = <1>;
                        #size-cells = <0>;
index 3444eb8f0ade62305d0a935ca50a02d1fca16933..24f668039295b1b95ff279ff91974a7ad65582ff 100644 (file)
                                reg = <0>;
                        };
                };
-
-               sclpc@3c00 {
-                       compatible = "fsl,mpc5200-lpbfifo";
-                       reg = <0x3c00 0x60>;
-                       interrupts = <3 23 0>;
-               };
        };
 
        localbus {
index 9e354997eb7e3ccc29ac70ee5e7a31c3ce319b01..96512c05803336d937cabcf5b06aa86e43bc538b 100644 (file)
@@ -59,7 +59,7 @@
                        #gpio-cells = <2>;
                };
 
-               psc@2000 { /* PSC1 in ac97 mode */
+               audioplatform: psc@2000 { /* PSC1 in ac97 mode */
                        compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97";
                        cell-index = <0>;
                };
        localbus {
                status = "disabled";
        };
+
+       sound {
+               compatible = "phytec,pcm030-audio-fabric";
+               asoc-platform = <&audioplatform>;
+       };
 };
index 38040ff82063c5572a35e70bde330e90386ec465..ce0ef6ce8f86a07ce74e6a11fcfaaa424a1e991c 100644 (file)
@@ -42,5 +42,6 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu)
 #define SID_SHIFT      28
 #define ESID_MASK      0xf0000000
 #define VSID_MASK      0x00fffffff0000000ULL
+#define VPN_SHIFT      12
 
 #endif /* __ASM_KVM_BOOK3S_32_H__ */
index 5f73ce63fcaeb79a6a10d7d77b92d82ad26331db..42b1f43b943ba197ce766067d735c47397519382 100644 (file)
 #define PPC_INST_AND                   0x7c000038
 #define PPC_INST_ANDDOT                        0x7c000039
 #define PPC_INST_OR                    0x7c000378
+#define PPC_INST_XOR                   0x7c000278
 #define PPC_INST_ANDI                  0x70000000
 #define PPC_INST_ORI                   0x60000000
 #define PPC_INST_ORIS                  0x64000000
+#define PPC_INST_XORI                  0x68000000
+#define PPC_INST_XORIS                 0x6c000000
 #define PPC_INST_NEG                   0x7c0000d0
 #define PPC_INST_BRANCH                        0x48000000
 #define PPC_INST_BRANCH_COND           0x40800000
index 8734b3855272b3583aa9ba7c723f5e6df01772b1..87502046c0dcfa9ed80ea856643abe05762aca13 100644 (file)
@@ -388,9 +388,9 @@ extern int powersave_nap;   /* set if nap mode can be used in idle loop */
 extern void power7_nap(void);
 
 #ifdef CONFIG_PSERIES_IDLE
-extern void update_smt_snooze_delay(int snooze);
+extern void update_smt_snooze_delay(int cpu, int residency);
 #else
-static inline void update_smt_snooze_delay(int snooze) {}
+static inline void update_smt_snooze_delay(int cpu, int residency) {}
 #endif
 
 extern void flush_instruction_cache(void);
index 3d5179bb122f120e24477c3be6f1459182b8bec5..eb0b1864d400b2a01386ed3a77fedb300a560227 100644 (file)
@@ -47,6 +47,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER       26
 #define SO_DETACH_FILTER       27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index 8302af6492195b77ac8a5b7f5dfbc69dfc7d43b8..cf357a059ddb73856275ad7c1fda70170356751d 100644 (file)
@@ -50,7 +50,7 @@ static ssize_t store_smt_snooze_delay(struct device *dev,
                return -EINVAL;
 
        per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
-       update_smt_snooze_delay(snooze);
+       update_smt_snooze_delay(cpu->dev.id, snooze);
 
        return count;
 }
index 00aa61268e0d6e66f34c9625365951ce29403990..b0f625a33345a6e7cf690d21b041507adae5f61f 100644 (file)
@@ -173,8 +173,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
        BUG_ON(!map);
 
        vsid = map->host_vsid;
-       vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) | ((eaddr & ~ESID_MASK) >> VPN_SHIFT)
-
+       vpn = (vsid << (SID_SHIFT - VPN_SHIFT)) |
+               ((eaddr & ~ESID_MASK) >> VPN_SHIFT);
 next_pteg:
        if (rr == 16) {
                primary = !primary;
index 1fc8109bf2f94761d01c21eb1f9358d58668aeee..8a5dfaf5c6b73fc94c7ceab634d1bf679a4f06b1 100644 (file)
@@ -134,6 +134,12 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
                                     ___PPC_RS(a) | IMM_L(i))
 #define PPC_ORIS(d, a, i)      EMIT(PPC_INST_ORIS | ___PPC_RA(d) |           \
                                     ___PPC_RS(a) | IMM_L(i))
+#define PPC_XOR(d, a, b)       EMIT(PPC_INST_XOR | ___PPC_RA(d) |            \
+                                    ___PPC_RS(a) | ___PPC_RB(b))
+#define PPC_XORI(d, a, i)      EMIT(PPC_INST_XORI | ___PPC_RA(d) |           \
+                                    ___PPC_RS(a) | IMM_L(i))
+#define PPC_XORIS(d, a, i)     EMIT(PPC_INST_XORIS | ___PPC_RA(d) |          \
+                                    ___PPC_RS(a) | IMM_L(i))
 #define PPC_SLW(d, a, s)       EMIT(PPC_INST_SLW | ___PPC_RA(d) |            \
                                     ___PPC_RS(a) | ___PPC_RB(s))
 #define PPC_SRW(d, a, s)       EMIT(PPC_INST_SRW | ___PPC_RA(d) |            \
index dd1130642d0753b217e9a73c3e9404bb2aef2d0d..e834f1ec23c8a4ad16c67b0d3349565e1813cf83 100644 (file)
@@ -13,6 +13,8 @@
 #include <asm/cacheflush.h>
 #include <linux/netdevice.h>
 #include <linux/filter.h>
+#include <linux/if_vlan.h>
+
 #include "bpf_jit.h"
 
 #ifndef __BIG_ENDIAN
@@ -89,6 +91,8 @@ static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
        case BPF_S_ANC_IFINDEX:
        case BPF_S_ANC_MARK:
        case BPF_S_ANC_RXHASH:
+       case BPF_S_ANC_VLAN_TAG:
+       case BPF_S_ANC_VLAN_TAG_PRESENT:
        case BPF_S_ANC_CPU:
        case BPF_S_ANC_QUEUE:
        case BPF_S_LD_W_ABS:
@@ -232,6 +236,17 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
                        if (K >= 65536)
                                PPC_ORIS(r_A, r_A, IMM_H(K));
                        break;
+               case BPF_S_ANC_ALU_XOR_X:
+               case BPF_S_ALU_XOR_X: /* A ^= X */
+                       ctx->seen |= SEEN_XREG;
+                       PPC_XOR(r_A, r_A, r_X);
+                       break;
+               case BPF_S_ALU_XOR_K: /* A ^= K */
+                       if (IMM_L(K))
+                               PPC_XORI(r_A, r_A, IMM_L(K));
+                       if (K >= 65536)
+                               PPC_XORIS(r_A, r_A, IMM_H(K));
+                       break;
                case BPF_S_ALU_LSH_X: /* A <<= X; */
                        ctx->seen |= SEEN_XREG;
                        PPC_SLW(r_A, r_A, r_X);
@@ -371,6 +386,16 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image,
                        PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          rxhash));
                        break;
+               case BPF_S_ANC_VLAN_TAG:
+               case BPF_S_ANC_VLAN_TAG_PRESENT:
+                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+                       PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
+                                                         vlan_tci));
+                       if (filter[i].code == BPF_S_ANC_VLAN_TAG)
+                               PPC_ANDI(r_A, r_A, VLAN_VID_MASK);
+                       else
+                               PPC_ANDI(r_A, r_A, VLAN_TAG_PRESENT);
+                       break;
                case BPF_S_ANC_QUEUE:
                        BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
                                                  queue_mapping) != 2);
index 0db88f501f91c953c86dcbef4ab2d768be126f9d..aa2465e21f1a87b989e49eae2027fee72dc4948f 100644 (file)
@@ -1463,7 +1463,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
                if (!event->hw.idx || is_limited_pmc(event->hw.idx))
                        continue;
                val = read_pmc(event->hw.idx);
-               if (pmc_overflow(val)) {
+               if ((int)val < 0) {
                        /* event has overflowed */
                        found = 1;
                        record_and_restart(event, val, regs);
index 8520b58a5e9a0f0027a95f0df2662cbab898c5cc..b89ef65392dc229b4ec026e23ddd9c5228ed05f1 100644 (file)
@@ -372,10 +372,11 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq,
        case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break;
        case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
        case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
-       default:
-               pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n",
-                      __func__, virq, l1irq, l2irq);
-               return -EINVAL;
+       case MPC52xx_IRQ_L1_CRIT:
+               pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n",
+                       __func__, l2irq);
+               irq_set_chip(virq, &no_irq_chip);
+               return 0;
        }
 
        irq_set_chip_and_handler(virq, irqchip, handle_level_irq);
index 797cd181dc3f615fab312df9ccce4813263eedf4..d16c8ded10847ce19d67f26a39179587707ddbf0 100644 (file)
@@ -449,7 +449,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
                        if (list_empty(&pe->edevs)) {
                                cnt = 0;
                                list_for_each_entry(child, &pe->child_list, child) {
-                                       if (!(pe->type & EEH_PE_INVALID)) {
+                                       if (!(child->type & EEH_PE_INVALID)) {
                                                cnt++;
                                                break;
                                        }
index d19f4977c83492e1174be5456e1d0ff7ee33ca33..e5b084723131cc1ef0b6260f2a571f7071ee5995 100644 (file)
@@ -220,7 +220,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 
        /* Get the top level device in the PE */
        edev = of_node_to_eeh_dev(dn);
-       edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+       if (edev->pe)
+               edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
        dn = eeh_dev_to_of_node(edev);
        if (!dn)
                return NULL;
index 455760b1fe6e1fde723ec96a4afeb24b75af6ca8..45d00e5fe14dad1f827acf3dacddddac067e003b 100644 (file)
@@ -33,13 +33,6 @@ static int max_idle_state = MAX_IDLE_STATE_COUNT - 1;
 static struct cpuidle_device __percpu *pseries_cpuidle_devices;
 static struct cpuidle_state *cpuidle_state_table;
 
-void update_smt_snooze_delay(int snooze)
-{
-       struct cpuidle_driver *drv = cpuidle_get_driver();
-       if (drv)
-               drv->states[0].target_residency = snooze;
-}
-
 static inline void idle_loop_prolog(unsigned long *in_purr, ktime_t *kt_before)
 {
 
@@ -66,32 +59,22 @@ static int snooze_loop(struct cpuidle_device *dev,
 {
        unsigned long in_purr;
        ktime_t kt_before;
-       unsigned long start_snooze;
-       long snooze = drv->states[0].target_residency;
+       int cpu = dev->cpu;
 
        idle_loop_prolog(&in_purr, &kt_before);
+       local_irq_enable();
+       set_thread_flag(TIF_POLLING_NRFLAG);
 
-       if (snooze) {
-               start_snooze = get_tb() + snooze * tb_ticks_per_usec;
-               local_irq_enable();
-               set_thread_flag(TIF_POLLING_NRFLAG);
-
-               while ((snooze < 0) || (get_tb() < start_snooze)) {
-                       if (need_resched() || cpu_is_offline(dev->cpu))
-                               goto out;
-                       ppc64_runlatch_off();
-                       HMT_low();
-                       HMT_very_low();
-               }
-
-               HMT_medium();
-               clear_thread_flag(TIF_POLLING_NRFLAG);
-               smp_mb();
-               local_irq_disable();
+       while ((!need_resched()) && cpu_online(cpu)) {
+               ppc64_runlatch_off();
+               HMT_low();
+               HMT_very_low();
        }
 
-out:
        HMT_medium();
+       clear_thread_flag(TIF_POLLING_NRFLAG);
+       smp_mb();
+
        dev->last_residency =
                (int)idle_loop_epilog(in_purr, kt_before);
        return index;
@@ -172,8 +155,8 @@ static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = {
                .name = "CEDE",
                .desc = "CEDE",
                .flags = CPUIDLE_FLAG_TIME_VALID,
-               .exit_latency = 1,
-               .target_residency = 10,
+               .exit_latency = 10,
+               .target_residency = 100,
                .enter = &dedicated_cede_loop },
 };
 
@@ -190,6 +173,23 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = {
                .enter = &shared_cede_loop },
 };
 
+void update_smt_snooze_delay(int cpu, int residency)
+{
+       struct cpuidle_driver *drv = cpuidle_get_driver();
+       struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
+
+       if (cpuidle_state_table != dedicated_states)
+               return;
+
+       if (residency < 0) {
+               /* Disable the Nap state on that cpu */
+               if (dev)
+                       dev->states_usage[1].disable = 1;
+       } else
+               if (drv)
+                       drv->states[1].target_residency = residency;
+}
+
 static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
                        unsigned long action, void *hcpu)
 {
@@ -246,10 +246,6 @@ static int pseries_cpuidle_driver_init(void)
                drv->states[drv->state_count] = /* structure copy */
                        cpuidle_state_table[idle_state];
 
-               if (cpuidle_state_table == dedicated_states)
-                       drv->states[drv->state_count].target_residency =
-                               __get_cpu_var(smt_snooze_delay);
-
                drv->state_count += 1;
        }
 
index 3f3d9ca7a5b68fefdb333818fe6189d8c6cbf3ae..d385f396dfee90172e5a984702cd9ded8a76387d 100644 (file)
@@ -96,6 +96,7 @@ config S390
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_CMPXCHG_LOCAL
        select HAVE_CMPXCHG_DOUBLE
+       select HAVE_ALIGNED_STRUCT_PAGE if SLUB
        select HAVE_VIRT_CPU_ACCOUNTING
        select VIRT_CPU_ACCOUNTING
        select ARCH_DISCARD_MEMBLOCK
@@ -130,6 +131,7 @@ config S390
        select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
        select HAVE_UID16 if 32BIT
        select ARCH_WANT_IPC_PARSE_VERSION
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_TIME_VSYSCALL_OLD
        select GENERIC_CLOCKEVENTS
index d80f79d8dd9cd03d237ee2e7af1531abba69f2b2..8e1fb82392873669ce34b03ed34f18b64cc5b2de 100644 (file)
@@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
 OUTPUT_ARCH(s390:64-bit)
 #else
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 #endif
 
 ENTRY(startup)
index 55bde6035216f35c5dc265b14366471cc1ce2b33..ad2b924167d799f4b410a1bc38e4350656f3da4c 100644 (file)
@@ -9,6 +9,8 @@
 
 #define LPM_ANYPATH 0xff
 #define __MAX_CSSID 0
+#define __MAX_SUBCHANNEL 65535
+#define __MAX_SSID 3
 
 #include <asm/scsw.h>
 
index a34a9d612fc0f2d4ecc9a4bfbcef2794fba7de41..18cd6b592650962010b7c72f32b0d401cf572a57 100644 (file)
@@ -20,7 +20,7 @@
 #define PSW32_MASK_CC          0x00003000UL
 #define PSW32_MASK_PM          0x00000f00UL
 
-#define PSW32_MASK_USER                0x00003F00UL
+#define PSW32_MASK_USER                0x0000FF00UL
 
 #define PSW32_ADDR_AMODE       0x80000000UL
 #define PSW32_ADDR_INSN                0x7FFFFFFFUL
index 7941968e12b48ced12b4122918f111485de1dc4e..5f0173a31693b19700b8afa92b60db199bfcb749 100644 (file)
@@ -9,7 +9,7 @@
 #include <asm/cpu_mf.h>
 
 /* CPU-measurement counter facility */
-#define PERF_CPUM_CF_MAX_CTR           160
+#define PERF_CPUM_CF_MAX_CTR           256
 
 /* Per-CPU flags for PMU states */
 #define PMU_F_RESERVED                 0x1000
index dd647c919a66c766a75a8114588f1cd51afdafd7..2d3b7cb2600593f102b23dc8094fe384aa151b28 100644 (file)
@@ -506,12 +506,15 @@ static inline int pud_bad(pud_t pud)
 
 static inline int pmd_present(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _SEGMENT_ENTRY_ORIGIN) != 0UL;
+       unsigned long mask = _SEGMENT_ENTRY_INV | _SEGMENT_ENTRY_RO;
+       return (pmd_val(pmd) & mask) == _HPAGE_TYPE_NONE ||
+              !(pmd_val(pmd) & _SEGMENT_ENTRY_INV);
 }
 
 static inline int pmd_none(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) != 0UL;
+       return (pmd_val(pmd) & _SEGMENT_ENTRY_INV) &&
+              !(pmd_val(pmd) & _SEGMENT_ENTRY_RO);
 }
 
 static inline int pmd_large(pmd_t pmd)
@@ -1223,6 +1226,11 @@ static inline void __pmd_idte(unsigned long address, pmd_t *pmdp)
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+
+#define SEGMENT_NONE   __pgprot(_HPAGE_TYPE_NONE)
+#define SEGMENT_RO     __pgprot(_HPAGE_TYPE_RO)
+#define SEGMENT_RW     __pgprot(_HPAGE_TYPE_RW)
+
 #define __HAVE_ARCH_PGTABLE_DEPOSIT
 extern void pgtable_trans_huge_deposit(struct mm_struct *mm, pgtable_t pgtable);
 
@@ -1242,16 +1250,15 @@ static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
 
 static inline unsigned long massage_pgprot_pmd(pgprot_t pgprot)
 {
-       unsigned long pgprot_pmd = 0;
-
-       if (pgprot_val(pgprot) & _PAGE_INVALID) {
-               if (pgprot_val(pgprot) & _PAGE_SWT)
-                       pgprot_pmd |= _HPAGE_TYPE_NONE;
-               pgprot_pmd |= _SEGMENT_ENTRY_INV;
-       }
-       if (pgprot_val(pgprot) & _PAGE_RO)
-               pgprot_pmd |= _SEGMENT_ENTRY_RO;
-       return pgprot_pmd;
+       /*
+        * pgprot is PAGE_NONE, PAGE_RO, or PAGE_RW (see __Pxxx / __Sxxx)
+        * Convert to segment table entry format.
+        */
+       if (pgprot_val(pgprot) == pgprot_val(PAGE_NONE))
+               return pgprot_val(SEGMENT_NONE);
+       if (pgprot_val(pgprot) == pgprot_val(PAGE_RO))
+               return pgprot_val(SEGMENT_RO);
+       return pgprot_val(SEGMENT_RW);
 }
 
 static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
@@ -1269,7 +1276,9 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
 
 static inline pmd_t pmd_mkwrite(pmd_t pmd)
 {
-       pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
+       /* Do not clobber _HPAGE_TYPE_NONE pages! */
+       if (!(pmd_val(pmd) & _SEGMENT_ENTRY_INV))
+               pmd_val(pmd) &= ~_SEGMENT_ENTRY_RO;
        return pmd;
 }
 
index 9ca30538376001ffe6b07e9cac9db311707e195f..9935cbd6a46fdee89e8cdfd65c7f9acc0de474b9 100644 (file)
@@ -8,6 +8,9 @@ struct cpu;
 
 #ifdef CONFIG_SCHED_BOOK
 
+extern unsigned char cpu_socket_id[NR_CPUS];
+#define topology_physical_package_id(cpu) (cpu_socket_id[cpu])
+
 extern unsigned char cpu_core_id[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
 
index 581992dfae27b605e49a8a6f5d2972cc0646fadc..6b4fb29cc197e5d9544fd124e61a742a41114464 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
 #define __MAX_CHPID 255
 
 struct chp_id {
-       u8 reserved1;
-       u8 cssid;
-       u8 reserved2;
-       u8 id;
+       __u8 reserved1;
+       __u8 cssid;
+       __u8 reserved2;
+       __u8 id;
 } __attribute__((packed));
 
 
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ff1f4e7b30157849b8673cfc369e92b2c0d695f4 100644 (file)
@@ -0,0 +1,11 @@
+/*
+ * User API definitions for paravirtual devices on s390
+ *
+ * Copyright IBM Corp. 2008
+ *
+ * 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): Christian Borntraeger <borntraeger@de.ibm.com>
+ */
index 705588a16d70da6322ca349074a1b30de92f658a..a5ca214b34fdb1271e4fad48d9c7c7fb8c5a9437 100644 (file)
@@ -239,7 +239,7 @@ typedef struct
 #define PSW_MASK_EA            0x00000000UL
 #define PSW_MASK_BA            0x00000000UL
 
-#define PSW_MASK_USER          0x00003F00UL
+#define PSW_MASK_USER          0x0000FF00UL
 
 #define PSW_ADDR_AMODE         0x80000000UL
 #define PSW_ADDR_INSN          0x7FFFFFFFUL
@@ -269,7 +269,7 @@ typedef struct
 #define PSW_MASK_EA            0x0000000100000000UL
 #define PSW_MASK_BA            0x0000000080000000UL
 
-#define PSW_MASK_USER          0x00003F8180000000UL
+#define PSW_MASK_USER          0x0000FF8180000000UL
 
 #define PSW_ADDR_AMODE         0x0000000000000000UL
 #define PSW_ADDR_INSN          0xFFFFFFFFFFFFFFFFUL
index 69718cd6d63503e657a4878a1277ab260fa44bf7..436d07c23be8febc9ad245fb73e4f1671a004cd9 100644 (file)
@@ -46,6 +46,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index 8df8d8a19c986e1b2fea8db91cf59d329fc3b877..64b24650e4f8c1d43f5cf151b46478f5a602e277 100644 (file)
@@ -59,8 +59,8 @@ enum {
 
 enum {
        CACHE_TI_UNIFIED = 0,
-       CACHE_TI_INSTRUCTION = 0,
-       CACHE_TI_DATA,
+       CACHE_TI_DATA = 0,
+       CACHE_TI_INSTRUCTION,
 };
 
 struct cache_info {
@@ -121,7 +121,10 @@ static int __init cache_add(int level, int private, int type)
        cache = kzalloc(sizeof(*cache), GFP_KERNEL);
        if (!cache)
                return -ENOMEM;
-       ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED;
+       if (type == CACHE_TYPE_INSTRUCTION)
+               ti = CACHE_TI_INSTRUCTION;
+       else
+               ti = CACHE_TI_UNIFIED;
        cache->size = ecag(EXTRACT_SIZE, level, ti);
        cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti);
        cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
index a1e8a8694bb70561a8c78c35558ff3a635e2203e..593fcc9253fc433650e54fbc8f8f829f5d961e98 100644 (file)
@@ -309,6 +309,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
                (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
                (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
+       /* Check for invalid user address space control. */
+       if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+               regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+                       (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
        for (i = 0; i < NUM_GPRS; i++)
                regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -481,7 +485,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (__force __u64) frame;
-       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       /* Force 31 bit amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__force __u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
@@ -549,7 +556,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (__force __u64) frame;
-       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       /* Force 31 bit amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
index acaaaf4b7055e2d50122f43e6f695771a6f781cd..085a95eb315f480dc2edb492fc58a80dde0ae7d5 100644 (file)
 .align 2
 startup_kdump_relocated:
        basr    %r13,0
-0:
-       mvc     0(8,%r0),.Lrestart_psw-0b(%r13) # Setup restart PSW
-       sam31                                   # Switch to 31 bit addr mode
-       sr      %r1,%r1                         # Erase register r1
-       sr      %r2,%r2                         # Erase register r2
-       sigp    %r1,%r2,SIGP_SET_ARCHITECTURE   # Switch to 31 bit arch mode
-       lpsw    0                               # Start new kernel...
+0:     lpswe   .Lrestart_psw-0b(%r13)          # Start new kernel...
 .align 8
 .Lrestart_psw:
-       .long   0x00080000,0x80000000 + startup
+       .quad   0x0000000080000000,0x0000000000000000 + startup
 #else
 .align 2
 .Lep_startup_kdump:
index 9871b1971ed7602a7efef88fc62d019dde3b98c4..c4e7269d4a0980d8736c5a9c32e916cb581b0a58 100644 (file)
@@ -94,7 +94,7 @@ static int get_counter_set(u64 event)
                set = CPUMF_CTR_SET_USER;
        else if (event < 128)
                set = CPUMF_CTR_SET_CRYPTO;
-       else if (event < 160)
+       else if (event < 256)
                set = CPUMF_CTR_SET_EXT;
 
        return set;
@@ -138,6 +138,10 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
        case CPUMF_CTR_SET_EXT:
                if (cpuhw->info.csvn < 1)
                        err = -EOPNOTSUPP;
+               if ((cpuhw->info.csvn == 1 && hwc->config > 159) ||
+                   (cpuhw->info.csvn == 2 && hwc->config > 175) ||
+                   (cpuhw->info.csvn  > 2 && hwc->config > 255))
+                       err = -EOPNOTSUPP;
                break;
        }
 
index bf053898630de935aa4bcbd875c62a405169384c..b6506ee32a363749c5effc99d81d551b90b9fc3d 100644 (file)
@@ -44,6 +44,12 @@ _sclp_wait_int:
 #endif
        mvc     .LoldpswS1-.LbaseS1(16,%r13),0(%r8)
        mvc     0(16,%r8),0(%r9)
+#ifdef CONFIG_64BIT
+       epsw    %r6,%r7                         # set current addressing mode
+       nill    %r6,0x1                         # in new psw (31 or 64 bit mode)
+       nilh    %r7,0x8000
+       stm     %r6,%r7,0(%r8)
+#endif
        lhi     %r6,0x0200                      # cr mask for ext int (cr0.54)
        ltr     %r2,%r2
        jz      .LsetctS1
@@ -87,7 +93,7 @@ _sclp_wait_int:
        .long   0x00080000, 0x80000000+.LwaitS1 # PSW to handle ext int
 #ifdef CONFIG_64BIT
 .LextpswS1_64:
-       .quad   0x0000000180000000, .LwaitS1    # PSW to handle ext int, 64 bit
+       .quad   0, .LwaitS1                     # PSW to handle ext int, 64 bit
 #endif
 .LwaitpswS1:
        .long   0x010a0000, 0x00000000+.LloopS1 # PSW to wait for ext int
index c13a2a37ef007b2634a508b7053b0c3cc12e30b2..d1259d875074179ff11b232258fcc36ef98b90c3 100644 (file)
@@ -136,6 +136,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
                (user_sregs.regs.psw.mask & PSW_MASK_USER);
+       /* Check for invalid user address space control. */
+       if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+               regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+                       (regs->psw.mask & ~PSW_MASK_ASC);
        /* Check for invalid amode */
        if (regs->psw.mask & PSW_MASK_EA)
                regs->psw.mask |= PSW_MASK_BA;
@@ -273,7 +277,10 @@ static int setup_frame(int sig, struct k_sigaction *ka,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (unsigned long) frame;
-       regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
+       /* Force default amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
        regs->gprs[2] = map_signal(sig);
@@ -346,7 +353,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (unsigned long) frame;
-       regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
+       /* Force default amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
        regs->gprs[2] = map_signal(sig);
index 54d93f4b681813927aabd8adbffbeb6204387d4b..dd55f7c2010448a5b842c741ac6d93fc673591da 100644 (file)
@@ -40,6 +40,7 @@ static DEFINE_SPINLOCK(topology_lock);
 static struct mask_info core_info;
 cpumask_t cpu_core_map[NR_CPUS];
 unsigned char cpu_core_id[NR_CPUS];
+unsigned char cpu_socket_id[NR_CPUS];
 
 static struct mask_info book_info;
 cpumask_t cpu_book_map[NR_CPUS];
@@ -83,11 +84,12 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
                        cpumask_set_cpu(lcpu, &book->mask);
                        cpu_book_id[lcpu] = book->id;
                        cpumask_set_cpu(lcpu, &core->mask);
+                       cpu_core_id[lcpu] = rcpu;
                        if (one_core_per_cpu) {
-                               cpu_core_id[lcpu] = rcpu;
+                               cpu_socket_id[lcpu] = rcpu;
                                core = core->next;
                        } else {
-                               cpu_core_id[lcpu] = core->id;
+                               cpu_socket_id[lcpu] = core->id;
                        }
                        smp_cpu_set_polarization(lcpu, tl_cpu->pp);
                }
index de8fa9bbd35ee9787537e93c18b561b75cacf72f..79cb51adc7419b52245d444c74e2c9378eaf99ab 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifndef CONFIG_64BIT
 OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390")
-OUTPUT_ARCH(s390)
+OUTPUT_ARCH(s390:31-bit)
 ENTRY(startup)
 jiffies = jiffies_64 + 4;
 #else
index 2d37bb861faf69cf43e30971881fae771322158a..9017a63dda3dd21df684563770819af53a2cb370 100644 (file)
@@ -39,7 +39,7 @@ static __always_inline unsigned long follow_table(struct mm_struct *mm,
        pmd = pmd_offset(pud, addr);
        if (pmd_none(*pmd))
                return -0x10UL;
-       if (pmd_huge(*pmd)) {
+       if (pmd_large(*pmd)) {
                if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
                        return -0x04UL;
                return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
index 60acb93a46809065b0d454e65f3837aa37e70aee..1f5315d1215c2640f5691555801e9ff7885c7fcf 100644 (file)
@@ -126,7 +126,7 @@ static inline int gup_pmd_range(pud_t *pudp, pud_t pud, unsigned long addr,
                 */
                if (pmd_none(pmd) || pmd_trans_splitting(pmd))
                        return 0;
-               if (unlikely(pmd_huge(pmd))) {
+               if (unlikely(pmd_large(pmd))) {
                        if (!gup_huge_pmd(pmdp, pmd, addr, next,
                                          write, pages, nr))
                                return 0;
@@ -180,8 +180,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
        addr = start;
        len = (unsigned long) nr_pages << PAGE_SHIFT;
        end = start + len;
-       if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
-                                       (void __user *)start, len)))
+       if ((end < start) || (end > TASK_SIZE))
                return 0;
 
        local_irq_save(flags);
@@ -229,7 +228,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
        addr = start;
        len = (unsigned long) nr_pages << PAGE_SHIFT;
        end = start + len;
-       if (end < start)
+       if ((end < start) || (end > TASK_SIZE))
                goto slow_irqon;
 
        /*
index 86eadceff097481b4ba5ce3494d60134f50e02ae..29f83beeef7a4c463d814ee445f73e47e2ff24b8 100644 (file)
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += bitsperlong.h
 generic-y += cputime.h
@@ -34,13 +33,3 @@ generic-y += termbits.h
 generic-y += termios.h
 generic-y += ucontext.h
 generic-y += xor.h
-
-header-y += cachectl.h
-header-y += cpu-features.h
-header-y += hw_breakpoint.h
-header-y += posix_types_32.h
-header-y += posix_types_64.h
-header-y += ptrace_32.h
-header-y += ptrace_64.h
-header-y += unistd_32.h
-header-y += unistd_64.h
diff --git a/arch/sh/include/asm/auxvec.h b/arch/sh/include/asm/auxvec.h
deleted file mode 100644 (file)
index 8bcc51a..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-#ifndef __ASM_SH_AUXVEC_H
-#define __ASM_SH_AUXVEC_H
-
-/*
- * Architecture-neutral AT_ values in 0-17, leave some room
- * for more of them.
- */
-
-/*
- * This entry gives some information about the FPU initialization
- * performed by the kernel.
- */
-#define AT_FPUCW               18      /* Used FPU control word.  */
-
-#if defined(CONFIG_VSYSCALL) || !defined(__KERNEL__)
-/*
- * Only define this in the vsyscall case, the entry point to
- * the vsyscall page gets placed here. The kernel will attempt
- * to build a gate VMA we don't care about otherwise..
- */
-#define AT_SYSINFO_EHDR                33
-#endif
-
-/*
- * More complete cache descriptions than AT_[DIU]CACHEBSIZE.  If the
- * value is -1, then the cache doesn't exist.  Otherwise:
- *
- *    bit 0-3:   Cache set-associativity; 0 means fully associative.
- *    bit 4-7:   Log2 of cacheline size.
- *    bit 8-31:          Size of the entire cache >> 8.
- */
-#define AT_L1I_CACHESHAPE      34
-#define AT_L1D_CACHESHAPE      35
-#define AT_L2_CACHESHAPE       36
-
-#define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */
-
-#endif /* __ASM_SH_AUXVEC_H */
diff --git a/arch/sh/include/asm/byteorder.h b/arch/sh/include/asm/byteorder.h
deleted file mode 100644 (file)
index db2f5d7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_SH_BYTEORDER_H
-#define __ASM_SH_BYTEORDER_H
-
-#ifdef __LITTLE_ENDIAN__
-#include <linux/byteorder/little_endian.h>
-#else
-#include <linux/byteorder/big_endian.h>
-#endif
-
-#endif /* __ASM_SH_BYTEORDER_H */
diff --git a/arch/sh/include/asm/cachectl.h b/arch/sh/include/asm/cachectl.h
deleted file mode 100644 (file)
index 6ffb4b7..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _SH_CACHECTL_H
-#define _SH_CACHECTL_H
-
-/* Definitions for the cacheflush system call.  */
-
-#define CACHEFLUSH_D_INVAL     0x1     /* invalidate (without write back) */
-#define CACHEFLUSH_D_WB                0x2     /* write back (without invalidate) */
-#define CACHEFLUSH_D_PURGE     0x3     /* writeback and invalidate */
-
-#define CACHEFLUSH_I           0x4
-
-/*
- * Options for cacheflush system call
- */
-#define ICACHE CACHEFLUSH_I            /* flush instruction cache */
-#define DCACHE CACHEFLUSH_D_PURGE      /* writeback and flush data cache */
-#define BCACHE (ICACHE|DCACHE)         /* flush both caches */
-
-#endif /* _SH_CACHECTL_H */
diff --git a/arch/sh/include/asm/cpu-features.h b/arch/sh/include/asm/cpu-features.h
deleted file mode 100644 (file)
index 694abe4..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __ASM_SH_CPU_FEATURES_H
-#define __ASM_SH_CPU_FEATURES_H
-
-/*
- * Processor flags
- *
- * Note: When adding a new flag, keep cpu_flags[] in
- * arch/sh/kernel/setup.c in sync so symbolic name
- * mapping of the processor flags has a chance of being
- * reasonably accurate.
- *
- * These flags are also available through the ELF
- * auxiliary vector as AT_HWCAP.
- */
-#define CPU_HAS_FPU            0x0001  /* Hardware FPU support */
-#define CPU_HAS_P2_FLUSH_BUG   0x0002  /* Need to flush the cache in P2 area */
-#define CPU_HAS_MMU_PAGE_ASSOC 0x0004  /* SH3: TLB way selection bit support */
-#define CPU_HAS_DSP            0x0008  /* SH-DSP: DSP support */
-#define CPU_HAS_PERF_COUNTER   0x0010  /* Hardware performance counters */
-#define CPU_HAS_PTEA           0x0020  /* PTEA register */
-#define CPU_HAS_LLSC           0x0040  /* movli.l/movco.l */
-#define CPU_HAS_L2_CACHE       0x0080  /* Secondary cache / URAM */
-#define CPU_HAS_OP32           0x0100  /* 32-bit instruction support */
-#define CPU_HAS_PTEAEX         0x0200  /* PTE ASID Extension support */
-
-#endif /* __ASM_SH_CPU_FEATURES_H */
index 89890f61a7b91d495a0cf4c72a45780fe6f389be..ec9ad593c3da743bacbd5875a577709a94e3333b 100644 (file)
@@ -1,7 +1,8 @@
 #ifndef __ASM_SH_HW_BREAKPOINT_H
 #define __ASM_SH_HW_BREAKPOINT_H
 
-#ifdef __KERNEL__
+#include <uapi/asm/hw_breakpoint.h>
+
 #define __ARCH_HW_BREAKPOINT_H
 
 #include <linux/kdebug.h>
@@ -66,5 +67,4 @@ extern int register_sh_ubc(struct sh_ubc *);
 
 extern struct pmu perf_ops_bp;
 
-#endif /* __KERNEL__ */
 #endif /* __ASM_SH_HW_BREAKPOINT_H */
diff --git a/arch/sh/include/asm/ioctls.h b/arch/sh/include/asm/ioctls.h
deleted file mode 100644 (file)
index a6769f3..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef __ASM_SH_IOCTLS_H
-#define __ASM_SH_IOCTLS_H
-
-#include <asm/ioctl.h>
-
-#define FIOCLEX                _IO('f', 1)
-#define FIONCLEX       _IO('f', 2)
-#define FIOASYNC       _IOW('f', 125, int)
-#define FIONBIO                _IOW('f', 126, int)
-#define FIONREAD       _IOR('f', 127, int)
-#define TIOCINQ                FIONREAD
-#define FIOQSIZE       _IOR('f', 128, loff_t)
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-
-#define TCGETA         0x80127417      /* _IOR('t', 23, struct termio) */
-#define TCSETA         0x40127418      /* _IOW('t', 24, struct termio) */
-#define TCSETAW                0x40127419      /* _IOW('t', 25, struct termio) */
-#define TCSETAF                0x4012741C      /* _IOW('t', 28, struct termio) */
-
-#define TCSBRK         _IO('t', 29)
-#define TCXONC         _IO('t', 30)
-#define TCFLSH         _IO('t', 31)
-
-#define TIOCSWINSZ     0x40087467      /* _IOW('t', 103, struct winsize) */
-#define TIOCGWINSZ     0x80087468      /* _IOR('t', 104, struct winsize) */
-#define        TIOCSTART       _IO('t', 110)           /* start output, like ^Q */
-#define        TIOCSTOP        _IO('t', 111)           /* stop output, like ^S */
-#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
-
-#define TIOCSPGRP      _IOW('t', 118, int)
-#define TIOCGPGRP      _IOR('t', 119, int)
-
-#define TIOCEXCL       _IO('T', 12) /* 0x540C */
-#define TIOCNXCL       _IO('T', 13) /* 0x540D */
-#define TIOCSCTTY      _IO('T', 14) /* 0x540E */
-
-#define TIOCSTI                _IOW('T', 18, char) /* 0x5412 */
-#define TIOCMGET       _IOR('T', 21, unsigned int) /* 0x5415 */
-#define TIOCMBIS       _IOW('T', 22, unsigned int) /* 0x5416 */
-#define TIOCMBIC       _IOW('T', 23, unsigned int) /* 0x5417 */
-#define TIOCMSET       _IOW('T', 24, unsigned int) /* 0x5418 */
-# define TIOCM_LE      0x001
-# define TIOCM_DTR     0x002
-# define TIOCM_RTS     0x004
-# define TIOCM_ST      0x008
-# define TIOCM_SR      0x010
-# define TIOCM_CTS     0x020
-# define TIOCM_CAR     0x040
-# define TIOCM_RNG     0x080
-# define TIOCM_DSR     0x100
-# define TIOCM_CD      TIOCM_CAR
-# define TIOCM_RI      TIOCM_RNG
-
-#define TIOCGSOFTCAR   _IOR('T', 25, unsigned int) /* 0x5419 */
-#define TIOCSSOFTCAR   _IOW('T', 26, unsigned int) /* 0x541A */
-#define TIOCLINUX      _IOW('T', 28, char) /* 0x541C */
-#define TIOCCONS       _IO('T', 29) /* 0x541D */
-#define TIOCGSERIAL    0x803C541E      /* _IOR('T', 30, struct serial_struct) 0x541E */
-#define TIOCSSERIAL    0x403C541F      /* _IOW('T', 31, struct serial_struct) 0x541F */
-#define TIOCPKT                _IOW('T', 32, int) /* 0x5420 */
-# define TIOCPKT_DATA           0
-# define TIOCPKT_FLUSHREAD      1
-# define TIOCPKT_FLUSHWRITE     2
-# define TIOCPKT_STOP           4
-# define TIOCPKT_START          8
-# define TIOCPKT_NOSTOP                16
-# define TIOCPKT_DOSTOP                32
-# define TIOCPKT_IOCTL         64
-
-
-#define TIOCNOTTY      _IO('T', 34) /* 0x5422 */
-#define TIOCSETD       _IOW('T', 35, int) /* 0x5423 */
-#define TIOCGETD       _IOR('T', 36, int) /* 0x5424 */
-#define TCSBRKP                _IOW('T', 37, int) /* 0x5425 */ /* Needed for POSIX tcsendbreak() */
-#define TIOCSBRK       _IO('T', 39) /* 0x5427 */ /* BSD compatibility */
-#define TIOCCBRK       _IO('T', 40) /* 0x5428 */ /* BSD compatibility */
-#define TIOCGSID       _IOR('T', 41, pid_t) /* 0x5429 */ /* Return the session ID of FD */
-#define TCGETS2                _IOR('T', 42, struct termios2)
-#define TCSETS2                _IOW('T', 43, struct termios2)
-#define TCSETSW2       _IOW('T', 44, struct termios2)
-#define TCSETSF2       _IOW('T', 45, struct termios2)
-#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCGDEV       _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
-#define TIOCSIG                _IOW('T',0x36, int)  /* Generate signal on Pty slave */
-#define TIOCVHANGUP    _IO('T', 0x37)
-
-#define TIOCSERCONFIG  _IO('T', 83) /* 0x5453 */
-#define TIOCSERGWILD   _IOR('T', 84,  int) /* 0x5454 */
-#define TIOCSERSWILD   _IOW('T', 85,  int) /* 0x5455 */
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x80d85458      /* _IOR('T', 88, struct async_struct) 0x5458 */ /* For debugging only */
-#define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* 0x5459 */ /* Get line status register */
-  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-# define TIOCSER_TEMT    0x01  /* Transmitter physically empty */
-#define TIOCSERGETMULTI 0x80A8545A     /* _IOR('T', 90, struct serial_multiport_struct) 0x545A */ /* Get multiport config */
-#define TIOCSERSETMULTI 0x40A8545B     /* _IOW('T', 91, struct serial_multiport_struct) 0x545B */ /* Set multiport config */
-
-#define TIOCMIWAIT     _IO('T', 92) /* 0x545C */       /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-
-#endif /* __ASM_SH_IOCTLS_H */
index f08449bcbde7e747f96d27d4397c46f97d0b593f..1aa781079b1edb4aaeeebd5b325475a35a7dfd6a 100644 (file)
@@ -1,13 +1,5 @@
-#ifdef __KERNEL__
 # ifdef CONFIG_SUPERH32
 #  include <asm/posix_types_32.h>
 # else
 #  include <asm/posix_types_64.h>
 # endif
-#else
-# ifdef __SH5__
-#  include <asm/posix_types_64.h>
-# else
-#  include <asm/posix_types_32.h>
-# endif
-#endif /* __KERNEL__ */
diff --git a/arch/sh/include/asm/posix_types_32.h b/arch/sh/include/asm/posix_types_32.h
deleted file mode 100644 (file)
index ba0bdc4..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef __ASM_SH_POSIX_TYPES_32_H
-#define __ASM_SH_POSIX_TYPES_32_H
-
-typedef unsigned short __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-typedef unsigned short __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-typedef unsigned short __kernel_uid_t;
-#define __kernel_uid_t __kernel_uid_t
-typedef unsigned short __kernel_gid_t;
-#define __kernel_gid_t __kernel_gid_t
-
-typedef unsigned short __kernel_old_uid_t;
-#define __kernel_old_uid_t __kernel_old_uid_t
-typedef unsigned short __kernel_old_gid_t;
-#define __kernel_old_gid_t __kernel_old_gid_t
-typedef unsigned short __kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif /* __ASM_SH_POSIX_TYPES_32_H */
diff --git a/arch/sh/include/asm/posix_types_64.h b/arch/sh/include/asm/posix_types_64.h
deleted file mode 100644 (file)
index 244f7e9..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __ASM_SH_POSIX_TYPES_64_H
-#define __ASM_SH_POSIX_TYPES_64_H
-
-typedef unsigned short __kernel_mode_t;
-#define __kernel_mode_t __kernel_mode_t
-typedef unsigned short __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-typedef unsigned short __kernel_uid_t;
-#define __kernel_uid_t __kernel_uid_t
-typedef unsigned short __kernel_gid_t;
-#define __kernel_gid_t __kernel_gid_t
-typedef long unsigned int      __kernel_size_t;
-#define __kernel_size_t __kernel_size_t
-typedef int            __kernel_ssize_t;
-#define __kernel_ssize_t __kernel_ssize_t
-typedef int            __kernel_ptrdiff_t;
-#define __kernel_ptrdiff_t __kernel_ptrdiff_t
-
-typedef unsigned short __kernel_old_uid_t;
-#define __kernel_old_uid_t __kernel_old_uid_t
-typedef unsigned short __kernel_old_gid_t;
-#define __kernel_old_gid_t __kernel_old_gid_t
-typedef unsigned short __kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif /* __ASM_SH_POSIX_TYPES_64_H */
index a4a38dff997adc4e01b50188d5ef5df796f0644f..2506c7db76b70ef83db681e14f49cee27ccb5933 100644 (file)
@@ -1,42 +1,16 @@
-#ifndef __ASM_SH_PTRACE_H
-#define __ASM_SH_PTRACE_H
-
 /*
  * Copyright (C) 1999, 2000  Niibe Yutaka
  */
+#ifndef __ASM_SH_PTRACE_H
+#define __ASM_SH_PTRACE_H
 
-#define PTRACE_GETREGS         12      /* General registers */
-#define PTRACE_SETREGS         13
-
-#define PTRACE_GETFPREGS       14      /* FPU registers */
-#define PTRACE_SETFPREGS       15
-
-#define PTRACE_GETFDPIC                31      /* get the ELF fdpic loadmap address */
-
-#define PTRACE_GETFDPIC_EXEC   0       /* [addr] request the executable loadmap */
-#define PTRACE_GETFDPIC_INTERP 1       /* [addr] request the interpreter loadmap */
-
-#define        PTRACE_GETDSPREGS       55      /* DSP registers */
-#define        PTRACE_SETDSPREGS       56
-
-#define PT_TEXT_END_ADDR       240
-#define PT_TEXT_ADDR           244     /* &(struct user)->start_code */
-#define PT_DATA_ADDR           248     /* &(struct user)->start_data */
-#define PT_TEXT_LEN            252
-
-#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
-#include <asm/ptrace_64.h>
-#else
-#include <asm/ptrace_32.h>
-#endif
-
-#ifdef __KERNEL__
 
 #include <linux/stringify.h>
 #include <linux/stddef.h>
 #include <linux/thread_info.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
+#include <uapi/asm/ptrace.h>
 
 #define user_mode(regs)                        (((regs)->sr & 0x40000000)==0)
 #define kernel_stack_pointer(_regs)    ((unsigned long)(_regs)->regs[15])
@@ -140,6 +114,4 @@ static inline unsigned long profile_pc(struct pt_regs *regs)
 #define profile_pc profile_pc
 
 #include <asm-generic/ptrace.h>
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_PTRACE_H */
index 2d3e906aa72252d3b827a12405546465127d5f78..1dd4480c5363f5e413dc35e0b65c9278ffbc1bae 100644 (file)
@@ -1,79 +1,8 @@
 #ifndef __ASM_SH_PTRACE_32_H
 #define __ASM_SH_PTRACE_32_H
 
-/*
- * GCC defines register number like this:
- * -----------------------------
- *      0 - 15 are integer registers
- *     17 - 22 are control/special registers
- *     24 - 39 fp registers
- *     40 - 47 xd registers
- *     48 -    fpscr register
- * -----------------------------
- *
- * We follows above, except:
- *     16 --- program counter (PC)
- *     22 --- syscall #
- *     23 --- floating point communication register
- */
-#define REG_REG0        0
-#define REG_REG15      15
+#include <uapi/asm/ptrace_32.h>
 
-#define REG_PC         16
-
-#define REG_PR         17
-#define REG_SR         18
-#define REG_GBR                19
-#define REG_MACH       20
-#define REG_MACL       21
-
-#define REG_SYSCALL    22
-
-#define REG_FPREG0     23
-#define REG_FPREG15    38
-#define REG_XFREG0     39
-#define REG_XFREG15    54
-
-#define REG_FPSCR      55
-#define REG_FPUL       56
-
-/*
- * This struct defines the way the registers are stored on the
- * kernel stack during a system call or other kernel entry.
- */
-struct pt_regs {
-       unsigned long regs[16];
-       unsigned long pc;
-       unsigned long pr;
-       unsigned long sr;
-       unsigned long gbr;
-       unsigned long mach;
-       unsigned long macl;
-       long tra;
-};
-
-/*
- * This struct defines the way the DSP registers are stored on the
- * kernel stack during a system call or other kernel entry.
- */
-struct pt_dspregs {
-       unsigned long   a1;
-       unsigned long   a0g;
-       unsigned long   a1g;
-       unsigned long   m0;
-       unsigned long   m1;
-       unsigned long   a0;
-       unsigned long   x0;
-       unsigned long   x1;
-       unsigned long   y0;
-       unsigned long   y1;
-       unsigned long   dsr;
-       unsigned long   rs;
-       unsigned long   re;
-       unsigned long   mod;
-};
-
-#ifdef __KERNEL__
 
 #define MAX_REG_OFFSET         offsetof(struct pt_regs, tra)
 static inline long regs_return_value(struct pt_regs *regs)
@@ -81,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs)
        return regs->regs[0];
 }
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_PTRACE_32_H */
index eb3fcceaf64b7bb5942a081637e78c5d479bad86..97f4b5660f2cdc62d112183e2e600c4456b6476e 100644 (file)
@@ -1,16 +1,8 @@
 #ifndef __ASM_SH_PTRACE_64_H
 #define __ASM_SH_PTRACE_64_H
 
-struct pt_regs {
-       unsigned long long pc;
-       unsigned long long sr;
-       long long syscall_nr;
-       unsigned long long regs[63];
-       unsigned long long tregs[8];
-       unsigned long long pad[2];
-};
+#include <uapi/asm/ptrace_64.h>
 
-#ifdef __KERNEL__
 
 #define MAX_REG_OFFSET         offsetof(struct pt_regs, tregs[7])
 static inline long regs_return_value(struct pt_regs *regs)
@@ -18,6 +10,4 @@ static inline long regs_return_value(struct pt_regs *regs)
        return regs->regs[3];
 }
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_PTRACE_64_H */
index 465a22df8fd029baa750e02c47b8ca438e22bd70..99238108e7a51b6af6815e42a6e34f1799a0bc99 100644 (file)
@@ -1,9 +1,8 @@
 #ifndef _SH_SETUP_H
 #define _SH_SETUP_H
 
-#include <asm-generic/setup.h>
+#include <uapi/asm/setup.h>
 
-#ifdef __KERNEL__
 /*
  * This is set up by the setup-routine at boot-time
  */
@@ -22,6 +21,4 @@ void sh_mv_setup(void);
 void check_for_initrd(void);
 void per_cpu_trap_init(void);
 
-#endif /* __KERNEL__ */
-
 #endif /* _SH_SETUP_H */
diff --git a/arch/sh/include/asm/sigcontext.h b/arch/sh/include/asm/sigcontext.h
deleted file mode 100644 (file)
index 8ce1435..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef __ASM_SH_SIGCONTEXT_H
-#define __ASM_SH_SIGCONTEXT_H
-
-struct sigcontext {
-       unsigned long   oldmask;
-
-#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
-       /* CPU registers */
-       unsigned long long sc_regs[63];
-       unsigned long long sc_tregs[8];
-       unsigned long long sc_pc;
-       unsigned long long sc_sr;
-
-       /* FPU registers */
-       unsigned long long sc_fpregs[32];
-       unsigned int sc_fpscr;
-       unsigned int sc_fpvalid;
-#else
-       /* CPU registers */
-       unsigned long sc_regs[16];
-       unsigned long sc_pc;
-       unsigned long sc_pr;
-       unsigned long sc_sr;
-       unsigned long sc_gbr;
-       unsigned long sc_mach;
-       unsigned long sc_macl;
-
-#if defined(__SH4__) || defined(CONFIG_CPU_SH4) || \
-    defined(__SH2A__) || defined(CONFIG_CPU_SH2A)
-       /* FPU registers */
-       unsigned long sc_fpregs[16];
-       unsigned long sc_xfpregs[16];
-       unsigned int sc_fpscr;
-       unsigned int sc_fpul;
-       unsigned int sc_ownedfp;
-#endif
-#endif
-};
-
-#endif /* __ASM_SH_SIGCONTEXT_H */
diff --git a/arch/sh/include/asm/signal.h b/arch/sh/include/asm/signal.h
deleted file mode 100644 (file)
index 9ac530a..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASM_SH_SIGNAL_H
-#define __ASM_SH_SIGNAL_H
-
-#define SA_RESTORER    0x04000000
-
-#include <asm-generic/signal.h>
-
-struct old_sigaction {
-       __sighandler_t sa_handler;
-       old_sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#endif /* __ASM_SH_SIGNAL_H */
diff --git a/arch/sh/include/asm/sockios.h b/arch/sh/include/asm/sockios.h
deleted file mode 100644 (file)
index cf8b96b..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef __ASM_SH_SOCKIOS_H
-#define __ASM_SH_SOCKIOS_H
-
-/* Socket-level I/O control calls. */
-#define FIOGETOWN      _IOR('f', 123, int)
-#define FIOSETOWN      _IOW('f', 124, int)
-
-#define SIOCATMARK     _IOR('s', 7, int)
-#define SIOCSPGRP      _IOW('s', 8, pid_t)
-#define SIOCGPGRP      _IOR('s', 9, pid_t)
-
-#define SIOCGSTAMP     _IOR('s', 100, struct timeval) /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   _IOR('s', 101, struct timespec) /* Get stamp (timespec) */
-#endif /* __ASM_SH_SOCKIOS_H */
diff --git a/arch/sh/include/asm/stat.h b/arch/sh/include/asm/stat.h
deleted file mode 100644 (file)
index e1810cc..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-#ifndef __ASM_SH_STAT_H
-#define __ASM_SH_STAT_H
-
-struct __old_kernel_stat {
-       unsigned short st_dev;
-       unsigned short st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned long  st_size;
-       unsigned long  st_atime;
-       unsigned long  st_mtime;
-       unsigned long  st_ctime;
-};
-
-#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
-struct stat {
-       unsigned short st_dev;
-       unsigned short __pad1;
-       unsigned long st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned short st_rdev;
-       unsigned short __pad2;
-       unsigned long  st_size;
-       unsigned long  st_blksize;
-       unsigned long  st_blocks;
-       unsigned long  st_atime;
-       unsigned long  st_atime_nsec;
-       unsigned long  st_mtime;
-       unsigned long  st_mtime_nsec;
-       unsigned long  st_ctime;
-       unsigned long  st_ctime_nsec;
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- */
-struct stat64 {
-       unsigned short  st_dev;
-       unsigned char   __pad0[10];
-
-       unsigned long   st_ino;
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-
-       unsigned long   st_uid;
-       unsigned long   st_gid;
-
-       unsigned short  st_rdev;
-       unsigned char   __pad3[10];
-
-       long long       st_size;
-       unsigned long   st_blksize;
-
-       unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
-       unsigned long   __pad4;         /* future possible st_blocks high bits */
-
-       unsigned long   st_atime;
-       unsigned long   st_atime_nsec;
-
-       unsigned long   st_mtime;
-       unsigned long   st_mtime_nsec;
-
-       unsigned long   st_ctime;
-       unsigned long   st_ctime_nsec;  /* will be high 32 bits of ctime someday */
-
-       unsigned long   __unused1;
-       unsigned long   __unused2;
-};
-#else
-struct stat {
-       unsigned long  st_dev;
-       unsigned long  st_ino;
-       unsigned short st_mode;
-       unsigned short st_nlink;
-       unsigned short st_uid;
-       unsigned short st_gid;
-       unsigned long  st_rdev;
-       unsigned long  st_size;
-       unsigned long  st_blksize;
-       unsigned long  st_blocks;
-       unsigned long  st_atime;
-       unsigned long  st_atime_nsec;
-       unsigned long  st_mtime;
-       unsigned long  st_mtime_nsec;
-       unsigned long  st_ctime;
-       unsigned long  st_ctime_nsec;
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-/* This matches struct stat64 in glibc2.1, hence the absolutely
- * insane amounts of padding around dev_t's.
- */
-struct stat64 {
-       unsigned long long      st_dev;
-       unsigned char   __pad0[4];
-
-#define STAT64_HAS_BROKEN_ST_INO       1
-       unsigned long   __st_ino;
-
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-
-       unsigned long   st_uid;
-       unsigned long   st_gid;
-
-       unsigned long long      st_rdev;
-       unsigned char   __pad3[4];
-
-       long long       st_size;
-       unsigned long   st_blksize;
-
-       unsigned long long      st_blocks;      /* Number 512-byte blocks allocated. */
-
-       unsigned long   st_atime;
-       unsigned long   st_atime_nsec;
-
-       unsigned long   st_mtime;
-       unsigned long   st_mtime_nsec;
-
-       unsigned long   st_ctime;
-       unsigned long   st_ctime_nsec;
-
-       unsigned long long      st_ino;
-};
-
-#define STAT_HAVE_NSEC 1
-#endif
-
-#endif /* __ASM_SH_STAT_H */
diff --git a/arch/sh/include/asm/swab.h b/arch/sh/include/asm/swab.h
deleted file mode 100644 (file)
index 1cd0976..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef __ASM_SH_SWAB_H
-#define __ASM_SH_SWAB_H
-
-/*
- * Copyright (C) 1999  Niibe Yutaka
- * Copyright (C) 2000, 2001  Paolo Alberelli
- */
-#include <linux/compiler.h>
-#include <linux/types.h>
-#include <asm-generic/swab.h>
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
-{
-       __asm__(
-#ifdef __SH5__
-               "byterev        %1, %0\n\t"
-               "shari          %0, 32, %0"
-#else
-               "swap.b         %1, %0\n\t"
-               "swap.w         %0, %0\n\t"
-               "swap.b         %0, %0"
-#endif
-               : "=r" (x)
-               : "r" (x));
-
-       return x;
-}
-#define __arch_swab32 __arch_swab32
-
-static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
-{
-       __asm__(
-#ifdef __SH5__
-               "byterev        %1, %0\n\t"
-               "shari          %0, 32, %0"
-#else
-               "swap.b         %1, %0"
-#endif
-               : "=r" (x)
-               :  "r" (x));
-
-       return x;
-}
-#define __arch_swab16 __arch_swab16
-
-static inline __u64 __arch_swab64(__u64 val)
-{
-       union {
-               struct { __u32 a,b; } s;
-               __u64 u;
-       } v, w;
-       v.u = val;
-       w.s.b = __arch_swab32(v.s.a);
-       w.s.a = __arch_swab32(v.s.b);
-       return w.u;
-}
-#define __arch_swab64 __arch_swab64
-
-#endif /* __ASM_SH_SWAB_H */
index f8421f7ad63a8b0c79ad3dc5e2fd6b64e2832203..6a31053fa5e32f4cd53a260ed9cf61f8e3ed1eb8 100644 (file)
@@ -1,12 +1,11 @@
 #ifndef __ASM_SH_TYPES_H
 #define __ASM_SH_TYPES_H
 
-#include <asm-generic/types.h>
+#include <uapi/asm/types.h>
 
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
-#ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
 #ifdef CONFIG_SUPERH32
@@ -18,6 +17,4 @@ typedef u64 reg_size_t;
 #endif
 
 #endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
 #endif /* __ASM_SH_TYPES_H */
index 307201a854f3902b84a100a4f0f72911a3a37932..38956dfa76f7fb52137375470d0ccb5b35f1741d 100644 (file)
@@ -1,4 +1,3 @@
-#ifdef __KERNEL__
 # ifdef CONFIG_SUPERH32
 #  include <asm/unistd_32.h>
 # else
  */
 # define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
-#else
-# ifdef __SH5__
-#  include <asm/unistd_64.h>
-# else
-#  include <asm/unistd_32.h>
-# endif
-#endif
+#include <uapi/asm/unistd.h>
diff --git a/arch/sh/include/asm/unistd_32.h b/arch/sh/include/asm/unistd_32.h
deleted file mode 100644 (file)
index 72fd1e0..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-#ifndef __ASM_SH_UNISTD_32_H
-#define __ASM_SH_UNISTD_32_H
-
-/*
- * Copyright (C) 1999  Niibe Yutaka
- */
-
-/*
- * This file contains the system call numbers.
- */
-
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_lchown             16
-                                /* 17 was sys_break */
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-                                /* 31 was sys_stty */
-                                /* 32 was sys_gtty */
-#define __NR_access             33
-#define __NR_nice               34
-                                /* 35 was sys_ftime */
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-                                /* 44 was sys_prof */
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-                                /* 53 was sys_lock */
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-                                /* 56 was sys_mpx */
-#define __NR_setpgid            57
-                                /* 58 was sys_ulimit */
-                                /* 59 was sys_olduname */
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-                                /* 82 was sys_oldselect */
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-                                /* 98 was sys_profil */
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-                               /* 101 was sys_ioperm */
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-#define __NR_olduname          109
-                               /* 110 was sys_iopl */
-#define __NR_vhangup           111
-                               /* 112 was sys_idle */
-                               /* 113 was sys_vm86old */
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_cacheflush                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-                               /* 127 was sys_create_module */
-#define __NR_init_module       128
-#define __NR_delete_module     129
-                               /* 130 was sys_get_kernel_syms */
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-                               /* 137 was sys_afs_syscall */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-                               /* 166 was sys_vm86 */
-                               /* 167 was sys_query_module */
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl              172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread64           180
-#define __NR_pwrite64          181
-#define __NR_chown             182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-                               /* 188 reserved for sys_getpmsg */
-                               /* 189 reserved for sys_putpmsg */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_lchown32          198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_chown32           212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-#define __NR_mincore           218
-#define __NR_madvise           219
-#define __NR_getdents64                220
-#define __NR_fcntl64           221
-                               /* 222 is reserved for tux */
-                               /* 223 is unused */
-#define __NR_gettid            224
-#define __NR_readahead         225
-#define __NR_setxattr          226
-#define __NR_lsetxattr         227
-#define __NR_fsetxattr         228
-#define __NR_getxattr          229
-#define __NR_lgetxattr         230
-#define __NR_fgetxattr         231
-#define __NR_listxattr         232
-#define __NR_llistxattr                233
-#define __NR_flistxattr                234
-#define __NR_removexattr       235
-#define __NR_lremovexattr      236
-#define __NR_fremovexattr      237
-#define __NR_tkill             238
-#define __NR_sendfile64                239
-#define __NR_futex             240
-#define __NR_sched_setaffinity 241
-#define __NR_sched_getaffinity 242
-                               /* 243 is reserved for set_thread_area */
-                               /* 244 is reserved for get_thread_area */
-#define __NR_io_setup          245
-#define __NR_io_destroy                246
-#define __NR_io_getevents      247
-#define __NR_io_submit         248
-#define __NR_io_cancel         249
-#define __NR_fadvise64         250
-                               /* 251 is unused */
-#define __NR_exit_group                252
-#define __NR_lookup_dcookie    253
-#define __NR_epoll_create      254
-#define __NR_epoll_ctl         255
-#define __NR_epoll_wait                256
-#define __NR_remap_file_pages  257
-#define __NR_set_tid_address   258
-#define __NR_timer_create      259
-#define __NR_timer_settime     (__NR_timer_create+1)
-#define __NR_timer_gettime     (__NR_timer_create+2)
-#define __NR_timer_getoverrun  (__NR_timer_create+3)
-#define __NR_timer_delete      (__NR_timer_create+4)
-#define __NR_clock_settime     (__NR_timer_create+5)
-#define __NR_clock_gettime     (__NR_timer_create+6)
-#define __NR_clock_getres      (__NR_timer_create+7)
-#define __NR_clock_nanosleep   (__NR_timer_create+8)
-#define __NR_statfs64          268
-#define __NR_fstatfs64         269
-#define __NR_tgkill            270
-#define __NR_utimes            271
-#define __NR_fadvise64_64      272
-                               /* 273 is reserved for vserver */
-#define __NR_mbind              274
-#define __NR_get_mempolicy      275
-#define __NR_set_mempolicy      276
-#define __NR_mq_open            277
-#define __NR_mq_unlink          (__NR_mq_open+1)
-#define __NR_mq_timedsend       (__NR_mq_open+2)
-#define __NR_mq_timedreceive    (__NR_mq_open+3)
-#define __NR_mq_notify          (__NR_mq_open+4)
-#define __NR_mq_getsetattr      (__NR_mq_open+5)
-#define __NR_kexec_load                283
-#define __NR_waitid            284
-#define __NR_add_key           285
-#define __NR_request_key       286
-#define __NR_keyctl            287
-#define __NR_ioprio_set                288
-#define __NR_ioprio_get                289
-#define __NR_inotify_init      290
-#define __NR_inotify_add_watch 291
-#define __NR_inotify_rm_watch  292
-                               /* 293 is unused */
-#define __NR_migrate_pages     294
-#define __NR_openat            295
-#define __NR_mkdirat           296
-#define __NR_mknodat           297
-#define __NR_fchownat          298
-#define __NR_futimesat         299
-#define __NR_fstatat64         300
-#define __NR_unlinkat          301
-#define __NR_renameat          302
-#define __NR_linkat            303
-#define __NR_symlinkat         304
-#define __NR_readlinkat                305
-#define __NR_fchmodat          306
-#define __NR_faccessat         307
-#define __NR_pselect6          308
-#define __NR_ppoll             309
-#define __NR_unshare           310
-#define __NR_set_robust_list   311
-#define __NR_get_robust_list   312
-#define __NR_splice            313
-#define __NR_sync_file_range   314
-#define __NR_tee               315
-#define __NR_vmsplice          316
-#define __NR_move_pages                317
-#define __NR_getcpu            318
-#define __NR_epoll_pwait       319
-#define __NR_utimensat         320
-#define __NR_signalfd          321
-#define __NR_timerfd_create    322
-#define __NR_eventfd           323
-#define __NR_fallocate         324
-#define __NR_timerfd_settime   325
-#define __NR_timerfd_gettime   326
-#define __NR_signalfd4         327
-#define __NR_eventfd2          328
-#define __NR_epoll_create1     329
-#define __NR_dup3              330
-#define __NR_pipe2             331
-#define __NR_inotify_init1     332
-#define __NR_preadv            333
-#define __NR_pwritev           334
-#define __NR_rt_tgsigqueueinfo 335
-#define __NR_perf_event_open   336
-#define __NR_fanotify_init     337
-#define __NR_fanotify_mark     338
-#define __NR_prlimit64         339
-
-/* Non-multiplexed socket family */
-#define __NR_socket            340
-#define __NR_bind              341
-#define __NR_connect           342
-#define __NR_listen            343
-#define __NR_accept            344
-#define __NR_getsockname       345
-#define __NR_getpeername       346
-#define __NR_socketpair                347
-#define __NR_send              348
-#define __NR_sendto            349
-#define __NR_recv              350
-#define __NR_recvfrom          351
-#define __NR_shutdown          352
-#define __NR_setsockopt                353
-#define __NR_getsockopt                354
-#define __NR_sendmsg           355
-#define __NR_recvmsg           356
-#define __NR_recvmmsg          357
-#define __NR_accept4           358
-#define __NR_name_to_handle_at 359
-#define __NR_open_by_handle_at 360
-#define __NR_clock_adjtime     361
-#define __NR_syncfs            362
-#define __NR_sendmmsg          363
-#define __NR_setns             364
-#define __NR_process_vm_readv  365
-#define __NR_process_vm_writev 366
-
-#define NR_syscalls 367
-
-#endif /* __ASM_SH_UNISTD_32_H */
diff --git a/arch/sh/include/asm/unistd_64.h b/arch/sh/include/asm/unistd_64.h
deleted file mode 100644 (file)
index a28edc3..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-#ifndef __ASM_SH_UNISTD_64_H
-#define __ASM_SH_UNISTD_64_H
-
-/*
- * include/asm-sh/unistd_64.h
- *
- * This file contains the system call numbers.
- *
- * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2003 - 2007 Paul Mundt
- * Copyright (C) 2004  Sean McGoogan
- *
- * 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.
- */
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_lchown             16
-                                /* 17 was sys_break */
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-                                /* 31 was sys_stty */
-                                /* 32 was sys_gtty */
-#define __NR_access             33
-#define __NR_nice               34
-                                /* 35 was sys_ftime */
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-                                /* 44 was sys_prof */
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-                                /* 53 was sys_lock */
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-                                /* 56 was sys_mpx */
-#define __NR_setpgid            57
-                                /* 58 was sys_ulimit */
-                                /* 59 was sys_olduname */
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-                                /* 82 was sys_select */
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-                                /* 98 was sys_profil */
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-                               /* 101 was sys_ioperm */
-#define __NR_socketcall                102     /* old implementation of socket systemcall */
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-#define __NR_olduname          109
-                               /* 110 was sys_iopl */
-#define __NR_vhangup           111
-                               /* 112 was sys_idle */
-                               /* 113 was sys_vm86old */
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_cacheflush                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-                               /* 127 was sys_create_module */
-#define __NR_init_module       128
-#define __NR_delete_module     129
-                               /* 130 was sys_get_kernel_syms */
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-                               /* 137 was sys_afs_syscall */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-                               /* 166 was sys_vm86 */
-                               /* 167 was sys_query_module */
-#define __NR_poll              168
-#define __NR_nfsservctl                169
-#define __NR_setresgid         170
-#define __NR_getresgid         171
-#define __NR_prctl              172
-#define __NR_rt_sigreturn      173
-#define __NR_rt_sigaction      174
-#define __NR_rt_sigprocmask    175
-#define __NR_rt_sigpending     176
-#define __NR_rt_sigtimedwait   177
-#define __NR_rt_sigqueueinfo   178
-#define __NR_rt_sigsuspend     179
-#define __NR_pread64           180
-#define __NR_pwrite64          181
-#define __NR_chown             182
-#define __NR_getcwd            183
-#define __NR_capget            184
-#define __NR_capset            185
-#define __NR_sigaltstack       186
-#define __NR_sendfile          187
-                               /* 188 reserved for getpmsg */
-                               /* 189 reserved for putpmsg */
-#define __NR_vfork             190
-#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#define __NR_lchown32          198
-#define __NR_getuid32          199
-#define __NR_getgid32          200
-#define __NR_geteuid32         201
-#define __NR_getegid32         202
-#define __NR_setreuid32                203
-#define __NR_setregid32                204
-#define __NR_getgroups32       205
-#define __NR_setgroups32       206
-#define __NR_fchown32          207
-#define __NR_setresuid32       208
-#define __NR_getresuid32       209
-#define __NR_setresgid32       210
-#define __NR_getresgid32       211
-#define __NR_chown32           212
-#define __NR_setuid32          213
-#define __NR_setgid32          214
-#define __NR_setfsuid32                215
-#define __NR_setfsgid32                216
-#define __NR_pivot_root                217
-#define __NR_mincore           218
-#define __NR_madvise           219
-
-/* Non-multiplexed socket family */
-#define __NR_socket            220
-#define __NR_bind              221
-#define __NR_connect           222
-#define __NR_listen            223
-#define __NR_accept            224
-#define __NR_getsockname       225
-#define __NR_getpeername       226
-#define __NR_socketpair                227
-#define __NR_send              228
-#define __NR_sendto            229
-#define __NR_recv              230
-#define __NR_recvfrom          231
-#define __NR_shutdown          232
-#define __NR_setsockopt                233
-#define __NR_getsockopt                234
-#define __NR_sendmsg           235
-#define __NR_recvmsg           236
-
-/* Non-multiplexed IPC family */
-#define __NR_semop             237
-#define __NR_semget            238
-#define __NR_semctl            239
-#define __NR_msgsnd            240
-#define __NR_msgrcv            241
-#define __NR_msgget            242
-#define __NR_msgctl            243
-#define __NR_shmat             244
-#define __NR_shmdt             245
-#define __NR_shmget            246
-#define __NR_shmctl            247
-
-#define __NR_getdents64                248
-#define __NR_fcntl64           249
-                               /* 250 is reserved for tux */
-                               /* 251 is unused */
-#define __NR_gettid            252
-#define __NR_readahead         253
-#define __NR_setxattr          254
-#define __NR_lsetxattr         255
-#define __NR_fsetxattr         256
-#define __NR_getxattr          257
-#define __NR_lgetxattr         258
-#define __NR_fgetxattr         269
-#define __NR_listxattr         260
-#define __NR_llistxattr                261
-#define __NR_flistxattr                262
-#define __NR_removexattr       263
-#define __NR_lremovexattr      264
-#define __NR_fremovexattr      265
-#define __NR_tkill             266
-#define __NR_sendfile64                267
-#define __NR_futex             268
-#define __NR_sched_setaffinity 269
-#define __NR_sched_getaffinity 270
-                               /* 271 is reserved for set_thread_area */
-                               /* 272 is reserved for get_thread_area */
-#define __NR_io_setup          273
-#define __NR_io_destroy                274
-#define __NR_io_getevents      275
-#define __NR_io_submit         276
-#define __NR_io_cancel         277
-#define __NR_fadvise64         278
-                               /* 279 is unused */
-#define __NR_exit_group                280
-
-#define __NR_lookup_dcookie    281
-#define __NR_epoll_create      282
-#define __NR_epoll_ctl         283
-#define __NR_epoll_wait                284
-#define __NR_remap_file_pages  285
-#define __NR_set_tid_address   286
-#define __NR_timer_create      287
-#define __NR_timer_settime     (__NR_timer_create+1)
-#define __NR_timer_gettime     (__NR_timer_create+2)
-#define __NR_timer_getoverrun  (__NR_timer_create+3)
-#define __NR_timer_delete      (__NR_timer_create+4)
-#define __NR_clock_settime     (__NR_timer_create+5)
-#define __NR_clock_gettime     (__NR_timer_create+6)
-#define __NR_clock_getres      (__NR_timer_create+7)
-#define __NR_clock_nanosleep   (__NR_timer_create+8)
-#define __NR_statfs64          296
-#define __NR_fstatfs64         297
-#define __NR_tgkill            298
-#define __NR_utimes            299
-#define __NR_fadvise64_64      300
-                               /* 301 is reserved for vserver */
-                               /* 302 is reserved for mbind */
-                               /* 303 is reserved for get_mempolicy */
-                               /* 304 is reserved for set_mempolicy */
-#define __NR_mq_open            305
-#define __NR_mq_unlink          (__NR_mq_open+1)
-#define __NR_mq_timedsend       (__NR_mq_open+2)
-#define __NR_mq_timedreceive    (__NR_mq_open+3)
-#define __NR_mq_notify          (__NR_mq_open+4)
-#define __NR_mq_getsetattr      (__NR_mq_open+5)
-                               /* 311 is reserved for kexec */
-#define __NR_waitid            312
-#define __NR_add_key           313
-#define __NR_request_key       314
-#define __NR_keyctl            315
-#define __NR_ioprio_set                316
-#define __NR_ioprio_get                317
-#define __NR_inotify_init      318
-#define __NR_inotify_add_watch 319
-#define __NR_inotify_rm_watch  320
-                               /* 321 is unused */
-#define __NR_migrate_pages     322
-#define __NR_openat            323
-#define __NR_mkdirat           324
-#define __NR_mknodat           325
-#define __NR_fchownat          326
-#define __NR_futimesat         327
-#define __NR_fstatat64         328
-#define __NR_unlinkat          329
-#define __NR_renameat          330
-#define __NR_linkat            331
-#define __NR_symlinkat         332
-#define __NR_readlinkat                333
-#define __NR_fchmodat          334
-#define __NR_faccessat         335
-#define __NR_pselect6          336
-#define __NR_ppoll             337
-#define __NR_unshare           338
-#define __NR_set_robust_list   339
-#define __NR_get_robust_list   340
-#define __NR_splice            341
-#define __NR_sync_file_range   342
-#define __NR_tee               343
-#define __NR_vmsplice          344
-#define __NR_move_pages                345
-#define __NR_getcpu            346
-#define __NR_epoll_pwait       347
-#define __NR_utimensat         348
-#define __NR_signalfd          349
-#define __NR_timerfd_create    350
-#define __NR_eventfd           351
-#define __NR_fallocate         352
-#define __NR_timerfd_settime   353
-#define __NR_timerfd_gettime   354
-#define __NR_signalfd4         355
-#define __NR_eventfd2          356
-#define __NR_epoll_create1     357
-#define __NR_dup3              358
-#define __NR_pipe2             359
-#define __NR_inotify_init1     360
-#define __NR_preadv            361
-#define __NR_pwritev           362
-#define __NR_rt_tgsigqueueinfo 363
-#define __NR_perf_event_open   364
-#define __NR_recvmmsg          365
-#define __NR_accept4           366
-#define __NR_fanotify_init     367
-#define __NR_fanotify_mark     368
-#define __NR_prlimit64         369
-#define __NR_name_to_handle_at 370
-#define __NR_open_by_handle_at 371
-#define __NR_clock_adjtime     372
-#define __NR_syncfs            373
-#define __NR_sendmmsg          374
-#define __NR_setns             375
-#define __NR_process_vm_readv  376
-#define __NR_process_vm_writev 377
-
-#define NR_syscalls 378
-
-#endif /* __ASM_SH_UNISTD_64_H */
index baebb3da1d44160fc6f6f259886656e6f494b167..60613ae78513a0c60ed146e9d11a0cf734adc4d0 100644 (file)
@@ -1,3 +1,25 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
+header-y += byteorder.h
+header-y += cachectl.h
+header-y += cpu-features.h
+header-y += hw_breakpoint.h
+header-y += ioctls.h
+header-y += posix_types.h
+header-y += posix_types_32.h
+header-y += posix_types_64.h
+header-y += ptrace.h
+header-y += ptrace_32.h
+header-y += ptrace_64.h
+header-y += setup.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += sockios.h
+header-y += stat.h
+header-y += swab.h
+header-y += types.h
+header-y += unistd.h
+header-y += unistd_32.h
+header-y += unistd_64.h
diff --git a/arch/sh/include/uapi/asm/auxvec.h b/arch/sh/include/uapi/asm/auxvec.h
new file mode 100644 (file)
index 0000000..8bcc51a
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __ASM_SH_AUXVEC_H
+#define __ASM_SH_AUXVEC_H
+
+/*
+ * Architecture-neutral AT_ values in 0-17, leave some room
+ * for more of them.
+ */
+
+/*
+ * This entry gives some information about the FPU initialization
+ * performed by the kernel.
+ */
+#define AT_FPUCW               18      /* Used FPU control word.  */
+
+#if defined(CONFIG_VSYSCALL) || !defined(__KERNEL__)
+/*
+ * Only define this in the vsyscall case, the entry point to
+ * the vsyscall page gets placed here. The kernel will attempt
+ * to build a gate VMA we don't care about otherwise..
+ */
+#define AT_SYSINFO_EHDR                33
+#endif
+
+/*
+ * More complete cache descriptions than AT_[DIU]CACHEBSIZE.  If the
+ * value is -1, then the cache doesn't exist.  Otherwise:
+ *
+ *    bit 0-3:   Cache set-associativity; 0 means fully associative.
+ *    bit 4-7:   Log2 of cacheline size.
+ *    bit 8-31:          Size of the entire cache >> 8.
+ */
+#define AT_L1I_CACHESHAPE      34
+#define AT_L1D_CACHESHAPE      35
+#define AT_L2_CACHESHAPE       36
+
+#define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */
+
+#endif /* __ASM_SH_AUXVEC_H */
diff --git a/arch/sh/include/uapi/asm/byteorder.h b/arch/sh/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..db2f5d7
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __ASM_SH_BYTEORDER_H
+#define __ASM_SH_BYTEORDER_H
+
+#ifdef __LITTLE_ENDIAN__
+#include <linux/byteorder/little_endian.h>
+#else
+#include <linux/byteorder/big_endian.h>
+#endif
+
+#endif /* __ASM_SH_BYTEORDER_H */
diff --git a/arch/sh/include/uapi/asm/cachectl.h b/arch/sh/include/uapi/asm/cachectl.h
new file mode 100644 (file)
index 0000000..6ffb4b7
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef _SH_CACHECTL_H
+#define _SH_CACHECTL_H
+
+/* Definitions for the cacheflush system call.  */
+
+#define CACHEFLUSH_D_INVAL     0x1     /* invalidate (without write back) */
+#define CACHEFLUSH_D_WB                0x2     /* write back (without invalidate) */
+#define CACHEFLUSH_D_PURGE     0x3     /* writeback and invalidate */
+
+#define CACHEFLUSH_I           0x4
+
+/*
+ * Options for cacheflush system call
+ */
+#define ICACHE CACHEFLUSH_I            /* flush instruction cache */
+#define DCACHE CACHEFLUSH_D_PURGE      /* writeback and flush data cache */
+#define BCACHE (ICACHE|DCACHE)         /* flush both caches */
+
+#endif /* _SH_CACHECTL_H */
diff --git a/arch/sh/include/uapi/asm/cpu-features.h b/arch/sh/include/uapi/asm/cpu-features.h
new file mode 100644 (file)
index 0000000..694abe4
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __ASM_SH_CPU_FEATURES_H
+#define __ASM_SH_CPU_FEATURES_H
+
+/*
+ * Processor flags
+ *
+ * Note: When adding a new flag, keep cpu_flags[] in
+ * arch/sh/kernel/setup.c in sync so symbolic name
+ * mapping of the processor flags has a chance of being
+ * reasonably accurate.
+ *
+ * These flags are also available through the ELF
+ * auxiliary vector as AT_HWCAP.
+ */
+#define CPU_HAS_FPU            0x0001  /* Hardware FPU support */
+#define CPU_HAS_P2_FLUSH_BUG   0x0002  /* Need to flush the cache in P2 area */
+#define CPU_HAS_MMU_PAGE_ASSOC 0x0004  /* SH3: TLB way selection bit support */
+#define CPU_HAS_DSP            0x0008  /* SH-DSP: DSP support */
+#define CPU_HAS_PERF_COUNTER   0x0010  /* Hardware performance counters */
+#define CPU_HAS_PTEA           0x0020  /* PTEA register */
+#define CPU_HAS_LLSC           0x0040  /* movli.l/movco.l */
+#define CPU_HAS_L2_CACHE       0x0080  /* Secondary cache / URAM */
+#define CPU_HAS_OP32           0x0100  /* 32-bit instruction support */
+#define CPU_HAS_PTEAEX         0x0200  /* PTE ASID Extension support */
+
+#endif /* __ASM_SH_CPU_FEATURES_H */
diff --git a/arch/sh/include/uapi/asm/hw_breakpoint.h b/arch/sh/include/uapi/asm/hw_breakpoint.h
new file mode 100644 (file)
index 0000000..ae5704f
--- /dev/null
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
diff --git a/arch/sh/include/uapi/asm/ioctls.h b/arch/sh/include/uapi/asm/ioctls.h
new file mode 100644 (file)
index 0000000..a6769f3
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef __ASM_SH_IOCTLS_H
+#define __ASM_SH_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+#define FIOCLEX                _IO('f', 1)
+#define FIONCLEX       _IO('f', 2)
+#define FIOASYNC       _IOW('f', 125, int)
+#define FIONBIO                _IOW('f', 126, int)
+#define FIONREAD       _IOR('f', 127, int)
+#define TIOCINQ                FIONREAD
+#define FIOQSIZE       _IOR('f', 128, loff_t)
+
+#define TCGETS         0x5401
+#define TCSETS         0x5402
+#define TCSETSW                0x5403
+#define TCSETSF                0x5404
+
+#define TCGETA         0x80127417      /* _IOR('t', 23, struct termio) */
+#define TCSETA         0x40127418      /* _IOW('t', 24, struct termio) */
+#define TCSETAW                0x40127419      /* _IOW('t', 25, struct termio) */
+#define TCSETAF                0x4012741C      /* _IOW('t', 28, struct termio) */
+
+#define TCSBRK         _IO('t', 29)
+#define TCXONC         _IO('t', 30)
+#define TCFLSH         _IO('t', 31)
+
+#define TIOCSWINSZ     0x40087467      /* _IOW('t', 103, struct winsize) */
+#define TIOCGWINSZ     0x80087468      /* _IOR('t', 104, struct winsize) */
+#define        TIOCSTART       _IO('t', 110)           /* start output, like ^Q */
+#define        TIOCSTOP        _IO('t', 111)           /* stop output, like ^S */
+#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
+
+#define TIOCSPGRP      _IOW('t', 118, int)
+#define TIOCGPGRP      _IOR('t', 119, int)
+
+#define TIOCEXCL       _IO('T', 12) /* 0x540C */
+#define TIOCNXCL       _IO('T', 13) /* 0x540D */
+#define TIOCSCTTY      _IO('T', 14) /* 0x540E */
+
+#define TIOCSTI                _IOW('T', 18, char) /* 0x5412 */
+#define TIOCMGET       _IOR('T', 21, unsigned int) /* 0x5415 */
+#define TIOCMBIS       _IOW('T', 22, unsigned int) /* 0x5416 */
+#define TIOCMBIC       _IOW('T', 23, unsigned int) /* 0x5417 */
+#define TIOCMSET       _IOW('T', 24, unsigned int) /* 0x5418 */
+# define TIOCM_LE      0x001
+# define TIOCM_DTR     0x002
+# define TIOCM_RTS     0x004
+# define TIOCM_ST      0x008
+# define TIOCM_SR      0x010
+# define TIOCM_CTS     0x020
+# define TIOCM_CAR     0x040
+# define TIOCM_RNG     0x080
+# define TIOCM_DSR     0x100
+# define TIOCM_CD      TIOCM_CAR
+# define TIOCM_RI      TIOCM_RNG
+
+#define TIOCGSOFTCAR   _IOR('T', 25, unsigned int) /* 0x5419 */
+#define TIOCSSOFTCAR   _IOW('T', 26, unsigned int) /* 0x541A */
+#define TIOCLINUX      _IOW('T', 28, char) /* 0x541C */
+#define TIOCCONS       _IO('T', 29) /* 0x541D */
+#define TIOCGSERIAL    0x803C541E      /* _IOR('T', 30, struct serial_struct) 0x541E */
+#define TIOCSSERIAL    0x403C541F      /* _IOW('T', 31, struct serial_struct) 0x541F */
+#define TIOCPKT                _IOW('T', 32, int) /* 0x5420 */
+# define TIOCPKT_DATA           0
+# define TIOCPKT_FLUSHREAD      1
+# define TIOCPKT_FLUSHWRITE     2
+# define TIOCPKT_STOP           4
+# define TIOCPKT_START          8
+# define TIOCPKT_NOSTOP                16
+# define TIOCPKT_DOSTOP                32
+# define TIOCPKT_IOCTL         64
+
+
+#define TIOCNOTTY      _IO('T', 34) /* 0x5422 */
+#define TIOCSETD       _IOW('T', 35, int) /* 0x5423 */
+#define TIOCGETD       _IOR('T', 36, int) /* 0x5424 */
+#define TCSBRKP                _IOW('T', 37, int) /* 0x5425 */ /* Needed for POSIX tcsendbreak() */
+#define TIOCSBRK       _IO('T', 39) /* 0x5427 */ /* BSD compatibility */
+#define TIOCCBRK       _IO('T', 40) /* 0x5428 */ /* BSD compatibility */
+#define TIOCGSID       _IOR('T', 41, pid_t) /* 0x5429 */ /* Return the session ID of FD */
+#define TCGETS2                _IOR('T', 42, struct termios2)
+#define TCSETS2                _IOW('T', 43, struct termios2)
+#define TCSETSW2       _IOW('T', 44, struct termios2)
+#define TCSETSF2       _IOW('T', 45, struct termios2)
+#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV       _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
+#define TIOCSIG                _IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP    _IO('T', 0x37)
+
+#define TIOCSERCONFIG  _IO('T', 83) /* 0x5453 */
+#define TIOCSERGWILD   _IOR('T', 84,  int) /* 0x5454 */
+#define TIOCSERSWILD   _IOW('T', 85,  int) /* 0x5455 */
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x80d85458      /* _IOR('T', 88, struct async_struct) 0x5458 */ /* For debugging only */
+#define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* 0x5459 */ /* Get line status register */
+  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TIOCSER_TEMT    0x01  /* Transmitter physically empty */
+#define TIOCSERGETMULTI 0x80A8545A     /* _IOR('T', 90, struct serial_multiport_struct) 0x545A */ /* Get multiport config */
+#define TIOCSERSETMULTI 0x40A8545B     /* _IOW('T', 91, struct serial_multiport_struct) 0x545B */ /* Set multiport config */
+
+#define TIOCMIWAIT     _IO('T', 92) /* 0x545C */       /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
+
+#endif /* __ASM_SH_IOCTLS_H */
diff --git a/arch/sh/include/uapi/asm/posix_types.h b/arch/sh/include/uapi/asm/posix_types.h
new file mode 100644 (file)
index 0000000..dc55e5a
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __KERNEL__
+# ifdef __SH5__
+#  include <asm/posix_types_64.h>
+# else
+#  include <asm/posix_types_32.h>
+# endif
+#endif /* __KERNEL__ */
diff --git a/arch/sh/include/uapi/asm/posix_types_32.h b/arch/sh/include/uapi/asm/posix_types_32.h
new file mode 100644 (file)
index 0000000..ba0bdc4
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef __ASM_SH_POSIX_TYPES_32_H
+#define __ASM_SH_POSIX_TYPES_32_H
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+typedef unsigned short __kernel_uid_t;
+#define __kernel_uid_t __kernel_uid_t
+typedef unsigned short __kernel_gid_t;
+#define __kernel_gid_t __kernel_gid_t
+
+typedef unsigned short __kernel_old_uid_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
+typedef unsigned short __kernel_old_gid_t;
+#define __kernel_old_gid_t __kernel_old_gid_t
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* __ASM_SH_POSIX_TYPES_32_H */
diff --git a/arch/sh/include/uapi/asm/posix_types_64.h b/arch/sh/include/uapi/asm/posix_types_64.h
new file mode 100644 (file)
index 0000000..244f7e9
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __ASM_SH_POSIX_TYPES_64_H
+#define __ASM_SH_POSIX_TYPES_64_H
+
+typedef unsigned short __kernel_mode_t;
+#define __kernel_mode_t __kernel_mode_t
+typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+typedef unsigned short __kernel_uid_t;
+#define __kernel_uid_t __kernel_uid_t
+typedef unsigned short __kernel_gid_t;
+#define __kernel_gid_t __kernel_gid_t
+typedef long unsigned int      __kernel_size_t;
+#define __kernel_size_t __kernel_size_t
+typedef int            __kernel_ssize_t;
+#define __kernel_ssize_t __kernel_ssize_t
+typedef int            __kernel_ptrdiff_t;
+#define __kernel_ptrdiff_t __kernel_ptrdiff_t
+
+typedef unsigned short __kernel_old_uid_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
+typedef unsigned short __kernel_old_gid_t;
+#define __kernel_old_gid_t __kernel_old_gid_t
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* __ASM_SH_POSIX_TYPES_64_H */
diff --git a/arch/sh/include/uapi/asm/ptrace.h b/arch/sh/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..8b8c5ac
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 1999, 2000  Niibe Yutaka
+ */
+#ifndef _UAPI__ASM_SH_PTRACE_H
+#define _UAPI__ASM_SH_PTRACE_H
+
+
+#define PTRACE_GETREGS         12      /* General registers */
+#define PTRACE_SETREGS         13
+
+#define PTRACE_GETFPREGS       14      /* FPU registers */
+#define PTRACE_SETFPREGS       15
+
+#define PTRACE_GETFDPIC                31      /* get the ELF fdpic loadmap address */
+
+#define PTRACE_GETFDPIC_EXEC   0       /* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP 1       /* [addr] request the interpreter loadmap */
+
+#define        PTRACE_GETDSPREGS       55      /* DSP registers */
+#define        PTRACE_SETDSPREGS       56
+
+#define PT_TEXT_END_ADDR       240
+#define PT_TEXT_ADDR           244     /* &(struct user)->start_code */
+#define PT_DATA_ADDR           248     /* &(struct user)->start_data */
+#define PT_TEXT_LEN            252
+
+#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
+#include <asm/ptrace_64.h>
+#else
+#include <asm/ptrace_32.h>
+#endif
+
+
+#endif /* _UAPI__ASM_SH_PTRACE_H */
diff --git a/arch/sh/include/uapi/asm/ptrace_32.h b/arch/sh/include/uapi/asm/ptrace_32.h
new file mode 100644 (file)
index 0000000..926e0ce
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef _UAPI__ASM_SH_PTRACE_32_H
+#define _UAPI__ASM_SH_PTRACE_32_H
+
+/*
+ * GCC defines register number like this:
+ * -----------------------------
+ *      0 - 15 are integer registers
+ *     17 - 22 are control/special registers
+ *     24 - 39 fp registers
+ *     40 - 47 xd registers
+ *     48 -    fpscr register
+ * -----------------------------
+ *
+ * We follows above, except:
+ *     16 --- program counter (PC)
+ *     22 --- syscall #
+ *     23 --- floating point communication register
+ */
+#define REG_REG0        0
+#define REG_REG15      15
+
+#define REG_PC         16
+
+#define REG_PR         17
+#define REG_SR         18
+#define REG_GBR                19
+#define REG_MACH       20
+#define REG_MACL       21
+
+#define REG_SYSCALL    22
+
+#define REG_FPREG0     23
+#define REG_FPREG15    38
+#define REG_XFREG0     39
+#define REG_XFREG15    54
+
+#define REG_FPSCR      55
+#define REG_FPUL       56
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+       unsigned long regs[16];
+       unsigned long pc;
+       unsigned long pr;
+       unsigned long sr;
+       unsigned long gbr;
+       unsigned long mach;
+       unsigned long macl;
+       long tra;
+};
+
+/*
+ * This struct defines the way the DSP registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_dspregs {
+       unsigned long   a1;
+       unsigned long   a0g;
+       unsigned long   a1g;
+       unsigned long   m0;
+       unsigned long   m1;
+       unsigned long   a0;
+       unsigned long   x0;
+       unsigned long   x1;
+       unsigned long   y0;
+       unsigned long   y1;
+       unsigned long   dsr;
+       unsigned long   rs;
+       unsigned long   re;
+       unsigned long   mod;
+};
+
+
+#endif /* _UAPI__ASM_SH_PTRACE_32_H */
diff --git a/arch/sh/include/uapi/asm/ptrace_64.h b/arch/sh/include/uapi/asm/ptrace_64.h
new file mode 100644 (file)
index 0000000..0e52ee8
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef _UAPI__ASM_SH_PTRACE_64_H
+#define _UAPI__ASM_SH_PTRACE_64_H
+
+struct pt_regs {
+       unsigned long long pc;
+       unsigned long long sr;
+       long long syscall_nr;
+       unsigned long long regs[63];
+       unsigned long long tregs[8];
+       unsigned long long pad[2];
+};
+
+
+#endif /* _UAPI__ASM_SH_PTRACE_64_H */
diff --git a/arch/sh/include/uapi/asm/setup.h b/arch/sh/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..552df83
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/setup.h>
diff --git a/arch/sh/include/uapi/asm/sigcontext.h b/arch/sh/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..8ce1435
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __ASM_SH_SIGCONTEXT_H
+#define __ASM_SH_SIGCONTEXT_H
+
+struct sigcontext {
+       unsigned long   oldmask;
+
+#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
+       /* CPU registers */
+       unsigned long long sc_regs[63];
+       unsigned long long sc_tregs[8];
+       unsigned long long sc_pc;
+       unsigned long long sc_sr;
+
+       /* FPU registers */
+       unsigned long long sc_fpregs[32];
+       unsigned int sc_fpscr;
+       unsigned int sc_fpvalid;
+#else
+       /* CPU registers */
+       unsigned long sc_regs[16];
+       unsigned long sc_pc;
+       unsigned long sc_pr;
+       unsigned long sc_sr;
+       unsigned long sc_gbr;
+       unsigned long sc_mach;
+       unsigned long sc_macl;
+
+#if defined(__SH4__) || defined(CONFIG_CPU_SH4) || \
+    defined(__SH2A__) || defined(CONFIG_CPU_SH2A)
+       /* FPU registers */
+       unsigned long sc_fpregs[16];
+       unsigned long sc_xfpregs[16];
+       unsigned int sc_fpscr;
+       unsigned int sc_fpul;
+       unsigned int sc_ownedfp;
+#endif
+#endif
+};
+
+#endif /* __ASM_SH_SIGCONTEXT_H */
diff --git a/arch/sh/include/uapi/asm/signal.h b/arch/sh/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..9ac530a
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __ASM_SH_SIGNAL_H
+#define __ASM_SH_SIGNAL_H
+
+#define SA_RESTORER    0x04000000
+
+#include <asm-generic/signal.h>
+
+struct old_sigaction {
+       __sighandler_t sa_handler;
+       old_sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#endif /* __ASM_SH_SIGNAL_H */
diff --git a/arch/sh/include/uapi/asm/sockios.h b/arch/sh/include/uapi/asm/sockios.h
new file mode 100644 (file)
index 0000000..cf8b96b
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __ASM_SH_SOCKIOS_H
+#define __ASM_SH_SOCKIOS_H
+
+/* Socket-level I/O control calls. */
+#define FIOGETOWN      _IOR('f', 123, int)
+#define FIOSETOWN      _IOW('f', 124, int)
+
+#define SIOCATMARK     _IOR('s', 7, int)
+#define SIOCSPGRP      _IOW('s', 8, pid_t)
+#define SIOCGPGRP      _IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP     _IOR('s', 100, struct timeval) /* Get stamp (timeval) */
+#define SIOCGSTAMPNS   _IOR('s', 101, struct timespec) /* Get stamp (timespec) */
+#endif /* __ASM_SH_SOCKIOS_H */
diff --git a/arch/sh/include/uapi/asm/stat.h b/arch/sh/include/uapi/asm/stat.h
new file mode 100644 (file)
index 0000000..e1810cc
--- /dev/null
@@ -0,0 +1,138 @@
+#ifndef __ASM_SH_STAT_H
+#define __ASM_SH_STAT_H
+
+struct __old_kernel_stat {
+       unsigned short st_dev;
+       unsigned short st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned long  st_size;
+       unsigned long  st_atime;
+       unsigned long  st_mtime;
+       unsigned long  st_ctime;
+};
+
+#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
+struct stat {
+       unsigned short st_dev;
+       unsigned short __pad1;
+       unsigned long st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned short st_rdev;
+       unsigned short __pad2;
+       unsigned long  st_size;
+       unsigned long  st_blksize;
+       unsigned long  st_blocks;
+       unsigned long  st_atime;
+       unsigned long  st_atime_nsec;
+       unsigned long  st_mtime;
+       unsigned long  st_mtime_nsec;
+       unsigned long  st_ctime;
+       unsigned long  st_ctime_nsec;
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+       unsigned short  st_dev;
+       unsigned char   __pad0[10];
+
+       unsigned long   st_ino;
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+
+       unsigned long   st_uid;
+       unsigned long   st_gid;
+
+       unsigned short  st_rdev;
+       unsigned char   __pad3[10];
+
+       long long       st_size;
+       unsigned long   st_blksize;
+
+       unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
+       unsigned long   __pad4;         /* future possible st_blocks high bits */
+
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+
+       unsigned long   st_mtime;
+       unsigned long   st_mtime_nsec;
+
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;  /* will be high 32 bits of ctime someday */
+
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+};
+#else
+struct stat {
+       unsigned long  st_dev;
+       unsigned long  st_ino;
+       unsigned short st_mode;
+       unsigned short st_nlink;
+       unsigned short st_uid;
+       unsigned short st_gid;
+       unsigned long  st_rdev;
+       unsigned long  st_size;
+       unsigned long  st_blksize;
+       unsigned long  st_blocks;
+       unsigned long  st_atime;
+       unsigned long  st_atime_nsec;
+       unsigned long  st_mtime;
+       unsigned long  st_mtime_nsec;
+       unsigned long  st_ctime;
+       unsigned long  st_ctime_nsec;
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+       unsigned long long      st_dev;
+       unsigned char   __pad0[4];
+
+#define STAT64_HAS_BROKEN_ST_INO       1
+       unsigned long   __st_ino;
+
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+
+       unsigned long   st_uid;
+       unsigned long   st_gid;
+
+       unsigned long long      st_rdev;
+       unsigned char   __pad3[4];
+
+       long long       st_size;
+       unsigned long   st_blksize;
+
+       unsigned long long      st_blocks;      /* Number 512-byte blocks allocated. */
+
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+
+       unsigned long   st_mtime;
+       unsigned long   st_mtime_nsec;
+
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;
+
+       unsigned long long      st_ino;
+};
+
+#define STAT_HAVE_NSEC 1
+#endif
+
+#endif /* __ASM_SH_STAT_H */
diff --git a/arch/sh/include/uapi/asm/swab.h b/arch/sh/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..1cd0976
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __ASM_SH_SWAB_H
+#define __ASM_SH_SWAB_H
+
+/*
+ * Copyright (C) 1999  Niibe Yutaka
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ */
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <asm-generic/swab.h>
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+       __asm__(
+#ifdef __SH5__
+               "byterev        %1, %0\n\t"
+               "shari          %0, 32, %0"
+#else
+               "swap.b         %1, %0\n\t"
+               "swap.w         %0, %0\n\t"
+               "swap.b         %0, %0"
+#endif
+               : "=r" (x)
+               : "r" (x));
+
+       return x;
+}
+#define __arch_swab32 __arch_swab32
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
+{
+       __asm__(
+#ifdef __SH5__
+               "byterev        %1, %0\n\t"
+               "shari          %0, 32, %0"
+#else
+               "swap.b         %1, %0"
+#endif
+               : "=r" (x)
+               :  "r" (x));
+
+       return x;
+}
+#define __arch_swab16 __arch_swab16
+
+static inline __u64 __arch_swab64(__u64 val)
+{
+       union {
+               struct { __u32 a,b; } s;
+               __u64 u;
+       } v, w;
+       v.u = val;
+       w.s.b = __arch_swab32(v.s.a);
+       w.s.a = __arch_swab32(v.s.b);
+       return w.u;
+}
+#define __arch_swab64 __arch_swab64
+
+#endif /* __ASM_SH_SWAB_H */
diff --git a/arch/sh/include/uapi/asm/types.h b/arch/sh/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..b9e79bc
--- /dev/null
@@ -0,0 +1 @@
+#include <asm-generic/types.h>
diff --git a/arch/sh/include/uapi/asm/unistd.h b/arch/sh/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..eeef88d
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __KERNEL__
+# ifdef __SH5__
+#  include <asm/unistd_64.h>
+# else
+#  include <asm/unistd_32.h>
+# endif
+#endif
diff --git a/arch/sh/include/uapi/asm/unistd_32.h b/arch/sh/include/uapi/asm/unistd_32.h
new file mode 100644 (file)
index 0000000..9e465f2
--- /dev/null
@@ -0,0 +1,385 @@
+#ifndef __ASM_SH_UNISTD_32_H
+#define __ASM_SH_UNISTD_32_H
+
+/*
+ * Copyright (C) 1999  Niibe Yutaka
+ */
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_restart_syscall     0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_lchown             16
+                                /* 17 was sys_break */
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+                                /* 31 was sys_stty */
+                                /* 32 was sys_gtty */
+#define __NR_access             33
+#define __NR_nice               34
+                                /* 35 was sys_ftime */
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+                                /* 44 was sys_prof */
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+                                /* 53 was sys_lock */
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+                                /* 56 was sys_mpx */
+#define __NR_setpgid            57
+                                /* 58 was sys_ulimit */
+                                /* 59 was sys_olduname */
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+                                /* 82 was sys_oldselect */
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+                                /* 98 was sys_profil */
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+                               /* 101 was sys_ioperm */
+#define __NR_socketcall                102
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+#define __NR_olduname          109
+                               /* 110 was sys_iopl */
+#define __NR_vhangup           111
+                               /* 112 was sys_idle */
+                               /* 113 was sys_vm86old */
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_cacheflush                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+                               /* 127 was sys_create_module */
+#define __NR_init_module       128
+#define __NR_delete_module     129
+                               /* 130 was sys_get_kernel_syms */
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+                               /* 137 was sys_afs_syscall */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+                               /* 166 was sys_vm86 */
+                               /* 167 was sys_query_module */
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread64           180
+#define __NR_pwrite64          181
+#define __NR_chown             182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+                               /* 188 reserved for sys_getpmsg */
+                               /* 189 reserved for sys_putpmsg */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_lchown32          198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_chown32           212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+#define __NR_mincore           218
+#define __NR_madvise           219
+#define __NR_getdents64                220
+#define __NR_fcntl64           221
+                               /* 222 is reserved for tux */
+                               /* 223 is unused */
+#define __NR_gettid            224
+#define __NR_readahead         225
+#define __NR_setxattr          226
+#define __NR_lsetxattr         227
+#define __NR_fsetxattr         228
+#define __NR_getxattr          229
+#define __NR_lgetxattr         230
+#define __NR_fgetxattr         231
+#define __NR_listxattr         232
+#define __NR_llistxattr                233
+#define __NR_flistxattr                234
+#define __NR_removexattr       235
+#define __NR_lremovexattr      236
+#define __NR_fremovexattr      237
+#define __NR_tkill             238
+#define __NR_sendfile64                239
+#define __NR_futex             240
+#define __NR_sched_setaffinity 241
+#define __NR_sched_getaffinity 242
+                               /* 243 is reserved for set_thread_area */
+                               /* 244 is reserved for get_thread_area */
+#define __NR_io_setup          245
+#define __NR_io_destroy                246
+#define __NR_io_getevents      247
+#define __NR_io_submit         248
+#define __NR_io_cancel         249
+#define __NR_fadvise64         250
+                               /* 251 is unused */
+#define __NR_exit_group                252
+#define __NR_lookup_dcookie    253
+#define __NR_epoll_create      254
+#define __NR_epoll_ctl         255
+#define __NR_epoll_wait                256
+#define __NR_remap_file_pages  257
+#define __NR_set_tid_address   258
+#define __NR_timer_create      259
+#define __NR_timer_settime     (__NR_timer_create+1)
+#define __NR_timer_gettime     (__NR_timer_create+2)
+#define __NR_timer_getoverrun  (__NR_timer_create+3)
+#define __NR_timer_delete      (__NR_timer_create+4)
+#define __NR_clock_settime     (__NR_timer_create+5)
+#define __NR_clock_gettime     (__NR_timer_create+6)
+#define __NR_clock_getres      (__NR_timer_create+7)
+#define __NR_clock_nanosleep   (__NR_timer_create+8)
+#define __NR_statfs64          268
+#define __NR_fstatfs64         269
+#define __NR_tgkill            270
+#define __NR_utimes            271
+#define __NR_fadvise64_64      272
+                               /* 273 is reserved for vserver */
+#define __NR_mbind              274
+#define __NR_get_mempolicy      275
+#define __NR_set_mempolicy      276
+#define __NR_mq_open            277
+#define __NR_mq_unlink          (__NR_mq_open+1)
+#define __NR_mq_timedsend       (__NR_mq_open+2)
+#define __NR_mq_timedreceive    (__NR_mq_open+3)
+#define __NR_mq_notify          (__NR_mq_open+4)
+#define __NR_mq_getsetattr      (__NR_mq_open+5)
+#define __NR_kexec_load                283
+#define __NR_waitid            284
+#define __NR_add_key           285
+#define __NR_request_key       286
+#define __NR_keyctl            287
+#define __NR_ioprio_set                288
+#define __NR_ioprio_get                289
+#define __NR_inotify_init      290
+#define __NR_inotify_add_watch 291
+#define __NR_inotify_rm_watch  292
+                               /* 293 is unused */
+#define __NR_migrate_pages     294
+#define __NR_openat            295
+#define __NR_mkdirat           296
+#define __NR_mknodat           297
+#define __NR_fchownat          298
+#define __NR_futimesat         299
+#define __NR_fstatat64         300
+#define __NR_unlinkat          301
+#define __NR_renameat          302
+#define __NR_linkat            303
+#define __NR_symlinkat         304
+#define __NR_readlinkat                305
+#define __NR_fchmodat          306
+#define __NR_faccessat         307
+#define __NR_pselect6          308
+#define __NR_ppoll             309
+#define __NR_unshare           310
+#define __NR_set_robust_list   311
+#define __NR_get_robust_list   312
+#define __NR_splice            313
+#define __NR_sync_file_range   314
+#define __NR_tee               315
+#define __NR_vmsplice          316
+#define __NR_move_pages                317
+#define __NR_getcpu            318
+#define __NR_epoll_pwait       319
+#define __NR_utimensat         320
+#define __NR_signalfd          321
+#define __NR_timerfd_create    322
+#define __NR_eventfd           323
+#define __NR_fallocate         324
+#define __NR_timerfd_settime   325
+#define __NR_timerfd_gettime   326
+#define __NR_signalfd4         327
+#define __NR_eventfd2          328
+#define __NR_epoll_create1     329
+#define __NR_dup3              330
+#define __NR_pipe2             331
+#define __NR_inotify_init1     332
+#define __NR_preadv            333
+#define __NR_pwritev           334
+#define __NR_rt_tgsigqueueinfo 335
+#define __NR_perf_event_open   336
+#define __NR_fanotify_init     337
+#define __NR_fanotify_mark     338
+#define __NR_prlimit64         339
+
+/* Non-multiplexed socket family */
+#define __NR_socket            340
+#define __NR_bind              341
+#define __NR_connect           342
+#define __NR_listen            343
+#define __NR_accept            344
+#define __NR_getsockname       345
+#define __NR_getpeername       346
+#define __NR_socketpair                347
+#define __NR_send              348
+#define __NR_sendto            349
+#define __NR_recv              350
+#define __NR_recvfrom          351
+#define __NR_shutdown          352
+#define __NR_setsockopt                353
+#define __NR_getsockopt                354
+#define __NR_sendmsg           355
+#define __NR_recvmsg           356
+#define __NR_recvmmsg          357
+#define __NR_accept4           358
+#define __NR_name_to_handle_at 359
+#define __NR_open_by_handle_at 360
+#define __NR_clock_adjtime     361
+#define __NR_syncfs            362
+#define __NR_sendmmsg          363
+#define __NR_setns             364
+#define __NR_process_vm_readv  365
+#define __NR_process_vm_writev 366
+#define __NR_kcmp              367
+
+#define NR_syscalls 368
+
+#endif /* __ASM_SH_UNISTD_32_H */
diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h
new file mode 100644 (file)
index 0000000..8e3a2ed
--- /dev/null
@@ -0,0 +1,405 @@
+#ifndef __ASM_SH_UNISTD_64_H
+#define __ASM_SH_UNISTD_64_H
+
+/*
+ * include/asm-sh/unistd_64.h
+ *
+ * This file contains the system call numbers.
+ *
+ * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2003 - 2007 Paul Mundt
+ * Copyright (C) 2004  Sean McGoogan
+ *
+ * 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.
+ */
+#define __NR_restart_syscall     0
+#define __NR_exit                1
+#define __NR_fork                2
+#define __NR_read                3
+#define __NR_write               4
+#define __NR_open                5
+#define __NR_close               6
+#define __NR_waitpid             7
+#define __NR_creat               8
+#define __NR_link                9
+#define __NR_unlink             10
+#define __NR_execve             11
+#define __NR_chdir              12
+#define __NR_time               13
+#define __NR_mknod              14
+#define __NR_chmod              15
+#define __NR_lchown             16
+                                /* 17 was sys_break */
+#define __NR_oldstat            18
+#define __NR_lseek              19
+#define __NR_getpid             20
+#define __NR_mount              21
+#define __NR_umount             22
+#define __NR_setuid             23
+#define __NR_getuid             24
+#define __NR_stime              25
+#define __NR_ptrace             26
+#define __NR_alarm              27
+#define __NR_oldfstat           28
+#define __NR_pause              29
+#define __NR_utime              30
+                                /* 31 was sys_stty */
+                                /* 32 was sys_gtty */
+#define __NR_access             33
+#define __NR_nice               34
+                                /* 35 was sys_ftime */
+#define __NR_sync               36
+#define __NR_kill               37
+#define __NR_rename             38
+#define __NR_mkdir              39
+#define __NR_rmdir              40
+#define __NR_dup                41
+#define __NR_pipe               42
+#define __NR_times              43
+                                /* 44 was sys_prof */
+#define __NR_brk                45
+#define __NR_setgid             46
+#define __NR_getgid             47
+#define __NR_signal             48
+#define __NR_geteuid            49
+#define __NR_getegid            50
+#define __NR_acct               51
+#define __NR_umount2            52
+                                /* 53 was sys_lock */
+#define __NR_ioctl              54
+#define __NR_fcntl              55
+                                /* 56 was sys_mpx */
+#define __NR_setpgid            57
+                                /* 58 was sys_ulimit */
+                                /* 59 was sys_olduname */
+#define __NR_umask              60
+#define __NR_chroot             61
+#define __NR_ustat              62
+#define __NR_dup2               63
+#define __NR_getppid            64
+#define __NR_getpgrp            65
+#define __NR_setsid             66
+#define __NR_sigaction          67
+#define __NR_sgetmask           68
+#define __NR_ssetmask           69
+#define __NR_setreuid           70
+#define __NR_setregid           71
+#define __NR_sigsuspend                 72
+#define __NR_sigpending                 73
+#define __NR_sethostname        74
+#define __NR_setrlimit          75
+#define __NR_getrlimit          76     /* Back compatible 2Gig limited rlimit */
+#define __NR_getrusage          77
+#define __NR_gettimeofday       78
+#define __NR_settimeofday       79
+#define __NR_getgroups          80
+#define __NR_setgroups          81
+                                /* 82 was sys_select */
+#define __NR_symlink            83
+#define __NR_oldlstat           84
+#define __NR_readlink           85
+#define __NR_uselib             86
+#define __NR_swapon             87
+#define __NR_reboot             88
+#define __NR_readdir            89
+#define __NR_mmap               90
+#define __NR_munmap             91
+#define __NR_truncate           92
+#define __NR_ftruncate          93
+#define __NR_fchmod             94
+#define __NR_fchown             95
+#define __NR_getpriority        96
+#define __NR_setpriority        97
+                                /* 98 was sys_profil */
+#define __NR_statfs             99
+#define __NR_fstatfs           100
+                               /* 101 was sys_ioperm */
+#define __NR_socketcall                102     /* old implementation of socket systemcall */
+#define __NR_syslog            103
+#define __NR_setitimer         104
+#define __NR_getitimer         105
+#define __NR_stat              106
+#define __NR_lstat             107
+#define __NR_fstat             108
+#define __NR_olduname          109
+                               /* 110 was sys_iopl */
+#define __NR_vhangup           111
+                               /* 112 was sys_idle */
+                               /* 113 was sys_vm86old */
+#define __NR_wait4             114
+#define __NR_swapoff           115
+#define __NR_sysinfo           116
+#define __NR_ipc               117
+#define __NR_fsync             118
+#define __NR_sigreturn         119
+#define __NR_clone             120
+#define __NR_setdomainname     121
+#define __NR_uname             122
+#define __NR_cacheflush                123
+#define __NR_adjtimex          124
+#define __NR_mprotect          125
+#define __NR_sigprocmask       126
+                               /* 127 was sys_create_module */
+#define __NR_init_module       128
+#define __NR_delete_module     129
+                               /* 130 was sys_get_kernel_syms */
+#define __NR_quotactl          131
+#define __NR_getpgid           132
+#define __NR_fchdir            133
+#define __NR_bdflush           134
+#define __NR_sysfs             135
+#define __NR_personality       136
+                               /* 137 was sys_afs_syscall */
+#define __NR_setfsuid          138
+#define __NR_setfsgid          139
+#define __NR__llseek           140
+#define __NR_getdents          141
+#define __NR__newselect                142
+#define __NR_flock             143
+#define __NR_msync             144
+#define __NR_readv             145
+#define __NR_writev            146
+#define __NR_getsid            147
+#define __NR_fdatasync         148
+#define __NR__sysctl           149
+#define __NR_mlock             150
+#define __NR_munlock           151
+#define __NR_mlockall          152
+#define __NR_munlockall                153
+#define __NR_sched_setparam            154
+#define __NR_sched_getparam            155
+#define __NR_sched_setscheduler                156
+#define __NR_sched_getscheduler                157
+#define __NR_sched_yield               158
+#define __NR_sched_get_priority_max    159
+#define __NR_sched_get_priority_min    160
+#define __NR_sched_rr_get_interval     161
+#define __NR_nanosleep         162
+#define __NR_mremap            163
+#define __NR_setresuid         164
+#define __NR_getresuid         165
+                               /* 166 was sys_vm86 */
+                               /* 167 was sys_query_module */
+#define __NR_poll              168
+#define __NR_nfsservctl                169
+#define __NR_setresgid         170
+#define __NR_getresgid         171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn      173
+#define __NR_rt_sigaction      174
+#define __NR_rt_sigprocmask    175
+#define __NR_rt_sigpending     176
+#define __NR_rt_sigtimedwait   177
+#define __NR_rt_sigqueueinfo   178
+#define __NR_rt_sigsuspend     179
+#define __NR_pread64           180
+#define __NR_pwrite64          181
+#define __NR_chown             182
+#define __NR_getcwd            183
+#define __NR_capget            184
+#define __NR_capset            185
+#define __NR_sigaltstack       186
+#define __NR_sendfile          187
+                               /* 188 reserved for getpmsg */
+                               /* 189 reserved for putpmsg */
+#define __NR_vfork             190
+#define __NR_ugetrlimit                191     /* SuS compliant getrlimit */
+#define __NR_mmap2             192
+#define __NR_truncate64                193
+#define __NR_ftruncate64       194
+#define __NR_stat64            195
+#define __NR_lstat64           196
+#define __NR_fstat64           197
+#define __NR_lchown32          198
+#define __NR_getuid32          199
+#define __NR_getgid32          200
+#define __NR_geteuid32         201
+#define __NR_getegid32         202
+#define __NR_setreuid32                203
+#define __NR_setregid32                204
+#define __NR_getgroups32       205
+#define __NR_setgroups32       206
+#define __NR_fchown32          207
+#define __NR_setresuid32       208
+#define __NR_getresuid32       209
+#define __NR_setresgid32       210
+#define __NR_getresgid32       211
+#define __NR_chown32           212
+#define __NR_setuid32          213
+#define __NR_setgid32          214
+#define __NR_setfsuid32                215
+#define __NR_setfsgid32                216
+#define __NR_pivot_root                217
+#define __NR_mincore           218
+#define __NR_madvise           219
+
+/* Non-multiplexed socket family */
+#define __NR_socket            220
+#define __NR_bind              221
+#define __NR_connect           222
+#define __NR_listen            223
+#define __NR_accept            224
+#define __NR_getsockname       225
+#define __NR_getpeername       226
+#define __NR_socketpair                227
+#define __NR_send              228
+#define __NR_sendto            229
+#define __NR_recv              230
+#define __NR_recvfrom          231
+#define __NR_shutdown          232
+#define __NR_setsockopt                233
+#define __NR_getsockopt                234
+#define __NR_sendmsg           235
+#define __NR_recvmsg           236
+
+/* Non-multiplexed IPC family */
+#define __NR_semop             237
+#define __NR_semget            238
+#define __NR_semctl            239
+#define __NR_msgsnd            240
+#define __NR_msgrcv            241
+#define __NR_msgget            242
+#define __NR_msgctl            243
+#define __NR_shmat             244
+#define __NR_shmdt             245
+#define __NR_shmget            246
+#define __NR_shmctl            247
+
+#define __NR_getdents64                248
+#define __NR_fcntl64           249
+                               /* 250 is reserved for tux */
+                               /* 251 is unused */
+#define __NR_gettid            252
+#define __NR_readahead         253
+#define __NR_setxattr          254
+#define __NR_lsetxattr         255
+#define __NR_fsetxattr         256
+#define __NR_getxattr          257
+#define __NR_lgetxattr         258
+#define __NR_fgetxattr         269
+#define __NR_listxattr         260
+#define __NR_llistxattr                261
+#define __NR_flistxattr                262
+#define __NR_removexattr       263
+#define __NR_lremovexattr      264
+#define __NR_fremovexattr      265
+#define __NR_tkill             266
+#define __NR_sendfile64                267
+#define __NR_futex             268
+#define __NR_sched_setaffinity 269
+#define __NR_sched_getaffinity 270
+                               /* 271 is reserved for set_thread_area */
+                               /* 272 is reserved for get_thread_area */
+#define __NR_io_setup          273
+#define __NR_io_destroy                274
+#define __NR_io_getevents      275
+#define __NR_io_submit         276
+#define __NR_io_cancel         277
+#define __NR_fadvise64         278
+                               /* 279 is unused */
+#define __NR_exit_group                280
+
+#define __NR_lookup_dcookie    281
+#define __NR_epoll_create      282
+#define __NR_epoll_ctl         283
+#define __NR_epoll_wait                284
+#define __NR_remap_file_pages  285
+#define __NR_set_tid_address   286
+#define __NR_timer_create      287
+#define __NR_timer_settime     (__NR_timer_create+1)
+#define __NR_timer_gettime     (__NR_timer_create+2)
+#define __NR_timer_getoverrun  (__NR_timer_create+3)
+#define __NR_timer_delete      (__NR_timer_create+4)
+#define __NR_clock_settime     (__NR_timer_create+5)
+#define __NR_clock_gettime     (__NR_timer_create+6)
+#define __NR_clock_getres      (__NR_timer_create+7)
+#define __NR_clock_nanosleep   (__NR_timer_create+8)
+#define __NR_statfs64          296
+#define __NR_fstatfs64         297
+#define __NR_tgkill            298
+#define __NR_utimes            299
+#define __NR_fadvise64_64      300
+                               /* 301 is reserved for vserver */
+                               /* 302 is reserved for mbind */
+                               /* 303 is reserved for get_mempolicy */
+                               /* 304 is reserved for set_mempolicy */
+#define __NR_mq_open            305
+#define __NR_mq_unlink          (__NR_mq_open+1)
+#define __NR_mq_timedsend       (__NR_mq_open+2)
+#define __NR_mq_timedreceive    (__NR_mq_open+3)
+#define __NR_mq_notify          (__NR_mq_open+4)
+#define __NR_mq_getsetattr      (__NR_mq_open+5)
+                               /* 311 is reserved for kexec */
+#define __NR_waitid            312
+#define __NR_add_key           313
+#define __NR_request_key       314
+#define __NR_keyctl            315
+#define __NR_ioprio_set                316
+#define __NR_ioprio_get                317
+#define __NR_inotify_init      318
+#define __NR_inotify_add_watch 319
+#define __NR_inotify_rm_watch  320
+                               /* 321 is unused */
+#define __NR_migrate_pages     322
+#define __NR_openat            323
+#define __NR_mkdirat           324
+#define __NR_mknodat           325
+#define __NR_fchownat          326
+#define __NR_futimesat         327
+#define __NR_fstatat64         328
+#define __NR_unlinkat          329
+#define __NR_renameat          330
+#define __NR_linkat            331
+#define __NR_symlinkat         332
+#define __NR_readlinkat                333
+#define __NR_fchmodat          334
+#define __NR_faccessat         335
+#define __NR_pselect6          336
+#define __NR_ppoll             337
+#define __NR_unshare           338
+#define __NR_set_robust_list   339
+#define __NR_get_robust_list   340
+#define __NR_splice            341
+#define __NR_sync_file_range   342
+#define __NR_tee               343
+#define __NR_vmsplice          344
+#define __NR_move_pages                345
+#define __NR_getcpu            346
+#define __NR_epoll_pwait       347
+#define __NR_utimensat         348
+#define __NR_signalfd          349
+#define __NR_timerfd_create    350
+#define __NR_eventfd           351
+#define __NR_fallocate         352
+#define __NR_timerfd_settime   353
+#define __NR_timerfd_gettime   354
+#define __NR_signalfd4         355
+#define __NR_eventfd2          356
+#define __NR_epoll_create1     357
+#define __NR_dup3              358
+#define __NR_pipe2             359
+#define __NR_inotify_init1     360
+#define __NR_preadv            361
+#define __NR_pwritev           362
+#define __NR_rt_tgsigqueueinfo 363
+#define __NR_perf_event_open   364
+#define __NR_recvmmsg          365
+#define __NR_accept4           366
+#define __NR_fanotify_init     367
+#define __NR_fanotify_mark     368
+#define __NR_prlimit64         369
+#define __NR_name_to_handle_at 370
+#define __NR_open_by_handle_at 371
+#define __NR_clock_adjtime     372
+#define __NR_syncfs            373
+#define __NR_sendmmsg          374
+#define __NR_setns             375
+#define __NR_process_vm_readv  376
+#define __NR_process_vm_writev 377
+#define __NR_kcmp              378
+
+#define NR_syscalls 379
+
+#endif /* __ASM_SH_UNISTD_64_H */
index 4b68f0f79761e404c5830d617547feae2806a712..fe97ae5e56f168e642e4825fc76575a8a61811b2 100644 (file)
@@ -384,3 +384,4 @@ ENTRY(sys_call_table)
        .long sys_setns
        .long sys_process_vm_readv      /* 365 */
        .long sys_process_vm_writev
+       .long sys_kcmp
index 0956345b36efecd9e6729180701aecf423979a86..5c7b1c67bdc1c04f9c858644c066063a7eaf6919 100644 (file)
@@ -404,3 +404,4 @@ sys_call_table:
        .long sys_setns                 /* 375 */
        .long sys_process_vm_readv
        .long sys_process_vm_writev
+       .long sys_kcmp
index b6b442b0d793daeff8caea90418458618a7ce506..9f2edb5c555179de8d00ee5d2031546df35f8a9d 100644 (file)
@@ -20,6 +20,7 @@ config SPARC
        select HAVE_ARCH_TRACEHOOK
        select SYSCTL_EXCEPTION_TRACE
        select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
        select RTC_CLASS
        select RTC_DRV_M48T59
        select HAVE_IRQ_WORK
index 6ae1ad5e502bda9de0833ebec5ee2d5758c5ceed..5d469d81761fcb039b44245b813d9f3a21310cad 100644 (file)
@@ -13,13 +13,13 @@ obj-$(CONFIG_CRYPTO_DES_SPARC64) += camellia-sparc64.o
 
 obj-$(CONFIG_CRYPTO_CRC32C_SPARC64) += crc32c-sparc64.o
 
-sha1-sparc64-y := sha1_asm.o sha1_glue.o crop_devid.o
-sha256-sparc64-y := sha256_asm.o sha256_glue.o crop_devid.o
-sha512-sparc64-y := sha512_asm.o sha512_glue.o crop_devid.o
-md5-sparc64-y := md5_asm.o md5_glue.o crop_devid.o
+sha1-sparc64-y := sha1_asm.o sha1_glue.o
+sha256-sparc64-y := sha256_asm.o sha256_glue.o
+sha512-sparc64-y := sha512_asm.o sha512_glue.o
+md5-sparc64-y := md5_asm.o md5_glue.o
 
-aes-sparc64-y := aes_asm.o aes_glue.o crop_devid.o
-des-sparc64-y := des_asm.o des_glue.o crop_devid.o
-camellia-sparc64-y := camellia_asm.o camellia_glue.o crop_devid.o
+aes-sparc64-y := aes_asm.o aes_glue.o
+des-sparc64-y := des_asm.o des_glue.o
+camellia-sparc64-y := camellia_asm.o camellia_glue.o
 
-crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o crop_devid.o
+crc32c-sparc64-y := crc32c_asm.o crc32c_glue.o
index 8f1c9980f63767254e2133f0218fc449754f3b0f..3965d1d36dfaa84e4634a7918bfdb9626f4bfe1a 100644 (file)
@@ -475,3 +475,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AES Secure Hash Algorithm, sparc64 aes opcode accelerated");
 
 MODULE_ALIAS("aes");
+
+#include "crop_devid.c"
index 42905c084299ebc962925cce691900bfd9fcad4a..62c89af3fd3fb3793a9dc0af63244fd94e7d808e 100644 (file)
@@ -320,3 +320,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
 
 MODULE_ALIAS("aes");
+
+#include "crop_devid.c"
index 0bd89cea8d8ed2798db52215b1d9810a07bf9cbc..5162fad912ce09faf6fcf5979e2ef60cadc03ba4 100644 (file)
@@ -177,3 +177,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("CRC32c (Castagnoli), sparc64 crc32c opcode accelerated");
 
 MODULE_ALIAS("crc32c");
+
+#include "crop_devid.c"
index c4940c2d307391dd47dbe04447ccc749b5b40962..41524cebcc49e4dfb48e0628efd67b9aa50619ac 100644 (file)
@@ -527,3 +527,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
 
 MODULE_ALIAS("des");
+
+#include "crop_devid.c"
index 603d723038ce2f6d909d2ff5d53a7d0a54197aa1..09a9ea1dfb697381a410cdaf043262d2e4e24898 100644 (file)
@@ -186,3 +186,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("MD5 Secure Hash Algorithm, sparc64 md5 opcode accelerated");
 
 MODULE_ALIAS("md5");
+
+#include "crop_devid.c"
index 2bbb20bee9f15c2404f1458a1815a901d3fb8828..6cd5f29e1e0d592050602afff567598d1062b713 100644 (file)
@@ -181,3 +181,5 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm, sparc64 sha1 opcode accelerated");
 
 MODULE_ALIAS("sha1");
+
+#include "crop_devid.c"
index 591e656bd891c4653ecf2c11d440eaf8f6a2593d..04f555ab268002d16ca0d1d1bf69e6e8829d4d04 100644 (file)
@@ -239,3 +239,5 @@ MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, sparc64 sha256 op
 
 MODULE_ALIAS("sha224");
 MODULE_ALIAS("sha256");
+
+#include "crop_devid.c"
index 486f0a2b7001fcda4d24edcfc5bea8ed78139080..f04d1994d19aa3acfc9286a82265a4a031b8ea5f 100644 (file)
@@ -224,3 +224,5 @@ MODULE_DESCRIPTION("SHA-384 and SHA-512 Secure Hash Algorithm, sparc64 sha512 op
 
 MODULE_ALIAS("sha384");
 MODULE_ALIAS("sha512");
+
+#include "crop_devid.c"
index ce35a1cf1a20b0b6f2ab7ae424c7ced8cc3da2f2..be56a244c9cf00de10e47b6d7933676791c8c4a8 100644 (file)
@@ -1,7 +1,7 @@
 /* atomic.h: Thankfully the V9 is at least reasonable for this
  *           stuff.
  *
- * Copyright (C) 1996, 1997, 2000 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1997, 2000, 2012 David S. Miller (davem@redhat.com)
  */
 
 #ifndef __ARCH_SPARC64_ATOMIC__
@@ -106,6 +106,8 @@ static inline long atomic64_add_unless(atomic64_t *v, long a, long u)
 
 #define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)
 
+extern long atomic64_dec_if_positive(atomic64_t *v);
+
 /* Atomic operations are already serializing */
 #define smp_mb__before_atomic_dec()    barrier()
 #define smp_mb__after_atomic_dec()     barrier()
index db3af0d30fb10129124c594d1f1195bb59f2a6f2..4e02086b839cf2146431265ce77dbb984840d33e 100644 (file)
@@ -1,6 +1,46 @@
 #ifndef _SPARC64_BACKOFF_H
 #define _SPARC64_BACKOFF_H
 
+/* The macros in this file implement an exponential backoff facility
+ * for atomic operations.
+ *
+ * When multiple threads compete on an atomic operation, it is
+ * possible for one thread to be continually denied a successful
+ * completion of the compare-and-swap instruction.  Heavily
+ * threaded cpu implementations like Niagara can compound this
+ * problem even further.
+ *
+ * When an atomic operation fails and needs to be retried, we spin a
+ * certain number of times.  At each subsequent failure of the same
+ * operation we double the spin count, realizing an exponential
+ * backoff.
+ *
+ * When we spin, we try to use an operation that will cause the
+ * current cpu strand to block, and therefore make the core fully
+ * available to any other other runnable strands.  There are two
+ * options, based upon cpu capabilities.
+ *
+ * On all cpus prior to SPARC-T4 we do three dummy reads of the
+ * condition code register.  Each read blocks the strand for something
+ * between 40 and 50 cpu cycles.
+ *
+ * For SPARC-T4 and later we have a special "pause" instruction
+ * available.  This is implemented using writes to register %asr27.
+ * The cpu will block the number of cycles written into the register,
+ * unless a disrupting trap happens first.  SPARC-T4 specifically
+ * implements pause with a granularity of 8 cycles.  Each strand has
+ * an internal pause counter which decrements every 8 cycles.  So the
+ * chip shifts the %asr27 value down by 3 bits, and writes the result
+ * into the pause counter.  If a value smaller than 8 is written, the
+ * chip blocks for 1 cycle.
+ *
+ * To achieve the same amount of backoff as the three %ccr reads give
+ * on earlier chips, we shift the backoff value up by 7 bits.  (Three
+ * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the
+ * whole amount we want to block into the pause register, rather than
+ * loop writing 128 each time.
+ */
+
 #define BACKOFF_LIMIT  (4 * 1024)
 
 #ifdef CONFIG_SMP
 #define BACKOFF_LABEL(spin_label, continue_label) \
        spin_label
 
-#define BACKOFF_SPIN(reg, tmp, label)  \
-       mov     reg, tmp; \
-88:    brnz,pt tmp, 88b; \
-        sub    tmp, 1, tmp; \
-       set     BACKOFF_LIMIT, tmp; \
-       cmp     reg, tmp; \
-       bg,pn   %xcc, label; \
-        nop; \
-       ba,pt   %xcc, label; \
-        sllx   reg, 1, reg;
+#define BACKOFF_SPIN(reg, tmp, label)          \
+       mov             reg, tmp;               \
+88:    rd              %ccr, %g0;              \
+       rd              %ccr, %g0;              \
+       rd              %ccr, %g0;              \
+       .section        .pause_3insn_patch,"ax";\
+       .word           88b;                    \
+       sllx            tmp, 7, tmp;            \
+       wr              tmp, 0, %asr27;         \
+       clr             tmp;                    \
+       .previous;                              \
+       brnz,pt         tmp, 88b;               \
+        sub            tmp, 1, tmp;            \
+       set             BACKOFF_LIMIT, tmp;     \
+       cmp             reg, tmp;               \
+       bg,pn           %xcc, label;            \
+        nop;                                   \
+       ba,pt           %xcc, label;            \
+        sllx           reg, 1, reg;
 
 #else
 
index cef99fbc0a214b80721029fd826d1733f066868e..830502fe62b4e6a3d334abaf4076a5957deb2d9c 100644 (file)
@@ -232,9 +232,10 @@ static inline void __user *arch_compat_alloc_user_space(long len)
        struct pt_regs *regs = current_thread_info()->kregs;
        unsigned long usp = regs->u_regs[UREG_I6];
 
-       if (!(test_thread_flag(TIF_32BIT)))
+       if (test_thread_64bit_stack(usp))
                usp += STACK_BIAS;
-       else
+
+       if (test_thread_flag(TIF_32BIT))
                usp &= 0xffffffffUL;
 
        usp -= len;
index 4e5a483122a043a7eeba9e42001d32cdf56c0015..721e25f0e2ea80f19d4a7868791d4653097a2124 100644 (file)
@@ -196,7 +196,22 @@ extern unsigned long get_wchan(struct task_struct *task);
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->tpc)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->u_regs[UREG_FP])
 
-#define cpu_relax()    barrier()
+/* Please see the commentary in asm/backoff.h for a description of
+ * what these instructions are doing and how they have been choosen.
+ * To make a long story short, we are trying to yield the current cpu
+ * strand during busy loops.
+ */
+#define cpu_relax()    asm volatile("\n99:\n\t"                        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    "rd        %%ccr, %%g0\n\t"        \
+                                    ".section  .pause_3insn_patch,\"ax\"\n\t"\
+                                    ".word     99b\n\t"                \
+                                    "wr        %%g0, 128, %%asr27\n\t" \
+                                    "nop\n\t"                          \
+                                    "nop\n\t"                          \
+                                    ".previous"                        \
+                                    ::: "memory")
 
 /* Prefetch support.  This is tuned for UltraSPARC-III and later.
  * UltraSPARC-I will treat these as nops, and UltraSPARC-II has
index c287651107069c58999381ba442bce84f2a6ed1f..67c62578d17043bbff42e1880f1f7e8986cb971c 100644 (file)
@@ -63,5 +63,13 @@ extern char *of_console_options;
 extern void irq_trans_init(struct device_node *dp);
 extern char *build_path_component(struct device_node *dp);
 
+/* SPARC has local implementations */
+extern int of_address_to_resource(struct device_node *dev, int index,
+                                 struct resource *r);
+#define of_address_to_resource of_address_to_resource
+
+void __iomem *of_iomap(struct device_node *node, int index);
+#define of_iomap of_iomap
+
 #endif /* __KERNEL__ */
 #endif /* _SPARC_PROM_H */
index 0c6f6b068289ad4e74f8ea563a6ccd569f6743f5..da43bdc622943bf422a396abba301148151f8f96 100644 (file)
@@ -42,7 +42,18 @@ struct global_reg_snapshot {
        struct thread_info      *thread;
        unsigned long           pad1;
 };
-extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
+
+struct global_pmu_snapshot {
+       unsigned long           pcr[4];
+       unsigned long           pic[4];
+};
+
+union global_cpu_snapshot {
+       struct global_reg_snapshot      reg;
+       struct global_pmu_snapshot      pmu;
+};
+
+extern union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
 
 #define force_successful_syscall_return()          \
 do {   current_thread_info()->syscall_noerror = 1; \
index 29862a9e906581d5fc58378db16c885992fcfa94..dd3bef4b9896c8921f2257cf5fab24399722495d 100644 (file)
@@ -48,6 +48,7 @@ extern void smp_fill_in_sib_core_maps(void);
 extern void cpu_play_dead(void);
 
 extern void smp_fetch_global_regs(void);
+extern void smp_fetch_global_pmu(void);
 
 struct seq_file;
 void smp_bogo(struct seq_file *);
@@ -65,6 +66,7 @@ extern void __cpu_die(unsigned int cpu);
 #define hard_smp_processor_id()                0
 #define smp_fill_in_sib_core_maps() do { } while (0)
 #define smp_fetch_global_regs() do { } while (0)
+#define smp_fetch_global_pmu() do { } while (0)
 
 #endif /* !(CONFIG_SMP) */
 
index 4e227663108181b45700b0cb879d5043ee1da64b..a3fe4dcc0aa6c5d25c7fa67ce3c74390b3a01876 100644 (file)
@@ -259,6 +259,11 @@ static inline bool test_and_clear_restore_sigmask(void)
 
 #define tsk_is_polling(t) test_tsk_thread_flag(t, TIF_POLLING_NRFLAG)
 
+#define thread32_stack_is_64bit(__SP) (((__SP) & 0x1) != 0)
+#define test_thread_64bit_stack(__SP) \
+       ((test_thread_flag(TIF_32BIT) && !thread32_stack_is_64bit(__SP)) ? \
+        false : true)
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 48f2807d326563da2bc95be4f870517685331aaf..71b5a67522abb2bb0d8457819612aa26e948fdc8 100644 (file)
@@ -372,7 +372,9 @@ etrap_spill_fixup_64bit:                            \
 
 /* Normal 32bit spill */
 #define SPILL_2_GENERIC(ASI)                           \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, (. - (128 + 4));                   \
+        srl    %sp, 0, %sp;                            \
        stwa    %l0, [%sp + %g0] ASI;                   \
        mov     0x04, %g3;                              \
        stwa    %l1, [%sp + %g3] ASI;                   \
@@ -398,14 +400,16 @@ etrap_spill_fixup_64bit:                          \
        stwa    %i6, [%g1 + %g0] ASI;                   \
        stwa    %i7, [%g1 + %g3] ASI;                   \
        saved;                                          \
-        retry; nop; nop;                               \
+        retry;                                         \
        b,a,pt  %xcc, spill_fixup_dax;                  \
        b,a,pt  %xcc, spill_fixup_mna;                  \
        b,a,pt  %xcc, spill_fixup;
 
 #define SPILL_2_GENERIC_ETRAP          \
 etrap_user_spill_32bit:                        \
-       srl     %sp, 0, %sp;            \
+       and     %sp, 1, %g3;            \
+       brnz,pn %g3, etrap_user_spill_64bit;    \
+        srl    %sp, 0, %sp;            \
        stwa    %l0, [%sp + 0x00] %asi; \
        stwa    %l1, [%sp + 0x04] %asi; \
        stwa    %l2, [%sp + 0x08] %asi; \
@@ -427,7 +431,7 @@ etrap_user_spill_32bit:                     \
        ba,pt   %xcc, etrap_save;       \
         wrpr   %g1, %cwp;              \
        nop; nop; nop; nop;             \
-       nop; nop; nop; nop;             \
+       nop; nop;                       \
        ba,a,pt %xcc, etrap_spill_fixup_32bit; \
        ba,a,pt %xcc, etrap_spill_fixup_32bit; \
        ba,a,pt %xcc, etrap_spill_fixup_32bit;
@@ -592,7 +596,9 @@ user_rtt_fill_64bit:                                        \
 
 /* Normal 32bit fill */
 #define FILL_2_GENERIC(ASI)                            \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, (. - (128 + 4));                   \
+        srl    %sp, 0, %sp;                            \
        lduwa   [%sp + %g0] ASI, %l0;                   \
        mov     0x04, %g2;                              \
        mov     0x08, %g3;                              \
@@ -616,14 +622,16 @@ user_rtt_fill_64bit:                                      \
        lduwa   [%g1 + %g3] ASI, %i6;                   \
        lduwa   [%g1 + %g5] ASI, %i7;                   \
        restored;                                       \
-       retry; nop; nop; nop; nop;                      \
+       retry; nop; nop;                                \
        b,a,pt  %xcc, fill_fixup_dax;                   \
        b,a,pt  %xcc, fill_fixup_mna;                   \
        b,a,pt  %xcc, fill_fixup;
 
 #define FILL_2_GENERIC_RTRAP                           \
 user_rtt_fill_32bit:                                   \
-       srl     %sp, 0, %sp;                            \
+       and     %sp, 1, %g3;                            \
+       brnz,pn %g3, user_rtt_fill_64bit;               \
+        srl    %sp, 0, %sp;                            \
        lduwa   [%sp + 0x00] %asi, %l0;                 \
        lduwa   [%sp + 0x04] %asi, %l1;                 \
        lduwa   [%sp + 0x08] %asi, %l2;                 \
@@ -643,7 +651,7 @@ user_rtt_fill_32bit:                                        \
        ba,pt   %xcc, user_rtt_pre_restore;             \
         restored;                                      \
        nop; nop; nop; nop; nop;                        \
-       nop; nop; nop; nop; nop;                        \
+       nop; nop; nop;                                  \
        ba,a,pt %xcc, user_rtt_fill_fixup;              \
        ba,a,pt %xcc, user_rtt_fill_fixup;              \
        ba,a,pt %xcc, user_rtt_fill_fixup;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ae5704fa77ad6d15e8de4623ca6465f24f2341b9 100644 (file)
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
index bea1568ae4af1aeee10008fbf1ae110dc6fa47ae..c83a937ead00676eefef950b6c00d77cd644c8a9 100644 (file)
@@ -41,6 +41,7 @@
 
 #define SO_ATTACH_FILTER       0x001a
 #define SO_DETACH_FILTER        0x001b
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            0x001c
 #define SO_TIMESTAMP           0x001d
index 8974ef7ae920685174f7d6427da816e4d3c7d3db..cac719d1bc5c6b8238ff0b6be5f34bc166980534 100644 (file)
 #define __NR_setns             337
 #define __NR_process_vm_readv  338
 #define __NR_process_vm_writev 339
+#define __NR_kern_features     340
+#define __NR_kcmp              341
 
-#define NR_syscalls            340
+#define NR_syscalls            342
+
+/* Bitmask values returned from kern_features system call.  */
+#define KERN_FEATURE_MIXED_MODE_STACK  0x00000001
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
index 0c218e4c0881fba70c1748e6a4c295e0db280652..cc3c5cb47cdaa4d18e14533f5078b2dbd5f51649 100644 (file)
@@ -59,6 +59,13 @@ struct popc_6insn_patch_entry {
 extern struct popc_6insn_patch_entry __popc_6insn_patch,
        __popc_6insn_patch_end;
 
+struct pause_patch_entry {
+       unsigned int    addr;
+       unsigned int    insns[3];
+};
+extern struct pause_patch_entry __pause_3insn_patch,
+       __pause_3insn_patch_end;
+
 extern void __init per_cpu_patch(void);
 extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
                                    struct sun4v_1insn_patch_entry *);
index f8b6eee40bde6596cdd9043e46aa9c9ef908fa4c..87f60ee6543394b4aea00d3d5e91082ef0b8a41f 100644 (file)
@@ -56,11 +56,13 @@ static inline unsigned int leon_eirq_get(int cpu)
 static void leon_handle_ext_irq(unsigned int irq, struct irq_desc *desc)
 {
        unsigned int eirq;
+       struct irq_bucket *p;
        int cpu = sparc_leon3_cpuid();
 
        eirq = leon_eirq_get(cpu);
-       if ((eirq & 0x10) && irq_map[eirq]->irq) /* bit4 tells if IRQ happened */
-               generic_handle_irq(irq_map[eirq]->irq);
+       p = irq_map[eirq];
+       if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */
+               generic_handle_irq(p->irq);
 }
 
 /* The extended IRQ controller has been found, this function registers it */
index e48651dace1bdca7812d285dd198f05e5068ab47..b5c38faa4eadf423db3bc20df35d2c98cd5dabf3 100644 (file)
@@ -817,15 +817,17 @@ static u64 nop_for_index(int idx)
 
 static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx)
 {
-       u64 val, mask = mask_for_index(idx);
+       u64 enc, val, mask = mask_for_index(idx);
        int pcr_index = 0;
 
        if (sparc_pmu->num_pcrs > 1)
                pcr_index = idx;
 
+       enc = perf_event_get_enc(cpuc->events[idx]);
+
        val = cpuc->pcr[pcr_index];
        val &= ~mask;
-       val |= hwc->config;
+       val |= event_encoding(enc, idx);
        cpuc->pcr[pcr_index] = val;
 
        pcr_ops->write_pcr(pcr_index, cpuc->pcr[pcr_index]);
@@ -1738,8 +1740,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
 {
        unsigned long ufp;
 
-       perf_callchain_store(entry, regs->tpc);
-
        ufp = regs->u_regs[UREG_I6] + STACK_BIAS;
        do {
                struct sparc_stackf *usf, sf;
@@ -1760,19 +1760,27 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
 {
        unsigned long ufp;
 
-       perf_callchain_store(entry, regs->tpc);
-
        ufp = regs->u_regs[UREG_I6] & 0xffffffffUL;
        do {
-               struct sparc_stackf32 *usf, sf;
                unsigned long pc;
 
-               usf = (struct sparc_stackf32 *) ufp;
-               if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
-                       break;
+               if (thread32_stack_is_64bit(ufp)) {
+                       struct sparc_stackf *usf, sf;
 
-               pc = sf.callers_pc;
-               ufp = (unsigned long)sf.fp;
+                       ufp += STACK_BIAS;
+                       usf = (struct sparc_stackf *) ufp;
+                       if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
+                               break;
+                       pc = sf.callers_pc & 0xffffffff;
+                       ufp = ((unsigned long) sf.fp) & 0xffffffff;
+               } else {
+                       struct sparc_stackf32 *usf, sf;
+                       usf = (struct sparc_stackf32 *) ufp;
+                       if (__copy_from_user_inatomic(&sf, usf, sizeof(sf)))
+                               break;
+                       pc = sf.callers_pc;
+                       ufp = (unsigned long)sf.fp;
+               }
                perf_callchain_store(entry, pc);
        } while (entry->nr < PERF_MAX_STACK_DEPTH);
 }
@@ -1780,6 +1788,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
 void
 perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 {
+       perf_callchain_store(entry, regs->tpc);
+
+       if (!current->mm)
+               return;
+
        flushw_user();
        if (test_thread_flag(TIF_32BIT))
                perf_callchain_user_32(entry, regs);
index fcaa59421126edf297d4e14dbbf2b90239d5d406..c6e0c2910043556a073ba8e8f11843f09d20ca71 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/tick.h>
 #include <linux/init.h>
 #include <linux/cpu.h>
+#include <linux/perf_event.h>
 #include <linux/elfcore.h>
 #include <linux/sysrq.h>
 #include <linux/nmi.h>
@@ -47,6 +48,7 @@
 #include <asm/syscalls.h>
 #include <asm/irq_regs.h>
 #include <asm/smp.h>
+#include <asm/pcr.h>
 
 #include "kstack.h"
 
@@ -204,18 +206,22 @@ void show_regs(struct pt_regs *regs)
        show_stack(current, (unsigned long *) regs->u_regs[UREG_FP]);
 }
 
-struct global_reg_snapshot global_reg_snapshot[NR_CPUS];
-static DEFINE_SPINLOCK(global_reg_snapshot_lock);
+union global_cpu_snapshot global_cpu_snapshot[NR_CPUS];
+static DEFINE_SPINLOCK(global_cpu_snapshot_lock);
 
 static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
                              int this_cpu)
 {
+       struct global_reg_snapshot *rp;
+
        flushw_all();
 
-       global_reg_snapshot[this_cpu].tstate = regs->tstate;
-       global_reg_snapshot[this_cpu].tpc = regs->tpc;
-       global_reg_snapshot[this_cpu].tnpc = regs->tnpc;
-       global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7];
+       rp = &global_cpu_snapshot[this_cpu].reg;
+
+       rp->tstate = regs->tstate;
+       rp->tpc = regs->tpc;
+       rp->tnpc = regs->tnpc;
+       rp->o7 = regs->u_regs[UREG_I7];
 
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *rw;
@@ -223,17 +229,17 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs,
                rw = (struct reg_window *)
                        (regs->u_regs[UREG_FP] + STACK_BIAS);
                if (kstack_valid(tp, (unsigned long) rw)) {
-                       global_reg_snapshot[this_cpu].i7 = rw->ins[7];
+                       rp->i7 = rw->ins[7];
                        rw = (struct reg_window *)
                                (rw->ins[6] + STACK_BIAS);
                        if (kstack_valid(tp, (unsigned long) rw))
-                               global_reg_snapshot[this_cpu].rpc = rw->ins[7];
+                               rp->rpc = rw->ins[7];
                }
        } else {
-               global_reg_snapshot[this_cpu].i7 = 0;
-               global_reg_snapshot[this_cpu].rpc = 0;
+               rp->i7 = 0;
+               rp->rpc = 0;
        }
-       global_reg_snapshot[this_cpu].thread = tp;
+       rp->thread = tp;
 }
 
 /* In order to avoid hangs we do not try to synchronize with the
@@ -261,9 +267,9 @@ void arch_trigger_all_cpu_backtrace(void)
        if (!regs)
                regs = tp->kregs;
 
-       spin_lock_irqsave(&global_reg_snapshot_lock, flags);
+       spin_lock_irqsave(&global_cpu_snapshot_lock, flags);
 
-       memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot));
+       memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
 
        this_cpu = raw_smp_processor_id();
 
@@ -272,7 +278,7 @@ void arch_trigger_all_cpu_backtrace(void)
        smp_fetch_global_regs();
 
        for_each_online_cpu(cpu) {
-               struct global_reg_snapshot *gp = &global_reg_snapshot[cpu];
+               struct global_reg_snapshot *gp = &global_cpu_snapshot[cpu].reg;
 
                __global_reg_poll(gp);
 
@@ -295,9 +301,9 @@ void arch_trigger_all_cpu_backtrace(void)
                }
        }
 
-       memset(global_reg_snapshot, 0, sizeof(global_reg_snapshot));
+       memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
 
-       spin_unlock_irqrestore(&global_reg_snapshot_lock, flags);
+       spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags);
 }
 
 #ifdef CONFIG_MAGIC_SYSRQ
@@ -309,16 +315,90 @@ static void sysrq_handle_globreg(int key)
 
 static struct sysrq_key_op sparc_globalreg_op = {
        .handler        = sysrq_handle_globreg,
-       .help_msg       = "Globalregs",
+       .help_msg       = "global-regs(Y)",
        .action_msg     = "Show Global CPU Regs",
 };
 
-static int __init sparc_globreg_init(void)
+static void __global_pmu_self(int this_cpu)
 {
-       return register_sysrq_key('y', &sparc_globalreg_op);
+       struct global_pmu_snapshot *pp;
+       int i, num;
+
+       pp = &global_cpu_snapshot[this_cpu].pmu;
+
+       num = 1;
+       if (tlb_type == hypervisor &&
+           sun4v_chip_type >= SUN4V_CHIP_NIAGARA4)
+               num = 4;
+
+       for (i = 0; i < num; i++) {
+               pp->pcr[i] = pcr_ops->read_pcr(i);
+               pp->pic[i] = pcr_ops->read_pic(i);
+       }
 }
 
-core_initcall(sparc_globreg_init);
+static void __global_pmu_poll(struct global_pmu_snapshot *pp)
+{
+       int limit = 0;
+
+       while (!pp->pcr[0] && ++limit < 100) {
+               barrier();
+               udelay(1);
+       }
+}
+
+static void pmu_snapshot_all_cpus(void)
+{
+       unsigned long flags;
+       int this_cpu, cpu;
+
+       spin_lock_irqsave(&global_cpu_snapshot_lock, flags);
+
+       memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
+
+       this_cpu = raw_smp_processor_id();
+
+       __global_pmu_self(this_cpu);
+
+       smp_fetch_global_pmu();
+
+       for_each_online_cpu(cpu) {
+               struct global_pmu_snapshot *pp = &global_cpu_snapshot[cpu].pmu;
+
+               __global_pmu_poll(pp);
+
+               printk("%c CPU[%3d]: PCR[%08lx:%08lx:%08lx:%08lx] PIC[%08lx:%08lx:%08lx:%08lx]\n",
+                      (cpu == this_cpu ? '*' : ' '), cpu,
+                      pp->pcr[0], pp->pcr[1], pp->pcr[2], pp->pcr[3],
+                      pp->pic[0], pp->pic[1], pp->pic[2], pp->pic[3]);
+       }
+
+       memset(global_cpu_snapshot, 0, sizeof(global_cpu_snapshot));
+
+       spin_unlock_irqrestore(&global_cpu_snapshot_lock, flags);
+}
+
+static void sysrq_handle_globpmu(int key)
+{
+       pmu_snapshot_all_cpus();
+}
+
+static struct sysrq_key_op sparc_globalpmu_op = {
+       .handler        = sysrq_handle_globpmu,
+       .help_msg       = "global-pmu(X)",
+       .action_msg     = "Show Global PMU Regs",
+};
+
+static int __init sparc_sysrq_init(void)
+{
+       int ret = register_sysrq_key('y', &sparc_globalreg_op);
+
+       if (!ret)
+               ret = register_sysrq_key('x', &sparc_globalpmu_op);
+       return ret;
+}
+
+core_initcall(sparc_sysrq_init);
 
 #endif
 
@@ -372,13 +452,16 @@ void flush_thread(void)
 /* It's a bit more tricky when 64-bit tasks are involved... */
 static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
 {
+       bool stack_64bit = test_thread_64bit_stack(psp);
        unsigned long fp, distance, rval;
 
-       if (!(test_thread_flag(TIF_32BIT))) {
+       if (stack_64bit) {
                csp += STACK_BIAS;
                psp += STACK_BIAS;
                __get_user(fp, &(((struct reg_window __user *)psp)->ins[6]));
                fp += STACK_BIAS;
+               if (test_thread_flag(TIF_32BIT))
+                       fp &= 0xffffffff;
        } else
                __get_user(fp, &(((struct reg_window32 __user *)psp)->ins[6]));
 
@@ -392,7 +475,7 @@ static unsigned long clone_stackframe(unsigned long csp, unsigned long psp)
        rval = (csp - distance);
        if (copy_in_user((void __user *) rval, (void __user *) psp, distance))
                rval = 0;
-       else if (test_thread_flag(TIF_32BIT)) {
+       else if (!stack_64bit) {
                if (put_user(((u32)csp),
                             &(((struct reg_window32 __user *)rval)->ins[6])))
                        rval = 0;
@@ -427,18 +510,18 @@ void synchronize_user_stack(void)
 
        flush_user_windows();
        if ((window = get_thread_wsaved()) != 0) {
-               int winsize = sizeof(struct reg_window);
-               int bias = 0;
-
-               if (test_thread_flag(TIF_32BIT))
-                       winsize = sizeof(struct reg_window32);
-               else
-                       bias = STACK_BIAS;
-
                window -= 1;
                do {
-                       unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
                        struct reg_window *rwin = &t->reg_window[window];
+                       int winsize = sizeof(struct reg_window);
+                       unsigned long sp;
+
+                       sp = t->rwbuf_stkptrs[window];
+
+                       if (test_thread_64bit_stack(sp))
+                               sp += STACK_BIAS;
+                       else
+                               winsize = sizeof(struct reg_window32);
 
                        if (!copy_to_user((char __user *)sp, rwin, winsize)) {
                                shift_window_buffer(window, get_thread_wsaved() - 1, t);
@@ -464,13 +547,6 @@ void fault_in_user_windows(void)
 {
        struct thread_info *t = current_thread_info();
        unsigned long window;
-       int winsize = sizeof(struct reg_window);
-       int bias = 0;
-
-       if (test_thread_flag(TIF_32BIT))
-               winsize = sizeof(struct reg_window32);
-       else
-               bias = STACK_BIAS;
 
        flush_user_windows();
        window = get_thread_wsaved();
@@ -478,8 +554,16 @@ void fault_in_user_windows(void)
        if (likely(window != 0)) {
                window -= 1;
                do {
-                       unsigned long sp = (t->rwbuf_stkptrs[window] + bias);
                        struct reg_window *rwin = &t->reg_window[window];
+                       int winsize = sizeof(struct reg_window);
+                       unsigned long sp;
+
+                       sp = t->rwbuf_stkptrs[window];
+
+                       if (test_thread_64bit_stack(sp))
+                               sp += STACK_BIAS;
+                       else
+                               winsize = sizeof(struct reg_window32);
 
                        if (unlikely(sp & 0x7UL))
                                stack_unaligned(sp);
index 484dabac7045aa2177df26f625ffabf9f6f523c7..7ff45e4ba6815080a29e02a64ad79bfdf9c1ed12 100644 (file)
@@ -151,7 +151,7 @@ static int regwindow64_get(struct task_struct *target,
 {
        unsigned long rw_addr = regs->u_regs[UREG_I6];
 
-       if (test_tsk_thread_flag(current, TIF_32BIT)) {
+       if (!test_thread_64bit_stack(rw_addr)) {
                struct reg_window32 win32;
                int i;
 
@@ -176,7 +176,7 @@ static int regwindow64_set(struct task_struct *target,
 {
        unsigned long rw_addr = regs->u_regs[UREG_I6];
 
-       if (test_tsk_thread_flag(current, TIF_32BIT)) {
+       if (!test_thread_64bit_stack(rw_addr)) {
                struct reg_window32 win32;
                int i;
 
index 0800e71d8a880242083688b385e88d564e4a681a..0eaf0059aaefa483bdbb228bf38c8154a7d9656b 100644 (file)
@@ -316,6 +316,25 @@ static void __init popc_patch(void)
        }
 }
 
+static void __init pause_patch(void)
+{
+       struct pause_patch_entry *p;
+
+       p = &__pause_3insn_patch;
+       while (p < &__pause_3insn_patch_end) {
+               unsigned long i, addr = p->addr;
+
+               for (i = 0; i < 3; i++) {
+                       *(unsigned int *) (addr +  (i * 4)) = p->insns[i];
+                       wmb();
+                       __asm__ __volatile__("flush     %0"
+                                            : : "r" (addr +  (i * 4)));
+               }
+
+               p++;
+       }
+}
+
 #ifdef CONFIG_SMP
 void __init boot_cpu_id_too_large(int cpu)
 {
@@ -528,6 +547,8 @@ static void __init init_sparc64_elf_hwcap(void)
 
        if (sparc64_elf_hwcap & AV_SPARC_POPC)
                popc_patch();
+       if (sparc64_elf_hwcap & AV_SPARC_PAUSE)
+               pause_patch();
 }
 
 void __init setup_arch(char **cmdline_p)
index 867de2f8189c32acf359fe5575cd139ede6b7048..689e1ba628097e12ab95496d60df2225817483d3 100644 (file)
@@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
                err |= restore_fpu_state(regs, fpu_save);
 
        err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
-       err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
-
-       if (err)
+       if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT)
                goto segv;
 
        err |= __get_user(rwin_save, &sf->rwin_save);
index 781bcb10b8bd6f0ac34e1df6cf079dd0d3d59106..d94b878577b7ea34bd674c50ab2817be7d2d93db 100644 (file)
@@ -852,6 +852,8 @@ extern unsigned long xcall_flush_tlb_mm;
 extern unsigned long xcall_flush_tlb_pending;
 extern unsigned long xcall_flush_tlb_kernel_range;
 extern unsigned long xcall_fetch_glob_regs;
+extern unsigned long xcall_fetch_glob_pmu;
+extern unsigned long xcall_fetch_glob_pmu_n4;
 extern unsigned long xcall_receive_signal;
 extern unsigned long xcall_new_mmu_context_version;
 #ifdef CONFIG_KGDB
@@ -1000,6 +1002,15 @@ void smp_fetch_global_regs(void)
        smp_cross_call(&xcall_fetch_glob_regs, 0, 0, 0);
 }
 
+void smp_fetch_global_pmu(void)
+{
+       if (tlb_type == hypervisor &&
+           sun4v_chip_type >= SUN4V_CHIP_NIAGARA4)
+               smp_cross_call(&xcall_fetch_glob_pmu_n4, 0, 0, 0);
+       else
+               smp_cross_call(&xcall_fetch_glob_pmu, 0, 0, 0);
+}
+
 /* We know that the window frames of the user have been flushed
  * to the stack before we get here because all callers of us
  * are flush_tlb_*() routines, and these run after flush_cache_*()
index 11c6c9603e71f03995a3c17fcdf2f28957d7fa43..878ef3d5fec522d6b23d0640df962f33c2b958df 100644 (file)
@@ -751,3 +751,8 @@ int kernel_execve(const char *filename,
                      : "cc");
        return __res;
 }
+
+asmlinkage long sys_kern_features(void)
+{
+       return KERN_FEATURE_MIXED_MODE_STACK;
+}
index 63402f9e9f51f75622f9132e0b8f5372bcc806c1..5147f574f1256a7f3304a716da22bfb2ef68d42a 100644 (file)
@@ -85,3 +85,4 @@ sys_call_table:
 /*325*/        .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 /*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
+/*340*/        .long sys_ni_syscall, sys_kcmp
index 3a58e0d66f51b0144ef5f9ca970bfbbbb9d01ed6..1c9af9fa38e9b0b489cb38899685e4c4c76b6584 100644 (file)
@@ -86,6 +86,7 @@ sys_call_table32:
        .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
        .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
+/*340*/        .word sys_kern_features, sys_kcmp
 
 #endif /* CONFIG_COMPAT */
 
@@ -163,3 +164,4 @@ sys_call_table:
        .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
        .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
+/*340*/        .word sys_kern_features, sys_kcmp
index f81d038f7340ce6b80cb65e0e27b2e7f2cb9edd2..8201c25e76697ad5f5a96de1b6921a3fb34372ac 100644 (file)
@@ -113,21 +113,24 @@ static inline long sign_extend_imm13(long imm)
 
 static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 {
-       unsigned long value;
+       unsigned long value, fp;
        
        if (reg < 16)
                return (!reg ? 0 : regs->u_regs[reg]);
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                value = win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                get_user(value, &win32->locals[reg - 16]);
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                get_user(value, &win->locals[reg - 16]);
        }
        return value;
@@ -135,19 +138,24 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 
 static unsigned long *fetch_reg_addr(unsigned int reg, struct pt_regs *regs)
 {
+       unsigned long fp;
+
        if (reg < 16)
                return &regs->u_regs[reg];
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 *win32;
-               win32 = (struct reg_window32 *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 *)((unsigned long)((u32)fp));
                return (unsigned long *)&win32->locals[reg - 16];
        } else {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
        }
 }
@@ -392,13 +400,15 @@ int handle_popc(u32 insn, struct pt_regs *regs)
                if (rd)
                        regs->u_regs[rd] = ret;
        } else {
-               if (test_thread_flag(TIF_32BIT)) {
+               unsigned long fp = regs->u_regs[UREG_FP];
+
+               if (!test_thread_64bit_stack(fp)) {
                        struct reg_window32 __user *win32;
-                       win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+                       win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                        put_user(ret, &win32->locals[rd - 16]);
                } else {
                        struct reg_window __user *win;
-                       win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+                       win = (struct reg_window __user *)(fp + STACK_BIAS);
                        put_user(ret, &win->locals[rd - 16]);
                }
        }
@@ -554,7 +564,7 @@ void handle_ld_nf(u32 insn, struct pt_regs *regs)
                reg[0] = 0;
                if ((insn & 0x780000) == 0x180000)
                        reg[1] = 0;
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
                put_user(0, (int __user *) reg);
                if ((insn & 0x780000) == 0x180000)
                        put_user(0, ((int __user *) reg) + 1);
index 08e074b7eb6a025e985700e0bf2443ef30fcb1d2..c096c624ac4d44ad6bd723b4bce88510dcdf70f5 100644 (file)
@@ -149,21 +149,24 @@ static inline void maybe_flush_windows(unsigned int rs1, unsigned int rs2,
 
 static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 {
-       unsigned long value;
+       unsigned long value, fp;
        
        if (reg < 16)
                return (!reg ? 0 : regs->u_regs[reg]);
+
+       fp = regs->u_regs[UREG_FP];
+
        if (regs->tstate & TSTATE_PRIV) {
                struct reg_window *win;
-               win = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window *)(fp + STACK_BIAS);
                value = win->locals[reg - 16];
-       } else if (test_thread_flag(TIF_32BIT)) {
+       } else if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                get_user(value, &win32->locals[reg - 16]);
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                get_user(value, &win->locals[reg - 16]);
        }
        return value;
@@ -172,16 +175,18 @@ static unsigned long fetch_reg(unsigned int reg, struct pt_regs *regs)
 static inline unsigned long __user *__fetch_reg_addr_user(unsigned int reg,
                                                          struct pt_regs *regs)
 {
+       unsigned long fp = regs->u_regs[UREG_FP];
+
        BUG_ON(reg < 16);
        BUG_ON(regs->tstate & TSTATE_PRIV);
 
-       if (test_thread_flag(TIF_32BIT)) {
+       if (!test_thread_64bit_stack(fp)) {
                struct reg_window32 __user *win32;
-               win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
+               win32 = (struct reg_window32 __user *)((unsigned long)((u32)fp));
                return (unsigned long __user *)&win32->locals[reg - 16];
        } else {
                struct reg_window __user *win;
-               win = (struct reg_window __user *)(regs->u_regs[UREG_FP] + STACK_BIAS);
+               win = (struct reg_window __user *)(fp + STACK_BIAS);
                return &win->locals[reg - 16];
        }
 }
@@ -204,7 +209,7 @@ static void store_reg(struct pt_regs *regs, unsigned long val, unsigned long rd)
        } else {
                unsigned long __user *rd_user = __fetch_reg_addr_user(rd, regs);
 
-               if (test_thread_flag(TIF_32BIT))
+               if (!test_thread_64bit_stack(regs->u_regs[UREG_FP]))
                        __put_user((u32)val, (u32 __user *)rd_user);
                else
                        __put_user(val, rd_user);
index 89c2c29f154b4c45114df0dce93feee4ce8330af..0bacceb19150ebff3a9e9088b11b66d8f5d4490b 100644 (file)
@@ -132,6 +132,11 @@ SECTIONS
                *(.popc_6insn_patch)
                __popc_6insn_patch_end = .;
        }
+       .pause_3insn_patch : {
+               __pause_3insn_patch = .;
+               *(.pause_3insn_patch)
+               __pause_3insn_patch_end = .;
+       }
        PERCPU_SECTION(SMP_CACHE_BYTES)
 
        . = ALIGN(PAGE_SIZE);
index a6b0863c27df48e12bfa656a83783fee6ecfa05c..1e67ce95836972d439b50c88aa77d8395a543652 100644 (file)
@@ -43,6 +43,8 @@ spill_fixup_mna:
 spill_fixup_dax:
        TRAP_LOAD_THREAD_REG(%g6, %g1)
        ldx     [%g6 + TI_FLAGS], %g1
+       andcc   %sp, 0x1, %g0
+       movne   %icc, 0, %g1
        andcc   %g1, _TIF_32BIT, %g0
        ldub    [%g6 + TI_WSAVED], %g1
        sll     %g1, 3, %g3
index 4d502da3de78f2c9e3987a8b7f2ab0f807879201..85c233d0a34003d551587c7c378bd813f64712fe 100644 (file)
@@ -1,6 +1,6 @@
 /* atomic.S: These things are too big to do inline.
  *
- * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1999, 2007 2012 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/linkage.h>
@@ -117,3 +117,17 @@ ENTRY(atomic64_sub_ret) /* %o0 = decrement, %o1 = atomic_ptr */
         sub    %g1, %o0, %o0
 2:     BACKOFF_SPIN(%o2, %o3, 1b)
 ENDPROC(atomic64_sub_ret)
+
+ENTRY(atomic64_dec_if_positive) /* %o0 = atomic_ptr */
+       BACKOFF_SETUP(%o2)
+1:     ldx     [%o0], %g1
+       brlez,pn %g1, 3f
+        sub    %g1, 1, %g7
+       casx    [%o0], %g1, %g7
+       cmp     %g1, %g7
+       bne,pn  %xcc, BACKOFF_LABEL(2f, 1b)
+        nop
+3:     retl
+        sub    %g1, 1, %o0
+2:     BACKOFF_SPIN(%o2, %o3, 1b)
+ENDPROC(atomic64_dec_if_positive)
index ee31b884c61b8390fa6a97e5d619ac4d1febe8cd..0c4e35e522fa0f5b719167cb90863e1343057968 100644 (file)
@@ -116,6 +116,7 @@ EXPORT_SYMBOL(atomic64_add);
 EXPORT_SYMBOL(atomic64_add_ret);
 EXPORT_SYMBOL(atomic64_sub);
 EXPORT_SYMBOL(atomic64_sub_ret);
+EXPORT_SYMBOL(atomic64_dec_if_positive);
 
 /* Atomic bit operations. */
 EXPORT_SYMBOL(test_and_set_bit);
index 1704068da92806d5868d0374bea669f31f21b113..034aadbff036fd617c8cae7afbcac20eee0ecaf8 100644 (file)
@@ -320,7 +320,7 @@ int do_mathemu(struct pt_regs *regs, struct fpustate *f, bool illegal_insn_trap)
                                        XR = 0;
                                else if (freg < 16)
                                        XR = regs->u_regs[freg];
-                               else if (test_thread_flag(TIF_32BIT)) {
+                               else if (!test_thread_64bit_stack(regs->u_regs[UREG_FP])) {
                                        struct reg_window32 __user *win32;
                                        flushw_user ();
                                        win32 = (struct reg_window32 __user *)((unsigned long)((u32)regs->u_regs[UREG_FP]));
index 874162a11ceb824eb9e1af311c81be052a934927..f8e13d421fcbf415dd49a50bc2ed4aaf2b3b6494 100644 (file)
@@ -481,8 +481,8 @@ xcall_sync_tick:
 
        .globl          xcall_fetch_glob_regs
 xcall_fetch_glob_regs:
-       sethi           %hi(global_reg_snapshot), %g1
-       or              %g1, %lo(global_reg_snapshot), %g1
+       sethi           %hi(global_cpu_snapshot), %g1
+       or              %g1, %lo(global_cpu_snapshot), %g1
        __GET_CPUID(%g2)
        sllx            %g2, 6, %g3
        add             %g1, %g3, %g1
@@ -509,6 +509,66 @@ xcall_fetch_glob_regs:
        stx             %g3, [%g1 + GR_SNAP_THREAD]
        retry
 
+       .globl          xcall_fetch_glob_pmu
+xcall_fetch_glob_pmu:
+       sethi           %hi(global_cpu_snapshot), %g1
+       or              %g1, %lo(global_cpu_snapshot), %g1
+       __GET_CPUID(%g2)
+       sllx            %g2, 6, %g3
+       add             %g1, %g3, %g1
+       rd              %pic, %g7
+       stx             %g7, [%g1 + (4 * 8)]
+       rd              %pcr, %g7
+       stx             %g7, [%g1 + (0 * 8)]
+       retry
+
+       .globl          xcall_fetch_glob_pmu_n4
+xcall_fetch_glob_pmu_n4:
+       sethi           %hi(global_cpu_snapshot), %g1
+       or              %g1, %lo(global_cpu_snapshot), %g1
+       __GET_CPUID(%g2)
+       sllx            %g2, 6, %g3
+       add             %g1, %g3, %g1
+
+       ldxa            [%g0] ASI_PIC, %g7
+       stx             %g7, [%g1 + (4 * 8)]
+       mov             0x08, %g3
+       ldxa            [%g3] ASI_PIC, %g7
+       stx             %g7, [%g1 + (5 * 8)]
+       mov             0x10, %g3
+       ldxa            [%g3] ASI_PIC, %g7
+       stx             %g7, [%g1 + (6 * 8)]
+       mov             0x18, %g3
+       ldxa            [%g3] ASI_PIC, %g7
+       stx             %g7, [%g1 + (7 * 8)]
+
+       mov             %o0, %g2
+       mov             %o1, %g3
+       mov             %o5, %g7
+
+       mov             HV_FAST_VT_GET_PERFREG, %o5
+       mov             3, %o0
+       ta              HV_FAST_TRAP
+       stx             %o1, [%g1 + (3 * 8)]
+       mov             HV_FAST_VT_GET_PERFREG, %o5
+       mov             2, %o0
+       ta              HV_FAST_TRAP
+       stx             %o1, [%g1 + (2 * 8)]
+       mov             HV_FAST_VT_GET_PERFREG, %o5
+       mov             1, %o0
+       ta              HV_FAST_TRAP
+       stx             %o1, [%g1 + (1 * 8)]
+       mov             HV_FAST_VT_GET_PERFREG, %o5
+       mov             0, %o0
+       ta              HV_FAST_TRAP
+       stx             %o1, [%g1 + (0 * 8)]
+
+       mov             %g2, %o0
+       mov             %g3, %o1
+       mov             %g7, %o5
+
+       retry
+
 #ifdef DCACHE_ALIASING_POSSIBLE
        .align          32
        .globl          xcall_flush_dcache_page_cheetah
index 28368701ef796ff5c4268398264cdfb504a0be84..3109ca684a99f31c3a52613e3ffd2f291d6f185d 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/netdevice.h>
 #include <linux/filter.h>
 #include <linux/cache.h>
+#include <linux/if_vlan.h>
 
 #include <asm/cacheflush.h>
 #include <asm/ptrace.h>
@@ -312,6 +313,12 @@ do {       *prog++ = BR_OPC | WDISP22(OFF);                \
 #define emit_addi(R1, IMM, R3) \
        *prog++ = (ADD | IMMED | RS1(R1) | S13(IMM) | RD(R3))
 
+#define emit_and(R1, R2, R3) \
+       *prog++ = (AND | RS1(R1) | RS2(R2) | RD(R3))
+
+#define emit_andi(R1, IMM, R3) \
+       *prog++ = (AND | IMMED | RS1(R1) | S13(IMM) | RD(R3))
+
 #define emit_alloc_stack(SZ) \
        *prog++ = (SUB | IMMED | RS1(SP) | S13(SZ) | RD(SP))
 
@@ -415,6 +422,8 @@ void bpf_jit_compile(struct sk_filter *fp)
                case BPF_S_ANC_IFINDEX:
                case BPF_S_ANC_MARK:
                case BPF_S_ANC_RXHASH:
+               case BPF_S_ANC_VLAN_TAG:
+               case BPF_S_ANC_VLAN_TAG_PRESENT:
                case BPF_S_ANC_CPU:
                case BPF_S_ANC_QUEUE:
                case BPF_S_LD_W_ABS:
@@ -600,6 +609,16 @@ void bpf_jit_compile(struct sk_filter *fp)
                        case BPF_S_ANC_RXHASH:
                                emit_skb_load32(rxhash, r_A);
                                break;
+                       case BPF_S_ANC_VLAN_TAG:
+                       case BPF_S_ANC_VLAN_TAG_PRESENT:
+                               emit_skb_load16(vlan_tci, r_A);
+                               if (filter[i].code == BPF_S_ANC_VLAN_TAG) {
+                                       emit_andi(r_A, VLAN_VID_MASK, r_A);
+                               } else {
+                                       emit_loadimm(VLAN_TAG_PRESENT, r_TMP);
+                                       emit_and(r_A, r_TMP, r_A);
+                               }
+                               break;
 
                        case BPF_S_LD_IMM:
                                emit_loadimm(K, r_A);
index 55640cf92597b11f943173928b4d7d7437d4be14..3d15364c60714bf661da140c8f6e67cde20001b3 100644 (file)
@@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH))
   endif
 endif
 
+# The tile compiler may emit .eh_frame information for backtracing.
+# In kernel modules, this causes load failures due to unsupported relocations.
+KBUILD_CFLAGS   += -fno-asynchronous-unwind-tables
+
 ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
 KBUILD_CFLAGS   += $(CONFIG_DEBUG_EXTRA_FLAGS)
 endif
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3751c9fabcf29b1a4f1164e8ff040ec8ac5ec9cf 100644 (file)
@@ -0,0 +1 @@
+# Tile arch headers
index c68808a09da7732ccab05fd2415e449c1e46bb99..6948015e08a2af582a8a539438460951ea3c8b45 100644 (file)
@@ -1,8 +1,6 @@
 
 header-y += ../arch/
 
-header-y += ucontext.h
-
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += clkdev.h
@@ -37,5 +35,4 @@ generic-y += statfs.h
 generic-y += termbits.h
 generic-y += termios.h
 generic-y += types.h
-generic-y += ucontext.h
 generic-y += xor.h
index 5c6915fd30b5c4397e12fe4e7662316320f0c68f..c20db8e428bf698cca387f3c71a29e44f1df48ce 100644 (file)
@@ -15,4 +15,7 @@ header-y += siginfo.h
 header-y += signal.h
 header-y += stat.h
 header-y += swab.h
+header-y += ucontext.h
 header-y += unistd.h
+
+generic-y += ucontext.h
index 001cbfa10ac6364a9136b9d4440bfe69730a08be..243ffebe38d69a510f16e53083c49b46f3e6531b 100644 (file)
 #include <asm/homecache.h>
 #include <arch/opcode.h>
 
-#ifdef __tilegx__
-# define Elf_Rela Elf64_Rela
-# define ELF_R_SYM ELF64_R_SYM
-# define ELF_R_TYPE ELF64_R_TYPE
-#else
-# define Elf_Rela Elf32_Rela
-# define ELF_R_SYM ELF32_R_SYM
-# define ELF_R_TYPE ELF32_R_TYPE
-#endif
-
 #ifdef MODULE_DEBUG
 #define DEBUGP printk
 #else
index e5c5473e69cea62bc28dcc281e4fb9d1cfcca704..c4fbb21e802b15349e7bfb09d06484b6163169cc 100644 (file)
@@ -16,6 +16,8 @@ config UNICORE32
        select ARCH_WANT_FRAME_POINTERS
        select GENERIC_IOMAP
        select MODULES_USE_ELF_REL
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        help
          UniCore-32 is 32-bit Instruction Set Architecture,
          including a series of low-power-consumption RISC chip
@@ -64,6 +66,9 @@ config GENERIC_CALIBRATE_DELAY
 config ARCH_MAY_HAVE_PC_FDC
        bool
 
+config ZONE_DMA
+       def_bool y
+
 config NEED_DMA_MAP_STATE
        def_bool y
 
@@ -216,7 +221,7 @@ config PUV3_GPIO
        bool
        depends on !ARCH_FPGA
        select GENERIC_GPIO
-       select GPIO_SYSFS if EXPERIMENTAL
+       select GPIO_SYSFS
        default y
 
 if PUV3_NB0916
index c910c9857e114316991b2e9c711819a3939cdad5..601e92f18af6d85d5bb314733e409f97436df804 100644 (file)
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += atomic.h
 generic-y += auxvec.h
index b1ff8cadb0866bf38ead0c95353c0020160a3c62..93a56f3e2344079b49de459ad08bb798ad9b7935 100644 (file)
@@ -19,9 +19,4 @@ extern void die(const char *msg, struct pt_regs *regs, int err);
 extern void uc32_notify_die(const char *str, struct pt_regs *regs,
                struct siginfo *info, unsigned long err, unsigned long trap);
 
-extern asmlinkage void __backtrace(void);
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-extern void __show_regs(struct pt_regs *);
-
 #endif /* __UNICORE_BUG_H__ */
diff --git a/arch/unicore32/include/asm/byteorder.h b/arch/unicore32/include/asm/byteorder.h
deleted file mode 100644 (file)
index ebe1b3f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/byteorder.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * 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.
- *
- * UniCore ONLY support Little Endian mode, the data bus is connected such
- * that byte accesses appear as:
- *  0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31
- * and word accesses (data or instruction) appear as:
- *  d0...d31
- */
-#ifndef __UNICORE_BYTEORDER_H__
-#define __UNICORE_BYTEORDER_H__
-
-#include <linux/byteorder/little_endian.h>
-
-#endif
-
index df4d5acfd19f96c9a10598a9230a0331fb7be798..8e797ad4fa24f52cbadb7b6a860a3b214d83eb3f 100644 (file)
@@ -35,7 +35,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
                        : "memory", "cc");
                break;
        default:
-               ret = __xchg_bad_pointer();
+               __xchg_bad_pointer();
        }
 
        return ret;
diff --git a/arch/unicore32/include/asm/kvm_para.h b/arch/unicore32/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
index 14382cb09657f67333f5a32f4d95910ae10e0b1d..4eaa4216766772055849a3ffdb1b6e20d30edecb 100644 (file)
@@ -72,11 +72,6 @@ unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()                    barrier()
 
-/*
- * Create a new kernel thread
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #define task_pt_regs(p) \
        ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
index b9caf9b0997b21952e5b8ecd26172e3933c8a97e..726749dab52fff679f6b787ff07498053f75e7e0 100644 (file)
 #ifndef __UNICORE_PTRACE_H__
 #define __UNICORE_PTRACE_H__
 
-#define PTRACE_GET_THREAD_AREA 22
-
-/*
- * PSR bits
- */
-#define USER_MODE      0x00000010
-#define REAL_MODE      0x00000011
-#define INTR_MODE      0x00000012
-#define PRIV_MODE      0x00000013
-#define ABRT_MODE      0x00000017
-#define EXTN_MODE      0x0000001b
-#define SUSR_MODE      0x0000001f
-#define MODE_MASK      0x0000001f
-#define PSR_R_BIT      0x00000040
-#define PSR_I_BIT      0x00000080
-#define PSR_V_BIT      0x10000000
-#define PSR_C_BIT      0x20000000
-#define PSR_Z_BIT      0x40000000
-#define PSR_S_BIT      0x80000000
-
-/*
- * Groups of PSR bits
- */
-#define PSR_f          0xff000000      /* Flags                */
-#define PSR_c          0x000000ff      /* Control              */
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-/*
- * This struct defines the way the registers are stored on the
- * stack during a system call.  Note that sizeof(struct pt_regs)
- * has to be a multiple of 8.
- */
-struct pt_regs {
-       unsigned long uregs[34];
-};
-
-#define UCreg_asr              uregs[32]
-#define UCreg_pc               uregs[31]
-#define UCreg_lr               uregs[30]
-#define UCreg_sp               uregs[29]
-#define UCreg_ip               uregs[28]
-#define UCreg_fp               uregs[27]
-#define UCreg_26               uregs[26]
-#define UCreg_25               uregs[25]
-#define UCreg_24               uregs[24]
-#define UCreg_23               uregs[23]
-#define UCreg_22               uregs[22]
-#define UCreg_21               uregs[21]
-#define UCreg_20               uregs[20]
-#define UCreg_19               uregs[19]
-#define UCreg_18               uregs[18]
-#define UCreg_17               uregs[17]
-#define UCreg_16               uregs[16]
-#define UCreg_15               uregs[15]
-#define UCreg_14               uregs[14]
-#define UCreg_13               uregs[13]
-#define UCreg_12               uregs[12]
-#define UCreg_11               uregs[11]
-#define UCreg_10               uregs[10]
-#define UCreg_09               uregs[9]
-#define UCreg_08               uregs[8]
-#define UCreg_07               uregs[7]
-#define UCreg_06               uregs[6]
-#define UCreg_05               uregs[5]
-#define UCreg_04               uregs[4]
-#define UCreg_03               uregs[3]
-#define UCreg_02               uregs[2]
-#define UCreg_01               uregs[1]
-#define UCreg_00               uregs[0]
-#define UCreg_ORIG_00          uregs[33]
-
-#ifdef __KERNEL__
-
 #define user_mode(regs)        \
        (processor_mode(regs) == USER_MODE)
 
@@ -125,9 +55,5 @@ static inline int valid_user_regs(struct pt_regs *regs)
 
 #define instruction_pointer(regs)      ((regs)->UCreg_pc)
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASSEMBLY__ */
-
 #endif
-
diff --git a/arch/unicore32/include/asm/sigcontext.h b/arch/unicore32/include/asm/sigcontext.h
deleted file mode 100644 (file)
index 6a2d767..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/sigcontext.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * 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 __UNICORE_SIGCONTEXT_H__
-#define __UNICORE_SIGCONTEXT_H__
-
-#include <asm/ptrace.h>
-/*
- * Signal context structure - contains all info to do with the state
- * before the signal handler was invoked.  Note: only add new entries
- * to the end of the structure.
- */
-struct sigcontext {
-       unsigned long trap_no;
-       unsigned long error_code;
-       unsigned long oldmask;
-       unsigned long fault_address;
-       struct pt_regs regs;
-};
-
-#endif
diff --git a/arch/unicore32/include/asm/unistd.h b/arch/unicore32/include/asm/unistd.h
deleted file mode 100644 (file)
index 2abcf61..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * linux/arch/unicore32/include/asm/unistd.h
- *
- * Code specific to PKUnity SoC and UniCore ISA
- *
- * Copyright (C) 2001-2010 GUAN Xue-tao
- *
- * 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.
- */
-
-/* Use the standard ABI for syscalls. */
-#include <asm-generic/unistd.h>
index baebb3da1d44160fc6f6f259886656e6f494b167..0514d7ad68551de6b0e7a7946263bfc6c6249ab0 100644 (file)
@@ -1,3 +1,10 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += byteorder.h
+header-y += kvm_para.h
+header-y += ptrace.h
+header-y += sigcontext.h
+header-y += unistd.h
+
+generic-y += kvm_para.h
diff --git a/arch/unicore32/include/uapi/asm/byteorder.h b/arch/unicore32/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..ebe1b3f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/include/asm/byteorder.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * UniCore ONLY support Little Endian mode, the data bus is connected such
+ * that byte accesses appear as:
+ *  0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31
+ * and word accesses (data or instruction) appear as:
+ *  d0...d31
+ */
+#ifndef __UNICORE_BYTEORDER_H__
+#define __UNICORE_BYTEORDER_H__
+
+#include <linux/byteorder/little_endian.h>
+
+#endif
+
diff --git a/arch/unicore32/include/uapi/asm/ptrace.h b/arch/unicore32/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..187aa2e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * linux/arch/unicore32/include/asm/ptrace.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 _UAPI__UNICORE_PTRACE_H__
+#define _UAPI__UNICORE_PTRACE_H__
+
+#define PTRACE_GET_THREAD_AREA 22
+
+/*
+ * PSR bits
+ */
+#define USER_MODE      0x00000010
+#define REAL_MODE      0x00000011
+#define INTR_MODE      0x00000012
+#define PRIV_MODE      0x00000013
+#define ABRT_MODE      0x00000017
+#define EXTN_MODE      0x0000001b
+#define SUSR_MODE      0x0000001f
+#define MODE_MASK      0x0000001f
+#define PSR_R_BIT      0x00000040
+#define PSR_I_BIT      0x00000080
+#define PSR_V_BIT      0x10000000
+#define PSR_C_BIT      0x20000000
+#define PSR_Z_BIT      0x40000000
+#define PSR_S_BIT      0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f          0xff000000      /* Flags                */
+#define PSR_c          0x000000ff      /* Control              */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call.  Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
+struct pt_regs {
+       unsigned long uregs[34];
+};
+
+#define UCreg_asr              uregs[32]
+#define UCreg_pc               uregs[31]
+#define UCreg_lr               uregs[30]
+#define UCreg_sp               uregs[29]
+#define UCreg_ip               uregs[28]
+#define UCreg_fp               uregs[27]
+#define UCreg_26               uregs[26]
+#define UCreg_25               uregs[25]
+#define UCreg_24               uregs[24]
+#define UCreg_23               uregs[23]
+#define UCreg_22               uregs[22]
+#define UCreg_21               uregs[21]
+#define UCreg_20               uregs[20]
+#define UCreg_19               uregs[19]
+#define UCreg_18               uregs[18]
+#define UCreg_17               uregs[17]
+#define UCreg_16               uregs[16]
+#define UCreg_15               uregs[15]
+#define UCreg_14               uregs[14]
+#define UCreg_13               uregs[13]
+#define UCreg_12               uregs[12]
+#define UCreg_11               uregs[11]
+#define UCreg_10               uregs[10]
+#define UCreg_09               uregs[9]
+#define UCreg_08               uregs[8]
+#define UCreg_07               uregs[7]
+#define UCreg_06               uregs[6]
+#define UCreg_05               uregs[5]
+#define UCreg_04               uregs[4]
+#define UCreg_03               uregs[3]
+#define UCreg_02               uregs[2]
+#define UCreg_01               uregs[1]
+#define UCreg_00               uregs[0]
+#define UCreg_ORIG_00          uregs[33]
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI__UNICORE_PTRACE_H__ */
diff --git a/arch/unicore32/include/uapi/asm/sigcontext.h b/arch/unicore32/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..6a2d767
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * linux/arch/unicore32/include/asm/sigcontext.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_SIGCONTEXT_H__
+#define __UNICORE_SIGCONTEXT_H__
+
+#include <asm/ptrace.h>
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+       unsigned long trap_no;
+       unsigned long error_code;
+       unsigned long oldmask;
+       unsigned long fault_address;
+       struct pt_regs regs;
+};
+
+#endif
diff --git a/arch/unicore32/include/uapi/asm/unistd.h b/arch/unicore32/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..d18a3be
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * linux/arch/unicore32/include/asm/unistd.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+
+/* Use the standard ABI for syscalls. */
+#include <asm-generic/unistd.h>
+#define __ARCH_WANT_SYS_EXECVE
index dcb87ab19ddd8b5912dfa2d765c4158fa1bbad73..7049350c790fea708301996647e041431a8feef5 100644 (file)
@@ -573,17 +573,16 @@ ENDPROC(ret_to_user)
  */
 ENTRY(ret_from_fork)
        b.l     schedule_tail
-       get_thread_info tsk
-       ldw     r1, [tsk+], #TI_FLAGS           @ check for syscall tracing
-       mov     why, #1
-       cand.a  r1, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
-       beq     ret_slow_syscall
-       mov     r1, sp
-       mov     r0, #1                          @ trace exit [IP = 1]
-       b.l     syscall_trace
        b       ret_slow_syscall
 ENDPROC(ret_from_fork)
 
+ENTRY(ret_from_kernel_thread)
+       b.l     schedule_tail
+       mov     r0, r5
+       adr     lr, ret_slow_syscall
+       mov     pc, r4
+ENDPROC(ret_from_kernel_thread)
+
 /*=============================================================================
  * SWI handler
  *-----------------------------------------------------------------------------
@@ -669,11 +668,6 @@ __cr_alignment:
 #endif
        .ltorg
 
-ENTRY(sys_execve)
-               add     r3, sp, #S_OFF
-               b       __sys_execve
-ENDPROC(sys_execve)
-
 ENTRY(sys_clone)
                add     ip, sp, #S_OFF
                stw     ip, [sp+], #4
index b008586dad753a1b29010735b95ee71e1a704900..a8fe265ce2c0fad25b2a2d330636b3ee05800392 100644 (file)
@@ -258,6 +258,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
 int
 copy_thread(unsigned long clone_flags, unsigned long stack_start,
@@ -266,17 +267,22 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        struct thread_info *thread = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
 
-       *childregs = *regs;
-       childregs->UCreg_00 = 0;
-       childregs->UCreg_sp = stack_start;
-
        memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
        thread->cpu_context.sp = (unsigned long)childregs;
-       thread->cpu_context.pc = (unsigned long)ret_from_fork;
-
-       if (clone_flags & CLONE_SETTLS)
-               childregs->UCreg_16 = regs->UCreg_03;
+       if (unlikely(!regs)) {
+               thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread;
+               thread->cpu_context.r4 = stack_start;
+               thread->cpu_context.r5 = stk_sz;
+               memset(childregs, 0, sizeof(struct pt_regs));
+       } else {
+               thread->cpu_context.pc = (unsigned long)ret_from_fork;
+               *childregs = *regs;
+               childregs->UCreg_00 = 0;
+               childregs->UCreg_sp = stack_start;
 
+               if (clone_flags & CLONE_SETTLS)
+                       childregs->UCreg_16 = regs->UCreg_03;
+       }
        return 0;
 }
 
@@ -305,42 +311,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-/*
- * Shuffle the argument into the correct register before calling the
- * thread function.  r1 is the thread argument, r2 is the pointer to
- * the thread function, and r3 points to the exit function.
- */
-asm(".pushsection .text\n"
-"      .align\n"
-"      .type   kernel_thread_helper, #function\n"
-"kernel_thread_helper:\n"
-"      mov.a   asr, r7\n"
-"      mov     r0, r4\n"
-"      mov     lr, r6\n"
-"      mov     pc, r5\n"
-"      .size   kernel_thread_helper, . - kernel_thread_helper\n"
-"      .popsection");
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.UCreg_04 = (unsigned long)arg;
-       regs.UCreg_05 = (unsigned long)fn;
-       regs.UCreg_06 = (unsigned long)do_exit;
-       regs.UCreg_07 = PRIV_MODE;
-       regs.UCreg_pc = (unsigned long)kernel_thread_helper;
-       regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT;
-
-       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
index f23955028a183f70c0e0982ff934a06157bad659..30f749da8f7317ecf0613089ad0876f02ed533c7 100644 (file)
@@ -30,4 +30,10 @@ extern char __vectors_start[], __vectors_end[];
 extern void kernel_thread_helper(void);
 
 extern void __init early_signal_init(void);
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+extern void __show_regs(struct pt_regs *);
+
 #endif
index fabdee96110b46821c911fa9de0be5ba30460b57..9680134b31f0ddd8a0be50f8dd2183a8392328c3 100644 (file)
@@ -42,69 +42,6 @@ asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
                        parent_tid, child_tid);
 }
 
-/* sys_execve() executes a new program.
- * This is called indirectly via a small wrapper
- */
-asmlinkage long __sys_execve(const char __user *filename,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp,
-                         struct pt_regs *regs)
-{
-       int error;
-       struct filename *fn;
-
-       fn = getname(filename);
-       error = PTR_ERR(fn);
-       if (IS_ERR(fn))
-               goto out;
-       error = do_execve(fn->name, argv, envp, regs);
-       putname(fn);
-out:
-       return error;
-}
-
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       struct pt_regs regs;
-       int ret;
-
-       memset(&regs, 0, sizeof(struct pt_regs));
-       ret = do_execve(filename,
-                       (const char __user *const __user *)argv,
-                       (const char __user *const __user *)envp, &regs);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * Save argc to the register structure for userspace.
-        */
-       regs.UCreg_00 = ret;
-
-       /*
-        * We were successful.  We won't be returning to our caller, but
-        * instead to user space by manipulating the kernel stack.
-        */
-       asm("add        r0, %0, %1\n\t"
-               "mov    r1, %2\n\t"
-               "mov    r2, %3\n\t"
-               "mov    r22, #0\n\t"    /* not a syscall */
-               "mov    r23, %0\n\t"    /* thread structure */
-               "b.l    memmove\n\t"    /* copy regs to top of stack */
-               "mov    sp, r0\n\t"     /* reposition stack pointer */
-               "b      ret_to_user"
-               :
-               : "r" (current_thread_info()),
-                 "Ir" (THREAD_START_SP - sizeof(regs)),
-                 "r" (&regs),
-                 "Ir" (sizeof(regs))
-               : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
-
- out:
-       return ret;
-}
-
 /* Note: used by the compat code even in 64-bit Linux. */
 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
                unsigned long, prot, unsigned long, flags,
index 2eeb9c04cab057b5a2c6f542e251d6762cd6621b..f9b5c10bccee96e8838484aaf6effc39b3c89bd1 100644 (file)
@@ -168,7 +168,7 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
 }
 
 static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
-               struct task_struct *tsk)
+               unsigned int flags, struct task_struct *tsk)
 {
        struct vm_area_struct *vma;
        int fault;
@@ -194,14 +194,7 @@ good_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, addr & PAGE_MASK,
-                           (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
-       if (unlikely(fault & VM_FAULT_ERROR))
-               return fault;
-       if (fault & VM_FAULT_MAJOR)
-               tsk->maj_flt++;
-       else
-               tsk->min_flt++;
+       fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, flags);
        return fault;
 
 check_stack:
@@ -216,6 +209,8 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        struct task_struct *tsk;
        struct mm_struct *mm;
        int fault, sig, code;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+                                ((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
 
        tsk = current;
        mm = tsk->mm;
@@ -236,6 +231,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                if (!user_mode(regs)
                    && !search_exception_tables(regs->UCreg_pc))
                        goto no_context;
+retry:
                down_read(&mm->mmap_sem);
        } else {
                /*
@@ -251,7 +247,28 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 #endif
        }
 
-       fault = __do_pf(mm, addr, fsr, tsk);
+       fault = __do_pf(mm, addr, fsr, flags, tsk);
+
+       /* If we need to retry but a fatal signal is pending, handle the
+        * signal first. We do not need to release the mmap_sem because
+        * it would already be released in __lock_page_or_retry in
+        * mm/filemap.c. */
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+               return 0;
+
+       if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) {
+               if (fault & VM_FAULT_MAJOR)
+                       tsk->maj_flt++;
+               else
+                       tsk->min_flt++;
+               if (fault & VM_FAULT_RETRY) {
+                       /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+                       * of starvation. */
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       goto retry;
+               }
+       }
+
        up_read(&mm->mmap_sem);
 
        /*
index 58790bd85c1d38b1f1080f0284fbe170e8b5acb9..05afcca66de68cf65c7c354b543881ea96a2cf74 100644 (file)
@@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
 KBUILD_CFLAGS += $(mflags-y)
 KBUILD_AFLAGS += $(mflags-y)
 
-archscripts:
+archscripts: scripts_basic
        $(Q)$(MAKE) $(build)=arch/x86/tools relocs
 
 ###
index c760e073963ed59004f66ed65aade6355c852da9..e87b0cac14b5e5d735ab21f9f3b163db52349938 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/setup.h>
 #include <asm/desc.h>
 
+#undef memcpy                  /* Use memcpy from misc.c */
+
 #include "eboot.h"
 
 static efi_system_table_t *sys_table;
index 2a017441b8b2ebc665a24a001f5d635f7dbc9955..8c132a625b94991c179def21973bb8ad3c3a56d5 100644 (file)
@@ -476,6 +476,3 @@ die:
 setup_corrupt:
        .byte   7
        .string "No setup signature found...\n"
-
-       .data
-dummy: .long   0
index 7c04d0da709b10a002ecd26db5bf0ec0b7b3bb6c..1b9c22bea8a7de8f6e63b200d77733bd2bb0f3c5 100644 (file)
@@ -515,6 +515,11 @@ static int xts_aesni_setkey(struct crypto_tfm *tfm, const u8 *key,
 }
 
 
+static void aesni_xts_tweak(void *ctx, u8 *out, const u8 *in)
+{
+       aesni_enc(ctx, out, in);
+}
+
 static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                       struct scatterlist *src, unsigned int nbytes)
 {
@@ -525,7 +530,7 @@ static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                .tbuflen = sizeof(buf),
 
                .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
-               .tweak_fn = XTS_TWEAK_CAST(aesni_enc),
+               .tweak_fn = aesni_xts_tweak,
                .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
                .crypt_fn = lrw_xts_encrypt_callback,
        };
@@ -550,7 +555,7 @@ static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
                .tbuflen = sizeof(buf),
 
                .tweak_ctx = aes_ctx(ctx->raw_tweak_ctx),
-               .tweak_fn = XTS_TWEAK_CAST(aesni_enc),
+               .tweak_fn = aesni_xts_tweak,
                .crypt_ctx = aes_ctx(ctx->raw_crypt_ctx),
                .crypt_fn = lrw_xts_decrypt_callback,
        };
index c9dcc181d4d1a814c10d6822d0801c7a1b2d7196..6e8fdf5ad1135c0100c8b7a5220bb79db2359ddb 100644 (file)
@@ -35,7 +35,7 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
 #define efi_call_virt6(f, a1, a2, a3, a4, a5, a6)      \
        efi_call_virt(f, a1, a2, a3, a4, a5, a6)
 
-#define efi_ioremap(addr, size, type)          ioremap_cache(addr, size)
+#define efi_ioremap(addr, size, type, attr)    ioremap_cache(addr, size)
 
 #else /* !CONFIG_X86_32 */
 
@@ -89,7 +89,7 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
                  (u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
 
 extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
-                                u32 type);
+                                u32 type, u64 attribute);
 
 #endif /* CONFIG_X86_32 */
 
@@ -98,6 +98,8 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
 extern void efi_call_phys_epilog(void);
+extern void efi_unmap_memmap(void);
+extern void efi_memory_uc(u64 addr, unsigned long size);
 
 #ifndef CONFIG_EFI
 /*
index dcfde52979c3e63be0d42627cc567cf76c733090..19f16ebaf4fa826216c7858d224365b2fdb74670 100644 (file)
@@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
 }
 #endif
 
-/*
- * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
- * when it traps.  The previous stack will be directly underneath the saved
- * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
- *
- * This is valid only for kernel mode traps.
- */
-static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
-{
 #ifdef CONFIG_X86_32
-       return (unsigned long)(&regs->sp);
+extern unsigned long kernel_stack_pointer(struct pt_regs *regs);
 #else
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
        return regs->sp;
-#endif
 }
+#endif
 
 #define GET_IP(regs) ((regs)->ip)
 #define GET_FP(regs) ((regs)->bp)
index 59c226d120cdeccb6d8615e396f65b3ff2d4c050..c20d1ce62dc6a0a236280ab51b7ac8386fb1c32b 100644 (file)
@@ -359,18 +359,14 @@ HYPERVISOR_update_va_mapping(unsigned long va, pte_t new_val,
                return _hypercall4(int, update_va_mapping, va,
                                   new_val.pte, new_val.pte >> 32, flags);
 }
+extern int __must_check xen_event_channel_op_compat(int, void *);
 
 static inline int
 HYPERVISOR_event_channel_op(int cmd, void *arg)
 {
        int rc = _hypercall2(int, event_channel_op, cmd, arg);
-       if (unlikely(rc == -ENOSYS)) {
-               struct evtchn_op op;
-               op.cmd = cmd;
-               memcpy(&op.u, arg, sizeof(op.u));
-               rc = _hypercall1(int, event_channel_op_compat, &op);
-               memcpy(arg, &op.u, sizeof(op.u));
-       }
+       if (unlikely(rc == -ENOSYS))
+               rc = xen_event_channel_op_compat(cmd, arg);
        return rc;
 }
 
@@ -386,17 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)
        return _hypercall3(int, console_io, cmd, count, str);
 }
 
+extern int __must_check HYPERVISOR_physdev_op_compat(int, void *);
+
 static inline int
 HYPERVISOR_physdev_op(int cmd, void *arg)
 {
        int rc = _hypercall2(int, physdev_op, cmd, arg);
-       if (unlikely(rc == -ENOSYS)) {
-               struct physdev_op op;
-               op.cmd = cmd;
-               memcpy(&op.u, arg, sizeof(op.u));
-               rc = _hypercall1(int, physdev_op_compat, &op);
-               memcpy(arg, &op.u, sizeof(op.u));
-       }
+       if (unlikely(rc == -ENOSYS))
+               rc = HYPERVISOR_physdev_op_compat(cmd, arg);
        return rc;
 }
 
index 66d0fff1ee8481ce0669cd5b0a137dde5d7dff8d..125f344f06a90e4d09dc4feab417042be9910e2a 100644 (file)
@@ -33,7 +33,6 @@
 #ifndef _ASM_X86_XEN_HYPERVISOR_H
 #define _ASM_X86_XEN_HYPERVISOR_H
 
-/* arch/i386/kernel/setup.c */
 extern struct shared_info *HYPERVISOR_shared_info;
 extern struct start_info *xen_start_info;
 
index 6d2f75a82a14bca62162f38cde9fff8e6404bec9..54d52ff1304a3496bc240ef193030adbb73ec4bb 100644 (file)
  * with Xen so that on ARM we can have one ABI that works for 32 and 64
  * bit guests. */
 typedef unsigned long xen_pfn_t;
+#define PRI_xen_pfn "lx"
 typedef unsigned long xen_ulong_t;
+#define PRI_xen_ulong "lx"
 /* Guest handles for primitive C types. */
 __DEFINE_GUEST_HANDLE(uchar, unsigned char);
 __DEFINE_GUEST_HANDLE(uint,  unsigned int);
-__DEFINE_GUEST_HANDLE(ulong, unsigned long);
 DEFINE_GUEST_HANDLE(char);
 DEFINE_GUEST_HANDLE(int);
-DEFINE_GUEST_HANDLE(long);
 DEFINE_GUEST_HANDLE(void);
 DEFINE_GUEST_HANDLE(uint64_t);
 DEFINE_GUEST_HANDLE(uint32_t);
index c265593ec2cdc3df35fda1586aaf91514fab62fa..1817fa911024f07151d3edf91bd350722c9f79f8 100644 (file)
@@ -2257,6 +2257,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
                        continue;
 
                cfg = irq_cfg(irq);
+               if (!cfg)
+                       continue;
+
                raw_spin_lock(&desc->lock);
 
                /*
index f7e98a2c0d123ae0ebe7f61f1521f7dd7090a335..1b7d1656a042ff5e1886c6fff40bbde1ff3a472d 100644 (file)
@@ -631,6 +631,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                }
        }
 
+       /*
+        * The way access filter has a performance penalty on some workloads.
+        * Disable it on the affected CPUs.
+        */
+       if ((c->x86 == 0x15) &&
+           (c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
+               u64 val;
+
+               if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) {
+                       val |= 0x1E;
+                       wrmsrl_safe(0xc0011021, val);
+               }
+       }
+
        cpu_detect_cache_sizes(c);
 
        /* Multi core CPU? */
index 9a7c90d80bc4c87bafd96cb73efb46ced84b5276..93c5451bdd527ca9436a98b661e9f3165e484570 100644 (file)
@@ -991,7 +991,7 @@ static struct attribute ** __cpuinit amd_l3_attrs(void)
        if (attrs)
                return attrs;
 
-       n = sizeof (default_attrs) / sizeof (struct attribute *);
+       n = ARRAY_SIZE(default_attrs);
 
        if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
                n += 2;
index 29e87d3b2843610207ebd875071a4291bec02cfe..46cbf8689692fdbd3d0517d6e20d20a9e192f5e0 100644 (file)
@@ -2209,11 +2209,6 @@ static struct dev_ext_attribute dev_attr_cmci_disabled = {
        &mce_cmci_disabled
 };
 
-static struct dev_ext_attribute dev_attr_bios_cmci_threshold = {
-       __ATTR(bios_cmci_threshold, 0444, device_show_int, NULL),
-       &mce_bios_cmci_threshold
-};
-
 static struct device_attribute *mce_device_attrs[] = {
        &dev_attr_tolerant.attr,
        &dev_attr_check_interval.attr,
@@ -2222,7 +2217,6 @@ static struct device_attribute *mce_device_attrs[] = {
        &dev_attr_dont_log_ce.attr,
        &dev_attr_ignore_ce.attr,
        &dev_attr_cmci_disabled.attr,
-       &dev_attr_bios_cmci_threshold.attr,
        NULL
 };
 
index c4e916d773780f4239ac831478c15aa2325c7382..1ac581f38dfa2771ba054c980cd9163546e8c9db 100644 (file)
@@ -6,7 +6,7 @@
  *
  *  Written by Jacob Shin - AMD, Inc.
  *
- *  Support: borislav.petkov@amd.com
+ *  Maintained by: Borislav Petkov <bp@alien8.de>
  *
  *  April 2006
  *     - added support for AMD Family 0x10 processors
@@ -576,12 +576,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
        int err = 0;
 
        if (shared_bank[bank]) {
-
                nb = node_to_amd_nb(amd_get_nb_id(cpu));
-               WARN_ON(!nb);
 
                /* threshold descriptor already initialized on this node? */
-               if (nb->bank4) {
+               if (nb && nb->bank4) {
                        /* yes, use it */
                        b = nb->bank4;
                        err = kobject_add(b->kobj, &dev->kobj, name);
@@ -615,8 +613,10 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
                atomic_set(&b->cpus, 1);
 
                /* nb is already initialized, see above */
-               WARN_ON(nb->bank4);
-               nb->bank4 = b;
+               if (nb) {
+                       WARN_ON(nb->bank4);
+                       nb->bank4 = b;
+               }
        }
 
        err = allocate_threshold_blocks(cpu, bank, 0,
index 5f88abf07e9ccc2237b27fea29c57b4b59315a64..4f9a3cbfc4a33fb801ab1bf2c822a83e76122897 100644 (file)
@@ -285,34 +285,39 @@ void cmci_clear(void)
        raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
+static long cmci_rediscover_work_func(void *arg)
+{
+       int banks;
+
+       /* Recheck banks in case CPUs don't all have the same */
+       if (cmci_supported(&banks))
+               cmci_discover(banks);
+
+       return 0;
+}
+
 /*
  * After a CPU went down cycle through all the others and rediscover
  * Must run in process context.
  */
 void cmci_rediscover(int dying)
 {
-       int banks;
-       int cpu;
-       cpumask_var_t old;
+       int cpu, banks;
 
        if (!cmci_supported(&banks))
                return;
-       if (!alloc_cpumask_var(&old, GFP_KERNEL))
-               return;
-       cpumask_copy(old, &current->cpus_allowed);
 
        for_each_online_cpu(cpu) {
                if (cpu == dying)
                        continue;
-               if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
+
+               if (cpu == smp_processor_id()) {
+                       cmci_rediscover_work_func(NULL);
                        continue;
-               /* Recheck banks in case CPUs don't all have the same */
-               if (cmci_supported(&banks))
-                       cmci_discover(banks);
-       }
+               }
 
-       set_cpus_allowed_ptr(current, old);
-       free_cpumask_var(old);
+               work_on_cpu(cpu, cmci_rediscover_work_func, NULL);
+       }
 }
 
 /*
index 915b876edd1e2b8a509786446642302648989a73..4a3374e61a93a033f24f03941b99c03e3906a726 100644 (file)
@@ -208,12 +208,14 @@ static bool check_hw_exists(void)
        }
 
        /*
-        * Now write a value and read it back to see if it matches,
-        * this is needed to detect certain hardware emulators (qemu/kvm)
-        * that don't trap on the MSR access and always return 0s.
+        * Read the current value, change it and read it back to see if it
+        * matches, this is needed to detect certain hardware emulators
+        * (qemu/kvm) that don't trap on the MSR access and always return 0s.
         */
-       val = 0xabcdUL;
        reg = x86_pmu_event_addr(0);
+       if (rdmsrl_safe(reg, &val))
+               goto msr_fail;
+       val ^= 0xffffUL;
        ret = wrmsrl_safe(reg, val);
        ret |= rdmsrl_safe(reg, &val_new);
        if (ret || val != val_new)
@@ -338,6 +340,9 @@ int x86_setup_perfctr(struct perf_event *event)
                /* BTS is currently only allowed for user-mode. */
                if (!attr->exclude_kernel)
                        return -EOPNOTSUPP;
+
+               if (!attr->exclude_guest)
+                       return -EOPNOTSUPP;
        }
 
        hwc->config |= config;
@@ -380,6 +385,9 @@ int x86_pmu_hw_config(struct perf_event *event)
        if (event->attr.precise_ip) {
                int precise = 0;
 
+               if (!event->attr.exclude_guest)
+                       return -EOPNOTSUPP;
+
                /* Support for constant skid */
                if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
                        precise++;
index 99d96a4978b56630115c2de5b465ca5eca0ffee0..3cf3d97cce3a7ab0b02c678f2535dc5ec03d09bb 100644 (file)
@@ -118,22 +118,24 @@ static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = box->pci_dev;
        int box_ctl = uncore_pci_box_ctl(box);
-       u32 config;
+       u32 config = 0;
 
-       pci_read_config_dword(pdev, box_ctl, &config);
-       config |= SNBEP_PMON_BOX_CTL_FRZ;
-       pci_write_config_dword(pdev, box_ctl, config);
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config |= SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
 }
 
 static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
 {
        struct pci_dev *pdev = box->pci_dev;
        int box_ctl = uncore_pci_box_ctl(box);
-       u32 config;
+       u32 config = 0;
 
-       pci_read_config_dword(pdev, box_ctl, &config);
-       config &= ~SNBEP_PMON_BOX_CTL_FRZ;
-       pci_write_config_dword(pdev, box_ctl, config);
+       if (!pci_read_config_dword(pdev, box_ctl, &config)) {
+               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+               pci_write_config_dword(pdev, box_ctl, config);
+       }
 }
 
 static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box, struct perf_event *event)
@@ -156,7 +158,7 @@ static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box, struct pe
 {
        struct pci_dev *pdev = box->pci_dev;
        struct hw_perf_event *hwc = &event->hw;
-       u64 count;
+       u64 count = 0;
 
        pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
        pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
@@ -603,11 +605,12 @@ static struct pci_driver snbep_uncore_pci_driver = {
 /*
  * build pci bus to socket mapping
  */
-static void snbep_pci2phy_map_init(void)
+static int snbep_pci2phy_map_init(void)
 {
        struct pci_dev *ubox_dev = NULL;
        int i, bus, nodeid;
-       u32 config;
+       int err = 0;
+       u32 config = 0;
 
        while (1) {
                /* find the UBOX device */
@@ -618,10 +621,14 @@ static void snbep_pci2phy_map_init(void)
                        break;
                bus = ubox_dev->bus->number;
                /* get the Node ID of the local register */
-               pci_read_config_dword(ubox_dev, 0x40, &config);
+               err = pci_read_config_dword(ubox_dev, 0x40, &config);
+               if (err)
+                       break;
                nodeid = config;
                /* get the Node ID mapping */
-               pci_read_config_dword(ubox_dev, 0x54, &config);
+               err = pci_read_config_dword(ubox_dev, 0x54, &config);
+               if (err)
+                       break;
                /*
                 * every three bits in the Node ID mapping register maps
                 * to a particular node.
@@ -633,7 +640,11 @@ static void snbep_pci2phy_map_init(void)
                        }
                }
        };
-       return;
+
+       if (ubox_dev)
+               pci_dev_put(ubox_dev);
+
+       return err ? pcibios_err_to_errno(err) : 0;
 }
 /* end of Sandy Bridge-EP uncore support */
 
@@ -1547,7 +1558,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
        struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
-       int port;
 
        /* adjust the main event selector and extra register index */
        if (reg1->idx % 2) {
@@ -1559,7 +1569,6 @@ void nhmex_rbox_alter_er(struct intel_uncore_box *box, struct perf_event *event)
        }
 
        /* adjust extra register config */
-       port = reg1->idx / 6 + box->pmu->pmu_idx * 4;
        switch (reg1->idx % 6) {
        case 2:
                /* shift the 8~15 bits to the 0~7 bits */
@@ -2578,9 +2587,11 @@ static int __init uncore_pci_init(void)
 
        switch (boot_cpu_data.x86_model) {
        case 45: /* Sandy Bridge-EP */
+               ret = snbep_pci2phy_map_init();
+               if (ret)
+                       return ret;
                pci_uncores = snbep_pci_uncores;
                uncore_pci_driver = &snbep_uncore_pci_driver;
-               snbep_pci2phy_map_init();
                break;
        default:
                return 0;
@@ -2926,6 +2937,9 @@ static int __init intel_uncore_init(void)
        if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
                return -ENODEV;
 
+       if (cpu_has_hypervisor)
+               return -ENODEV;
+
        ret = uncore_pci_init();
        if (ret)
                goto fail;
index 7c46bfdbc3732f87b005ecb7196a635eba5db546..4b7731bf23a812a4631aa7c53196068924b52ee7 100644 (file)
@@ -3,6 +3,8 @@
 #include <linux/perf_event.h>
 #include <linux/types.h>
 
+#include <asm/hardirq.h>
+
 #include "perf_event.h"
 
 static const u64 knc_perfmon_event_map[] =
@@ -173,30 +175,100 @@ static void knc_pmu_enable_all(int added)
 static inline void
 knc_pmu_disable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
+       val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
 }
 
 static void knc_pmu_enable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+       val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
        (void)wrmsrl_safe(hwc->config_base + hwc->idx, val);
 }
 
+static inline u64 knc_pmu_get_status(void)
+{
+       u64 status;
+
+       rdmsrl(MSR_KNC_IA32_PERF_GLOBAL_STATUS, status);
+
+       return status;
+}
+
+static inline void knc_pmu_ack_status(u64 ack)
+{
+       wrmsrl(MSR_KNC_IA32_PERF_GLOBAL_OVF_CONTROL, ack);
+}
+
+static int knc_pmu_handle_irq(struct pt_regs *regs)
+{
+       struct perf_sample_data data;
+       struct cpu_hw_events *cpuc;
+       int handled = 0;
+       int bit, loops;
+       u64 status;
+
+       cpuc = &__get_cpu_var(cpu_hw_events);
+
+       knc_pmu_disable_all();
+
+       status = knc_pmu_get_status();
+       if (!status) {
+               knc_pmu_enable_all(0);
+               return handled;
+       }
+
+       loops = 0;
+again:
+       knc_pmu_ack_status(status);
+       if (++loops > 100) {
+               WARN_ONCE(1, "perf: irq loop stuck!\n");
+               perf_event_print_debug();
+               goto done;
+       }
+
+       inc_irq_stat(apic_perf_irqs);
+
+       for_each_set_bit(bit, (unsigned long *)&status, X86_PMC_IDX_MAX) {
+               struct perf_event *event = cpuc->events[bit];
+
+               handled++;
+
+               if (!test_bit(bit, cpuc->active_mask))
+                       continue;
+
+               if (!intel_pmu_save_and_restart(event))
+                       continue;
+
+               perf_sample_data_init(&data, 0, event->hw.last_period);
+
+               if (perf_event_overflow(event, &data, regs))
+                       x86_pmu_stop(event, 0);
+       }
+
+       /*
+        * Repeat if there is more work to be done:
+        */
+       status = knc_pmu_get_status();
+       if (status)
+               goto again;
+
+done:
+       knc_pmu_enable_all(0);
+
+       return handled;
+}
+
+
 PMU_FORMAT_ATTR(event, "config:0-7"    );
 PMU_FORMAT_ATTR(umask, "config:8-15"   );
 PMU_FORMAT_ATTR(edge,  "config:18"     );
@@ -214,7 +286,7 @@ static struct attribute *intel_knc_formats_attr[] = {
 
 static __initconst struct x86_pmu knc_pmu = {
        .name                   = "knc",
-       .handle_irq             = x86_pmu_handle_irq,
+       .handle_irq             = knc_pmu_handle_irq,
        .disable_all            = knc_pmu_disable_all,
        .enable_all             = knc_pmu_enable_all,
        .enable                 = knc_pmu_enable_event,
@@ -226,12 +298,11 @@ static __initconst struct x86_pmu knc_pmu = {
        .event_map              = knc_pmu_event_map,
        .max_events             = ARRAY_SIZE(knc_perfmon_event_map),
        .apic                   = 1,
-       .max_period             = (1ULL << 31) - 1,
+       .max_period             = (1ULL << 39) - 1,
        .version                = 0,
        .num_counters           = 2,
-       /* in theory 40 bits, early silicon is buggy though */
-       .cntval_bits            = 32,
-       .cntval_mask            = (1ULL << 32) - 1,
+       .cntval_bits            = 40,
+       .cntval_mask            = (1ULL << 40) - 1,
        .get_event_constraints  = x86_get_event_constraints,
        .event_constraints      = knc_event_constraints,
        .format_attrs           = intel_knc_formats_attr,
index e4dd0f7a04535f09b83d47d95868bcc1c152dff3..7d0270bd793ebd8580d63e21a1be521b2aeea91f 100644 (file)
  */
 static const u64 p6_perfmon_event_map[] =
 {
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
-  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,
+  [PERF_COUNT_HW_CPU_CYCLES]           = 0x0079,       /* CPU_CLK_UNHALTED */
+  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,       /* INST_RETIRED     */
+  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x0f2e,       /* L2_RQSTS:M:E:S:I */
+  [PERF_COUNT_HW_CACHE_MISSES]         = 0x012e,       /* L2_RQSTS:I       */
+  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,       /* BR_INST_RETIRED  */
+  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,       /* BR_MISS_PRED_RETIRED */
+  [PERF_COUNT_HW_BUS_CYCLES]           = 0x0062,       /* BUS_DRDY_CLOCKS  */
+  [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x00a2,    /* RESOURCE_STALLS  */
+
+};
+
+static __initconst u64 p6_hw_cache_event_ids
+                               [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) ] = 0x0043,  /* DATA_MEM_REFS       */
+                [ C(RESULT_MISS)   ] = 0x0045, /* DCU_LINES_IN        */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0f29,  /* L2_LD:M:E:S:I       */
+       },
+        [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+        },
+ },
+ [ C(L1I ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0f28,  /* L2_IFETCH:M:E:S:I  */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(LL  ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0x0025,  /* L2_M_LINES_INM     */
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(DTLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0043,  /* DATA_MEM_REFS      */
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = 0,
+               [ C(RESULT_MISS)   ] = 0,
+       },
+ },
+ [ C(ITLB) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x0080,  /* IFU_IFETCH         */
+               [ C(RESULT_MISS)   ] = 0x0085,  /* ITLB_MISS          */
+       },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
+ [ C(BPU ) ] = {
+       [ C(OP_READ) ] = {
+               [ C(RESULT_ACCESS) ] = 0x00c4,  /* BR_INST_RETIRED      */
+               [ C(RESULT_MISS)   ] = 0x00c5,  /* BR_MISS_PRED_RETIRED */
+        },
+       [ C(OP_WRITE) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+       [ C(OP_PREFETCH) ] = {
+               [ C(RESULT_ACCESS) ] = -1,
+               [ C(RESULT_MISS)   ] = -1,
+       },
+ },
 };
 
 static u64 p6_pmu_event_map(int hw_event)
@@ -34,7 +127,7 @@ static struct event_constraint p6_event_constraints[] =
 {
        INTEL_EVENT_CONSTRAINT(0xc1, 0x1),      /* FLOPS */
        INTEL_EVENT_CONSTRAINT(0x10, 0x1),      /* FP_COMP_OPS_EXE */
-       INTEL_EVENT_CONSTRAINT(0x11, 0x1),      /* FP_ASSIST */
+       INTEL_EVENT_CONSTRAINT(0x11, 0x2),      /* FP_ASSIST */
        INTEL_EVENT_CONSTRAINT(0x12, 0x2),      /* MUL */
        INTEL_EVENT_CONSTRAINT(0x13, 0x2),      /* DIV */
        INTEL_EVENT_CONSTRAINT(0x14, 0x1),      /* CYCLES_DIV_BUSY */
@@ -64,25 +157,25 @@ static void p6_pmu_enable_all(int added)
 static inline void
 p6_pmu_disable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val = P6_NOP_EVENT;
 
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
-
        (void)wrmsrl_safe(hwc->config_base, val);
 }
 
 static void p6_pmu_enable_event(struct perf_event *event)
 {
-       struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
        struct hw_perf_event *hwc = &event->hw;
        u64 val;
 
        val = hwc->config;
-       if (cpuc->enabled)
-               val |= ARCH_PERFMON_EVENTSEL_ENABLE;
+
+       /*
+        * p6 only has a global event enable, set on PerfEvtSel0
+        * We "disable" events by programming P6_NOP_EVENT
+        * and we rely on p6_pmu_enable_all() being called
+        * to actually enable the events.
+        */
 
        (void)wrmsrl_safe(hwc->config_base, val);
 }
@@ -158,5 +251,9 @@ __init int p6_pmu_init(void)
 
        x86_pmu = p6_pmu;
 
+       memcpy(hw_cache_event_ids, p6_hw_cache_event_ids,
+               sizeof(hw_cache_event_ids));
+
+
        return 0;
 }
index ed858e9e9a7461aa9b4f8aa42a52c79d57d84507..df06ade26bef8485af1a66d797370385d0012e52 100644 (file)
@@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void)
                memblock_add(ei->addr, ei->size);
        }
 
+       /* throw away partial pages */
+       memblock_trim_memory(PAGE_SIZE);
+
        memblock_dump_all();
 }
 
index a1193aef6d7d2ef1af31a4b257ed0e161876ad19..88b725aa1d52463d7534882a187da4c392bf3947 100644 (file)
@@ -1035,7 +1035,7 @@ ENTRY(xen_sysenter_target)
 
 ENTRY(xen_hypervisor_callback)
        CFI_STARTPROC
-       pushl_cfi $0
+       pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        TRACE_IRQS_OFF
 
@@ -1077,14 +1077,16 @@ ENTRY(xen_failsafe_callback)
 2:     mov 8(%esp),%es
 3:     mov 12(%esp),%fs
 4:     mov 16(%esp),%gs
+       /* EAX == 0 => Category 1 (Bad segment)
+          EAX != 0 => Category 2 (Bad IRET) */
        testl %eax,%eax
        popl_cfi %eax
        lea 16(%esp),%esp
        CFI_ADJUST_CFA_OFFSET -16
        jz 5f
        addl $16,%esp
-       jmp iret_exc            # EAX != 0 => Category 2 (Bad IRET)
-5:     pushl_cfi $0            # EAX == 0 => Category 1 (Bad segment)
+       jmp iret_exc
+5:     pushl_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        jmp ret_from_exception
        CFI_ENDPROC
index 0c58952d64e8723b4486ce620c8b11bcfe8d01f5..1328fe49a3f14d7a33615e892efca8d110aeb6e6 100644 (file)
@@ -995,8 +995,8 @@ END(interrupt)
         */
        .p2align CONFIG_X86_L1_CACHE_SHIFT
 common_interrupt:
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        addq $-0x80,(%rsp)              /* Adjust vector to [-256,-1] range */
        interrupt do_IRQ
        /* 0(%rsp): old_rsp-ARGOFFSET */
@@ -1135,8 +1135,8 @@ END(common_interrupt)
  */
 .macro apicinterrupt num sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        pushq_cfi $~(\num)
 .Lcommon_\sym:
        interrupt \do_sym
@@ -1190,8 +1190,8 @@ apicinterrupt IRQ_WORK_VECTOR \
  */
 .macro zeroentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1208,8 +1208,8 @@ END(\sym)
 
 .macro paranoidzeroentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1227,8 +1227,8 @@ END(\sym)
 #define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
 .macro paranoidzeroentry_ist sym do_sym ist
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1247,8 +1247,8 @@ END(\sym)
 
 .macro errorentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
@@ -1266,8 +1266,8 @@ END(\sym)
        /* error code is on the stack already */
 .macro paranoiderrorentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
@@ -1435,7 +1435,7 @@ ENTRY(xen_failsafe_callback)
        CFI_RESTORE r11
        addq $0x30,%rsp
        CFI_ADJUST_CFA_OFFSET -0x30
-       pushq_cfi $0
+       pushq_cfi $-1 /* orig_ax = -1 => not a system call */
        SAVE_ALL
        jmp error_exit
        CFI_ENDPROC
index b3e5e51bc907ef4da71549ff7e2214467721af0a..4180a874c764d4df9d514648082eee5ac6907930 100644 (file)
@@ -247,7 +247,10 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code)
                break;
        case KVM_PV_REASON_PAGE_NOT_PRESENT:
                /* page is swapped out by the host. */
+               rcu_irq_enter();
+               exit_idle();
                kvm_async_pf_task_wait((u32)read_cr2());
+               rcu_irq_exit();
                break;
        case KVM_PV_REASON_PAGE_READY:
                rcu_irq_enter();
index 7720ff5a9ee292a449ad13a9347e603def50df53..efdec7cd8e01057aeee63c95b16713c4803c7e61 100644 (file)
@@ -8,8 +8,8 @@
  *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *
  *  Maintainers:
- *  Andreas Herrmann <andreas.herrmann3@amd.com>
- *  Borislav Petkov <borislav.petkov@amd.com>
+ *  Andreas Herrmann <herrmann.der.user@googlemail.com>
+ *  Borislav Petkov <bp@alien8.de>
  *
  *  This driver allows to upgrade microcode on F10h AMD
  *  CPUs and later.
@@ -190,6 +190,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
 #define F1XH_MPB_MAX_SIZE 2048
 #define F14H_MPB_MAX_SIZE 1824
 #define F15H_MPB_MAX_SIZE 4096
+#define F16H_MPB_MAX_SIZE 3458
 
        switch (c->x86) {
        case 0x14:
@@ -198,6 +199,9 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
        case 0x15:
                max_size = F15H_MPB_MAX_SIZE;
                break;
+       case 0x16:
+               max_size = F16H_MPB_MAX_SIZE;
+               break;
        default:
                max_size = F1XH_MPB_MAX_SIZE;
                break;
index b00b33a183908bdb201aa38266e40ad87d89754d..5e0596b0632e244676c686bb0b338ea1e255473f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/rcupdate.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -166,6 +167,35 @@ static inline bool invalid_selector(u16 value)
 
 #define FLAG_MASK              FLAG_MASK_32
 
+/*
+ * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
+ * when it traps.  The previous stack will be directly underneath the saved
+ * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
+ *
+ * Now, if the stack is empty, '&regs->sp' is out of range. In this
+ * case we try to take the previous stack. To always return a non-null
+ * stack pointer we fall back to regs as stack if no previous stack
+ * exists.
+ *
+ * This is valid only for kernel mode traps.
+ */
+unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+       unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1);
+       unsigned long sp = (unsigned long)&regs->sp;
+       struct thread_info *tinfo;
+
+       if (context == (sp & ~(THREAD_SIZE - 1)))
+               return sp;
+
+       tinfo = (struct thread_info *)context;
+       if (tinfo->previous_esp)
+               return tinfo->previous_esp;
+
+       return (unsigned long)regs;
+}
+EXPORT_SYMBOL_GPL(kernel_stack_pointer);
+
 static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno)
 {
        BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0);
index 52190a938b4ac0d26a85704e6db4c131dd938aca..4e8ba39eaf0fd93cbca557eaecf3efcd954ee05b 100644 (file)
@@ -358,14 +358,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "VGN-Z540N"),
                },
        },
-       {       /* Handle problems with rebooting on CompuLab SBC-FITPC2 */
-               .callback = set_bios_reboot,
-               .ident = "CompuLab SBC-FITPC2",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "CompuLab"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "SBC-FITPC2"),
-               },
-       },
        {       /* Handle problems with rebooting on ASUS P4S800 */
                .callback = set_bios_reboot,
                .ident = "ASUS P4S800",
index a2bb18e02839489dcbf9dbc1e3d348f5fb176c34..ca45696f30fb8a01a4d6852388d08ab19d4bb778 100644 (file)
@@ -920,8 +920,22 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_X86_64
        if (max_pfn > max_low_pfn) {
-               max_pfn_mapped = init_memory_mapping(1UL<<32,
-                                                    max_pfn<<PAGE_SHIFT);
+               int i;
+               unsigned long start, end;
+               unsigned long start_pfn, end_pfn;
+
+               for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn,
+                                                        NULL) {
+
+                       end = PFN_PHYS(end_pfn);
+                       if (end <= (1UL<<32))
+                               continue;
+
+                       start = PFN_PHYS(start_pfn);
+                       max_pfn_mapped = init_memory_mapping(
+                                               max((1UL<<32), start), end);
+               }
+
                /* can we preseve max_low_pfn ?*/
                max_low_pfn = max_pfn;
        }
@@ -1035,6 +1049,18 @@ void __init setup_arch(char **cmdline_p)
        arch_init_ideal_nops();
 
        register_refined_jiffies(CLOCK_TICK_RATE);
+
+#ifdef CONFIG_EFI
+       /* Once setup is done above, disable efi_enabled on mismatched
+        * firmware/kernel archtectures since there is no support for
+        * runtime services.
+        */
+       if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
+               pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
+               efi_unmap_memmap();
+               efi_enabled = 0;
+       }
+#endif
 }
 
 #ifdef CONFIG_X86_32
index 29ad351804e9324d3aaf59c07c86d274958516b3..70b27ee6118e12c8411c7903e2254aeff44cd90e 100644 (file)
@@ -824,10 +824,8 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
                mce_notify_process();
 #endif /* CONFIG_X86_64 && CONFIG_X86_MCE */
 
-       if (thread_info_flags & _TIF_UPROBE) {
-               clear_thread_flag(TIF_UPROBE);
+       if (thread_info_flags & _TIF_UPROBE)
                uprobe_notify_resume(regs);
-       }
 
        /* deal with pending signal delivery */
        if (thread_info_flags & _TIF_SIGPENDING)
index 9538f00827a9b25257debf63aaa438ef6e40d68b..aafa5557b3964a57bf0abbdd9c849786688f1ce9 100644 (file)
@@ -651,31 +651,19 @@ void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
 
 /*
  * Skip these instructions as per the currently known x86 ISA.
- * 0x66* { 0x90 | 0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0 }
+ * rep=0x66*; nop=0x90
  */
 static bool __skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
 {
        int i;
 
        for (i = 0; i < MAX_UINSN_BYTES; i++) {
-               if ((auprobe->insn[i] == 0x66))
+               if (auprobe->insn[i] == 0x66)
                        continue;
 
                if (auprobe->insn[i] == 0x90)
                        return true;
 
-               if (i == (MAX_UINSN_BYTES - 1))
-                       break;
-
-               if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x1f))
-                       return true;
-
-               if ((auprobe->insn[i] == 0x0f) && (auprobe->insn[i+1] == 0x19))
-                       return true;
-
-               if ((auprobe->insn[i] == 0x87) && (auprobe->insn[i+1] == 0xc0))
-                       return true;
-
                break;
        }
        return false;
index a10e4601685135f0b5da599508be35eb754816ec..58fc5148882857c014a49b78403a597424c08e64 100644 (file)
@@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
 
+       if (!static_cpu_has(X86_FEATURE_XSAVE))
+               return 0;
+
        best = kvm_find_cpuid_entry(vcpu, 1, 0);
        return best && (best->ecx & bit(X86_FEATURE_XSAVE));
 }
index c6e6b721b6ee3a38d6267ee8867bd029fbdc6d6a..43e9fadca5d080a4e98a65735cbe071102742911 100644 (file)
@@ -1311,7 +1311,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
        vcpu->arch.apic_base = value;
        if (apic_x2apic_mode(apic)) {
                u32 id = kvm_apic_id(apic);
-               u32 ldr = ((id & ~0xf) << 16) | (1 << (id & 0xf));
+               u32 ldr = ((id >> 4) << 16) | (1 << (id & 0xf));
                kvm_apic_set_ldr(apic, ldr);
        }
        apic->base_address = apic->vcpu->arch.apic_base &
index d289fee1ffb8631c0b93f663104965fe7def7b11..6f85fe0bf958987f0275f1fa25e2b9e5240aad02 100644 (file)
@@ -2497,8 +2497,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
                }
        }
 
-       if (!is_error_pfn(pfn))
-               kvm_release_pfn_clean(pfn);
+       kvm_release_pfn_clean(pfn);
 }
 
 static void nonpaging_new_cr3(struct kvm_vcpu *vcpu)
index ad6b1dd06f8b967356d4f081f4cde119f2a2bfe8..f85815945fc6d62532c9735747759452cbe7c101 100644 (file)
@@ -6549,19 +6549,22 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
                }
        }
 
-       exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
        /* Exposing INVPCID only when PCID is exposed */
        best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
        if (vmx_invpcid_supported() &&
            best && (best->ebx & bit(X86_FEATURE_INVPCID)) &&
            guest_cpuid_has_pcid(vcpu)) {
+               exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
                exec_control |= SECONDARY_EXEC_ENABLE_INVPCID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
                             exec_control);
        } else {
-               exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
-               vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
-                            exec_control);
+               if (cpu_has_secondary_exec_ctrls()) {
+                       exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+                       exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
+                       vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+                                    exec_control);
+               }
                if (best)
                        best->ebx &= ~bit(X86_FEATURE_INVPCID);
        }
index 1eefebe5d72758873df0d13e4ae8c686a7d016ee..4f7641756be2d046cd55e3d59de76e145d3c39ae 100644 (file)
@@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
 {
        struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0];
 
-       memcpy(vcpu->run->mmio.data, frag->data, frag->len);
+       memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));
        return X86EMUL_CONTINUE;
 }
 
@@ -3832,18 +3832,11 @@ mmio:
        bytes -= handled;
        val += handled;
 
-       while (bytes) {
-               unsigned now = min(bytes, 8U);
-
-               frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
-               frag->gpa = gpa;
-               frag->data = val;
-               frag->len = now;
-
-               gpa += now;
-               val += now;
-               bytes -= now;
-       }
+       WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS);
+       frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++];
+       frag->gpa = gpa;
+       frag->data = val;
+       frag->len = bytes;
        return X86EMUL_CONTINUE;
 }
 
@@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,
        vcpu->mmio_needed = 1;
        vcpu->mmio_cur_fragment = 0;
 
-       vcpu->run->mmio.len = vcpu->mmio_fragments[0].len;
+       vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);
        vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;
        vcpu->run->exit_reason = KVM_EXIT_MMIO;
        vcpu->run->mmio.phys_addr = gpa;
@@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)
  *
  * read:
  *   for each fragment
- *     write gpa, len
- *     exit
- *     copy data
+ *     for each mmio piece in the fragment
+ *       write gpa, len
+ *       exit
+ *       copy data
  *   execute insn
  *
  * write:
  *   for each fragment
- *      write gpa, len
- *      copy data
- *      exit
+ *     for each mmio piece in the fragment
+ *       write gpa, len
+ *       copy data
+ *       exit
  */
 static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
 {
        struct kvm_run *run = vcpu->run;
        struct kvm_mmio_fragment *frag;
+       unsigned len;
 
        BUG_ON(!vcpu->mmio_needed);
 
        /* Complete previous fragment */
-       frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++];
+       frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment];
+       len = min(8u, frag->len);
        if (!vcpu->mmio_is_write)
-               memcpy(frag->data, run->mmio.data, frag->len);
+               memcpy(frag->data, run->mmio.data, len);
+
+       if (frag->len <= 8) {
+               /* Switch to the next fragment. */
+               frag++;
+               vcpu->mmio_cur_fragment++;
+       } else {
+               /* Go forward to the next mmio piece. */
+               frag->data += len;
+               frag->gpa += len;
+               frag->len -= len;
+       }
+
        if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {
                vcpu->mmio_needed = 0;
                if (vcpu->mmio_is_write)
@@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)
                vcpu->mmio_read_completed = 1;
                return complete_emulated_io(vcpu);
        }
-       /* Initiate next fragment */
-       ++frag;
+
        run->exit_reason = KVM_EXIT_MMIO;
        run->mmio.phys_addr = frag->gpa;
        if (vcpu->mmio_is_write)
-               memcpy(run->mmio.data, frag->data, frag->len);
-       run->mmio.len = frag->len;
+               memcpy(run->mmio.data, frag->data, min(8u, frag->len));
+       run->mmio.len = min(8u, frag->len);
        run->mmio.is_write = vcpu->mmio_is_write;
        vcpu->arch.complete_userspace_io = complete_emulated_mmio;
        return 0;
@@ -5773,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        int pending_vec, max_bits, idx;
        struct desc_ptr dt;
 
+       if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE))
+               return -EINVAL;
+
        dt.size = sregs->idt.limit;
        dt.address = sregs->idt.base;
        kvm_x86_ops->set_idt(vcpu, &dt);
index ab1f6a93b527c9bd50acc12a52e9ce157f2cc48b..d7aea41563b372437eb227a499259be23d755564 100644 (file)
@@ -35,40 +35,44 @@ struct map_range {
        unsigned page_size_mask;
 };
 
-static void __init find_early_table_space(struct map_range *mr, unsigned long end,
-                                         int use_pse, int use_gbpages)
+/*
+ * First calculate space needed for kernel direct mapping page tables to cover
+ * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB
+ * pages. Then find enough contiguous space for those page tables.
+ */
+static void __init find_early_table_space(struct map_range *mr, int nr_range)
 {
-       unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
+       int i;
+       unsigned long puds = 0, pmds = 0, ptes = 0, tables;
+       unsigned long start = 0, good_end;
        phys_addr_t base;
 
-       puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
-       tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
-
-       if (use_gbpages) {
-               unsigned long extra;
-
-               extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT);
-               pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT;
-       } else
-               pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT;
+       for (i = 0; i < nr_range; i++) {
+               unsigned long range, extra;
 
-       tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
+               range = mr[i].end - mr[i].start;
+               puds += (range + PUD_SIZE - 1) >> PUD_SHIFT;
 
-       if (use_pse) {
-               unsigned long extra;
+               if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) {
+                       extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT);
+                       pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT;
+               } else {
+                       pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT;
+               }
 
-               extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT);
+               if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) {
+                       extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT);
 #ifdef CONFIG_X86_32
-               extra += PMD_SIZE;
+                       extra += PMD_SIZE;
 #endif
-               /* The first 2/4M doesn't use large pages. */
-               if (mr->start < PMD_SIZE)
-                       extra += mr->end - mr->start;
-
-               ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       } else
-               ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
+                       ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               } else {
+                       ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT;
+               }
+       }
 
+       tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
+       tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
        tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
 
 #ifdef CONFIG_X86_32
@@ -86,7 +90,7 @@ static void __init find_early_table_space(struct map_range *mr, unsigned long en
        pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
 
        printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n",
-               end - 1, pgt_buf_start << PAGE_SHIFT,
+               mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT,
                (pgt_buf_top << PAGE_SHIFT) - 1);
 }
 
@@ -267,7 +271,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
         * nodes are discovered.
         */
        if (!after_bootmem)
-               find_early_table_space(&mr[0], end, use_pse, use_gbpages);
+               find_early_table_space(mr, nr_range);
 
        for (i = 0; i < nr_range; i++)
                ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,
index 2b6b4a3c8beb8727d27b1cdba22411fe0d271efb..3baff255adac6472570298d7e9ee60df75e93dfc 100644 (file)
@@ -386,7 +386,8 @@ phys_pte_init(pte_t *pte_page, unsigned long addr, unsigned long end,
                 * these mappings are more intelligent.
                 */
                if (pte_val(*pte)) {
-                       pages++;
+                       if (!after_bootmem)
+                               pages++;
                        continue;
                }
 
@@ -451,6 +452,8 @@ phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
                         * attributes.
                         */
                        if (page_size_mask & (1 << PG_LEVEL_2M)) {
+                               if (!after_bootmem)
+                                       pages++;
                                last_map_addr = next;
                                continue;
                        }
@@ -526,6 +529,8 @@ phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
                         * attributes.
                         */
                        if (page_size_mask & (1 << PG_LEVEL_1G)) {
+                               if (!after_bootmem)
+                                       pages++;
                                last_map_addr = next;
                                continue;
                        }
index 0777f042e4002e695b316c99889b594daebc5448..60f926cd8b0edbf44277a18718dd86cb4a077bd1 100644 (file)
@@ -197,7 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
        }
 
        if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1
-                                       || vmflag == VM_HUGETLB) {
+                                       || vmflag & VM_HUGETLB) {
                local_flush_tlb();
                goto flush_all;
        }
index 520d2bd0b9c583de16ce246ffbf938c5c9f48b33..d11a47099d330d1dcdc21261df571212551f3f03 100644 (file)
@@ -11,6 +11,7 @@
 #include <asm/cacheflush.h>
 #include <linux/netdevice.h>
 #include <linux/filter.h>
+#include <linux/if_vlan.h>
 
 /*
  * Conventions :
@@ -212,6 +213,8 @@ void bpf_jit_compile(struct sk_filter *fp)
                case BPF_S_ANC_MARK:
                case BPF_S_ANC_RXHASH:
                case BPF_S_ANC_CPU:
+               case BPF_S_ANC_VLAN_TAG:
+               case BPF_S_ANC_VLAN_TAG_PRESENT:
                case BPF_S_ANC_QUEUE:
                case BPF_S_LD_W_ABS:
                case BPF_S_LD_H_ABS:
@@ -515,6 +518,24 @@ void bpf_jit_compile(struct sk_filter *fp)
                                CLEAR_A();
 #endif
                                break;
+                       case BPF_S_ANC_VLAN_TAG:
+                       case BPF_S_ANC_VLAN_TAG_PRESENT:
+                               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+                               if (is_imm8(offsetof(struct sk_buff, vlan_tci))) {
+                                       /* movzwl off8(%rdi),%eax */
+                                       EMIT4(0x0f, 0xb7, 0x47, offsetof(struct sk_buff, vlan_tci));
+                               } else {
+                                       EMIT3(0x0f, 0xb7, 0x87); /* movzwl off32(%rdi),%eax */
+                                       EMIT(offsetof(struct sk_buff, vlan_tci), 4);
+                               }
+                               BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000);
+                               if (filter[i].code == BPF_S_ANC_VLAN_TAG) {
+                                       EMIT3(0x80, 0xe4, 0xef); /* and    $0xef,%ah */
+                               } else {
+                                       EMIT3(0xc1, 0xe8, 0x0c); /* shr    $0xc,%eax */
+                                       EMIT3(0x83, 0xe0, 0x01); /* and    $0x1,%eax */
+                               }
+                               break;
                        case BPF_S_LD_W_ABS:
                                func = CHOOSE_LOAD_FUNC(K, sk_load_word);
 common_load:                   seen |= SEEN_DATAREF;
index 26b8a8514ee566e8a7d235a06de1037c2641adec..48768df2471af2bc9e4059fad6eb8c583f93f4d0 100644 (file)
@@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model,
        val |= counter_config->extra;
        event &= model->event_mask ? model->event_mask : 0xFF;
        val |= event & 0xFF;
-       val |= (event & 0x0F00) << 24;
+       val |= (u64)(event & 0x0F00) << 24;
 
        return val;
 }
index 41bd2a2d2c50f61a4948f954f296631c8dfd7961..b914e20b5a0033c7cb856c1e82eeea207187eb07 100644 (file)
@@ -115,6 +115,16 @@ static void sata_revid_read(struct sim_dev_reg *reg, u32 *value)
        reg_read(reg, value);
 }
 
+static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
+       /* force interrupt pin value to 0 */
+       *value = reg->sim_reg.value & 0xfff00ff;
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+}
+
 static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write)
        DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write)
@@ -144,6 +154,7 @@ static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write)
        DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write)
+       DEFINE_REG(11, 7, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
        DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write)
        DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write)
@@ -161,8 +172,10 @@ static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write)
        DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write)
+       DEFINE_REG(16, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
        DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write)
+       DEFINE_REG(18, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
 };
 
 static void __init init_sim_regs(void)
index 4c61b52191eb293bcaef2cac2380c6114cdaefcf..92525cb8e54c84c0ebe6b2caeacb47f4f8ab299b 100644 (file)
 #include <asm/i8259.h>
 #include <asm/io.h>
 #include <asm/io_apic.h>
+#include <asm/emergency-restart.h>
 
 static int ce4100_i8042_detect(void)
 {
        return 0;
 }
 
+/*
+ * The CE4100 platform has an internal 8051 Microcontroller which is
+ * responsible for signaling to the external Power Management Unit the
+ * intention to reset, reboot or power off the system. This 8051 device has
+ * its command register mapped at I/O port 0xcf9 and the value 0x4 is used
+ * to power off the system.
+ */
+static void ce4100_power_off(void)
+{
+       outb(0x4, 0xcf9);
+}
+
 #ifdef CONFIG_SERIAL_8250
 
 static unsigned int mem_serial_in(struct uart_port *p, int offset)
@@ -139,8 +152,19 @@ void __init x86_ce4100_early_setup(void)
        x86_init.mpparse.find_smp_config = x86_init_noop;
        x86_init.pci.init = ce4100_pci_init;
 
+       /*
+        * By default, the reboot method is ACPI which is supported by the
+        * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue
+        * the bootloader will however issue a system power off instead of
+        * reboot. By using BOOT_KBD we ensure proper system reboot as
+        * expected.
+        */
+       reboot_type = BOOT_KBD;
+
 #ifdef CONFIG_X86_IO_APIC
        x86_init.pci.init_irq = sdv_pci_init;
        x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
 #endif
+
+       pm_power_off = ce4100_power_off;
 }
index aded2a91162a8af12ad104d047544afce91ff4c4..ad4439145f858314dfe518cf7cd9336c5fe9c96d 100644 (file)
@@ -70,11 +70,15 @@ EXPORT_SYMBOL(efi);
 struct efi_memory_map memmap;
 
 bool efi_64bit;
-static bool efi_native;
 
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
+static inline bool efi_is_native(void)
+{
+       return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
+}
+
 static int __init setup_noefi(char *arg)
 {
        efi_enabled = 0;
@@ -420,7 +424,7 @@ void __init efi_reserve_boot_services(void)
        }
 }
 
-static void __init efi_unmap_memmap(void)
+void __init efi_unmap_memmap(void)
 {
        if (memmap.map) {
                early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
@@ -432,7 +436,7 @@ void __init efi_free_boot_services(void)
 {
        void *p;
 
-       if (!efi_native)
+       if (!efi_is_native())
                return;
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
@@ -684,12 +688,10 @@ void __init efi_init(void)
                return;
        }
        efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
-       efi_native = !efi_64bit;
 #else
        efi_phys.systab = (efi_system_table_t *)
                          (boot_params.efi_info.efi_systab |
                          ((__u64)boot_params.efi_info.efi_systab_hi<<32));
-       efi_native = efi_64bit;
 #endif
 
        if (efi_systab_init(efi_phys.systab)) {
@@ -723,7 +725,7 @@ void __init efi_init(void)
         * that doesn't match the kernel 32/64-bit mode.
         */
 
-       if (!efi_native)
+       if (!efi_is_native())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
        else if (efi_runtime_init()) {
                efi_enabled = 0;
@@ -735,7 +737,7 @@ void __init efi_init(void)
                return;
        }
 #ifdef CONFIG_X86_32
-       if (efi_native) {
+       if (efi_is_native()) {
                x86_platform.get_wallclock = efi_get_time;
                x86_platform.set_wallclock = efi_set_rtc_mmss;
        }
@@ -810,6 +812,16 @@ void __iomem *efi_lookup_mapped_addr(u64 phys_addr)
        return NULL;
 }
 
+void efi_memory_uc(u64 addr, unsigned long size)
+{
+       unsigned long page_shift = 1UL << EFI_PAGE_SHIFT;
+       u64 npages;
+
+       npages = round_up(size, page_shift) / page_shift;
+       memrange_efi_to_native(&addr, &npages);
+       set_memory_uc(addr, npages);
+}
+
 /*
  * This function will switch the EFI runtime services to virtual mode.
  * Essentially, look through the EFI memmap and map every region that
@@ -823,7 +835,7 @@ void __init efi_enter_virtual_mode(void)
        efi_memory_desc_t *md, *prev_md = NULL;
        efi_status_t status;
        unsigned long size;
-       u64 end, systab, addr, npages, end_pfn;
+       u64 end, systab, end_pfn;
        void *p, *va, *new_memmap = NULL;
        int count = 0;
 
@@ -834,7 +846,7 @@ void __init efi_enter_virtual_mode(void)
         * non-native EFI
         */
 
-       if (!efi_native) {
+       if (!efi_is_native()) {
                efi_unmap_memmap();
                return;
        }
@@ -879,10 +891,14 @@ void __init efi_enter_virtual_mode(void)
                end_pfn = PFN_UP(end);
                if (end_pfn <= max_low_pfn_mapped
                    || (end_pfn > (1UL << (32 - PAGE_SHIFT))
-                       && end_pfn <= max_pfn_mapped))
+                       && end_pfn <= max_pfn_mapped)) {
                        va = __va(md->phys_addr);
-               else
-                       va = efi_ioremap(md->phys_addr, size, md->type);
+
+                       if (!(md->attribute & EFI_MEMORY_WB))
+                               efi_memory_uc((u64)(unsigned long)va, size);
+               } else
+                       va = efi_ioremap(md->phys_addr, size,
+                                        md->type, md->attribute);
 
                md->virt_addr = (u64) (unsigned long) va;
 
@@ -892,13 +908,6 @@ void __init efi_enter_virtual_mode(void)
                        continue;
                }
 
-               if (!(md->attribute & EFI_MEMORY_WB)) {
-                       addr = md->virt_addr;
-                       npages = md->num_pages;
-                       memrange_efi_to_native(&addr, &npages);
-                       set_memory_uc(addr, npages);
-               }
-
                systab = (u64) (unsigned long) efi_phys.systab;
                if (md->phys_addr <= systab && systab < end) {
                        systab += md->virt_addr - md->phys_addr;
index ac3aa54e26546ba5cb4121eba0c58ca00f06ea82..95fd505dfeb6e43dd37b0c41954f0b0db6535d1c 100644 (file)
@@ -82,7 +82,7 @@ void __init efi_call_phys_epilog(void)
 }
 
 void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
-                                u32 type)
+                                u32 type, u64 attribute)
 {
        unsigned long last_map_pfn;
 
@@ -92,8 +92,11 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
        last_map_pfn = init_memory_mapping(phys_addr, phys_addr + size);
        if ((last_map_pfn << PAGE_SHIFT) < phys_addr + size) {
                unsigned long top = last_map_pfn << PAGE_SHIFT;
-               efi_ioremap(top, size - (top - phys_addr), type);
+               efi_ioremap(top, size - (top - phys_addr), type, attribute);
        }
 
+       if (!(attribute & EFI_MEMORY_WB))
+               efi_memory_uc((u64)(unsigned long)__va(phys_addr), size);
+
        return (void __iomem *)__va(phys_addr);
 }
index e56479e580534ffd0cd5b3eb70531d4dd716869f..9e7e14797a72dda0b85d4c70afca61fdb2fdf92e 100644 (file)
@@ -74,18 +74,9 @@ ENTRY(wakeup_start)
 
        lidtl   wakeup_idt
 
-       /* Clear the EFLAGS but remember if we have EFLAGS.ID */
-       movl $X86_EFLAGS_ID, %ecx
-       pushl %ecx
-       popfl
-       pushfl
-       popl %edi
+       /* Clear the EFLAGS */
        pushl $0
        popfl
-       pushfl
-       popl %edx
-       xorl %edx, %edi
-       andl %ecx, %edi         /* %edi is zero iff CPUID & %cr4 are missing */
 
        /* Check header signature... */
        movl    signature, %eax
@@ -120,12 +111,12 @@ ENTRY(wakeup_start)
        movl    %eax, %cr3
 
        btl     $WAKEUP_BEHAVIOR_RESTORE_CR4, %edi
-       j     1f
+       jnc     1f
        movl    pmode_cr4, %eax
        movl    %eax, %cr4
 1:
        btl     $WAKEUP_BEHAVIOR_RESTORE_EFER, %edi
-       j     1f
+       jnc     1f
        movl    pmode_efer, %eax
        movl    pmode_efer + 4, %edx
        movl    $MSR_EFER, %ecx
index e3497f240eabb869e6cda863036689e6b093899d..586d83812b67b64f96594f1eebdc859bdcb12adc 100644 (file)
@@ -81,8 +81,6 @@
 #include "smp.h"
 #include "multicalls.h"
 
-#include <xen/events.h>
-
 EXPORT_SYMBOL_GPL(hypercall_page);
 
 DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
index 6226c99729b963594a2e133290cbf8f3c6e681b8..dcf5f2dd91ec4fd91d814d46c7d6dbd6c5312a61 100644 (file)
@@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)
        return this_cpu_read(xen_vcpu_info.arch.cr2);
 }
 
+void xen_flush_tlb_all(void)
+{
+       struct mmuext_op *op;
+       struct multicall_space mcs;
+
+       trace_xen_mmu_flush_tlb_all(0);
+
+       preempt_disable();
+
+       mcs = xen_mc_entry(sizeof(*op));
+
+       op = mcs.args;
+       op->cmd = MMUEXT_TLB_FLUSH_ALL;
+       MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
+
+       xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+       preempt_enable();
+}
 static void xen_flush_tlb(void)
 {
        struct mmuext_op *op;
@@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,
        err = 0;
 out:
 
-       flush_tlb_all();
+       xen_flush_tlb_all();
 
        return err;
 }
index cdcb48adee4c6d05f65f34fb9893a55afdb4c5f1..0d1f36a22c98827ba204af46859b349ac3da91ae 100644 (file)
@@ -13,6 +13,8 @@ config XTENSA
        select GENERIC_CPU_DEVICES
        select MODULES_USE_ELF_RELA
        select GENERIC_PCI_IOMAP
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        select ARCH_WANT_OPTIONAL_GPIOLIB
        help
          Xtensa processors are 32-bit RISC machines designed by Tensilica
index 4c316cd28a542b2f06685179eb0e37b7819b539a..86c34dbc9cd0abdf1b5b055f6d9a7b46e082aae2 100644 (file)
@@ -51,17 +51,17 @@ _start:
        /* 'reset' window registers */
 
        movi    a4, 1
-       wsr     a4, PS
+       wsr     a4, ps
        rsync
 
-       rsr     a5, WINDOWBASE
+       rsr     a5, windowbase
        ssl     a5
        sll     a4, a4
-       wsr     a4, WINDOWSTART
+       wsr     a4, windowstart
        rsync
 
        movi    a4, 0x00040000
-       wsr     a4, PS
+       wsr     a4, ps
        rsync
 
        /* copy the loader to its address
index fccd81eddff1f6de89b07cc13c362809364c9507..6d13027899957d528a142964db0b299d36b74a13 100644 (file)
@@ -1,4 +1,28 @@
-include include/asm-generic/Kbuild.asm
-
+generic-y += bitsperlong.h
+generic-y += bug.h
 generic-y += clkdev.h
+generic-y += cputime.h
+generic-y += device.h
+generic-y += div64.h
+generic-y += emergency-restart.h
+generic-y += errno.h
 generic-y += exec.h
+generic-y += fcntl.h
+generic-y += futex.h
+generic-y += hardirq.h
+generic-y += ioctl.h
+generic-y += irq_regs.h
+generic-y += kdebug.h
+generic-y += kmap_types.h
+generic-y += kvm_para.h
+generic-y += local.h
+generic-y += local64.h
+generic-y += percpu.h
+generic-y += resource.h
+generic-y += scatterlist.h
+generic-y += sections.h
+generic-y += siginfo.h
+generic-y += statfs.h
+generic-y += termios.h
+generic-y += topology.h
+generic-y += xor.h
index b4098930877587d7dec309bbc702a5ed674c94f6..24f50cada70c27ae041356f960b728dc285e4e5b 100644 (file)
@@ -73,7 +73,7 @@ static inline void atomic_add(int i, atomic_t * v)
        "l32i    %0, %2, 0              \n\t"
        "add     %0, %0, %1             \n\t"
        "s32i    %0, %2, 0              \n\t"
-       "wsr     a15, "__stringify(PS)"       \n\t"
+       "wsr     a15, ps                \n\t"
        "rsync                          \n"
        : "=&a" (vval)
        : "a" (i), "a" (v)
@@ -97,7 +97,7 @@ static inline void atomic_sub(int i, atomic_t *v)
        "l32i    %0, %2, 0              \n\t"
        "sub     %0, %0, %1             \n\t"
        "s32i    %0, %2, 0              \n\t"
-       "wsr     a15, "__stringify(PS)"       \n\t"
+       "wsr     a15, ps                \n\t"
        "rsync                          \n"
        : "=&a" (vval)
        : "a" (i), "a" (v)
@@ -118,7 +118,7 @@ static inline int atomic_add_return(int i, atomic_t * v)
        "l32i    %0, %2, 0             \n\t"
        "add     %0, %0, %1            \n\t"
        "s32i    %0, %2, 0             \n\t"
-       "wsr     a15, "__stringify(PS)"      \n\t"
+       "wsr     a15, ps               \n\t"
        "rsync                         \n"
        : "=&a" (vval)
        : "a" (i), "a" (v)
@@ -137,7 +137,7 @@ static inline int atomic_sub_return(int i, atomic_t * v)
        "l32i    %0, %2, 0             \n\t"
        "sub     %0, %0, %1            \n\t"
        "s32i    %0, %2, 0             \n\t"
-       "wsr     a15, "__stringify(PS)"       \n\t"
+       "wsr     a15, ps               \n\t"
        "rsync                         \n"
        : "=&a" (vval)
        : "a" (i), "a" (v)
@@ -260,7 +260,7 @@ static inline void atomic_clear_mask(unsigned int mask, atomic_t *v)
        "xor     %1, %4, %3            \n\t"
        "and     %0, %0, %4            \n\t"
        "s32i    %0, %2, 0             \n\t"
-       "wsr     a15, "__stringify(PS)"      \n\t"
+       "wsr     a15, ps               \n\t"
        "rsync                         \n"
        : "=&a" (vval), "=a" (mask)
        : "a" (v), "a" (all_f), "1" (mask)
@@ -277,7 +277,7 @@ static inline void atomic_set_mask(unsigned int mask, atomic_t *v)
        "l32i    %0, %2, 0             \n\t"
        "or      %0, %0, %1            \n\t"
        "s32i    %0, %2, 0             \n\t"
-       "wsr     a15, "__stringify(PS)"       \n\t"
+       "wsr     a15, ps               \n\t"
        "rsync                         \n"
        : "=&a" (vval)
        : "a" (mask), "a" (v)
diff --git a/arch/xtensa/include/asm/auxvec.h b/arch/xtensa/include/asm/auxvec.h
deleted file mode 100644 (file)
index 257dec7..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#ifndef __XTENSA_AUXVEC_H
-#define __XTENSA_AUXVEC_H
-
-#endif
diff --git a/arch/xtensa/include/asm/bitsperlong.h b/arch/xtensa/include/asm/bitsperlong.h
deleted file mode 100644 (file)
index 6dc0bb0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/bitsperlong.h>
diff --git a/arch/xtensa/include/asm/bug.h b/arch/xtensa/include/asm/bug.h
deleted file mode 100644 (file)
index 3e52d72..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * include/asm-xtensa/bug.h
- *
- * Macros to cause a 'bug' message.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_BUG_H
-#define _XTENSA_BUG_H
-
-#include <asm-generic/bug.h>
-
-#endif /* _XTENSA_BUG_H */
diff --git a/arch/xtensa/include/asm/byteorder.h b/arch/xtensa/include/asm/byteorder.h
deleted file mode 100644 (file)
index 54eb631..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef _XTENSA_BYTEORDER_H
-#define _XTENSA_BYTEORDER_H
-
-#ifdef __XTENSA_EL__
-#include <linux/byteorder/little_endian.h>
-#elif defined(__XTENSA_EB__)
-#include <linux/byteorder/big_endian.h>
-#else
-# error processor byte order undefined!
-#endif
-
-#endif /* _XTENSA_BYTEORDER_H */
index 376cd9d5f45529c48078b7a84e9c7618ad865060..569fec4f9a20db0899e8ee92085ba4faea2fa4d2 100644 (file)
@@ -165,7 +165,7 @@ extern void copy_from_user_page(struct vm_area_struct*, struct page*,
 static inline u32 xtensa_get_cacheattr(void)
 {
        u32 r;
-       asm volatile("  rsr %0, CACHEATTR" : "=a"(r));
+       asm volatile("  rsr %0, cacheattr" : "=a"(r));
        return r;
 }
 
index e32149063d83163cdb3ac68132f5c10e981f0ce4..64dad04a9d276453cfca46df63eabcad816a07e2 100644 (file)
@@ -27,7 +27,7 @@ __cmpxchg_u32(volatile int *p, int old, int new)
                       "bne     %0, %2, 1f             \n\t"
                       "s32i    %3, %1, 0              \n\t"
                       "1:                             \n\t"
-                      "wsr     a15, "__stringify(PS)" \n\t"
+                      "wsr     a15, ps                \n\t"
                       "rsync                          \n\t"
                       : "=&a" (old)
                       : "a" (p), "a" (old), "r" (new)
@@ -97,7 +97,7 @@ static inline unsigned long xchg_u32(volatile int * m, unsigned long val)
   __asm__ __volatile__("rsil    a15, "__stringify(LOCKLEVEL)"\n\t"
                       "l32i    %0, %1, 0              \n\t"
                       "s32i    %2, %1, 0              \n\t"
-                      "wsr     a15, "__stringify(PS)" \n\t"
+                      "wsr     a15, ps                \n\t"
                       "rsync                          \n\t"
                       : "=&a" (tmp)
                       : "a" (m), "a" (val)
index 75c94a1658b02b81b14ec3759c5f29cb8db97a4d..677501b32dfcfa0b5a8471c73cc118b3d4415855 100644 (file)
 #if XCHAL_HAVE_CP
 
 #define RSR_CPENABLE(x)        do {                                              \
-       __asm__ __volatile__("rsr %0," __stringify(CPENABLE) : "=a" (x)); \
+       __asm__ __volatile__("rsr %0, cpenable" : "=a" (x));              \
        } while(0);
 #define WSR_CPENABLE(x)        do {                                              \
-       __asm__ __volatile__("wsr %0," __stringify(CPENABLE) "; rsync"    \
-                            :: "a" (x));                                 \
+       __asm__ __volatile__("wsr %0, cpenable; rsync" :: "a" (x));       \
        } while(0);
 
 #endif /* XCHAL_HAVE_CP */
diff --git a/arch/xtensa/include/asm/cputime.h b/arch/xtensa/include/asm/cputime.h
deleted file mode 100644 (file)
index a7fb864..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _XTENSA_CPUTIME_H
-#define _XTENSA_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* _XTENSA_CPUTIME_H */
index e1d8c9e010c1df976624ce71ea0449d6c8f47ae4..58c0a4fd4003891f18cd1c9a4f8babe4f1923be3 100644 (file)
@@ -27,7 +27,7 @@ static inline void __delay(unsigned long loops)
 static __inline__ u32 xtensa_get_ccount(void)
 {
        u32 ccount;
-       asm volatile ("rsr %0, 234; # CCOUNT\n" : "=r" (ccount));
+       asm volatile ("rsr %0, ccount\n" : "=r" (ccount));
        return ccount;
 }
 
diff --git a/arch/xtensa/include/asm/device.h b/arch/xtensa/include/asm/device.h
deleted file mode 100644 (file)
index d8f9872..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#include <asm-generic/device.h>
-
diff --git a/arch/xtensa/include/asm/div64.h b/arch/xtensa/include/asm/div64.h
deleted file mode 100644 (file)
index f35678c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/div64.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2007 Tensilica Inc.
- */
-
-#ifndef _XTENSA_DIV64_H
-#define _XTENSA_DIV64_H
-
-#include <asm-generic/div64.h>
-
-#endif /* _XTENSA_DIV64_H */
diff --git a/arch/xtensa/include/asm/emergency-restart.h b/arch/xtensa/include/asm/emergency-restart.h
deleted file mode 100644 (file)
index 108d8c4..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
diff --git a/arch/xtensa/include/asm/errno.h b/arch/xtensa/include/asm/errno.h
deleted file mode 100644 (file)
index a0f3b96..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/errno.h
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_ERRNO_H
-#define _XTENSA_ERRNO_H
-
-#include <asm-generic/errno.h>
-
-#endif /* _XTENSA_ERRNO_H */
diff --git a/arch/xtensa/include/asm/fcntl.h b/arch/xtensa/include/asm/fcntl.h
deleted file mode 100644 (file)
index 46ab12d..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/fcntl.h>
diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h
deleted file mode 100644 (file)
index 0b74582..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/futex.h>
diff --git a/arch/xtensa/include/asm/hardirq.h b/arch/xtensa/include/asm/hardirq.h
deleted file mode 100644 (file)
index 91695a1..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/hardirq.h
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2002 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_HARDIRQ_H
-#define _XTENSA_HARDIRQ_H
-
-#include <asm-generic/hardirq.h>
-
-#endif /* _XTENSA_HARDIRQ_H */
index e6be5b9091c2a65509f721ed3e5f92bc7c6783bc..700c2e6f2d259d454f5f8f310b431d6b20ecbc1f 100644 (file)
@@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
 static inline void iounmap(volatile void __iomem *addr)
 {
 }
+
+#define virt_to_bus     virt_to_phys
+#define bus_to_virt     phys_to_virt
+
 #endif /* CONFIG_MMU */
 
 /*
diff --git a/arch/xtensa/include/asm/ioctl.h b/arch/xtensa/include/asm/ioctl.h
deleted file mode 100644 (file)
index b279fe0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/ioctl.h>
diff --git a/arch/xtensa/include/asm/ioctls.h b/arch/xtensa/include/asm/ioctls.h
deleted file mode 100644 (file)
index 2aa4cd9..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * include/asm-xtensa/ioctls.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2003 - 2005 Tensilica Inc.
- *
- * Derived from "include/asm-i386/ioctls.h"
- */
-
-#ifndef _XTENSA_IOCTLS_H
-#define _XTENSA_IOCTLS_H
-
-#include <asm/ioctl.h>
-
-#define FIOCLEX                _IO('f', 1)
-#define FIONCLEX       _IO('f', 2)
-#define FIOASYNC       _IOW('f', 125, int)
-#define FIONBIO                _IOW('f', 126, int)
-#define FIONREAD       _IOR('f', 127, int)
-#define TIOCINQ                FIONREAD
-#define FIOQSIZE       _IOR('f', 128, loff_t)
-
-#define TCGETS         0x5401
-#define TCSETS         0x5402
-#define TCSETSW                0x5403
-#define TCSETSF                0x5404
-
-#define TCGETA         _IOR('t', 23, struct termio)
-#define TCSETA         _IOW('t', 24, struct termio)
-#define TCSETAW                _IOW('t', 25, struct termio)
-#define TCSETAF                _IOW('t', 28, struct termio)
-
-#define TCSBRK         _IO('t', 29)
-#define TCXONC         _IO('t', 30)
-#define TCFLSH         _IO('t', 31)
-
-#define TIOCSWINSZ     _IOW('t', 103, struct winsize)
-#define TIOCGWINSZ     _IOR('t', 104, struct winsize)
-#define        TIOCSTART       _IO('t', 110)           /* start output, like ^Q */
-#define        TIOCSTOP        _IO('t', 111)           /* stop output, like ^S */
-#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
-
-#define TIOCSPGRP      _IOW('t', 118, int)
-#define TIOCGPGRP      _IOR('t', 119, int)
-
-#define TIOCEXCL       _IO('T', 12)
-#define TIOCNXCL       _IO('T', 13)
-#define TIOCSCTTY      _IO('T', 14)
-
-#define TIOCSTI                _IOW('T', 18, char)
-#define TIOCMGET       _IOR('T', 21, unsigned int)
-#define TIOCMBIS       _IOW('T', 22, unsigned int)
-#define TIOCMBIC       _IOW('T', 23, unsigned int)
-#define TIOCMSET       _IOW('T', 24, unsigned int)
-# define TIOCM_LE      0x001
-# define TIOCM_DTR     0x002
-# define TIOCM_RTS     0x004
-# define TIOCM_ST      0x008
-# define TIOCM_SR      0x010
-# define TIOCM_CTS     0x020
-# define TIOCM_CAR     0x040
-# define TIOCM_RNG     0x080
-# define TIOCM_DSR     0x100
-# define TIOCM_CD      TIOCM_CAR
-# define TIOCM_RI      TIOCM_RNG
-
-#define TIOCGSOFTCAR   _IOR('T', 25, unsigned int)
-#define TIOCSSOFTCAR   _IOW('T', 26, unsigned int)
-#define TIOCLINUX      _IOW('T', 28, char)
-#define TIOCCONS       _IO('T', 29)
-#define TIOCGSERIAL    0x803C541E      /*_IOR('T', 30, struct serial_struct)*/
-#define TIOCSSERIAL    0x403C541F      /*_IOW('T', 31, struct serial_struct)*/
-#define TIOCPKT                _IOW('T', 32, int)
-# define TIOCPKT_DATA           0
-# define TIOCPKT_FLUSHREAD      1
-# define TIOCPKT_FLUSHWRITE     2
-# define TIOCPKT_STOP           4
-# define TIOCPKT_START          8
-# define TIOCPKT_NOSTOP                16
-# define TIOCPKT_DOSTOP                32
-# define TIOCPKT_IOCTL         64
-
-
-#define TIOCNOTTY      _IO('T', 34)
-#define TIOCSETD       _IOW('T', 35, int)
-#define TIOCGETD       _IOR('T', 36, int)
-#define TCSBRKP                _IOW('T', 37, int)   /* Needed for POSIX tcsendbreak()*/
-#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/
-#define TIOCSBRK       _IO('T', 39)         /* BSD compatibility */
-#define TIOCCBRK       _IO('T', 40)         /* BSD compatibility */
-#define TIOCGSID       _IOR('T', 41, pid_t) /* Return the session ID of FD*/
-#define TCGETS2                _IOR('T', 42, struct termios2)
-#define TCSETS2                _IOW('T', 43, struct termios2)
-#define TCSETSW2       _IOW('T', 44, struct termios2)
-#define TCSETSF2       _IOW('T', 45, struct termios2)
-#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
-#define TIOCGDEV       _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
-#define TIOCSIG                _IOW('T',0x36, int)  /* Generate signal on Pty slave */
-#define TIOCVHANGUP    _IO('T', 0x37)
-
-#define TIOCSERCONFIG  _IO('T', 83)
-#define TIOCSERGWILD   _IOR('T', 84,  int)
-#define TIOCSERSWILD   _IOW('T', 85,  int)
-#define TIOCGLCKTRMIOS 0x5456
-#define TIOCSLCKTRMIOS 0x5457
-#define TIOCSERGSTRUCT 0x5458               /* For debugging only */
-#define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* Get line status reg. */
-  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-# define TIOCSER_TEMT    0x01               /* Transmitter physically empty */
-#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config  */
-#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
-
-#define TIOCMIWAIT     _IO('T', 92) /* wait for a change on serial input line(s) */
-#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
-
-#endif /* _XTENSA_IOCTLS_H */
diff --git a/arch/xtensa/include/asm/ipcbuf.h b/arch/xtensa/include/asm/ipcbuf.h
deleted file mode 100644 (file)
index c33aa6a..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * include/asm-xtensa/ipcbuf.h
- *
- * The ipc64_perm structure for the Xtensa architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_IPCBUF_H
-#define _XTENSA_IPCBUF_H
-
-/*
- * Pad space is left for:
- * - 32-bit mode_t and seq
- * - 2 miscellaneous 32-bit values
- *
- * 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.
- */
-
-struct ipc64_perm
-{
-       __kernel_key_t          key;
-       __kernel_uid32_t        uid;
-       __kernel_gid32_t        gid;
-       __kernel_uid32_t        cuid;
-       __kernel_gid32_t        cgid;
-       __kernel_mode_t         mode;
-       unsigned long           seq;
-       unsigned long           __unused1;
-       unsigned long           __unused2;
-};
-
-#endif /* _XTENSA_IPCBUF_H */
diff --git a/arch/xtensa/include/asm/irq_regs.h b/arch/xtensa/include/asm/irq_regs.h
deleted file mode 100644 (file)
index 3dd9c0b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/irq_regs.h>
index dae9a8bdcb1725ce6a38db642fdc777403d354e1..f865b1c1eae497fefdba3cccf90ac07d218e9d06 100644 (file)
@@ -16,7 +16,7 @@
 static inline unsigned long arch_local_save_flags(void)
 {
        unsigned long flags;
-       asm volatile("rsr %0,"__stringify(PS) : "=a" (flags));
+       asm volatile("rsr %0, ps" : "=a" (flags));
        return flags;
 }
 
@@ -41,7 +41,7 @@ static inline void arch_local_irq_enable(void)
 
 static inline void arch_local_irq_restore(unsigned long flags)
 {
-       asm volatile("wsr %0, "__stringify(PS)" ; rsync"
+       asm volatile("wsr %0, ps; rsync"
                     :: "a" (flags) : "memory");
 }
 
diff --git a/arch/xtensa/include/asm/kdebug.h b/arch/xtensa/include/asm/kdebug.h
deleted file mode 100644 (file)
index 6ece1b0..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kdebug.h>
diff --git a/arch/xtensa/include/asm/kmap_types.h b/arch/xtensa/include/asm/kmap_types.h
deleted file mode 100644 (file)
index 11c687e..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef _XTENSA_KMAP_TYPES_H
-#define _XTENSA_KMAP_TYPES_H
-
-#include <asm-generic/kmap_types.h>
-
-#endif /* _XTENSA_KMAP_TYPES_H */
diff --git a/arch/xtensa/include/asm/kvm_para.h b/arch/xtensa/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
diff --git a/arch/xtensa/include/asm/local.h b/arch/xtensa/include/asm/local.h
deleted file mode 100644 (file)
index 48723e5..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/local.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_LOCAL_H
-#define _XTENSA_LOCAL_H
-
-#include <asm-generic/local.h>
-
-#endif /* _XTENSA_LOCAL_H */
diff --git a/arch/xtensa/include/asm/local64.h b/arch/xtensa/include/asm/local64.h
deleted file mode 100644 (file)
index 36c93b5..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/local64.h>
diff --git a/arch/xtensa/include/asm/mman.h b/arch/xtensa/include/asm/mman.h
deleted file mode 100644 (file)
index 25bc6c1..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * include/asm-xtensa/mman.h
- *
- * Xtensa Processor memory-manager definitions
- *
- * 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) 1995 by Ralf Baechle
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_MMAN_H
-#define _XTENSA_MMAN_H
-
-/*
- * Protections are chosen from these bits, OR'd together.  The
- * implementation does not necessarily support PROT_EXEC or PROT_WRITE
- * without PROT_READ.  The only guarantees are that no writing will be
- * allowed without PROT_WRITE and no access will be allowed for PROT_NONE.
- */
-
-#define PROT_NONE      0x0             /* page can not be accessed */
-#define PROT_READ      0x1             /* page can be read */
-#define PROT_WRITE     0x2             /* page can be written */
-#define PROT_EXEC      0x4             /* page can be executed */
-
-#define PROT_SEM       0x10            /* page may be used for atomic ops */
-#define PROT_GROWSDOWN 0x01000000      /* mprotect flag: extend change to start of growsdown vma */
-#define PROT_GROWSUP   0x02000000      /* mprotect flag: extend change to end fo growsup vma */
-
-/*
- * Flags for mmap
- */
-#define MAP_SHARED     0x001           /* Share changes */
-#define MAP_PRIVATE    0x002           /* Changes are private */
-#define MAP_TYPE       0x00f           /* Mask for type of mapping */
-#define MAP_FIXED      0x010           /* Interpret addr exactly */
-
-/* not used by linux, but here to make sure we don't clash with ABI defines */
-#define MAP_RENAME     0x020           /* Assign page to file */
-#define MAP_AUTOGROW   0x040           /* File may grow by writing */
-#define MAP_LOCAL      0x080           /* Copy on fork/sproc */
-#define MAP_AUTORSRV   0x100           /* Logical swap reserved on demand */
-
-/* These are linux-specific */
-#define MAP_NORESERVE  0x0400          /* don't check for reservations */
-#define MAP_ANONYMOUS  0x0800          /* don't use a file */
-#define MAP_GROWSDOWN  0x1000          /* stack-like segment */
-#define MAP_DENYWRITE  0x2000          /* ETXTBSY */
-#define MAP_EXECUTABLE 0x4000          /* mark it as an executable */
-#define MAP_LOCKED     0x8000          /* pages are locked */
-#define MAP_POPULATE   0x10000         /* populate (prefault) pagetables */
-#define MAP_NONBLOCK   0x20000         /* do not block on IO */
-#define MAP_STACK      0x40000         /* give out an address that is best suited for process/thread stacks */
-#define MAP_HUGETLB    0x80000         /* create a huge page mapping */
-
-/*
- * Flags for msync
- */
-#define MS_ASYNC       0x0001          /* sync memory asynchronously */
-#define MS_INVALIDATE  0x0002          /* invalidate mappings & caches */
-#define MS_SYNC                0x0004          /* synchronous memory sync */
-
-/*
- * Flags for mlockall
- */
-#define MCL_CURRENT    1               /* lock all current mappings */
-#define MCL_FUTURE     2               /* lock all future mappings */
-
-#define MADV_NORMAL    0               /* no further special treatment */
-#define MADV_RANDOM    1               /* expect random page references */
-#define MADV_SEQUENTIAL        2               /* expect sequential page references */
-#define MADV_WILLNEED  3               /* will need these pages */
-#define MADV_DONTNEED  4               /* don't need these pages */
-
-/* common parameters: try to keep these consistent across architectures */
-#define MADV_REMOVE    9               /* remove these pages & resources */
-#define MADV_DONTFORK  10              /* don't inherit across fork */
-#define MADV_DOFORK    11              /* do inherit across fork */
-
-#define MADV_MERGEABLE   12            /* KSM may merge identical pages */
-#define MADV_UNMERGEABLE 13            /* KSM may not merge identical pages */
-
-#define MADV_HUGEPAGE  14              /* Worth backing with hugepages */
-#define MADV_NOHUGEPAGE        15              /* Not worth backing with hugepages */
-
-#define MADV_DONTDUMP   16             /* Explicity exclude from the core dump,
-                                          overrides the coredump filter bits */
-#define MADV_DODUMP    17              /* Clear the MADV_NODUMP flag */
-
-/* compatibility flags */
-#define MAP_FILE       0
-
-#endif /* _XTENSA_MMAN_H */
index dbd8731a876aec90c2765df2dd1a1c6d5e2310d0..feb10af96519900e3cf64341b6c425b5e017e924 100644 (file)
@@ -51,14 +51,14 @@ extern unsigned long asid_cache;
 
 static inline void set_rasid_register (unsigned long val)
 {
-       __asm__ __volatile__ (" wsr %0, "__stringify(RASID)"\n\t"
+       __asm__ __volatile__ (" wsr %0, rasid\n\t"
                              " isync\n" : : "a" (val));
 }
 
 static inline unsigned long get_rasid_register (void)
 {
        unsigned long tmp;
-       __asm__ __volatile__ (" rsr %0,"__stringify(RASID)"\n\t" : "=a" (tmp));
+       __asm__ __volatile__ (" rsr %0, rasid\n\t" : "=a" (tmp));
        return tmp;
 }
 
diff --git a/arch/xtensa/include/asm/msgbuf.h b/arch/xtensa/include/asm/msgbuf.h
deleted file mode 100644 (file)
index 693c967..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * include/asm-xtensa/msgbuf.h
- *
- * The msqid64_ds structure for the Xtensa architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- *
- * 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 _XTENSA_MSGBUF_H
-#define _XTENSA_MSGBUF_H
-
-struct msqid64_ds {
-       struct ipc64_perm msg_perm;
-#ifdef __XTENSA_EB__
-       unsigned int    __unused1;
-       __kernel_time_t msg_stime;      /* last msgsnd time */
-       unsigned int    __unused2;
-       __kernel_time_t msg_rtime;      /* last msgrcv time */
-       unsigned int    __unused3;
-       __kernel_time_t msg_ctime;      /* last change time */
-#elif defined(__XTENSA_EL__)
-       __kernel_time_t msg_stime;      /* last msgsnd time */
-       unsigned int    __unused1;
-       __kernel_time_t msg_rtime;      /* last msgrcv time */
-       unsigned int    __unused2;
-       __kernel_time_t msg_ctime;      /* last change time */
-       unsigned int    __unused3;
-#else
-# error processor byte order undefined!
-#endif
-       unsigned long  msg_cbytes;      /* current number of bytes on queue */
-       unsigned long  msg_qnum;        /* number of messages in queue */
-       unsigned long  msg_qbytes;      /* max number of bytes on queue */
-       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
-       __kernel_pid_t msg_lrpid;       /* last receive pid */
-       unsigned long  __unused4;
-       unsigned long  __unused5;
-};
-
-#endif /* _XTENSA_MSGBUF_H */
index ba03d5aeab6b085d21bd0b14db47163552f04be7..0a70e780ef2a33f3466fe9201897578d2771ba70 100644 (file)
@@ -7,28 +7,12 @@
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
-
 #ifndef _XTENSA_PARAM_H
 #define _XTENSA_PARAM_H
 
-#ifdef __KERNEL__
+#include <uapi/asm/param.h>
+
 # define HZ            CONFIG_HZ       /* internal timer frequency */
 # define USER_HZ       100             /* for user interfaces in "ticks" */
 # define CLOCKS_PER_SEC (USER_HZ)      /* frequnzy at which times() counts */
-#else
-# define HZ            100
-#endif
-
-#define EXEC_PAGESIZE  4096
-
-#ifndef NGROUPS
-#define NGROUPS                32
-#endif
-
-#ifndef NOGROUP
-#define NOGROUP                (-1)
-#endif
-
-#define MAXHOSTNAMELEN 64      /* max length of hostname */
-
 #endif /* _XTENSA_PARAM_H */
diff --git a/arch/xtensa/include/asm/percpu.h b/arch/xtensa/include/asm/percpu.h
deleted file mode 100644 (file)
index 6d2bc2a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * linux/include/asm-xtensa/percpu.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_PERCPU__
-#define _XTENSA_PERCPU__
-
-#include <asm-generic/percpu.h>
-
-#endif /* _XTENSA_PERCPU__ */
diff --git a/arch/xtensa/include/asm/poll.h b/arch/xtensa/include/asm/poll.h
deleted file mode 100644 (file)
index 9d2d599..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * include/asm-xtensa/poll.h
- *
- * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file "COPYING" in the main directory of
- * this archive for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_POLL_H
-#define _XTENSA_POLL_H
-
-#define POLLWRNORM     POLLOUT
-#define POLLWRBAND     0x0100
-#define POLLREMOVE     0x0800
-
-#include <asm-generic/poll.h>
-
-#endif /* _XTENSA_POLL_H */
diff --git a/arch/xtensa/include/asm/posix_types.h b/arch/xtensa/include/asm/posix_types.h
deleted file mode 100644 (file)
index 6e96be0..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * include/asm-xtensa/posix_types.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Largely copied from include/asm-ppc/posix_types.h
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_POSIX_TYPES_H
-#define _XTENSA_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc.  Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned short __kernel_ipc_pid_t;
-#define __kernel_ipc_pid_t __kernel_ipc_pid_t
-
-typedef unsigned int   __kernel_size_t;
-typedef int            __kernel_ssize_t;
-typedef long           __kernel_ptrdiff_t;
-#define __kernel_size_t __kernel_size_t
-
-typedef unsigned short __kernel_old_uid_t;
-typedef unsigned short __kernel_old_gid_t;
-#define __kernel_old_uid_t __kernel_old_uid_t
-
-typedef unsigned short __kernel_old_dev_t;
-#define __kernel_old_dev_t __kernel_old_dev_t
-
-#include <asm-generic/posix_types.h>
-
-#endif /* _XTENSA_POSIX_TYPES_H */
index 5c371d8d45284a1c35808d2b9e4928db03cc7652..2d630e7399ca4f94584a77cdf2a150d6c9ff7319 100644 (file)
@@ -152,6 +152,7 @@ struct thread_struct {
 
 /* Clearing a0 terminates the backtrace. */
 #define start_thread(regs, new_pc, new_sp) \
+       memset(regs, 0, sizeof(*regs)); \
        regs->pc = new_pc; \
        regs->ps = USER_PS_VALUE; \
        regs->areg[1] = new_sp; \
@@ -168,9 +169,6 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
-/* Create a kernel thread without removing it from tasklists */
-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-
 /* Copy and release all segment info associated with a VM */
 #define copy_segments(p, mm)   do { } while(0)
 #define release_segments(mm)   do { } while(0)
index d85d38da8eecc28df1be5c318e08e550b4b7e4eb..da21c17f23aad235c313c02683e87ccbfb9e23bf 100644 (file)
@@ -7,73 +7,11 @@
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
-
 #ifndef _XTENSA_PTRACE_H
 #define _XTENSA_PTRACE_H
 
-/*
- * Kernel stack
- *
- *             +-----------------------+  -------- STACK_SIZE
- *             |     register file     |  |
- *             +-----------------------+  |
- *             |    struct pt_regs     |  |
- *             +-----------------------+  | ------ PT_REGS_OFFSET
- * double      :  16 bytes spill area  :  |  ^
- * excetion    :- - - - - - - - - - - -:  |  |
- * frame       :    struct pt_regs     :  |  |
- *             :- - - - - - - - - - - -:  |  |
- *             |                       |  |  |
- *             |     memory stack      |  |  |
- *             |                       |  |  |
- *             ~                       ~  ~  ~
- *             ~                       ~  ~  ~
- *             |                       |  |  |
- *             |                       |  |  |
- *             +-----------------------+  |  | --- STACK_BIAS
- *             |  struct task_struct   |  |  |  ^
- *  current --> +-----------------------+  |  |  |
- *             |  struct thread_info   |  |  |  |
- *             +-----------------------+ --------
- */
-
-#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
-
-/*  Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */
-
-#define EXC_TABLE_KSTK         0x004   /* Kernel Stack */
-#define EXC_TABLE_DOUBLE_SAVE  0x008   /* Double exception save area for a0 */
-#define EXC_TABLE_FIXUP                0x00c   /* Fixup handler */
-#define EXC_TABLE_PARAM                0x010   /* For passing a parameter to fixup */
-#define EXC_TABLE_SYSCALL_SAVE 0x014   /* For fast syscall handler */
-#define EXC_TABLE_FAST_USER    0x100   /* Fast user exception handler */
-#define EXC_TABLE_FAST_KERNEL  0x200   /* Fast kernel exception handler */
-#define EXC_TABLE_DEFAULT      0x300   /* Default C-Handler */
-#define EXC_TABLE_SIZE         0x400
+#include <uapi/asm/ptrace.h>
 
-/* Registers used by strace */
-
-#define REG_A_BASE     0x0000
-#define REG_AR_BASE    0x0100
-#define REG_PC         0x0020
-#define REG_PS         0x02e6
-#define REG_WB         0x0248
-#define REG_WS         0x0249
-#define REG_LBEG       0x0200
-#define REG_LEND       0x0201
-#define REG_LCOUNT     0x0202
-#define REG_SAR                0x0203
-
-#define SYSCALL_NR     0x00ff
-
-/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
-
-#define PTRACE_GETREGS         12
-#define PTRACE_SETREGS         13
-#define PTRACE_GETXTREGS       18
-#define PTRACE_SETXTREGS       19
-
-#ifdef __KERNEL__
 
 #ifndef __ASSEMBLY__
 
@@ -132,6 +70,4 @@ struct pt_regs {
 
 #endif /* !__ASSEMBLY__ */
 
-#endif  /* __KERNEL__ */
-
 #endif /* _XTENSA_PTRACE_H */
index a3075b12aff112c4f3ed7176fccb8125b9336db8..8a8aa61ccc8df27075e4f2671715e9884571cc26 100644 (file)
 
 /*  Special registers.  */
 
-#define LBEG           0
-#define LEND           1
-#define LCOUNT         2
-#define SAR            3
-#define BR             4
-#define SCOMPARE1      12
-#define ACCHI          16
-#define ACCLO          17
-#define MR             32
-#define WINDOWBASE     72
-#define WINDOWSTART    73
-#define PTEVADDR       83
-#define RASID          90
-#define ITLBCFG                91
-#define DTLBCFG                92
-#define IBREAKENABLE   96
-#define DDR            104
-#define IBREAKA                128
-#define DBREAKA                144
-#define DBREAKC                160
-#define EPC            176
-#define EPC_1          177
-#define DEPC           192
-#define EPS            192
-#define EPS_1          193
-#define EXCSAVE                208
-#define EXCSAVE_1      209
-#define INTERRUPT      226
-#define INTENABLE      228
-#define PS             230
-#define THREADPTR      231
-#define EXCCAUSE       232
-#define DEBUGCAUSE     233
-#define CCOUNT         234
-#define PRID           235
-#define ICOUNT         236
-#define ICOUNTLEVEL    237
-#define EXCVADDR       238
-#define CCOMPARE       240
-#define MISC_SR                244
-
-/*  Special names for read-only and write-only interrupt registers.  */
-
-#define INTREAD                226
-#define INTSET         226
-#define INTCLEAR       227
+#define SREG_MR                        32
+#define SREG_IBREAKA           128
+#define SREG_DBREAKA           144
+#define SREG_DBREAKC           160
+#define SREG_EPC               176
+#define SREG_EPS               192
+#define SREG_EXCSAVE           208
+#define SREG_CCOMPARE          240
+#define SREG_MISC              244
 
 /*  EXCCAUSE register fields  */
 
diff --git a/arch/xtensa/include/asm/resource.h b/arch/xtensa/include/asm/resource.h
deleted file mode 100644 (file)
index 17b5ab3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/resource.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_RESOURCE_H
-#define _XTENSA_RESOURCE_H
-
-#include <asm-generic/resource.h>
-
-#endif /* _XTENSA_RESOURCE_H */
diff --git a/arch/xtensa/include/asm/scatterlist.h b/arch/xtensa/include/asm/scatterlist.h
deleted file mode 100644 (file)
index a0421a6..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/scatterlist.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SCATTERLIST_H
-#define _XTENSA_SCATTERLIST_H
-
-#include <asm-generic/scatterlist.h>
-
-#endif /* _XTENSA_SCATTERLIST_H */
diff --git a/arch/xtensa/include/asm/sections.h b/arch/xtensa/include/asm/sections.h
deleted file mode 100644 (file)
index 40b5191..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/sections.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SECTIONS_H
-#define _XTENSA_SECTIONS_H
-
-#include <asm-generic/sections.h>
-
-#endif /* _XTENSA_SECTIONS_H */
diff --git a/arch/xtensa/include/asm/sembuf.h b/arch/xtensa/include/asm/sembuf.h
deleted file mode 100644 (file)
index c158704..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * include/asm-xtensa/sembuf.h
- *
- * The semid64_ds structure for Xtensa 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) 2001 - 2005 Tensilica Inc.
- *
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- *
- */
-
-#ifndef _XTENSA_SEMBUF_H
-#define _XTENSA_SEMBUF_H
-
-#include <asm/byteorder.h>
-
-struct semid64_ds {
-       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
-#ifdef __XTENSA_EL__
-       __kernel_time_t sem_otime;              /* last semop time */
-       unsigned long   __unused1;
-       __kernel_time_t sem_ctime;              /* last change time */
-       unsigned long   __unused2;
-#else
-       unsigned long   __unused1;
-       __kernel_time_t sem_otime;              /* last semop time */
-       unsigned long   __unused2;
-       __kernel_time_t sem_ctime;              /* last change time */
-#endif
-       unsigned long   sem_nsems;              /* no. of semaphores in array */
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* __ASM_XTENSA_SEMBUF_H */
diff --git a/arch/xtensa/include/asm/setup.h b/arch/xtensa/include/asm/setup.h
deleted file mode 100644 (file)
index 9fa8ad9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * include/asm-xtensa/setup.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SETUP_H
-#define _XTENSA_SETUP_H
-
-#define COMMAND_LINE_SIZE      256
-
-extern void set_except_vector(int n, void *addr);
-
-#endif
diff --git a/arch/xtensa/include/asm/shmbuf.h b/arch/xtensa/include/asm/shmbuf.h
deleted file mode 100644 (file)
index ad4b012..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * include/asm-xtensa/shmbuf.h
- *
- * The shmid64_ds structure for Xtensa architecture.
- * Note extra padding because this structure is passed back and forth
- * between kernel and user space.
- *
- * Pad space is left for:
- * - 64-bit time_t to solve y2038 problem
- * - 2 miscellaneous 32-bit values
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SHMBUF_H
-#define _XTENSA_SHMBUF_H
-
-#if defined (__XTENSA_EL__)
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm;       /* operation perms */
-       size_t                  shm_segsz;      /* size of segment (bytes) */
-       __kernel_time_t         shm_atime;      /* last attach time */
-       unsigned long           __unused1;
-       __kernel_time_t         shm_dtime;      /* last detach time */
-       unsigned long           __unused2;
-       __kernel_time_t         shm_ctime;      /* last change time */
-       unsigned long           __unused3;
-       __kernel_pid_t          shm_cpid;       /* pid of creator */
-       __kernel_pid_t          shm_lpid;       /* pid of last operator */
-       unsigned long           shm_nattch;     /* no. of current attaches */
-       unsigned long           __unused4;
-       unsigned long           __unused5;
-};
-#elif defined (__XTENSA_EB__)
-struct shmid64_ds {
-       struct ipc64_perm       shm_perm;       /* operation perms */
-       size_t                  shm_segsz;      /* size of segment (bytes) */
-       __kernel_time_t         shm_atime;      /* last attach time */
-       unsigned long           __unused1;
-       __kernel_time_t         shm_dtime;      /* last detach time */
-       unsigned long           __unused2;
-       __kernel_time_t         shm_ctime;      /* last change time */
-       unsigned long           __unused3;
-       __kernel_pid_t          shm_cpid;       /* pid of creator */
-       __kernel_pid_t          shm_lpid;       /* pid of last operator */
-       unsigned long           shm_nattch;     /* no. of current attaches */
-       unsigned long           __unused4;
-       unsigned long           __unused5;
-};
-#else
-# error endian order not defined
-#endif
-
-
-struct shminfo64 {
-       unsigned long   shmmax;
-       unsigned long   shmmin;
-       unsigned long   shmmni;
-       unsigned long   shmseg;
-       unsigned long   shmall;
-       unsigned long   __unused1;
-       unsigned long   __unused2;
-       unsigned long   __unused3;
-       unsigned long   __unused4;
-};
-
-#endif /* _XTENSA_SHMBUF_H */
diff --git a/arch/xtensa/include/asm/sigcontext.h b/arch/xtensa/include/asm/sigcontext.h
deleted file mode 100644 (file)
index 03383af..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * include/asm-xtensa/sigcontext.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2007 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SIGCONTEXT_H
-#define _XTENSA_SIGCONTEXT_H
-
-
-struct sigcontext {
-       unsigned long sc_pc;
-       unsigned long sc_ps;
-       unsigned long sc_lbeg;
-       unsigned long sc_lend;
-       unsigned long sc_lcount;
-       unsigned long sc_sar;
-       unsigned long sc_acclo;
-       unsigned long sc_acchi;
-       unsigned long sc_a[16];
-       void *sc_xtregs;
-};
-
-#endif /* _XTENSA_SIGCONTEXT_H */
diff --git a/arch/xtensa/include/asm/siginfo.h b/arch/xtensa/include/asm/siginfo.h
deleted file mode 100644 (file)
index 6916248..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/siginfo.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SIGINFO_H
-#define _XTENSA_SIGINFO_H
-
-#include <asm-generic/siginfo.h>
-
-#endif /* _XTENSA_SIGINFO_H */
index 7f201b9d4195747f153c13f4e2f495fd53343bf5..72fd44c85b702ad3c2c78da2e6cf64bc74545d46 100644 (file)
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
-
 #ifndef _XTENSA_SIGNAL_H
 #define _XTENSA_SIGNAL_H
 
-
-#define _NSIG          64
-#define _NSIG_BPW      32
-#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
-
-#ifndef __ASSEMBLY__
-
-#include <linux/types.h>
-
-/* Avoid too many header ordering problems.  */
-struct siginfo;
-typedef unsigned long old_sigset_t;            /* at least 32 bits */
-typedef struct {
-       unsigned long sig[_NSIG_WORDS];
-} sigset_t;
-
-#endif
-
-#define SIGHUP          1
-#define SIGINT          2
-#define SIGQUIT                 3
-#define SIGILL          4
-#define SIGTRAP                 5
-#define SIGABRT                 6
-#define SIGIOT          6
-#define SIGBUS          7
-#define SIGFPE          8
-#define SIGKILL                 9
-#define SIGUSR1                10
-#define SIGSEGV                11
-#define SIGUSR2                12
-#define SIGPIPE                13
-#define SIGALRM                14
-#define SIGTERM                15
-#define SIGSTKFLT      16
-#define SIGCHLD                17
-#define SIGCONT                18
-#define SIGSTOP                19
-#define SIGTSTP                20
-#define SIGTTIN                21
-#define SIGTTOU                22
-#define SIGURG         23
-#define SIGXCPU                24
-#define SIGXFSZ                25
-#define SIGVTALRM      26
-#define SIGPROF                27
-#define SIGWINCH       28
-#define SIGIO          29
-#define SIGPOLL                SIGIO
-/* #define SIGLOST             29 */
-#define SIGPWR         30
-#define SIGSYS         31
-#define        SIGUNUSED       31
-
-/* These should not be considered constants from userland.  */
-#define SIGRTMIN       32
-#define SIGRTMAX       (_NSIG-1)
-
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP   0x00000001
-#define SA_NOCLDWAIT   0x00000002 /* not supported yet */
-#define SA_SIGINFO     0x00000004
-#define SA_ONSTACK     0x08000000
-#define SA_RESTART     0x10000000
-#define SA_NODEFER     0x40000000
-#define SA_RESETHAND   0x80000000
-
-#define SA_NOMASK      SA_NODEFER
-#define SA_ONESHOT     SA_RESETHAND
-
-#define SA_RESTORER    0x04000000
-
-/*
- * sigaltstack controls
- */
-#define SS_ONSTACK     1
-#define SS_DISABLE     2
-
-#define MINSIGSTKSZ    2048
-#define SIGSTKSZ       8192
+#include <uapi/asm/signal.h>
 
 #ifndef __ASSEMBLY__
-
-#define SIG_BLOCK          0   /* for blocking signals */
-#define SIG_UNBLOCK        1   /* for unblocking signals */
-#define SIG_SETMASK        2   /* for setting the signal mask */
-
-/* Type of a signal handler.  */
-typedef void (*__sighandler_t)(int);
-
-#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
-#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
-#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
-
-#ifdef __KERNEL__
 struct sigaction {
        __sighandler_t sa_handler;
        unsigned long sa_flags;
@@ -131,35 +26,8 @@ struct k_sigaction {
        struct sigaction sa;
 };
 
-#else
-
-/* Here we must cater to libcs that poke about in kernel headers.  */
-
-struct sigaction {
-       union {
-         __sighandler_t _sa_handler;
-         void (*_sa_sigaction)(int, struct siginfo *, void *);
-       } _u;
-       sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
-#define sa_handler     _u._sa_handler
-#define sa_sigaction   _u._sa_sigaction
-
-#endif /* __KERNEL__ */
-
-typedef struct sigaltstack {
-       void *ss_sp;
-       int ss_flags;
-       size_t ss_size;
-} stack_t;
-
-#ifdef __KERNEL__
 #include <asm/sigcontext.h>
 #define ptrace_signal_deliver(regs, cookie) do { } while (0)
 
-#endif /* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 #endif /* _XTENSA_SIGNAL_H */
diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/asm/socket.h
deleted file mode 100644 (file)
index e36c681..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * include/asm-xtensa/socket.h
- *
- * Copied from i386.
- *
- * 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 _XTENSA_SOCKET_H
-#define _XTENSA_SOCKET_H
-
-#include <asm/sockios.h>
-
-/* For setsockoptions(2) */
-#define SOL_SOCKET     1
-
-#define SO_DEBUG       1
-#define SO_REUSEADDR   2
-#define SO_TYPE                3
-#define SO_ERROR       4
-#define SO_DONTROUTE   5
-#define SO_BROADCAST   6
-#define SO_SNDBUF      7
-#define SO_RCVBUF      8
-#define SO_SNDBUFFORCE 32
-#define SO_RCVBUFFORCE 33
-#define SO_KEEPALIVE   9
-#define SO_OOBINLINE   10
-#define SO_NO_CHECK    11
-#define SO_PRIORITY    12
-#define SO_LINGER      13
-#define SO_BSDCOMPAT   14
-/* To add :#define SO_REUSEPORT 15 */
-#define SO_PASSCRED    16
-#define SO_PEERCRED    17
-#define SO_RCVLOWAT    18
-#define SO_SNDLOWAT    19
-#define SO_RCVTIMEO    20
-#define SO_SNDTIMEO    21
-
-/* Security levels - as per NRL IPv6 - don't actually do anything */
-
-#define SO_SECURITY_AUTHENTICATION             22
-#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
-#define SO_SECURITY_ENCRYPTION_NETWORK         24
-
-#define SO_BINDTODEVICE        25
-
-/* Socket filtering */
-
-#define SO_ATTACH_FILTER        26
-#define SO_DETACH_FILTER        27
-
-#define SO_PEERNAME            28
-#define SO_TIMESTAMP           29
-#define SCM_TIMESTAMP          SO_TIMESTAMP
-
-#define SO_ACCEPTCONN          30
-#define SO_PEERSEC             31
-#define SO_PASSSEC             34
-#define SO_TIMESTAMPNS         35
-#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
-
-#define SO_MARK                        36
-
-#define SO_TIMESTAMPING                37
-#define SCM_TIMESTAMPING       SO_TIMESTAMPING
-
-#define SO_PROTOCOL            38
-#define SO_DOMAIN              39
-
-#define SO_RXQ_OVFL             40
-
-#define SO_WIFI_STATUS         41
-#define SCM_WIFI_STATUS                SO_WIFI_STATUS
-#define SO_PEEK_OFF            42
-
-/* Instruct lower device to use last 4-bytes of skb data as FCS */
-#define SO_NOFCS               43
-
-#endif /* _XTENSA_SOCKET_H */
diff --git a/arch/xtensa/include/asm/sockios.h b/arch/xtensa/include/asm/sockios.h
deleted file mode 100644 (file)
index efe0af3..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * include/asm-xtensa/sockios.h
- *
- * Socket-level I/O control calls.  Copied from MIPS.
- *
- * 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) 1995 by Ralf Baechle
- * Copyright (C) 2001 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SOCKIOS_H
-#define _XTENSA_SOCKIOS_H
-
-#include <asm/ioctl.h>
-
-/* Socket-level I/O control calls. */
-
-#define FIOGETOWN      _IOR('f', 123, int)
-#define FIOSETOWN      _IOW('f', 124, int)
-
-#define SIOCATMARK     _IOR('s', 7, int)
-#define SIOCSPGRP      _IOW('s', 8, pid_t)
-#define SIOCGPGRP      _IOR('s', 9, pid_t)
-
-#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
-#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
-
-#endif /* _XTENSA_SOCKIOS_H */
diff --git a/arch/xtensa/include/asm/stat.h b/arch/xtensa/include/asm/stat.h
deleted file mode 100644 (file)
index c499203..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * include/asm-xtensa/stat.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2007 Tensilica Inc.
- */
-
-#ifndef _XTENSA_STAT_H
-#define _XTENSA_STAT_H
-
-#define STAT_HAVE_NSEC 1
-
-struct stat {
-       unsigned long   st_dev;
-       unsigned long   st_ino;
-       unsigned int    st_mode;
-       unsigned int    st_nlink;
-       unsigned int    st_uid;
-       unsigned int    st_gid;
-       unsigned long   st_rdev;
-       long            st_size;
-       unsigned long   st_blksize;
-       unsigned long   st_blocks;
-       unsigned long   st_atime;
-       unsigned long   st_atime_nsec;
-       unsigned long   st_mtime;
-       unsigned long   st_mtime_nsec;
-       unsigned long   st_ctime;
-       unsigned long   st_ctime_nsec;
-       unsigned long   __unused4;
-       unsigned long   __unused5;
-};
-
-struct stat64  {
-       unsigned long long st_dev;      /* Device */
-       unsigned long long st_ino;      /* File serial number */
-       unsigned int  st_mode;          /* File mode. */
-       unsigned int  st_nlink;         /* Link count. */
-       unsigned int  st_uid;           /* User ID of the file's owner. */
-       unsigned int  st_gid;           /* Group ID of the file's group. */
-       unsigned long long st_rdev;     /* Device number, if device. */
-       long long st_size;              /* Size of file, in bytes. */
-       unsigned long st_blksize;       /* Optimal block size for I/O. */
-       unsigned long __unused2;
-       unsigned long long st_blocks;   /* Number 512-byte blocks allocated. */
-       unsigned long st_atime;         /* Time of last access. */
-       unsigned long st_atime_nsec;
-       unsigned long st_mtime;         /* Time of last modification. */
-       unsigned long st_mtime_nsec;
-       unsigned long st_ctime;         /* Time of last status change. */
-       unsigned long st_ctime_nsec;
-       unsigned long __unused4;
-       unsigned long __unused5;
-};
-
-#endif /* _XTENSA_STAT_H */
diff --git a/arch/xtensa/include/asm/statfs.h b/arch/xtensa/include/asm/statfs.h
deleted file mode 100644 (file)
index 9c3d1a2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * include/asm-xtensa/statfs.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_STATFS_H
-#define _XTENSA_STATFS_H
-
-#include <asm-generic/statfs.h>
-
-#endif /* _XTENSA_STATFS_H */
-
diff --git a/arch/xtensa/include/asm/swab.h b/arch/xtensa/include/asm/swab.h
deleted file mode 100644 (file)
index 226a391..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * include/asm-xtensa/swab.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_SWAB_H
-#define _XTENSA_SWAB_H
-
-#include <linux/types.h>
-#include <linux/compiler.h>
-
-#define __SWAB_64_THRU_32__
-
-static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
-{
-    __u32 res;
-    /* instruction sequence from Xtensa ISA release 2/2000 */
-    __asm__("ssai     8           \n\t"
-           "srli     %0, %1, 16  \n\t"
-           "src      %0, %0, %1  \n\t"
-           "src      %0, %0, %0  \n\t"
-           "src      %0, %1, %0  \n"
-           : "=&a" (res)
-           : "a" (x)
-           );
-    return res;
-}
-#define __arch_swab32 __arch_swab32
-
-static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
-{
-    /* Given that 'short' values are signed (i.e., can be negative),
-     * we cannot assume that the upper 16-bits of the register are
-     * zero.  We are careful to mask values after shifting.
-     */
-
-    /* There exists an anomaly between xt-gcc and xt-xcc.  xt-gcc
-     * inserts an extui instruction after putting this function inline
-     * to ensure that it uses only the least-significant 16 bits of
-     * the result.  xt-xcc doesn't use an extui, but assumes the
-     * __asm__ macro follows convention that the upper 16 bits of an
-     * 'unsigned short' result are still zero.  This macro doesn't
-     * follow convention; indeed, it leaves garbage in the upport 16
-     * bits of the register.
-
-     * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
-     * types while the return type of the function is a 16-bit type
-     * forces both compilers to insert exactly one extui instruction
-     * (or equivalent) to mask off the upper 16 bits. */
-
-    __u32 res;
-    __u32 tmp;
-
-    __asm__("extui    %1, %2, 8, 8\n\t"
-           "slli     %0, %2, 8   \n\t"
-           "or       %0, %0, %1  \n"
-           : "=&a" (res), "=&a" (tmp)
-           : "a" (x)
-           );
-
-    return res;
-}
-#define __arch_swab16 __arch_swab16
-
-#endif /* _XTENSA_SWAB_H */
index c1dacca312f3906374614ae4eb0a486ab8070e8a..124aeee0d3816cadf7abe7317d168b5f3b326891 100644 (file)
@@ -10,7 +10,7 @@
 
 struct pt_regs;
 struct sigaction;
-asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*);
+asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);
 asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
diff --git a/arch/xtensa/include/asm/termbits.h b/arch/xtensa/include/asm/termbits.h
deleted file mode 100644 (file)
index 0d6c871..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * include/asm-xtensa/termbits.h
- *
- * Copied from SH.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_TERMBITS_H
-#define _XTENSA_TERMBITS_H
-
-
-#include <linux/posix_types.h>
-
-typedef unsigned char  cc_t;
-typedef unsigned int   speed_t;
-typedef unsigned int   tcflag_t;
-
-#define NCCS 19
-struct termios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-};
-
-struct termios2 {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-struct ktermios {
-       tcflag_t c_iflag;               /* input mode flags */
-       tcflag_t c_oflag;               /* output mode flags */
-       tcflag_t c_cflag;               /* control mode flags */
-       tcflag_t c_lflag;               /* local mode flags */
-       cc_t c_line;                    /* line discipline */
-       cc_t c_cc[NCCS];                /* control characters */
-       speed_t c_ispeed;               /* input speed */
-       speed_t c_ospeed;               /* output speed */
-};
-
-/* c_cc characters */
-
-#define VINTR 0
-#define VQUIT 1
-#define VERASE 2
-#define VKILL 3
-#define VEOF 4
-#define VTIME 5
-#define VMIN 6
-#define VSWTC 7
-#define VSTART 8
-#define VSTOP 9
-#define VSUSP 10
-#define VEOL 11
-#define VREPRINT 12
-#define VDISCARD 13
-#define VWERASE 14
-#define VLNEXT 15
-#define VEOL2 16
-
-/* c_iflag bits */
-
-#define IGNBRK 0000001
-#define BRKINT 0000002
-#define IGNPAR 0000004
-#define PARMRK 0000010
-#define INPCK  0000020
-#define ISTRIP 0000040
-#define INLCR  0000100
-#define IGNCR  0000200
-#define ICRNL  0000400
-#define IUCLC  0001000
-#define IXON   0002000
-#define IXANY  0004000
-#define IXOFF  0010000
-#define IMAXBEL        0020000
-#define IUTF8  0040000
-
-/* c_oflag bits */
-
-#define OPOST  0000001
-#define OLCUC  0000002
-#define ONLCR  0000004
-#define OCRNL  0000010
-#define ONOCR  0000020
-#define ONLRET 0000040
-#define OFILL  0000100
-#define OFDEL  0000200
-#define NLDLY  0000400
-#define   NL0  0000000
-#define   NL1  0000400
-#define CRDLY  0003000
-#define   CR0  0000000
-#define   CR1  0001000
-#define   CR2  0002000
-#define   CR3  0003000
-#define TABDLY 0014000
-#define   TAB0 0000000
-#define   TAB1 0004000
-#define   TAB2 0010000
-#define   TAB3 0014000
-#define   XTABS        0014000
-#define BSDLY  0020000
-#define   BS0  0000000
-#define   BS1  0020000
-#define VTDLY  0040000
-#define   VT0  0000000
-#define   VT1  0040000
-#define FFDLY  0100000
-#define   FF0  0000000
-#define   FF1  0100000
-
-/* c_cflag bit meaning */
-
-#define CBAUD  0010017
-#define  B0    0000000         /* hang up */
-#define  B50   0000001
-#define  B75   0000002
-#define  B110  0000003
-#define  B134  0000004
-#define  B150  0000005
-#define  B200  0000006
-#define  B300  0000007
-#define  B600  0000010
-#define  B1200 0000011
-#define  B1800 0000012
-#define  B2400 0000013
-#define  B4800 0000014
-#define  B9600 0000015
-#define  B19200        0000016
-#define  B38400        0000017
-#define EXTA B19200
-#define EXTB B38400
-#define CSIZE  0000060
-#define   CS5  0000000
-#define   CS6  0000020
-#define   CS7  0000040
-#define   CS8  0000060
-#define CSTOPB 0000100
-#define CREAD  0000200
-#define PARENB 0000400
-#define PARODD 0001000
-#define HUPCL  0002000
-#define CLOCAL 0004000
-#define CBAUDEX 0010000
-#define           BOTHER 0010000
-#define    B57600 0010001
-#define   B115200 0010002
-#define   B230400 0010003
-#define   B460800 0010004
-#define   B500000 0010005
-#define   B576000 0010006
-#define   B921600 0010007
-#define  B1000000 0010010
-#define  B1152000 0010011
-#define  B1500000 0010012
-#define  B2000000 0010013
-#define  B2500000 0010014
-#define  B3000000 0010015
-#define  B3500000 0010016
-#define  B4000000 0010017
-#define CIBAUD   002003600000          /* input baud rate */
-#define CMSPAR   010000000000          /* mark or space (stick) parity */
-#define CRTSCTS          020000000000          /* flow control */
-
-#define IBSHIFT        16              /* Shift from CBAUD to CIBAUD */
-
-/* c_lflag bits */
-
-#define ISIG   0000001
-#define ICANON 0000002
-#define XCASE  0000004
-#define ECHO   0000010
-#define ECHOE  0000020
-#define ECHOK  0000040
-#define ECHONL 0000100
-#define NOFLSH 0000200
-#define TOSTOP 0000400
-#define ECHOCTL        0001000
-#define ECHOPRT        0002000
-#define ECHOKE 0004000
-#define FLUSHO 0010000
-#define PENDIN 0040000
-#define IEXTEN 0100000
-#define EXTPROC        0200000
-
-/* tcflow() and TCXONC use these */
-
-#define        TCOOFF          0
-#define        TCOON           1
-#define        TCIOFF          2
-#define        TCION           3
-
-/* tcflush() and TCFLSH use these */
-
-#define        TCIFLUSH        0
-#define        TCOFLUSH        1
-#define        TCIOFLUSH       2
-
-/* tcsetattr uses these */
-
-#define        TCSANOW         0
-#define        TCSADRAIN       1
-#define        TCSAFLUSH       2
-
-#endif /* _XTENSA_TERMBITS_H */
diff --git a/arch/xtensa/include/asm/termios.h b/arch/xtensa/include/asm/termios.h
deleted file mode 100644 (file)
index 4673f42..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * include/asm-xtensa/termios.h
- *
- * Copied from SH.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_TERMIOS_H
-#define _XTENSA_TERMIOS_H
-
-#include <asm/termbits.h>
-#include <asm/ioctls.h>
-
-struct winsize {
-       unsigned short ws_row;
-       unsigned short ws_col;
-       unsigned short ws_xpixel;
-       unsigned short ws_ypixel;
-};
-
-#define NCC 8
-struct termio {
-       unsigned short c_iflag;         /* input mode flags */
-       unsigned short c_oflag;         /* output mode flags */
-       unsigned short c_cflag;         /* control mode flags */
-       unsigned short c_lflag;         /* local mode flags */
-       unsigned char c_line;           /* line discipline */
-       unsigned char c_cc[NCC];        /* control characters */
-};
-
-/* Modem lines */
-
-#define TIOCM_LE       0x001
-#define TIOCM_DTR      0x002
-#define TIOCM_RTS      0x004
-#define TIOCM_ST       0x008
-#define TIOCM_SR       0x010
-#define TIOCM_CTS      0x020
-#define TIOCM_CAR      0x040
-#define TIOCM_RNG      0x080
-#define TIOCM_DSR      0x100
-#define TIOCM_CD       TIOCM_CAR
-#define TIOCM_RI       TIOCM_RNG
-#define TIOCM_OUT1     0x2000
-#define TIOCM_OUT2     0x4000
-#define TIOCM_LOOP     0x8000
-
-/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-
-#ifdef __KERNEL__
-
-/*     intr=^C         quit=^\         erase=del       kill=^U
-       eof=^D          vtime=\0        vmin=\1         sxtc=\0
-       start=^Q        stop=^S         susp=^Z         eol=\0
-       reprint=^R      discard=^U      werase=^W       lnext=^V
-       eol2=\0
-*/
-#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
-
-/*
- * Translate a "termio" structure into a "termios". Ugh.
- */
-
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
-       unsigned short __tmp; \
-       get_user(__tmp,&(termio)->x); \
-       *(unsigned short *) &(termios)->x = __tmp; \
-}
-
-#define user_termio_to_kernel_termios(termios, termio) \
-({ \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
-       SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
-       copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
-})
-
-/*
- * Translate a "termios" structure into a "termio". Ugh.
- */
-
-#define kernel_termios_to_user_termio(termio, termios) \
-({ \
-       put_user((termios)->c_iflag, &(termio)->c_iflag); \
-       put_user((termios)->c_oflag, &(termio)->c_oflag); \
-       put_user((termios)->c_cflag, &(termio)->c_cflag); \
-       put_user((termios)->c_lflag, &(termio)->c_lflag); \
-       put_user((termios)->c_line,  &(termio)->c_line); \
-       copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
-})
-
-#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2))
-#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2))
-#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
-#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
-
-#endif /* __KERNEL__ */
-
-#endif /* _XTENSA_TERMIOS_H */
index 053bc42721067de7dbdf51fd50ab2b3c75b6dc27..175b3d5e1b01cd29f8c849f37db3496cc0005531 100644 (file)
@@ -63,10 +63,10 @@ extern cycles_t cacheflush_time;
  * Register access.
  */
 
-#define WSR_CCOUNT(r)    asm volatile ("wsr %0,"__stringify(CCOUNT) :: "a" (r))
-#define RSR_CCOUNT(r)    asm volatile ("rsr %0,"__stringify(CCOUNT) : "=a" (r))
-#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(CCOMPARE)"+"__stringify(x) :: "a"(r))
-#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(CCOMPARE)"+"__stringify(x) : "=a"(r))
+#define WSR_CCOUNT(r)    asm volatile ("wsr %0, ccount" :: "a" (r))
+#define RSR_CCOUNT(r)    asm volatile ("rsr %0, ccount" : "=a" (r))
+#define WSR_CCOMPARE(x,r) asm volatile ("wsr %0,"__stringify(SREG_CCOMPARE)"+"__stringify(x) :: "a"(r))
+#define RSR_CCOMPARE(x,r) asm volatile ("rsr %0,"__stringify(SREG_CCOMPARE)"+"__stringify(x) : "=a"(r))
 
 static inline unsigned long get_ccount (void)
 {
index 46d240074f747aa622711b35d0b130cedba6b812..43dd348a5a478d27daa70f2e8b019b8cfa0fcd22 100644 (file)
@@ -86,26 +86,26 @@ static inline void invalidate_dtlb_entry_no_isync (unsigned entry)
 
 static inline void set_itlbcfg_register (unsigned long val)
 {
-       __asm__ __volatile__("wsr  %0, "__stringify(ITLBCFG)"\n\t" "isync\n\t"
+       __asm__ __volatile__("wsr  %0, itlbcfg\n\t" "isync\n\t"
                             : : "a" (val));
 }
 
 static inline void set_dtlbcfg_register (unsigned long val)
 {
-       __asm__ __volatile__("wsr  %0, "__stringify(DTLBCFG)"; dsync\n\t"
+       __asm__ __volatile__("wsr  %0, dtlbcfg; dsync\n\t"
                             : : "a" (val));
 }
 
 static inline void set_ptevaddr_register (unsigned long val)
 {
-       __asm__ __volatile__(" wsr  %0, "__stringify(PTEVADDR)"; isync\n"
+       __asm__ __volatile__(" wsr  %0, ptevaddr; isync\n"
                             : : "a" (val));
 }
 
 static inline unsigned long read_ptevaddr_register (void)
 {
        unsigned long tmp;
-       __asm__ __volatile__("rsr  %0, "__stringify(PTEVADDR)"\n\t" : "=a" (tmp));
+       __asm__ __volatile__("rsr  %0, ptevaddr\n\t" : "=a" (tmp));
        return tmp;
 }
 
diff --git a/arch/xtensa/include/asm/topology.h b/arch/xtensa/include/asm/topology.h
deleted file mode 100644 (file)
index 7309e38..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/topology.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_TOPOLOGY_H
-#define _XTENSA_TOPOLOGY_H
-
-#include <asm-generic/topology.h>
-
-#endif /* _XTENSA_TOPOLOGY_H */
index 6d4db7e8ffac608520d9985a3680fddcfcfc9a1b..2b410b8c7f79fcbe4e9e29fb1901dc8ad73395cb 100644 (file)
@@ -7,30 +7,17 @@
  *
  * Copyright (C) 2001 - 2005 Tensilica Inc.
  */
-
 #ifndef _XTENSA_TYPES_H
 #define _XTENSA_TYPES_H
 
-#include <asm-generic/int-ll64.h>
-
-#ifdef __ASSEMBLY__
-# define __XTENSA_UL(x)                (x)
-# define __XTENSA_UL_CONST(x)  x
-#else
-# define __XTENSA_UL(x)                ((unsigned long)(x))
-# define __XTENSA_UL_CONST(x)  x##UL
-#endif
+#include <uapi/asm/types.h>
 
 #ifndef __ASSEMBLY__
-
 /*
  * These aren't exported outside the kernel to avoid name space clashes
  */
-#ifdef __KERNEL__
 
 #define BITS_PER_LONG 32
 
-#endif /* __KERNEL__ */
 #endif
-
 #endif /* _XTENSA_TYPES_H */
index bc7e005faa602f5eb61beaf886f5a83c1ea1d209..f4e6eaa40d1ca86946799a1f7eab6d7047a69dd5 100644 (file)
@@ -1,712 +1,8 @@
-/*
- * include/asm-xtensa/unistd.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
 #ifndef _XTENSA_UNISTD_H
 #define _XTENSA_UNISTD_H
 
-#ifndef __SYSCALL
-# define __SYSCALL(nr,func,nargs)
-#endif
-
-#define __NR_spill                               0
-__SYSCALL(  0, sys_ni_syscall, 0)
-#define __NR_xtensa                              1
-__SYSCALL(  1, sys_ni_syscall, 0)
-#define __NR_available4                                  2
-__SYSCALL(  2, sys_ni_syscall, 0)
-#define __NR_available5                                  3
-__SYSCALL(  3, sys_ni_syscall, 0)
-#define __NR_available6                                  4
-__SYSCALL(  4, sys_ni_syscall, 0)
-#define __NR_available7                                  5
-__SYSCALL(  5, sys_ni_syscall, 0)
-#define __NR_available8                                  6
-__SYSCALL(  6, sys_ni_syscall, 0)
-#define __NR_available9                                  7
-__SYSCALL(  7, sys_ni_syscall, 0)
-
-/* File Operations */
-
-#define __NR_open                                8
-__SYSCALL(  8, sys_open, 3)
-#define __NR_close                               9
-__SYSCALL(  9, sys_close, 1)
-#define __NR_dup                                10
-__SYSCALL( 10, sys_dup, 1)
-#define __NR_dup2                               11
-__SYSCALL( 11, sys_dup2, 2)
-#define __NR_read                               12
-__SYSCALL( 12, sys_read, 3)
-#define __NR_write                              13
-__SYSCALL( 13, sys_write, 3)
-#define __NR_select                             14
-__SYSCALL( 14, sys_select, 5)
-#define __NR_lseek                              15
-__SYSCALL( 15, sys_lseek, 3)
-#define __NR_poll                               16
-__SYSCALL( 16, sys_poll, 3)
-#define __NR__llseek                            17
-__SYSCALL( 17, sys_llseek, 5)
-#define __NR_epoll_wait                         18
-__SYSCALL( 18, sys_epoll_wait, 4)
-#define __NR_epoll_ctl                                  19
-__SYSCALL( 19, sys_epoll_ctl, 4)
-#define __NR_epoll_create                       20
-__SYSCALL( 20, sys_epoll_create, 1)
-#define __NR_creat                              21
-__SYSCALL( 21, sys_creat, 2)
-#define __NR_truncate                           22
-__SYSCALL( 22, sys_truncate, 2)
-#define __NR_ftruncate                                  23
-__SYSCALL( 23, sys_ftruncate, 2)
-#define __NR_readv                              24
-__SYSCALL( 24, sys_readv, 3)
-#define __NR_writev                             25
-__SYSCALL( 25, sys_writev, 3)
-#define __NR_fsync                              26
-__SYSCALL( 26, sys_fsync, 1)
-#define __NR_fdatasync                                  27
-__SYSCALL( 27, sys_fdatasync, 1)
-#define __NR_truncate64                         28
-__SYSCALL( 28, sys_truncate64, 2)
-#define __NR_ftruncate64                        29
-__SYSCALL( 29, sys_ftruncate64, 2)
-#define __NR_pread64                            30
-__SYSCALL( 30, sys_pread64, 6)
-#define __NR_pwrite64                           31
-__SYSCALL( 31, sys_pwrite64, 6)
-
-#define __NR_link                               32
-__SYSCALL( 32, sys_link, 2)
-#define __NR_rename                             33
-__SYSCALL( 33, sys_rename, 2)
-#define __NR_symlink                            34
-__SYSCALL( 34, sys_symlink, 2)
-#define __NR_readlink                           35
-__SYSCALL( 35, sys_readlink, 3)
-#define __NR_mknod                              36
-__SYSCALL( 36, sys_mknod, 3)
-#define __NR_pipe                               37
-__SYSCALL( 37, sys_pipe, 1)
-#define __NR_unlink                             38
-__SYSCALL( 38, sys_unlink, 1)
-#define __NR_rmdir                              39
-__SYSCALL( 39, sys_rmdir, 1)
-
-#define __NR_mkdir                              40
-__SYSCALL( 40, sys_mkdir, 2)
-#define __NR_chdir                              41
-__SYSCALL( 41, sys_chdir, 1)
-#define __NR_fchdir                             42
-__SYSCALL( 42, sys_fchdir, 1)
-#define __NR_getcwd                             43
-__SYSCALL( 43, sys_getcwd, 2)
-
-#define __NR_chmod                              44
-__SYSCALL( 44, sys_chmod, 2)
-#define __NR_chown                              45
-__SYSCALL( 45, sys_chown, 3)
-#define __NR_stat                               46
-__SYSCALL( 46, sys_newstat, 2)
-#define __NR_stat64                             47
-__SYSCALL( 47, sys_stat64, 2)
-
-#define __NR_lchown                             48
-__SYSCALL( 48, sys_lchown, 3)
-#define __NR_lstat                              49
-__SYSCALL( 49, sys_newlstat, 2)
-#define __NR_lstat64                            50
-__SYSCALL( 50, sys_lstat64, 2)
-#define __NR_available51                        51
-__SYSCALL( 51, sys_ni_syscall, 0)
-
-#define __NR_fchmod                             52
-__SYSCALL( 52, sys_fchmod, 2)
-#define __NR_fchown                             53
-__SYSCALL( 53, sys_fchown, 3)
-#define __NR_fstat                              54
-__SYSCALL( 54, sys_newfstat, 2)
-#define __NR_fstat64                            55
-__SYSCALL( 55, sys_fstat64, 2)
-
-#define __NR_flock                              56
-__SYSCALL( 56, sys_flock, 2)
-#define __NR_access                             57
-__SYSCALL( 57, sys_access, 2)
-#define __NR_umask                              58
-__SYSCALL( 58, sys_umask, 1)
-#define __NR_getdents                           59
-__SYSCALL( 59, sys_getdents, 3)
-#define __NR_getdents64                         60
-__SYSCALL( 60, sys_getdents64, 3)
-#define __NR_fcntl64                            61
-__SYSCALL( 61, sys_fcntl64, 3)
-#define __NR_available62                        62
-__SYSCALL( 62, sys_ni_syscall, 0)
-#define __NR_fadvise64_64                       63
-__SYSCALL( 63, xtensa_fadvise64_64, 6)
-#define __NR_utime                              64     /* glibc 2.3.3 ?? */
-__SYSCALL( 64, sys_utime, 2)
-#define __NR_utimes                             65
-__SYSCALL( 65, sys_utimes, 2)
-#define __NR_ioctl                              66
-__SYSCALL( 66, sys_ioctl, 3)
-#define __NR_fcntl                              67
-__SYSCALL( 67, sys_fcntl, 3)
-
-#define __NR_setxattr                           68
-__SYSCALL( 68, sys_setxattr, 5)
-#define __NR_getxattr                           69
-__SYSCALL( 69, sys_getxattr, 4)
-#define __NR_listxattr                                  70
-__SYSCALL( 70, sys_listxattr, 3)
-#define __NR_removexattr                        71
-__SYSCALL( 71, sys_removexattr, 2)
-#define __NR_lsetxattr                                  72
-__SYSCALL( 72, sys_lsetxattr, 5)
-#define __NR_lgetxattr                                  73
-__SYSCALL( 73, sys_lgetxattr, 4)
-#define __NR_llistxattr                         74
-__SYSCALL( 74, sys_llistxattr, 3)
-#define __NR_lremovexattr                       75
-__SYSCALL( 75, sys_lremovexattr, 2)
-#define __NR_fsetxattr                                  76
-__SYSCALL( 76, sys_fsetxattr, 5)
-#define __NR_fgetxattr                                  77
-__SYSCALL( 77, sys_fgetxattr, 4)
-#define __NR_flistxattr                         78
-__SYSCALL( 78, sys_flistxattr, 3)
-#define __NR_fremovexattr                       79
-__SYSCALL( 79, sys_fremovexattr, 2)
-
-/* File Map / Shared Memory Operations */
-
-#define __NR_mmap2                              80
-__SYSCALL( 80, sys_mmap_pgoff, 6)
-#define __NR_munmap                             81
-__SYSCALL( 81, sys_munmap, 2)
-#define __NR_mprotect                           82
-__SYSCALL( 82, sys_mprotect, 3)
-#define __NR_brk                                83
-__SYSCALL( 83, sys_brk, 1)
-#define __NR_mlock                              84
-__SYSCALL( 84, sys_mlock, 2)
-#define __NR_munlock                            85
-__SYSCALL( 85, sys_munlock, 2)
-#define __NR_mlockall                           86
-__SYSCALL( 86, sys_mlockall, 1)
-#define __NR_munlockall                         87
-__SYSCALL( 87, sys_munlockall, 0)
-#define __NR_mremap                             88
-__SYSCALL( 88, sys_mremap, 4)
-#define __NR_msync                              89
-__SYSCALL( 89, sys_msync, 3)
-#define __NR_mincore                            90
-__SYSCALL( 90, sys_mincore, 3)
-#define __NR_madvise                            91
-__SYSCALL( 91, sys_madvise, 3)
-#define __NR_shmget                             92
-__SYSCALL( 92, sys_shmget, 4)
-#define __NR_shmat                              93
-__SYSCALL( 93, xtensa_shmat, 4)
-#define __NR_shmctl                             94
-__SYSCALL( 94, sys_shmctl, 4)
-#define __NR_shmdt                              95
-__SYSCALL( 95, sys_shmdt, 4)
-
-/* Socket Operations */
-
-#define __NR_socket                             96
-__SYSCALL( 96, sys_socket, 3)
-#define __NR_setsockopt                         97
-__SYSCALL( 97, sys_setsockopt, 5)
-#define __NR_getsockopt                         98
-__SYSCALL( 98, sys_getsockopt, 5)
-#define __NR_shutdown                           99
-__SYSCALL( 99, sys_shutdown, 2)
-
-#define __NR_bind                              100
-__SYSCALL(100, sys_bind, 3)
-#define __NR_connect                           101
-__SYSCALL(101, sys_connect, 3)
-#define __NR_listen                            102
-__SYSCALL(102, sys_listen, 2)
-#define __NR_accept                            103
-__SYSCALL(103, sys_accept, 3)
-
-#define __NR_getsockname                       104
-__SYSCALL(104, sys_getsockname, 3)
-#define __NR_getpeername                       105
-__SYSCALL(105, sys_getpeername, 3)
-#define __NR_sendmsg                           106
-__SYSCALL(106, sys_sendmsg, 3)
-#define __NR_recvmsg                           107
-__SYSCALL(107, sys_recvmsg, 3)
-#define __NR_send                              108
-__SYSCALL(108, sys_send, 4)
-#define __NR_recv                              109
-__SYSCALL(109, sys_recv, 4)
-#define __NR_sendto                            110
-__SYSCALL(110, sys_sendto, 6)
-#define __NR_recvfrom                          111
-__SYSCALL(111, sys_recvfrom, 6)
-
-#define __NR_socketpair                        112
-__SYSCALL(112, sys_socketpair, 4)
-#define __NR_sendfile                          113
-__SYSCALL(113, sys_sendfile, 4)
-#define __NR_sendfile64                        114
-__SYSCALL(114, sys_sendfile64, 4)
-#define __NR_available115                      115
-__SYSCALL(115, sys_ni_syscall, 0)
-
-/* Process Operations */
-
-#define __NR_clone                             116
-__SYSCALL(116, xtensa_clone, 5)
-#define __NR_execve                            117
-__SYSCALL(117, xtensa_execve, 3)
-#define __NR_exit                              118
-__SYSCALL(118, sys_exit, 1)
-#define __NR_exit_group                        119
-__SYSCALL(119, sys_exit_group, 1)
-#define __NR_getpid                            120
-__SYSCALL(120, sys_getpid, 0)
-#define __NR_wait4                             121
-__SYSCALL(121, sys_wait4, 4)
-#define __NR_waitid                            122
-__SYSCALL(122, sys_waitid, 5)
-#define __NR_kill                              123
-__SYSCALL(123, sys_kill, 2)
-#define __NR_tkill                             124
-__SYSCALL(124, sys_tkill, 2)
-#define __NR_tgkill                            125
-__SYSCALL(125, sys_tgkill, 3)
-#define __NR_set_tid_address                   126
-__SYSCALL(126, sys_set_tid_address, 1)
-#define __NR_gettid                            127
-__SYSCALL(127, sys_gettid, 0)
-#define __NR_setsid                            128
-__SYSCALL(128, sys_setsid, 0)
-#define __NR_getsid                            129
-__SYSCALL(129, sys_getsid, 1)
-#define __NR_prctl                             130
-__SYSCALL(130, sys_prctl, 5)
-#define __NR_personality                       131
-__SYSCALL(131, sys_personality, 1)
-#define __NR_getpriority                       132
-__SYSCALL(132, sys_getpriority, 2)
-#define __NR_setpriority                       133
-__SYSCALL(133, sys_setpriority, 3)
-#define __NR_setitimer                                 134
-__SYSCALL(134, sys_setitimer, 3)
-#define __NR_getitimer                                 135
-__SYSCALL(135, sys_getitimer, 2)
-#define __NR_setuid                            136
-__SYSCALL(136, sys_setuid, 1)
-#define __NR_getuid                            137
-__SYSCALL(137, sys_getuid, 0)
-#define __NR_setgid                            138
-__SYSCALL(138, sys_setgid, 1)
-#define __NR_getgid                            139
-__SYSCALL(139, sys_getgid, 0)
-#define __NR_geteuid                           140
-__SYSCALL(140, sys_geteuid, 0)
-#define __NR_getegid                           141
-__SYSCALL(141, sys_getegid, 0)
-#define __NR_setreuid                          142
-__SYSCALL(142, sys_setreuid, 2)
-#define __NR_setregid                          143
-__SYSCALL(143, sys_setregid, 2)
-#define __NR_setresuid                                 144
-__SYSCALL(144, sys_setresuid, 3)
-#define __NR_getresuid                                 145
-__SYSCALL(145, sys_getresuid, 3)
-#define __NR_setresgid                                 146
-__SYSCALL(146, sys_setresgid, 3)
-#define __NR_getresgid                                 147
-__SYSCALL(147, sys_getresgid, 3)
-#define __NR_setpgid                           148
-__SYSCALL(148, sys_setpgid, 2)
-#define __NR_getpgid                           149
-__SYSCALL(149, sys_getpgid, 1)
-#define __NR_getppid                           150
-__SYSCALL(150, sys_getppid, 0)
-#define __NR_getpgrp                           151
-__SYSCALL(151, sys_getpgrp, 0)
-
-#define __NR_reserved152                       152     /* set_thread_area */
-__SYSCALL(152, sys_ni_syscall, 0)
-#define __NR_reserved153                       153     /* get_thread_area */
-__SYSCALL(153, sys_ni_syscall, 0)
-#define __NR_times                             154
-__SYSCALL(154, sys_times, 1)
-#define __NR_acct                              155
-__SYSCALL(155, sys_acct, 1)
-#define __NR_sched_setaffinity                         156
-__SYSCALL(156, sys_sched_setaffinity, 3)
-#define __NR_sched_getaffinity                         157
-__SYSCALL(157, sys_sched_getaffinity, 3)
-#define __NR_capget                            158
-__SYSCALL(158, sys_capget, 2)
-#define __NR_capset                            159
-__SYSCALL(159, sys_capset, 2)
-#define __NR_ptrace                            160
-__SYSCALL(160, sys_ptrace, 4)
-#define __NR_semtimedop                                161
-__SYSCALL(161, sys_semtimedop, 5)
-#define __NR_semget                            162
-__SYSCALL(162, sys_semget, 4)
-#define __NR_semop                             163
-__SYSCALL(163, sys_semop, 4)
-#define __NR_semctl                            164
-__SYSCALL(164, sys_semctl, 4)
-#define __NR_available165                      165
-__SYSCALL(165, sys_ni_syscall, 0)
-#define __NR_msgget                            166
-__SYSCALL(166, sys_msgget, 4)
-#define __NR_msgsnd                            167
-__SYSCALL(167, sys_msgsnd, 4)
-#define __NR_msgrcv                            168
-__SYSCALL(168, sys_msgrcv, 4)
-#define __NR_msgctl                            169
-__SYSCALL(169, sys_msgctl, 4)
-#define __NR_available170                      170
-__SYSCALL(170, sys_ni_syscall, 0)
-#define __NR_available171                      171
-__SYSCALL(171, sys_ni_syscall, 0)
-
-/* File System */
-
-#define __NR_mount                             172
-__SYSCALL(172, sys_mount, 5)
-#define __NR_swapon                            173
-__SYSCALL(173, sys_swapon, 2)
-#define __NR_chroot                            174
-__SYSCALL(174, sys_chroot, 1)
-#define __NR_pivot_root                        175
-__SYSCALL(175, sys_pivot_root, 2)
-#define __NR_umount                            176
-__SYSCALL(176, sys_umount, 2)
-#define __NR_swapoff                           177
-__SYSCALL(177, sys_swapoff, 1)
-#define __NR_sync                              178
-__SYSCALL(178, sys_sync, 0)
-#define __NR_available179                      179
-__SYSCALL(179, sys_ni_syscall, 0)
-#define __NR_setfsuid                          180
-__SYSCALL(180, sys_setfsuid, 1)
-#define __NR_setfsgid                          181
-__SYSCALL(181, sys_setfsgid, 1)
-#define __NR_sysfs                             182
-__SYSCALL(182, sys_sysfs, 3)
-#define __NR_ustat                             183
-__SYSCALL(183, sys_ustat, 2)
-#define __NR_statfs                            184
-__SYSCALL(184, sys_statfs, 2)
-#define __NR_fstatfs                           185
-__SYSCALL(185, sys_fstatfs, 2)
-#define __NR_statfs64                          186
-__SYSCALL(186, sys_statfs64, 3)
-#define __NR_fstatfs64                                 187
-__SYSCALL(187, sys_fstatfs64, 3)
-
-/* System */
-
-#define __NR_setrlimit                                 188
-__SYSCALL(188, sys_setrlimit, 2)
-#define __NR_getrlimit                                 189
-__SYSCALL(189, sys_getrlimit, 2)
-#define __NR_getrusage                                 190
-__SYSCALL(190, sys_getrusage, 2)
-#define __NR_futex                             191
-__SYSCALL(191, sys_futex, 5)
-#define __NR_gettimeofday                      192
-__SYSCALL(192, sys_gettimeofday, 2)
-#define __NR_settimeofday                      193
-__SYSCALL(193, sys_settimeofday, 2)
-#define __NR_adjtimex                          194
-__SYSCALL(194, sys_adjtimex, 1)
-#define __NR_nanosleep                         195
-__SYSCALL(195, sys_nanosleep, 2)
-#define __NR_getgroups                                 196
-__SYSCALL(196, sys_getgroups, 2)
-#define __NR_setgroups                                 197
-__SYSCALL(197, sys_setgroups, 2)
-#define __NR_sethostname                       198
-__SYSCALL(198, sys_sethostname, 2)
-#define __NR_setdomainname                     199
-__SYSCALL(199, sys_setdomainname, 2)
-#define __NR_syslog                            200
-__SYSCALL(200, sys_syslog, 3)
-#define __NR_vhangup                           201
-__SYSCALL(201, sys_vhangup, 0)
-#define __NR_uselib                            202
-__SYSCALL(202, sys_uselib, 1)
-#define __NR_reboot                            203
-__SYSCALL(203, sys_reboot, 3)
-#define __NR_quotactl                          204
-__SYSCALL(204, sys_quotactl, 4)
-#define __NR_nfsservctl                        205
-__SYSCALL(205, sys_ni_syscall, 0)
-#define __NR__sysctl                           206
-__SYSCALL(206, sys_sysctl, 1)
-#define __NR_bdflush                           207
-__SYSCALL(207, sys_bdflush, 2)
-#define __NR_uname                             208
-__SYSCALL(208, sys_newuname, 1)
-#define __NR_sysinfo                           209
-__SYSCALL(209, sys_sysinfo, 1)
-#define __NR_init_module                       210
-__SYSCALL(210, sys_init_module, 2)
-#define __NR_delete_module                     211
-__SYSCALL(211, sys_delete_module, 1)
-
-#define __NR_sched_setparam                    212
-__SYSCALL(212, sys_sched_setparam, 2)
-#define __NR_sched_getparam                    213
-__SYSCALL(213, sys_sched_getparam, 2)
-#define __NR_sched_setscheduler                214
-__SYSCALL(214, sys_sched_setscheduler, 3)
-#define __NR_sched_getscheduler                215
-__SYSCALL(215, sys_sched_getscheduler, 1)
-#define __NR_sched_get_priority_max            216
-__SYSCALL(216, sys_sched_get_priority_max, 1)
-#define __NR_sched_get_priority_min            217
-__SYSCALL(217, sys_sched_get_priority_min, 1)
-#define __NR_sched_rr_get_interval             218
-__SYSCALL(218, sys_sched_rr_get_interval, 2)
-#define __NR_sched_yield                       219
-__SYSCALL(219, sys_sched_yield, 0)
-#define __NR_available222                      222
-__SYSCALL(222, sys_ni_syscall, 0)
-
-/* Signal Handling */
-
-#define __NR_restart_syscall                   223
-__SYSCALL(223, sys_restart_syscall, 0)
-#define __NR_sigaltstack                       224
-__SYSCALL(224, xtensa_sigaltstack, 2)
-#define __NR_rt_sigreturn                      225
-__SYSCALL(225, xtensa_rt_sigreturn, 1)
-#define __NR_rt_sigaction                      226
-__SYSCALL(226, sys_rt_sigaction, 4)
-#define __NR_rt_sigprocmask                    227
-__SYSCALL(227, sys_rt_sigprocmask, 4)
-#define __NR_rt_sigpending                     228
-__SYSCALL(228, sys_rt_sigpending, 2)
-#define __NR_rt_sigtimedwait                   229
-__SYSCALL(229, sys_rt_sigtimedwait, 4)
-#define __NR_rt_sigqueueinfo                   230
-__SYSCALL(230, sys_rt_sigqueueinfo, 3)
-#define __NR_rt_sigsuspend                     231
-__SYSCALL(231, sys_rt_sigsuspend, 2)
-
-/* Message */
-
-#define __NR_mq_open                           232
-__SYSCALL(232, sys_mq_open, 4)
-#define __NR_mq_unlink                                 233
-__SYSCALL(233, sys_mq_unlink, 1)
-#define __NR_mq_timedsend                      234
-__SYSCALL(234, sys_mq_timedsend, 5)
-#define __NR_mq_timedreceive                   235
-__SYSCALL(235, sys_mq_timedreceive, 5)
-#define __NR_mq_notify                                 236
-__SYSCALL(236, sys_mq_notify, 2)
-#define __NR_mq_getsetattr                     237
-__SYSCALL(237, sys_mq_getsetattr, 3)
-#define __NR_available238                      238
-__SYSCALL(238, sys_ni_syscall, 0)
-
-/* IO */
-
-#define __NR_io_setup                          239
-__SYSCALL(239, sys_io_setup, 2)
-#define __NR_io_destroy                        240
-__SYSCALL(240, sys_io_destroy, 1)
-#define __NR_io_submit                                 241
-__SYSCALL(241, sys_io_submit, 3)
-#define __NR_io_getevents                      242
-__SYSCALL(242, sys_io_getevents, 5)
-#define __NR_io_cancel                                 243
-__SYSCALL(243, sys_io_cancel, 3)
-#define __NR_clock_settime                     244
-__SYSCALL(244, sys_clock_settime, 2)
-#define __NR_clock_gettime                     245
-__SYSCALL(245, sys_clock_gettime, 2)
-#define __NR_clock_getres                      246
-__SYSCALL(246, sys_clock_getres, 2)
-#define __NR_clock_nanosleep                   247
-__SYSCALL(247, sys_clock_nanosleep, 4)
-
-/* Timer */
-
-#define __NR_timer_create                      248
-__SYSCALL(248, sys_timer_create, 3)
-#define __NR_timer_delete                      249
-__SYSCALL(249, sys_timer_delete, 1)
-#define __NR_timer_settime                     250
-__SYSCALL(250, sys_timer_settime, 4)
-#define __NR_timer_gettime                     251
-__SYSCALL(251, sys_timer_gettime, 2)
-#define __NR_timer_getoverrun                  252
-__SYSCALL(252, sys_timer_getoverrun, 1)
-
-/* System */
-
-#define __NR_reserved244                       253
-__SYSCALL(253, sys_ni_syscall, 0)
-#define __NR_lookup_dcookie                    254
-__SYSCALL(254, sys_lookup_dcookie, 4)
-#define __NR_available255                      255
-__SYSCALL(255, sys_ni_syscall, 0)
-#define __NR_add_key                           256
-__SYSCALL(256, sys_add_key, 5)
-#define __NR_request_key                       257
-__SYSCALL(257, sys_request_key, 5)
-#define __NR_keyctl                            258
-__SYSCALL(258, sys_keyctl, 5)
-#define __NR_available259                      259
-__SYSCALL(259, sys_ni_syscall, 0)
-
-
-#define __NR_readahead                         260
-__SYSCALL(260, sys_readahead, 5)
-#define __NR_remap_file_pages                  261
-__SYSCALL(261, sys_remap_file_pages, 5)
-#define __NR_migrate_pages                     262
-__SYSCALL(262, sys_migrate_pages, 0)
-#define __NR_mbind                             263
-__SYSCALL(263, sys_mbind, 6)
-#define __NR_get_mempolicy                     264
-__SYSCALL(264, sys_get_mempolicy, 5)
-#define __NR_set_mempolicy                     265
-__SYSCALL(265, sys_set_mempolicy, 3)
-#define __NR_unshare                           266
-__SYSCALL(266, sys_unshare, 1)
-#define __NR_move_pages                                267
-__SYSCALL(267, sys_move_pages, 0)
-#define __NR_splice                            268
-__SYSCALL(268, sys_splice, 0)
-#define __NR_tee                               269
-__SYSCALL(269, sys_tee, 0)
-#define __NR_vmsplice                          270
-__SYSCALL(270, sys_vmsplice, 0)
-#define __NR_available271                      271
-__SYSCALL(271, sys_ni_syscall, 0)
-
-#define __NR_pselect6                          272
-__SYSCALL(272, sys_pselect6, 0)
-#define __NR_ppoll                             273
-__SYSCALL(273, sys_ppoll, 0)
-#define __NR_epoll_pwait                       274
-__SYSCALL(274, sys_epoll_pwait, 0)
-#define __NR_available275                      275
-__SYSCALL(275, sys_ni_syscall, 0)
-
-#define __NR_inotify_init                      276
-__SYSCALL(276, sys_inotify_init, 0)
-#define __NR_inotify_add_watch                 277
-__SYSCALL(277, sys_inotify_add_watch, 3)
-#define __NR_inotify_rm_watch                  278
-__SYSCALL(278, sys_inotify_rm_watch, 2)
-#define __NR_available279                      279
-__SYSCALL(279, sys_ni_syscall, 0)
-
-#define __NR_getcpu                            280
-__SYSCALL(280, sys_getcpu, 0)
-#define __NR_kexec_load                                281
-__SYSCALL(281, sys_ni_syscall, 0)
-
-#define __NR_ioprio_set                                282
-__SYSCALL(282, sys_ioprio_set, 2)
-#define __NR_ioprio_get                                283
-__SYSCALL(283, sys_ioprio_get, 3)
-
-#define __NR_set_robust_list                   284
-__SYSCALL(284, sys_set_robust_list, 3)
-#define __NR_get_robust_list                   285
-__SYSCALL(285, sys_get_robust_list, 3)
-#define __NR_reserved286                       286     /* sync_file_rangeX */
-__SYSCALL(286, sys_ni_syscall, 3)
-#define __NR_available287                      287
-__SYSCALL(287, sys_faccessat, 0)
-
-/* Relative File Operations */
-
-#define __NR_openat                            288
-__SYSCALL(288, sys_openat, 4)
-#define __NR_mkdirat                           289
-__SYSCALL(289, sys_mkdirat, 3)
-#define __NR_mknodat                           290
-__SYSCALL(290, sys_mknodat, 4)
-#define __NR_unlinkat                          291
-__SYSCALL(291, sys_unlinkat, 3)
-#define __NR_renameat                          292
-__SYSCALL(292, sys_renameat, 4)
-#define __NR_linkat                            293
-__SYSCALL(293, sys_linkat, 5)
-#define __NR_symlinkat                         294
-__SYSCALL(294, sys_symlinkat, 3)
-#define __NR_readlinkat                                295
-__SYSCALL(295, sys_readlinkat, 4)
-#define __NR_utimensat                         296
-__SYSCALL(296, sys_utimensat, 0)
-#define __NR_fchownat                          297
-__SYSCALL(297, sys_fchownat, 5)
-#define __NR_futimesat                         298
-__SYSCALL(298, sys_futimesat, 4)
-#define __NR_fstatat64                         299
-__SYSCALL(299, sys_fstatat64, 0)
-#define __NR_fchmodat                          300
-__SYSCALL(300, sys_fchmodat, 4)
-#define __NR_faccessat                         301
-__SYSCALL(301, sys_faccessat, 4)
-#define __NR_available302                      302
-__SYSCALL(302, sys_ni_syscall, 0)
-#define __NR_available303                      303
-__SYSCALL(303, sys_ni_syscall, 0)
-
-#define __NR_signalfd                          304
-__SYSCALL(304, sys_signalfd, 3)
-/*  305 was __NR_timerfd  */
-__SYSCALL(305, sys_ni_syscall, 0)
-#define __NR_eventfd                           306
-__SYSCALL(306, sys_eventfd, 1)
-#define __NR_recvmmsg                          307
-__SYSCALL(307, sys_recvmmsg, 5)
-#define __NR_setns                             308
-__SYSCALL(308, sys_setns, 2)
-
-#define __NR_syscall_count                     309
-
-/*
- * sysxtensa syscall handler
- *
- * int sysxtensa (SYS_XTENSA_ATOMIC_SET,     ptr, val,    unused);
- * int sysxtensa (SYS_XTENSA_ATOMIC_ADD,     ptr, val,    unused);
- * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val,    unused);
- * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
- *        a2            a6                   a3    a4      a5
- */
-
-#define SYS_XTENSA_RESERVED               0     /* don't use this */
-#define SYS_XTENSA_ATOMIC_SET             1     /* set variable */
-#define SYS_XTENSA_ATOMIC_EXG_ADD         2     /* exchange memory and add */
-#define SYS_XTENSA_ATOMIC_ADD             3     /* add to memory */
-#define SYS_XTENSA_ATOMIC_CMP_SWP         4     /* compare and swap */
-
-#define SYS_XTENSA_COUNT                  5     /* count */
-
-#ifdef __KERNEL__
+#define __ARCH_WANT_SYS_EXECVE
+#include <uapi/asm/unistd.h>
 
 /*
  * "Conditional" syscalls
@@ -735,5 +31,4 @@ __SYSCALL(308, sys_setns, 2)
 #define __IGNORE_vfork                         /* use clone */
 #define __IGNORE_fadvise64                     /* use fadvise64_64 */
 
-#endif /* __KERNEL__ */
-#endif /* _XTENSA_UNISTD_H */
+#endif /* _XTENSA_UNISTD_H */
diff --git a/arch/xtensa/include/asm/xor.h b/arch/xtensa/include/asm/xor.h
deleted file mode 100644 (file)
index e7b1f08..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * include/asm-xtensa/xor.h
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
- */
-
-#ifndef _XTENSA_XOR_H
-#define _XTENSA_XOR_H
-
-#include <asm-generic/xor.h>
-
-#endif
index baebb3da1d44160fc6f6f259886656e6f494b167..56aad54e7fb7b7fd62c5a55e13589705d194ebb7 100644 (file)
@@ -1,3 +1,25 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += auxvec.h
+header-y += byteorder.h
+header-y += ioctls.h
+header-y += ipcbuf.h
+header-y += mman.h
+header-y += msgbuf.h
+header-y += param.h
+header-y += poll.h
+header-y += posix_types.h
+header-y += ptrace.h
+header-y += sembuf.h
+header-y += setup.h
+header-y += shmbuf.h
+header-y += sigcontext.h
+header-y += signal.h
+header-y += socket.h
+header-y += sockios.h
+header-y += stat.h
+header-y += swab.h
+header-y += termbits.h
+header-y += types.h
+header-y += unistd.h
diff --git a/arch/xtensa/include/uapi/asm/auxvec.h b/arch/xtensa/include/uapi/asm/auxvec.h
new file mode 100644 (file)
index 0000000..257dec7
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __XTENSA_AUXVEC_H
+#define __XTENSA_AUXVEC_H
+
+#endif
diff --git a/arch/xtensa/include/uapi/asm/byteorder.h b/arch/xtensa/include/uapi/asm/byteorder.h
new file mode 100644 (file)
index 0000000..54eb631
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _XTENSA_BYTEORDER_H
+#define _XTENSA_BYTEORDER_H
+
+#ifdef __XTENSA_EL__
+#include <linux/byteorder/little_endian.h>
+#elif defined(__XTENSA_EB__)
+#include <linux/byteorder/big_endian.h>
+#else
+# error processor byte order undefined!
+#endif
+
+#endif /* _XTENSA_BYTEORDER_H */
diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h
new file mode 100644 (file)
index 0000000..2aa4cd9
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * include/asm-xtensa/ioctls.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003 - 2005 Tensilica Inc.
+ *
+ * Derived from "include/asm-i386/ioctls.h"
+ */
+
+#ifndef _XTENSA_IOCTLS_H
+#define _XTENSA_IOCTLS_H
+
+#include <asm/ioctl.h>
+
+#define FIOCLEX                _IO('f', 1)
+#define FIONCLEX       _IO('f', 2)
+#define FIOASYNC       _IOW('f', 125, int)
+#define FIONBIO                _IOW('f', 126, int)
+#define FIONREAD       _IOR('f', 127, int)
+#define TIOCINQ                FIONREAD
+#define FIOQSIZE       _IOR('f', 128, loff_t)
+
+#define TCGETS         0x5401
+#define TCSETS         0x5402
+#define TCSETSW                0x5403
+#define TCSETSF                0x5404
+
+#define TCGETA         _IOR('t', 23, struct termio)
+#define TCSETA         _IOW('t', 24, struct termio)
+#define TCSETAW                _IOW('t', 25, struct termio)
+#define TCSETAF                _IOW('t', 28, struct termio)
+
+#define TCSBRK         _IO('t', 29)
+#define TCXONC         _IO('t', 30)
+#define TCFLSH         _IO('t', 31)
+
+#define TIOCSWINSZ     _IOW('t', 103, struct winsize)
+#define TIOCGWINSZ     _IOR('t', 104, struct winsize)
+#define        TIOCSTART       _IO('t', 110)           /* start output, like ^Q */
+#define        TIOCSTOP        _IO('t', 111)           /* stop output, like ^S */
+#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
+
+#define TIOCSPGRP      _IOW('t', 118, int)
+#define TIOCGPGRP      _IOR('t', 119, int)
+
+#define TIOCEXCL       _IO('T', 12)
+#define TIOCNXCL       _IO('T', 13)
+#define TIOCSCTTY      _IO('T', 14)
+
+#define TIOCSTI                _IOW('T', 18, char)
+#define TIOCMGET       _IOR('T', 21, unsigned int)
+#define TIOCMBIS       _IOW('T', 22, unsigned int)
+#define TIOCMBIC       _IOW('T', 23, unsigned int)
+#define TIOCMSET       _IOW('T', 24, unsigned int)
+# define TIOCM_LE      0x001
+# define TIOCM_DTR     0x002
+# define TIOCM_RTS     0x004
+# define TIOCM_ST      0x008
+# define TIOCM_SR      0x010
+# define TIOCM_CTS     0x020
+# define TIOCM_CAR     0x040
+# define TIOCM_RNG     0x080
+# define TIOCM_DSR     0x100
+# define TIOCM_CD      TIOCM_CAR
+# define TIOCM_RI      TIOCM_RNG
+
+#define TIOCGSOFTCAR   _IOR('T', 25, unsigned int)
+#define TIOCSSOFTCAR   _IOW('T', 26, unsigned int)
+#define TIOCLINUX      _IOW('T', 28, char)
+#define TIOCCONS       _IO('T', 29)
+#define TIOCGSERIAL    0x803C541E      /*_IOR('T', 30, struct serial_struct)*/
+#define TIOCSSERIAL    0x403C541F      /*_IOW('T', 31, struct serial_struct)*/
+#define TIOCPKT                _IOW('T', 32, int)
+# define TIOCPKT_DATA           0
+# define TIOCPKT_FLUSHREAD      1
+# define TIOCPKT_FLUSHWRITE     2
+# define TIOCPKT_STOP           4
+# define TIOCPKT_START          8
+# define TIOCPKT_NOSTOP                16
+# define TIOCPKT_DOSTOP                32
+# define TIOCPKT_IOCTL         64
+
+
+#define TIOCNOTTY      _IO('T', 34)
+#define TIOCSETD       _IOW('T', 35, int)
+#define TIOCGETD       _IOR('T', 36, int)
+#define TCSBRKP                _IOW('T', 37, int)   /* Needed for POSIX tcsendbreak()*/
+#define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/
+#define TIOCSBRK       _IO('T', 39)         /* BSD compatibility */
+#define TIOCCBRK       _IO('T', 40)         /* BSD compatibility */
+#define TIOCGSID       _IOR('T', 41, pid_t) /* Return the session ID of FD*/
+#define TCGETS2                _IOR('T', 42, struct termios2)
+#define TCSETS2                _IOW('T', 43, struct termios2)
+#define TCSETSW2       _IOW('T', 44, struct termios2)
+#define TCSETSF2       _IOW('T', 45, struct termios2)
+#define TIOCGPTN       _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK     _IOW('T',0x31, int)  /* Lock/unlock Pty */
+#define TIOCGDEV       _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
+#define TIOCSIG                _IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP    _IO('T', 0x37)
+
+#define TIOCSERCONFIG  _IO('T', 83)
+#define TIOCSERGWILD   _IOR('T', 84,  int)
+#define TIOCSERSWILD   _IOW('T', 85,  int)
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458               /* For debugging only */
+#define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* Get line status reg. */
+  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+# define TIOCSER_TEMT    0x01               /* Transmitter physically empty */
+#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config  */
+#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */
+
+#define TIOCMIWAIT     _IO('T', 92) /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT    0x545D  /* read serial port inline interrupt counts */
+
+#endif /* _XTENSA_IOCTLS_H */
diff --git a/arch/xtensa/include/uapi/asm/ipcbuf.h b/arch/xtensa/include/uapi/asm/ipcbuf.h
new file mode 100644 (file)
index 0000000..c33aa6a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * include/asm-xtensa/ipcbuf.h
+ *
+ * The ipc64_perm structure for the Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_IPCBUF_H
+#define _XTENSA_IPCBUF_H
+
+/*
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ *
+ * 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.
+ */
+
+struct ipc64_perm
+{
+       __kernel_key_t          key;
+       __kernel_uid32_t        uid;
+       __kernel_gid32_t        gid;
+       __kernel_uid32_t        cuid;
+       __kernel_gid32_t        cgid;
+       __kernel_mode_t         mode;
+       unsigned long           seq;
+       unsigned long           __unused1;
+       unsigned long           __unused2;
+};
+
+#endif /* _XTENSA_IPCBUF_H */
diff --git a/arch/xtensa/include/uapi/asm/mman.h b/arch/xtensa/include/uapi/asm/mman.h
new file mode 100644 (file)
index 0000000..25bc6c1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * include/asm-xtensa/mman.h
+ *
+ * Xtensa Processor memory-manager definitions
+ *
+ * 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) 1995 by Ralf Baechle
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_MMAN_H
+#define _XTENSA_MMAN_H
+
+/*
+ * Protections are chosen from these bits, OR'd together.  The
+ * implementation does not necessarily support PROT_EXEC or PROT_WRITE
+ * without PROT_READ.  The only guarantees are that no writing will be
+ * allowed without PROT_WRITE and no access will be allowed for PROT_NONE.
+ */
+
+#define PROT_NONE      0x0             /* page can not be accessed */
+#define PROT_READ      0x1             /* page can be read */
+#define PROT_WRITE     0x2             /* page can be written */
+#define PROT_EXEC      0x4             /* page can be executed */
+
+#define PROT_SEM       0x10            /* page may be used for atomic ops */
+#define PROT_GROWSDOWN 0x01000000      /* mprotect flag: extend change to start of growsdown vma */
+#define PROT_GROWSUP   0x02000000      /* mprotect flag: extend change to end fo growsup vma */
+
+/*
+ * Flags for mmap
+ */
+#define MAP_SHARED     0x001           /* Share changes */
+#define MAP_PRIVATE    0x002           /* Changes are private */
+#define MAP_TYPE       0x00f           /* Mask for type of mapping */
+#define MAP_FIXED      0x010           /* Interpret addr exactly */
+
+/* not used by linux, but here to make sure we don't clash with ABI defines */
+#define MAP_RENAME     0x020           /* Assign page to file */
+#define MAP_AUTOGROW   0x040           /* File may grow by writing */
+#define MAP_LOCAL      0x080           /* Copy on fork/sproc */
+#define MAP_AUTORSRV   0x100           /* Logical swap reserved on demand */
+
+/* These are linux-specific */
+#define MAP_NORESERVE  0x0400          /* don't check for reservations */
+#define MAP_ANONYMOUS  0x0800          /* don't use a file */
+#define MAP_GROWSDOWN  0x1000          /* stack-like segment */
+#define MAP_DENYWRITE  0x2000          /* ETXTBSY */
+#define MAP_EXECUTABLE 0x4000          /* mark it as an executable */
+#define MAP_LOCKED     0x8000          /* pages are locked */
+#define MAP_POPULATE   0x10000         /* populate (prefault) pagetables */
+#define MAP_NONBLOCK   0x20000         /* do not block on IO */
+#define MAP_STACK      0x40000         /* give out an address that is best suited for process/thread stacks */
+#define MAP_HUGETLB    0x80000         /* create a huge page mapping */
+
+/*
+ * Flags for msync
+ */
+#define MS_ASYNC       0x0001          /* sync memory asynchronously */
+#define MS_INVALIDATE  0x0002          /* invalidate mappings & caches */
+#define MS_SYNC                0x0004          /* synchronous memory sync */
+
+/*
+ * Flags for mlockall
+ */
+#define MCL_CURRENT    1               /* lock all current mappings */
+#define MCL_FUTURE     2               /* lock all future mappings */
+
+#define MADV_NORMAL    0               /* no further special treatment */
+#define MADV_RANDOM    1               /* expect random page references */
+#define MADV_SEQUENTIAL        2               /* expect sequential page references */
+#define MADV_WILLNEED  3               /* will need these pages */
+#define MADV_DONTNEED  4               /* don't need these pages */
+
+/* common parameters: try to keep these consistent across architectures */
+#define MADV_REMOVE    9               /* remove these pages & resources */
+#define MADV_DONTFORK  10              /* don't inherit across fork */
+#define MADV_DOFORK    11              /* do inherit across fork */
+
+#define MADV_MERGEABLE   12            /* KSM may merge identical pages */
+#define MADV_UNMERGEABLE 13            /* KSM may not merge identical pages */
+
+#define MADV_HUGEPAGE  14              /* Worth backing with hugepages */
+#define MADV_NOHUGEPAGE        15              /* Not worth backing with hugepages */
+
+#define MADV_DONTDUMP   16             /* Explicity exclude from the core dump,
+                                          overrides the coredump filter bits */
+#define MADV_DODUMP    17              /* Clear the MADV_NODUMP flag */
+
+/* compatibility flags */
+#define MAP_FILE       0
+
+#endif /* _XTENSA_MMAN_H */
diff --git a/arch/xtensa/include/uapi/asm/msgbuf.h b/arch/xtensa/include/uapi/asm/msgbuf.h
new file mode 100644 (file)
index 0000000..693c967
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * include/asm-xtensa/msgbuf.h
+ *
+ * The msqid64_ds structure for the Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ * 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 _XTENSA_MSGBUF_H
+#define _XTENSA_MSGBUF_H
+
+struct msqid64_ds {
+       struct ipc64_perm msg_perm;
+#ifdef __XTENSA_EB__
+       unsigned int    __unused1;
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned int    __unused2;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned int    __unused3;
+       __kernel_time_t msg_ctime;      /* last change time */
+#elif defined(__XTENSA_EL__)
+       __kernel_time_t msg_stime;      /* last msgsnd time */
+       unsigned int    __unused1;
+       __kernel_time_t msg_rtime;      /* last msgrcv time */
+       unsigned int    __unused2;
+       __kernel_time_t msg_ctime;      /* last change time */
+       unsigned int    __unused3;
+#else
+# error processor byte order undefined!
+#endif
+       unsigned long  msg_cbytes;      /* current number of bytes on queue */
+       unsigned long  msg_qnum;        /* number of messages in queue */
+       unsigned long  msg_qbytes;      /* max number of bytes on queue */
+       __kernel_pid_t msg_lspid;       /* pid of last msgsnd */
+       __kernel_pid_t msg_lrpid;       /* last receive pid */
+       unsigned long  __unused4;
+       unsigned long  __unused5;
+};
+
+#endif /* _XTENSA_MSGBUF_H */
diff --git a/arch/xtensa/include/uapi/asm/param.h b/arch/xtensa/include/uapi/asm/param.h
new file mode 100644 (file)
index 0000000..87bc2ea
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * include/asm-xtensa/param.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_PARAM_H
+#define _UAPI_XTENSA_PARAM_H
+
+#ifndef __KERNEL__
+# define HZ            100
+#endif
+
+#define EXEC_PAGESIZE  4096
+
+#ifndef NGROUPS
+#define NGROUPS                32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP                (-1)
+#endif
+
+#define MAXHOSTNAMELEN 64      /* max length of hostname */
+
+#endif /* _UAPI_XTENSA_PARAM_H */
diff --git a/arch/xtensa/include/uapi/asm/poll.h b/arch/xtensa/include/uapi/asm/poll.h
new file mode 100644 (file)
index 0000000..9d2d599
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * include/asm-xtensa/poll.h
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file "COPYING" in the main directory of
+ * this archive for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_POLL_H
+#define _XTENSA_POLL_H
+
+#define POLLWRNORM     POLLOUT
+#define POLLWRBAND     0x0100
+#define POLLREMOVE     0x0800
+
+#include <asm-generic/poll.h>
+
+#endif /* _XTENSA_POLL_H */
diff --git a/arch/xtensa/include/uapi/asm/posix_types.h b/arch/xtensa/include/uapi/asm/posix_types.h
new file mode 100644 (file)
index 0000000..6e96be0
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * include/asm-xtensa/posix_types.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Largely copied from include/asm-ppc/posix_types.h
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_POSIX_TYPES_H
+#define _XTENSA_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_ipc_pid_t;
+#define __kernel_ipc_pid_t __kernel_ipc_pid_t
+
+typedef unsigned int   __kernel_size_t;
+typedef int            __kernel_ssize_t;
+typedef long           __kernel_ptrdiff_t;
+#define __kernel_size_t __kernel_size_t
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+#define __kernel_old_uid_t __kernel_old_uid_t
+
+typedef unsigned short __kernel_old_dev_t;
+#define __kernel_old_dev_t __kernel_old_dev_t
+
+#include <asm-generic/posix_types.h>
+
+#endif /* _XTENSA_POSIX_TYPES_H */
diff --git a/arch/xtensa/include/uapi/asm/ptrace.h b/arch/xtensa/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..ee17aa8
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * include/asm-xtensa/ptrace.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_PTRACE_H
+#define _UAPI_XTENSA_PTRACE_H
+
+/*
+ * Kernel stack
+ *
+ *             +-----------------------+  -------- STACK_SIZE
+ *             |     register file     |  |
+ *             +-----------------------+  |
+ *             |    struct pt_regs     |  |
+ *             +-----------------------+  | ------ PT_REGS_OFFSET
+ * double      :  16 bytes spill area  :  |  ^
+ * excetion    :- - - - - - - - - - - -:  |  |
+ * frame       :    struct pt_regs     :  |  |
+ *             :- - - - - - - - - - - -:  |  |
+ *             |                       |  |  |
+ *             |     memory stack      |  |  |
+ *             |                       |  |  |
+ *             ~                       ~  ~  ~
+ *             ~                       ~  ~  ~
+ *             |                       |  |  |
+ *             |                       |  |  |
+ *             +-----------------------+  |  | --- STACK_BIAS
+ *             |  struct task_struct   |  |  |  ^
+ *  current --> +-----------------------+  |  |  |
+ *             |  struct thread_info   |  |  |  |
+ *             +-----------------------+ --------
+ */
+
+#define KERNEL_STACK_SIZE (2 * PAGE_SIZE)
+
+/*  Offsets for exception_handlers[] (3 x 64-entries x 4-byte tables). */
+
+#define EXC_TABLE_KSTK         0x004   /* Kernel Stack */
+#define EXC_TABLE_DOUBLE_SAVE  0x008   /* Double exception save area for a0 */
+#define EXC_TABLE_FIXUP                0x00c   /* Fixup handler */
+#define EXC_TABLE_PARAM                0x010   /* For passing a parameter to fixup */
+#define EXC_TABLE_SYSCALL_SAVE 0x014   /* For fast syscall handler */
+#define EXC_TABLE_FAST_USER    0x100   /* Fast user exception handler */
+#define EXC_TABLE_FAST_KERNEL  0x200   /* Fast kernel exception handler */
+#define EXC_TABLE_DEFAULT      0x300   /* Default C-Handler */
+#define EXC_TABLE_SIZE         0x400
+
+/* Registers used by strace */
+
+#define REG_A_BASE     0x0000
+#define REG_AR_BASE    0x0100
+#define REG_PC         0x0020
+#define REG_PS         0x02e6
+#define REG_WB         0x0248
+#define REG_WS         0x0249
+#define REG_LBEG       0x0200
+#define REG_LEND       0x0201
+#define REG_LCOUNT     0x0202
+#define REG_SAR                0x0203
+
+#define SYSCALL_NR     0x00ff
+
+/* Other PTRACE_ values defined in <linux/ptrace.h> using values 0-9,16,17,24 */
+
+#define PTRACE_GETREGS         12
+#define PTRACE_SETREGS         13
+#define PTRACE_GETXTREGS       18
+#define PTRACE_SETXTREGS       19
+
+
+#endif /* _UAPI_XTENSA_PTRACE_H */
diff --git a/arch/xtensa/include/uapi/asm/sembuf.h b/arch/xtensa/include/uapi/asm/sembuf.h
new file mode 100644 (file)
index 0000000..c158704
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * include/asm-xtensa/sembuf.h
+ *
+ * The semid64_ds structure for Xtensa 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) 2001 - 2005 Tensilica Inc.
+ *
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ */
+
+#ifndef _XTENSA_SEMBUF_H
+#define _XTENSA_SEMBUF_H
+
+#include <asm/byteorder.h>
+
+struct semid64_ds {
+       struct ipc64_perm sem_perm;             /* permissions .. see ipc.h */
+#ifdef __XTENSA_EL__
+       __kernel_time_t sem_otime;              /* last semop time */
+       unsigned long   __unused1;
+       __kernel_time_t sem_ctime;              /* last change time */
+       unsigned long   __unused2;
+#else
+       unsigned long   __unused1;
+       __kernel_time_t sem_otime;              /* last semop time */
+       unsigned long   __unused2;
+       __kernel_time_t sem_ctime;              /* last change time */
+#endif
+       unsigned long   sem_nsems;              /* no. of semaphores in array */
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* __ASM_XTENSA_SEMBUF_H */
diff --git a/arch/xtensa/include/uapi/asm/setup.h b/arch/xtensa/include/uapi/asm/setup.h
new file mode 100644 (file)
index 0000000..9fa8ad9
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * include/asm-xtensa/setup.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SETUP_H
+#define _XTENSA_SETUP_H
+
+#define COMMAND_LINE_SIZE      256
+
+extern void set_except_vector(int n, void *addr);
+
+#endif
diff --git a/arch/xtensa/include/uapi/asm/shmbuf.h b/arch/xtensa/include/uapi/asm/shmbuf.h
new file mode 100644 (file)
index 0000000..ad4b012
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * include/asm-xtensa/shmbuf.h
+ *
+ * The shmid64_ds structure for Xtensa architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SHMBUF_H
+#define _XTENSA_SHMBUF_H
+
+#if defined (__XTENSA_EL__)
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+#elif defined (__XTENSA_EB__)
+struct shmid64_ds {
+       struct ipc64_perm       shm_perm;       /* operation perms */
+       size_t                  shm_segsz;      /* size of segment (bytes) */
+       __kernel_time_t         shm_atime;      /* last attach time */
+       unsigned long           __unused1;
+       __kernel_time_t         shm_dtime;      /* last detach time */
+       unsigned long           __unused2;
+       __kernel_time_t         shm_ctime;      /* last change time */
+       unsigned long           __unused3;
+       __kernel_pid_t          shm_cpid;       /* pid of creator */
+       __kernel_pid_t          shm_lpid;       /* pid of last operator */
+       unsigned long           shm_nattch;     /* no. of current attaches */
+       unsigned long           __unused4;
+       unsigned long           __unused5;
+};
+#else
+# error endian order not defined
+#endif
+
+
+struct shminfo64 {
+       unsigned long   shmmax;
+       unsigned long   shmmin;
+       unsigned long   shmmni;
+       unsigned long   shmseg;
+       unsigned long   shmall;
+       unsigned long   __unused1;
+       unsigned long   __unused2;
+       unsigned long   __unused3;
+       unsigned long   __unused4;
+};
+
+#endif /* _XTENSA_SHMBUF_H */
diff --git a/arch/xtensa/include/uapi/asm/sigcontext.h b/arch/xtensa/include/uapi/asm/sigcontext.h
new file mode 100644 (file)
index 0000000..03383af
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * include/asm-xtensa/sigcontext.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SIGCONTEXT_H
+#define _XTENSA_SIGCONTEXT_H
+
+
+struct sigcontext {
+       unsigned long sc_pc;
+       unsigned long sc_ps;
+       unsigned long sc_lbeg;
+       unsigned long sc_lend;
+       unsigned long sc_lcount;
+       unsigned long sc_sar;
+       unsigned long sc_acclo;
+       unsigned long sc_acchi;
+       unsigned long sc_a[16];
+       void *sc_xtregs;
+};
+
+#endif /* _XTENSA_SIGCONTEXT_H */
diff --git a/arch/xtensa/include/uapi/asm/signal.h b/arch/xtensa/include/uapi/asm/signal.h
new file mode 100644 (file)
index 0000000..b88ce96
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * include/asm-xtensa/signal.h
+ *
+ * Swiped from SH.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_SIGNAL_H
+#define _UAPI_XTENSA_SIGNAL_H
+
+
+#define _NSIG          64
+#define _NSIG_BPW      32
+#define _NSIG_WORDS    (_NSIG / _NSIG_BPW)
+
+#ifndef __ASSEMBLY__
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+typedef unsigned long old_sigset_t;            /* at least 32 bits */
+typedef struct {
+       unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#endif
+
+#define SIGHUP          1
+#define SIGINT          2
+#define SIGQUIT                 3
+#define SIGILL          4
+#define SIGTRAP                 5
+#define SIGABRT                 6
+#define SIGIOT          6
+#define SIGBUS          7
+#define SIGFPE          8
+#define SIGKILL                 9
+#define SIGUSR1                10
+#define SIGSEGV                11
+#define SIGUSR2                12
+#define SIGPIPE                13
+#define SIGALRM                14
+#define SIGTERM                15
+#define SIGSTKFLT      16
+#define SIGCHLD                17
+#define SIGCONT                18
+#define SIGSTOP                19
+#define SIGTSTP                20
+#define SIGTTIN                21
+#define SIGTTOU                22
+#define SIGURG         23
+#define SIGXCPU                24
+#define SIGXFSZ                25
+#define SIGVTALRM      26
+#define SIGPROF                27
+#define SIGWINCH       28
+#define SIGIO          29
+#define SIGPOLL                SIGIO
+/* #define SIGLOST             29 */
+#define SIGPWR         30
+#define SIGSYS         31
+#define        SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN       32
+#define SIGRTMAX       (_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP   0x00000001
+#define SA_NOCLDWAIT   0x00000002 /* not supported yet */
+#define SA_SIGINFO     0x00000004
+#define SA_ONSTACK     0x08000000
+#define SA_RESTART     0x10000000
+#define SA_NODEFER     0x40000000
+#define SA_RESETHAND   0x80000000
+
+#define SA_NOMASK      SA_NODEFER
+#define SA_ONESHOT     SA_RESETHAND
+
+#define SA_RESTORER    0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK     1
+#define SS_DISABLE     2
+
+#define MINSIGSTKSZ    2048
+#define SIGSTKSZ       8192
+
+#ifndef __ASSEMBLY__
+
+#define SIG_BLOCK          0   /* for blocking signals */
+#define SIG_UNBLOCK        1   /* for unblocking signals */
+#define SIG_SETMASK        2   /* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
+#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
+#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+
+#ifndef __KERNEL__
+
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+       union {
+         __sighandler_t _sa_handler;
+         void (*_sa_sigaction)(int, struct siginfo *, void *);
+       } _u;
+       sigset_t sa_mask;
+       unsigned long sa_flags;
+       void (*sa_restorer)(void);
+};
+
+#define sa_handler     _u._sa_handler
+#define sa_sigaction   _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+       void *ss_sp;
+       int ss_flags;
+       size_t ss_size;
+} stack_t;
+
+#endif /* __ASSEMBLY__ */
+#endif /* _UAPI_XTENSA_SIGNAL_H */
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
new file mode 100644 (file)
index 0000000..38079be
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * include/asm-xtensa/socket.h
+ *
+ * Copied from i386.
+ *
+ * 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 _XTENSA_SOCKET_H
+#define _XTENSA_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET     1
+
+#define SO_DEBUG       1
+#define SO_REUSEADDR   2
+#define SO_TYPE                3
+#define SO_ERROR       4
+#define SO_DONTROUTE   5
+#define SO_BROADCAST   6
+#define SO_SNDBUF      7
+#define SO_RCVBUF      8
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_KEEPALIVE   9
+#define SO_OOBINLINE   10
+#define SO_NO_CHECK    11
+#define SO_PRIORITY    12
+#define SO_LINGER      13
+#define SO_BSDCOMPAT   14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED    16
+#define SO_PEERCRED    17
+#define SO_RCVLOWAT    18
+#define SO_SNDLOWAT    19
+#define SO_RCVTIMEO    20
+#define SO_SNDTIMEO    21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+
+#define SO_SECURITY_AUTHENTICATION             22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT       23
+#define SO_SECURITY_ENCRYPTION_NETWORK         24
+
+#define SO_BINDTODEVICE        25
+
+/* Socket filtering */
+
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
+
+#define SO_PEERNAME            28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
+
+#define SO_ACCEPTCONN          30
+#define SO_PEERSEC             31
+#define SO_PASSSEC             34
+#define SO_TIMESTAMPNS         35
+#define SCM_TIMESTAMPNS                SO_TIMESTAMPNS
+
+#define SO_MARK                        36
+
+#define SO_TIMESTAMPING                37
+#define SCM_TIMESTAMPING       SO_TIMESTAMPING
+
+#define SO_PROTOCOL            38
+#define SO_DOMAIN              39
+
+#define SO_RXQ_OVFL             40
+
+#define SO_WIFI_STATUS         41
+#define SCM_WIFI_STATUS                SO_WIFI_STATUS
+#define SO_PEEK_OFF            42
+
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
+#endif /* _XTENSA_SOCKET_H */
diff --git a/arch/xtensa/include/uapi/asm/sockios.h b/arch/xtensa/include/uapi/asm/sockios.h
new file mode 100644 (file)
index 0000000..efe0af3
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * include/asm-xtensa/sockios.h
+ *
+ * Socket-level I/O control calls.  Copied from MIPS.
+ *
+ * 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) 1995 by Ralf Baechle
+ * Copyright (C) 2001 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SOCKIOS_H
+#define _XTENSA_SOCKIOS_H
+
+#include <asm/ioctl.h>
+
+/* Socket-level I/O control calls. */
+
+#define FIOGETOWN      _IOR('f', 123, int)
+#define FIOSETOWN      _IOW('f', 124, int)
+
+#define SIOCATMARK     _IOR('s', 7, int)
+#define SIOCSPGRP      _IOW('s', 8, pid_t)
+#define SIOCGPGRP      _IOR('s', 9, pid_t)
+
+#define SIOCGSTAMP     0x8906          /* Get stamp (timeval) */
+#define SIOCGSTAMPNS   0x8907          /* Get stamp (timespec) */
+
+#endif /* _XTENSA_SOCKIOS_H */
diff --git a/arch/xtensa/include/uapi/asm/stat.h b/arch/xtensa/include/uapi/asm/stat.h
new file mode 100644 (file)
index 0000000..c499203
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * include/asm-xtensa/stat.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2007 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_STAT_H
+#define _XTENSA_STAT_H
+
+#define STAT_HAVE_NSEC 1
+
+struct stat {
+       unsigned long   st_dev;
+       unsigned long   st_ino;
+       unsigned int    st_mode;
+       unsigned int    st_nlink;
+       unsigned int    st_uid;
+       unsigned int    st_gid;
+       unsigned long   st_rdev;
+       long            st_size;
+       unsigned long   st_blksize;
+       unsigned long   st_blocks;
+       unsigned long   st_atime;
+       unsigned long   st_atime_nsec;
+       unsigned long   st_mtime;
+       unsigned long   st_mtime_nsec;
+       unsigned long   st_ctime;
+       unsigned long   st_ctime_nsec;
+       unsigned long   __unused4;
+       unsigned long   __unused5;
+};
+
+struct stat64  {
+       unsigned long long st_dev;      /* Device */
+       unsigned long long st_ino;      /* File serial number */
+       unsigned int  st_mode;          /* File mode. */
+       unsigned int  st_nlink;         /* Link count. */
+       unsigned int  st_uid;           /* User ID of the file's owner. */
+       unsigned int  st_gid;           /* Group ID of the file's group. */
+       unsigned long long st_rdev;     /* Device number, if device. */
+       long long st_size;              /* Size of file, in bytes. */
+       unsigned long st_blksize;       /* Optimal block size for I/O. */
+       unsigned long __unused2;
+       unsigned long long st_blocks;   /* Number 512-byte blocks allocated. */
+       unsigned long st_atime;         /* Time of last access. */
+       unsigned long st_atime_nsec;
+       unsigned long st_mtime;         /* Time of last modification. */
+       unsigned long st_mtime_nsec;
+       unsigned long st_ctime;         /* Time of last status change. */
+       unsigned long st_ctime_nsec;
+       unsigned long __unused4;
+       unsigned long __unused5;
+};
+
+#endif /* _XTENSA_STAT_H */
diff --git a/arch/xtensa/include/uapi/asm/swab.h b/arch/xtensa/include/uapi/asm/swab.h
new file mode 100644 (file)
index 0000000..226a391
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * include/asm-xtensa/swab.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_SWAB_H
+#define _XTENSA_SWAB_H
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+
+#define __SWAB_64_THRU_32__
+
+static inline __attribute_const__ __u32 __arch_swab32(__u32 x)
+{
+    __u32 res;
+    /* instruction sequence from Xtensa ISA release 2/2000 */
+    __asm__("ssai     8           \n\t"
+           "srli     %0, %1, 16  \n\t"
+           "src      %0, %0, %1  \n\t"
+           "src      %0, %0, %0  \n\t"
+           "src      %0, %1, %0  \n"
+           : "=&a" (res)
+           : "a" (x)
+           );
+    return res;
+}
+#define __arch_swab32 __arch_swab32
+
+static inline __attribute_const__ __u16 __arch_swab16(__u16 x)
+{
+    /* Given that 'short' values are signed (i.e., can be negative),
+     * we cannot assume that the upper 16-bits of the register are
+     * zero.  We are careful to mask values after shifting.
+     */
+
+    /* There exists an anomaly between xt-gcc and xt-xcc.  xt-gcc
+     * inserts an extui instruction after putting this function inline
+     * to ensure that it uses only the least-significant 16 bits of
+     * the result.  xt-xcc doesn't use an extui, but assumes the
+     * __asm__ macro follows convention that the upper 16 bits of an
+     * 'unsigned short' result are still zero.  This macro doesn't
+     * follow convention; indeed, it leaves garbage in the upport 16
+     * bits of the register.
+
+     * Declaring the temporary variables 'res' and 'tmp' to be 32-bit
+     * types while the return type of the function is a 16-bit type
+     * forces both compilers to insert exactly one extui instruction
+     * (or equivalent) to mask off the upper 16 bits. */
+
+    __u32 res;
+    __u32 tmp;
+
+    __asm__("extui    %1, %2, 8, 8\n\t"
+           "slli     %0, %2, 8   \n\t"
+           "or       %0, %0, %1  \n"
+           : "=&a" (res), "=&a" (tmp)
+           : "a" (x)
+           );
+
+    return res;
+}
+#define __arch_swab16 __arch_swab16
+
+#endif /* _XTENSA_SWAB_H */
diff --git a/arch/xtensa/include/uapi/asm/termbits.h b/arch/xtensa/include/uapi/asm/termbits.h
new file mode 100644 (file)
index 0000000..0d6c871
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * include/asm-xtensa/termbits.h
+ *
+ * Copied from SH.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _XTENSA_TERMBITS_H
+#define _XTENSA_TERMBITS_H
+
+
+#include <linux/posix_types.h>
+
+typedef unsigned char  cc_t;
+typedef unsigned int   speed_t;
+typedef unsigned int   tcflag_t;
+
+#define NCCS 19
+struct termios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+};
+
+struct termios2 {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+struct ktermios {
+       tcflag_t c_iflag;               /* input mode flags */
+       tcflag_t c_oflag;               /* output mode flags */
+       tcflag_t c_cflag;               /* control mode flags */
+       tcflag_t c_lflag;               /* local mode flags */
+       cc_t c_line;                    /* line discipline */
+       cc_t c_cc[NCCS];                /* control characters */
+       speed_t c_ispeed;               /* input speed */
+       speed_t c_ospeed;               /* output speed */
+};
+
+/* c_cc characters */
+
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+
+#define IGNBRK 0000001
+#define BRKINT 0000002
+#define IGNPAR 0000004
+#define PARMRK 0000010
+#define INPCK  0000020
+#define ISTRIP 0000040
+#define INLCR  0000100
+#define IGNCR  0000200
+#define ICRNL  0000400
+#define IUCLC  0001000
+#define IXON   0002000
+#define IXANY  0004000
+#define IXOFF  0010000
+#define IMAXBEL        0020000
+#define IUTF8  0040000
+
+/* c_oflag bits */
+
+#define OPOST  0000001
+#define OLCUC  0000002
+#define ONLCR  0000004
+#define OCRNL  0000010
+#define ONOCR  0000020
+#define ONLRET 0000040
+#define OFILL  0000100
+#define OFDEL  0000200
+#define NLDLY  0000400
+#define   NL0  0000000
+#define   NL1  0000400
+#define CRDLY  0003000
+#define   CR0  0000000
+#define   CR1  0001000
+#define   CR2  0002000
+#define   CR3  0003000
+#define TABDLY 0014000
+#define   TAB0 0000000
+#define   TAB1 0004000
+#define   TAB2 0010000
+#define   TAB3 0014000
+#define   XTABS        0014000
+#define BSDLY  0020000
+#define   BS0  0000000
+#define   BS1  0020000
+#define VTDLY  0040000
+#define   VT0  0000000
+#define   VT1  0040000
+#define FFDLY  0100000
+#define   FF0  0000000
+#define   FF1  0100000
+
+/* c_cflag bit meaning */
+
+#define CBAUD  0010017
+#define  B0    0000000         /* hang up */
+#define  B50   0000001
+#define  B75   0000002
+#define  B110  0000003
+#define  B134  0000004
+#define  B150  0000005
+#define  B200  0000006
+#define  B300  0000007
+#define  B600  0000010
+#define  B1200 0000011
+#define  B1800 0000012
+#define  B2400 0000013
+#define  B4800 0000014
+#define  B9600 0000015
+#define  B19200        0000016
+#define  B38400        0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE  0000060
+#define   CS5  0000000
+#define   CS6  0000020
+#define   CS7  0000040
+#define   CS8  0000060
+#define CSTOPB 0000100
+#define CREAD  0000200
+#define PARENB 0000400
+#define PARODD 0001000
+#define HUPCL  0002000
+#define CLOCAL 0004000
+#define CBAUDEX 0010000
+#define           BOTHER 0010000
+#define    B57600 0010001
+#define   B115200 0010002
+#define   B230400 0010003
+#define   B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD   002003600000          /* input baud rate */
+#define CMSPAR   010000000000          /* mark or space (stick) parity */
+#define CRTSCTS          020000000000          /* flow control */
+
+#define IBSHIFT        16              /* Shift from CBAUD to CIBAUD */
+
+/* c_lflag bits */
+
+#define ISIG   0000001
+#define ICANON 0000002
+#define XCASE  0000004
+#define ECHO   0000010
+#define ECHOE  0000020
+#define ECHOK  0000040
+#define ECHONL 0000100
+#define NOFLSH 0000200
+#define TOSTOP 0000400
+#define ECHOCTL        0001000
+#define ECHOPRT        0002000
+#define ECHOKE 0004000
+#define FLUSHO 0010000
+#define PENDIN 0040000
+#define IEXTEN 0100000
+#define EXTPROC        0200000
+
+/* tcflow() and TCXONC use these */
+
+#define        TCOOFF          0
+#define        TCOON           1
+#define        TCIOFF          2
+#define        TCION           3
+
+/* tcflush() and TCFLSH use these */
+
+#define        TCIFLUSH        0
+#define        TCOFLUSH        1
+#define        TCIOFLUSH       2
+
+/* tcsetattr uses these */
+
+#define        TCSANOW         0
+#define        TCSADRAIN       1
+#define        TCSAFLUSH       2
+
+#endif /* _XTENSA_TERMBITS_H */
diff --git a/arch/xtensa/include/uapi/asm/types.h b/arch/xtensa/include/uapi/asm/types.h
new file mode 100644 (file)
index 0000000..87ec7ae
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * include/asm-xtensa/types.h
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2001 - 2005 Tensilica Inc.
+ */
+
+#ifndef _UAPI_XTENSA_TYPES_H
+#define _UAPI_XTENSA_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+#ifdef __ASSEMBLY__
+# define __XTENSA_UL(x)                (x)
+# define __XTENSA_UL_CONST(x)  x
+#else
+# define __XTENSA_UL(x)                ((unsigned long)(x))
+# define __XTENSA_UL_CONST(x)  x##UL
+#endif
+
+#ifndef __ASSEMBLY__
+
+#endif
+
+#endif /* _UAPI_XTENSA_TYPES_H */
diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h
new file mode 100644 (file)
index 0000000..9f36d0e
--- /dev/null
@@ -0,0 +1,754 @@
+#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)
+#define _UAPI_XTENSA_UNISTD_H
+
+#ifndef __SYSCALL
+# define __SYSCALL(nr,func,nargs)
+#endif
+
+#define __NR_spill                               0
+__SYSCALL(  0, sys_ni_syscall, 0)
+#define __NR_xtensa                              1
+__SYSCALL(  1, sys_ni_syscall, 0)
+#define __NR_available4                                  2
+__SYSCALL(  2, sys_ni_syscall, 0)
+#define __NR_available5                                  3
+__SYSCALL(  3, sys_ni_syscall, 0)
+#define __NR_available6                                  4
+__SYSCALL(  4, sys_ni_syscall, 0)
+#define __NR_available7                                  5
+__SYSCALL(  5, sys_ni_syscall, 0)
+#define __NR_available8                                  6
+__SYSCALL(  6, sys_ni_syscall, 0)
+#define __NR_available9                                  7
+__SYSCALL(  7, sys_ni_syscall, 0)
+
+/* File Operations */
+
+#define __NR_open                                8
+__SYSCALL(  8, sys_open, 3)
+#define __NR_close                               9
+__SYSCALL(  9, sys_close, 1)
+#define __NR_dup                                10
+__SYSCALL( 10, sys_dup, 1)
+#define __NR_dup2                               11
+__SYSCALL( 11, sys_dup2, 2)
+#define __NR_read                               12
+__SYSCALL( 12, sys_read, 3)
+#define __NR_write                              13
+__SYSCALL( 13, sys_write, 3)
+#define __NR_select                             14
+__SYSCALL( 14, sys_select, 5)
+#define __NR_lseek                              15
+__SYSCALL( 15, sys_lseek, 3)
+#define __NR_poll                               16
+__SYSCALL( 16, sys_poll, 3)
+#define __NR__llseek                            17
+__SYSCALL( 17, sys_llseek, 5)
+#define __NR_epoll_wait                         18
+__SYSCALL( 18, sys_epoll_wait, 4)
+#define __NR_epoll_ctl                                  19
+__SYSCALL( 19, sys_epoll_ctl, 4)
+#define __NR_epoll_create                       20
+__SYSCALL( 20, sys_epoll_create, 1)
+#define __NR_creat                              21
+__SYSCALL( 21, sys_creat, 2)
+#define __NR_truncate                           22
+__SYSCALL( 22, sys_truncate, 2)
+#define __NR_ftruncate                                  23
+__SYSCALL( 23, sys_ftruncate, 2)
+#define __NR_readv                              24
+__SYSCALL( 24, sys_readv, 3)
+#define __NR_writev                             25
+__SYSCALL( 25, sys_writev, 3)
+#define __NR_fsync                              26
+__SYSCALL( 26, sys_fsync, 1)
+#define __NR_fdatasync                                  27
+__SYSCALL( 27, sys_fdatasync, 1)
+#define __NR_truncate64                         28
+__SYSCALL( 28, sys_truncate64, 2)
+#define __NR_ftruncate64                        29
+__SYSCALL( 29, sys_ftruncate64, 2)
+#define __NR_pread64                            30
+__SYSCALL( 30, sys_pread64, 6)
+#define __NR_pwrite64                           31
+__SYSCALL( 31, sys_pwrite64, 6)
+
+#define __NR_link                               32
+__SYSCALL( 32, sys_link, 2)
+#define __NR_rename                             33
+__SYSCALL( 33, sys_rename, 2)
+#define __NR_symlink                            34
+__SYSCALL( 34, sys_symlink, 2)
+#define __NR_readlink                           35
+__SYSCALL( 35, sys_readlink, 3)
+#define __NR_mknod                              36
+__SYSCALL( 36, sys_mknod, 3)
+#define __NR_pipe                               37
+__SYSCALL( 37, sys_pipe, 1)
+#define __NR_unlink                             38
+__SYSCALL( 38, sys_unlink, 1)
+#define __NR_rmdir                              39
+__SYSCALL( 39, sys_rmdir, 1)
+
+#define __NR_mkdir                              40
+__SYSCALL( 40, sys_mkdir, 2)
+#define __NR_chdir                              41
+__SYSCALL( 41, sys_chdir, 1)
+#define __NR_fchdir                             42
+__SYSCALL( 42, sys_fchdir, 1)
+#define __NR_getcwd                             43
+__SYSCALL( 43, sys_getcwd, 2)
+
+#define __NR_chmod                              44
+__SYSCALL( 44, sys_chmod, 2)
+#define __NR_chown                              45
+__SYSCALL( 45, sys_chown, 3)
+#define __NR_stat                               46
+__SYSCALL( 46, sys_newstat, 2)
+#define __NR_stat64                             47
+__SYSCALL( 47, sys_stat64, 2)
+
+#define __NR_lchown                             48
+__SYSCALL( 48, sys_lchown, 3)
+#define __NR_lstat                              49
+__SYSCALL( 49, sys_newlstat, 2)
+#define __NR_lstat64                            50
+__SYSCALL( 50, sys_lstat64, 2)
+#define __NR_available51                        51
+__SYSCALL( 51, sys_ni_syscall, 0)
+
+#define __NR_fchmod                             52
+__SYSCALL( 52, sys_fchmod, 2)
+#define __NR_fchown                             53
+__SYSCALL( 53, sys_fchown, 3)
+#define __NR_fstat                              54
+__SYSCALL( 54, sys_newfstat, 2)
+#define __NR_fstat64                            55
+__SYSCALL( 55, sys_fstat64, 2)
+
+#define __NR_flock                              56
+__SYSCALL( 56, sys_flock, 2)
+#define __NR_access                             57
+__SYSCALL( 57, sys_access, 2)
+#define __NR_umask                              58
+__SYSCALL( 58, sys_umask, 1)
+#define __NR_getdents                           59
+__SYSCALL( 59, sys_getdents, 3)
+#define __NR_getdents64                         60
+__SYSCALL( 60, sys_getdents64, 3)
+#define __NR_fcntl64                            61
+__SYSCALL( 61, sys_fcntl64, 3)
+#define __NR_fallocate                          62
+__SYSCALL( 62, sys_fallocate, 6)
+#define __NR_fadvise64_64                       63
+__SYSCALL( 63, xtensa_fadvise64_64, 6)
+#define __NR_utime                              64     /* glibc 2.3.3 ?? */
+__SYSCALL( 64, sys_utime, 2)
+#define __NR_utimes                             65
+__SYSCALL( 65, sys_utimes, 2)
+#define __NR_ioctl                              66
+__SYSCALL( 66, sys_ioctl, 3)
+#define __NR_fcntl                              67
+__SYSCALL( 67, sys_fcntl, 3)
+
+#define __NR_setxattr                           68
+__SYSCALL( 68, sys_setxattr, 5)
+#define __NR_getxattr                           69
+__SYSCALL( 69, sys_getxattr, 4)
+#define __NR_listxattr                                  70
+__SYSCALL( 70, sys_listxattr, 3)
+#define __NR_removexattr                        71
+__SYSCALL( 71, sys_removexattr, 2)
+#define __NR_lsetxattr                                  72
+__SYSCALL( 72, sys_lsetxattr, 5)
+#define __NR_lgetxattr                                  73
+__SYSCALL( 73, sys_lgetxattr, 4)
+#define __NR_llistxattr                         74
+__SYSCALL( 74, sys_llistxattr, 3)
+#define __NR_lremovexattr                       75
+__SYSCALL( 75, sys_lremovexattr, 2)
+#define __NR_fsetxattr                                  76
+__SYSCALL( 76, sys_fsetxattr, 5)
+#define __NR_fgetxattr                                  77
+__SYSCALL( 77, sys_fgetxattr, 4)
+#define __NR_flistxattr                         78
+__SYSCALL( 78, sys_flistxattr, 3)
+#define __NR_fremovexattr                       79
+__SYSCALL( 79, sys_fremovexattr, 2)
+
+/* File Map / Shared Memory Operations */
+
+#define __NR_mmap2                              80
+__SYSCALL( 80, sys_mmap_pgoff, 6)
+#define __NR_munmap                             81
+__SYSCALL( 81, sys_munmap, 2)
+#define __NR_mprotect                           82
+__SYSCALL( 82, sys_mprotect, 3)
+#define __NR_brk                                83
+__SYSCALL( 83, sys_brk, 1)
+#define __NR_mlock                              84
+__SYSCALL( 84, sys_mlock, 2)
+#define __NR_munlock                            85
+__SYSCALL( 85, sys_munlock, 2)
+#define __NR_mlockall                           86
+__SYSCALL( 86, sys_mlockall, 1)
+#define __NR_munlockall                         87
+__SYSCALL( 87, sys_munlockall, 0)
+#define __NR_mremap                             88
+__SYSCALL( 88, sys_mremap, 4)
+#define __NR_msync                              89
+__SYSCALL( 89, sys_msync, 3)
+#define __NR_mincore                            90
+__SYSCALL( 90, sys_mincore, 3)
+#define __NR_madvise                            91
+__SYSCALL( 91, sys_madvise, 3)
+#define __NR_shmget                             92
+__SYSCALL( 92, sys_shmget, 4)
+#define __NR_shmat                              93
+__SYSCALL( 93, xtensa_shmat, 4)
+#define __NR_shmctl                             94
+__SYSCALL( 94, sys_shmctl, 4)
+#define __NR_shmdt                              95
+__SYSCALL( 95, sys_shmdt, 4)
+
+/* Socket Operations */
+
+#define __NR_socket                             96
+__SYSCALL( 96, sys_socket, 3)
+#define __NR_setsockopt                         97
+__SYSCALL( 97, sys_setsockopt, 5)
+#define __NR_getsockopt                         98
+__SYSCALL( 98, sys_getsockopt, 5)
+#define __NR_shutdown                           99
+__SYSCALL( 99, sys_shutdown, 2)
+
+#define __NR_bind                              100
+__SYSCALL(100, sys_bind, 3)
+#define __NR_connect                           101
+__SYSCALL(101, sys_connect, 3)
+#define __NR_listen                            102
+__SYSCALL(102, sys_listen, 2)
+#define __NR_accept                            103
+__SYSCALL(103, sys_accept, 3)
+
+#define __NR_getsockname                       104
+__SYSCALL(104, sys_getsockname, 3)
+#define __NR_getpeername                       105
+__SYSCALL(105, sys_getpeername, 3)
+#define __NR_sendmsg                           106
+__SYSCALL(106, sys_sendmsg, 3)
+#define __NR_recvmsg                           107
+__SYSCALL(107, sys_recvmsg, 3)
+#define __NR_send                              108
+__SYSCALL(108, sys_send, 4)
+#define __NR_recv                              109
+__SYSCALL(109, sys_recv, 4)
+#define __NR_sendto                            110
+__SYSCALL(110, sys_sendto, 6)
+#define __NR_recvfrom                          111
+__SYSCALL(111, sys_recvfrom, 6)
+
+#define __NR_socketpair                        112
+__SYSCALL(112, sys_socketpair, 4)
+#define __NR_sendfile                          113
+__SYSCALL(113, sys_sendfile, 4)
+#define __NR_sendfile64                        114
+__SYSCALL(114, sys_sendfile64, 4)
+#define __NR_sendmmsg                          115
+__SYSCALL(115, sys_sendmmsg, 4)
+
+/* Process Operations */
+
+#define __NR_clone                             116
+__SYSCALL(116, xtensa_clone, 5)
+#define __NR_execve                            117
+__SYSCALL(117, sys_execve, 3)
+#define __NR_exit                              118
+__SYSCALL(118, sys_exit, 1)
+#define __NR_exit_group                        119
+__SYSCALL(119, sys_exit_group, 1)
+#define __NR_getpid                            120
+__SYSCALL(120, sys_getpid, 0)
+#define __NR_wait4                             121
+__SYSCALL(121, sys_wait4, 4)
+#define __NR_waitid                            122
+__SYSCALL(122, sys_waitid, 5)
+#define __NR_kill                              123
+__SYSCALL(123, sys_kill, 2)
+#define __NR_tkill                             124
+__SYSCALL(124, sys_tkill, 2)
+#define __NR_tgkill                            125
+__SYSCALL(125, sys_tgkill, 3)
+#define __NR_set_tid_address                   126
+__SYSCALL(126, sys_set_tid_address, 1)
+#define __NR_gettid                            127
+__SYSCALL(127, sys_gettid, 0)
+#define __NR_setsid                            128
+__SYSCALL(128, sys_setsid, 0)
+#define __NR_getsid                            129
+__SYSCALL(129, sys_getsid, 1)
+#define __NR_prctl                             130
+__SYSCALL(130, sys_prctl, 5)
+#define __NR_personality                       131
+__SYSCALL(131, sys_personality, 1)
+#define __NR_getpriority                       132
+__SYSCALL(132, sys_getpriority, 2)
+#define __NR_setpriority                       133
+__SYSCALL(133, sys_setpriority, 3)
+#define __NR_setitimer                                 134
+__SYSCALL(134, sys_setitimer, 3)
+#define __NR_getitimer                                 135
+__SYSCALL(135, sys_getitimer, 2)
+#define __NR_setuid                            136
+__SYSCALL(136, sys_setuid, 1)
+#define __NR_getuid                            137
+__SYSCALL(137, sys_getuid, 0)
+#define __NR_setgid                            138
+__SYSCALL(138, sys_setgid, 1)
+#define __NR_getgid                            139
+__SYSCALL(139, sys_getgid, 0)
+#define __NR_geteuid                           140
+__SYSCALL(140, sys_geteuid, 0)
+#define __NR_getegid                           141
+__SYSCALL(141, sys_getegid, 0)
+#define __NR_setreuid                          142
+__SYSCALL(142, sys_setreuid, 2)
+#define __NR_setregid                          143
+__SYSCALL(143, sys_setregid, 2)
+#define __NR_setresuid                                 144
+__SYSCALL(144, sys_setresuid, 3)
+#define __NR_getresuid                                 145
+__SYSCALL(145, sys_getresuid, 3)
+#define __NR_setresgid                                 146
+__SYSCALL(146, sys_setresgid, 3)
+#define __NR_getresgid                                 147
+__SYSCALL(147, sys_getresgid, 3)
+#define __NR_setpgid                           148
+__SYSCALL(148, sys_setpgid, 2)
+#define __NR_getpgid                           149
+__SYSCALL(149, sys_getpgid, 1)
+#define __NR_getppid                           150
+__SYSCALL(150, sys_getppid, 0)
+#define __NR_getpgrp                           151
+__SYSCALL(151, sys_getpgrp, 0)
+
+#define __NR_reserved152                       152     /* set_thread_area */
+__SYSCALL(152, sys_ni_syscall, 0)
+#define __NR_reserved153                       153     /* get_thread_area */
+__SYSCALL(153, sys_ni_syscall, 0)
+#define __NR_times                             154
+__SYSCALL(154, sys_times, 1)
+#define __NR_acct                              155
+__SYSCALL(155, sys_acct, 1)
+#define __NR_sched_setaffinity                         156
+__SYSCALL(156, sys_sched_setaffinity, 3)
+#define __NR_sched_getaffinity                         157
+__SYSCALL(157, sys_sched_getaffinity, 3)
+#define __NR_capget                            158
+__SYSCALL(158, sys_capget, 2)
+#define __NR_capset                            159
+__SYSCALL(159, sys_capset, 2)
+#define __NR_ptrace                            160
+__SYSCALL(160, sys_ptrace, 4)
+#define __NR_semtimedop                                161
+__SYSCALL(161, sys_semtimedop, 5)
+#define __NR_semget                            162
+__SYSCALL(162, sys_semget, 4)
+#define __NR_semop                             163
+__SYSCALL(163, sys_semop, 4)
+#define __NR_semctl                            164
+__SYSCALL(164, sys_semctl, 4)
+#define __NR_available165                      165
+__SYSCALL(165, sys_ni_syscall, 0)
+#define __NR_msgget                            166
+__SYSCALL(166, sys_msgget, 4)
+#define __NR_msgsnd                            167
+__SYSCALL(167, sys_msgsnd, 4)
+#define __NR_msgrcv                            168
+__SYSCALL(168, sys_msgrcv, 4)
+#define __NR_msgctl                            169
+__SYSCALL(169, sys_msgctl, 4)
+#define __NR_available170                      170
+__SYSCALL(170, sys_ni_syscall, 0)
+
+/* File System */
+
+#define __NR_umount2                           171
+__SYSCALL(171, sys_umount, 2)
+#define __NR_mount                             172
+__SYSCALL(172, sys_mount, 5)
+#define __NR_swapon                            173
+__SYSCALL(173, sys_swapon, 2)
+#define __NR_chroot                            174
+__SYSCALL(174, sys_chroot, 1)
+#define __NR_pivot_root                        175
+__SYSCALL(175, sys_pivot_root, 2)
+#define __NR_umount                            176
+__SYSCALL(176, sys_umount, 2)
+#define __NR_swapoff                           177
+__SYSCALL(177, sys_swapoff, 1)
+#define __NR_sync                              178
+__SYSCALL(178, sys_sync, 0)
+#define __NR_syncfs                            179
+__SYSCALL(179, sys_syncfs, 1)
+#define __NR_setfsuid                          180
+__SYSCALL(180, sys_setfsuid, 1)
+#define __NR_setfsgid                          181
+__SYSCALL(181, sys_setfsgid, 1)
+#define __NR_sysfs                             182
+__SYSCALL(182, sys_sysfs, 3)
+#define __NR_ustat                             183
+__SYSCALL(183, sys_ustat, 2)
+#define __NR_statfs                            184
+__SYSCALL(184, sys_statfs, 2)
+#define __NR_fstatfs                           185
+__SYSCALL(185, sys_fstatfs, 2)
+#define __NR_statfs64                          186
+__SYSCALL(186, sys_statfs64, 3)
+#define __NR_fstatfs64                                 187
+__SYSCALL(187, sys_fstatfs64, 3)
+
+/* System */
+
+#define __NR_setrlimit                                 188
+__SYSCALL(188, sys_setrlimit, 2)
+#define __NR_getrlimit                                 189
+__SYSCALL(189, sys_getrlimit, 2)
+#define __NR_getrusage                                 190
+__SYSCALL(190, sys_getrusage, 2)
+#define __NR_futex                             191
+__SYSCALL(191, sys_futex, 5)
+#define __NR_gettimeofday                      192
+__SYSCALL(192, sys_gettimeofday, 2)
+#define __NR_settimeofday                      193
+__SYSCALL(193, sys_settimeofday, 2)
+#define __NR_adjtimex                          194
+__SYSCALL(194, sys_adjtimex, 1)
+#define __NR_nanosleep                         195
+__SYSCALL(195, sys_nanosleep, 2)
+#define __NR_getgroups                                 196
+__SYSCALL(196, sys_getgroups, 2)
+#define __NR_setgroups                                 197
+__SYSCALL(197, sys_setgroups, 2)
+#define __NR_sethostname                       198
+__SYSCALL(198, sys_sethostname, 2)
+#define __NR_setdomainname                     199
+__SYSCALL(199, sys_setdomainname, 2)
+#define __NR_syslog                            200
+__SYSCALL(200, sys_syslog, 3)
+#define __NR_vhangup                           201
+__SYSCALL(201, sys_vhangup, 0)
+#define __NR_uselib                            202
+__SYSCALL(202, sys_uselib, 1)
+#define __NR_reboot                            203
+__SYSCALL(203, sys_reboot, 3)
+#define __NR_quotactl                          204
+__SYSCALL(204, sys_quotactl, 4)
+#define __NR_nfsservctl                        205
+__SYSCALL(205, sys_ni_syscall, 0)                      /* old nfsservctl */
+#define __NR__sysctl                           206
+__SYSCALL(206, sys_sysctl, 1)
+#define __NR_bdflush                           207
+__SYSCALL(207, sys_bdflush, 2)
+#define __NR_uname                             208
+__SYSCALL(208, sys_newuname, 1)
+#define __NR_sysinfo                           209
+__SYSCALL(209, sys_sysinfo, 1)
+#define __NR_init_module                       210
+__SYSCALL(210, sys_init_module, 2)
+#define __NR_delete_module                     211
+__SYSCALL(211, sys_delete_module, 1)
+
+#define __NR_sched_setparam                    212
+__SYSCALL(212, sys_sched_setparam, 2)
+#define __NR_sched_getparam                    213
+__SYSCALL(213, sys_sched_getparam, 2)
+#define __NR_sched_setscheduler                214
+__SYSCALL(214, sys_sched_setscheduler, 3)
+#define __NR_sched_getscheduler                215
+__SYSCALL(215, sys_sched_getscheduler, 1)
+#define __NR_sched_get_priority_max            216
+__SYSCALL(216, sys_sched_get_priority_max, 1)
+#define __NR_sched_get_priority_min            217
+__SYSCALL(217, sys_sched_get_priority_min, 1)
+#define __NR_sched_rr_get_interval             218
+__SYSCALL(218, sys_sched_rr_get_interval, 2)
+#define __NR_sched_yield                       219
+__SYSCALL(219, sys_sched_yield, 0)
+#define __NR_available222                      222
+__SYSCALL(222, sys_ni_syscall, 0)
+
+/* Signal Handling */
+
+#define __NR_restart_syscall                   223
+__SYSCALL(223, sys_restart_syscall, 0)
+#define __NR_sigaltstack                       224
+__SYSCALL(224, xtensa_sigaltstack, 2)
+#define __NR_rt_sigreturn                      225
+__SYSCALL(225, xtensa_rt_sigreturn, 1)
+#define __NR_rt_sigaction                      226
+__SYSCALL(226, sys_rt_sigaction, 4)
+#define __NR_rt_sigprocmask                    227
+__SYSCALL(227, sys_rt_sigprocmask, 4)
+#define __NR_rt_sigpending                     228
+__SYSCALL(228, sys_rt_sigpending, 2)
+#define __NR_rt_sigtimedwait                   229
+__SYSCALL(229, sys_rt_sigtimedwait, 4)
+#define __NR_rt_sigqueueinfo                   230
+__SYSCALL(230, sys_rt_sigqueueinfo, 3)
+#define __NR_rt_sigsuspend                     231
+__SYSCALL(231, sys_rt_sigsuspend, 2)
+
+/* Message */
+
+#define __NR_mq_open                           232
+__SYSCALL(232, sys_mq_open, 4)
+#define __NR_mq_unlink                                 233
+__SYSCALL(233, sys_mq_unlink, 1)
+#define __NR_mq_timedsend                      234
+__SYSCALL(234, sys_mq_timedsend, 5)
+#define __NR_mq_timedreceive                   235
+__SYSCALL(235, sys_mq_timedreceive, 5)
+#define __NR_mq_notify                                 236
+__SYSCALL(236, sys_mq_notify, 2)
+#define __NR_mq_getsetattr                     237
+__SYSCALL(237, sys_mq_getsetattr, 3)
+#define __NR_available238                      238
+__SYSCALL(238, sys_ni_syscall, 0)
+
+/* IO */
+
+#define __NR_io_setup                          239
+__SYSCALL(239, sys_io_setup, 2)
+#define __NR_io_destroy                        240
+__SYSCALL(240, sys_io_destroy, 1)
+#define __NR_io_submit                                 241
+__SYSCALL(241, sys_io_submit, 3)
+#define __NR_io_getevents                      242
+__SYSCALL(242, sys_io_getevents, 5)
+#define __NR_io_cancel                                 243
+__SYSCALL(243, sys_io_cancel, 3)
+#define __NR_clock_settime                     244
+__SYSCALL(244, sys_clock_settime, 2)
+#define __NR_clock_gettime                     245
+__SYSCALL(245, sys_clock_gettime, 2)
+#define __NR_clock_getres                      246
+__SYSCALL(246, sys_clock_getres, 2)
+#define __NR_clock_nanosleep                   247
+__SYSCALL(247, sys_clock_nanosleep, 4)
+
+/* Timer */
+
+#define __NR_timer_create                      248
+__SYSCALL(248, sys_timer_create, 3)
+#define __NR_timer_delete                      249
+__SYSCALL(249, sys_timer_delete, 1)
+#define __NR_timer_settime                     250
+__SYSCALL(250, sys_timer_settime, 4)
+#define __NR_timer_gettime                     251
+__SYSCALL(251, sys_timer_gettime, 2)
+#define __NR_timer_getoverrun                  252
+__SYSCALL(252, sys_timer_getoverrun, 1)
+
+/* System */
+
+#define __NR_reserved253                       253
+__SYSCALL(253, sys_ni_syscall, 0)
+#define __NR_lookup_dcookie                    254
+__SYSCALL(254, sys_lookup_dcookie, 4)
+#define __NR_available255                      255
+__SYSCALL(255, sys_ni_syscall, 0)
+#define __NR_add_key                           256
+__SYSCALL(256, sys_add_key, 5)
+#define __NR_request_key                       257
+__SYSCALL(257, sys_request_key, 5)
+#define __NR_keyctl                            258
+__SYSCALL(258, sys_keyctl, 5)
+#define __NR_available259                      259
+__SYSCALL(259, sys_ni_syscall, 0)
+
+
+#define __NR_readahead                         260
+__SYSCALL(260, sys_readahead, 5)
+#define __NR_remap_file_pages                  261
+__SYSCALL(261, sys_remap_file_pages, 5)
+#define __NR_migrate_pages                     262
+__SYSCALL(262, sys_migrate_pages, 0)
+#define __NR_mbind                             263
+__SYSCALL(263, sys_mbind, 6)
+#define __NR_get_mempolicy                     264
+__SYSCALL(264, sys_get_mempolicy, 5)
+#define __NR_set_mempolicy                     265
+__SYSCALL(265, sys_set_mempolicy, 3)
+#define __NR_unshare                           266
+__SYSCALL(266, sys_unshare, 1)
+#define __NR_move_pages                                267
+__SYSCALL(267, sys_move_pages, 0)
+#define __NR_splice                            268
+__SYSCALL(268, sys_splice, 0)
+#define __NR_tee                               269
+__SYSCALL(269, sys_tee, 0)
+#define __NR_vmsplice                          270
+__SYSCALL(270, sys_vmsplice, 0)
+#define __NR_available271                      271
+__SYSCALL(271, sys_ni_syscall, 0)
+
+#define __NR_pselect6                          272
+__SYSCALL(272, sys_pselect6, 0)
+#define __NR_ppoll                             273
+__SYSCALL(273, sys_ppoll, 0)
+#define __NR_epoll_pwait                       274
+__SYSCALL(274, sys_epoll_pwait, 0)
+#define __NR_epoll_create1             275
+__SYSCALL(275, sys_epoll_create1, 1)
+
+#define __NR_inotify_init                      276
+__SYSCALL(276, sys_inotify_init, 0)
+#define __NR_inotify_add_watch                 277
+__SYSCALL(277, sys_inotify_add_watch, 3)
+#define __NR_inotify_rm_watch                  278
+__SYSCALL(278, sys_inotify_rm_watch, 2)
+#define __NR_inotify_init1                     279
+__SYSCALL(279, sys_inotify_init1, 1)
+
+#define __NR_getcpu                            280
+__SYSCALL(280, sys_getcpu, 0)
+#define __NR_kexec_load                                281
+__SYSCALL(281, sys_ni_syscall, 0)
+
+#define __NR_ioprio_set                                282
+__SYSCALL(282, sys_ioprio_set, 2)
+#define __NR_ioprio_get                                283
+__SYSCALL(283, sys_ioprio_get, 3)
+
+#define __NR_set_robust_list                   284
+__SYSCALL(284, sys_set_robust_list, 3)
+#define __NR_get_robust_list                   285
+__SYSCALL(285, sys_get_robust_list, 3)
+#define __NR_available286                      286
+__SYSCALL(286, sys_ni_syscall, 0)
+#define __NR_available287                      287
+__SYSCALL(287, sys_ni_syscall, 0)
+
+/* Relative File Operations */
+
+#define __NR_openat                            288
+__SYSCALL(288, sys_openat, 4)
+#define __NR_mkdirat                           289
+__SYSCALL(289, sys_mkdirat, 3)
+#define __NR_mknodat                           290
+__SYSCALL(290, sys_mknodat, 4)
+#define __NR_unlinkat                          291
+__SYSCALL(291, sys_unlinkat, 3)
+#define __NR_renameat                          292
+__SYSCALL(292, sys_renameat, 4)
+#define __NR_linkat                            293
+__SYSCALL(293, sys_linkat, 5)
+#define __NR_symlinkat                         294
+__SYSCALL(294, sys_symlinkat, 3)
+#define __NR_readlinkat                                295
+__SYSCALL(295, sys_readlinkat, 4)
+#define __NR_utimensat                         296
+__SYSCALL(296, sys_utimensat, 0)
+#define __NR_fchownat                          297
+__SYSCALL(297, sys_fchownat, 5)
+#define __NR_futimesat                         298
+__SYSCALL(298, sys_futimesat, 4)
+#define __NR_fstatat64                         299
+__SYSCALL(299, sys_fstatat64, 0)
+#define __NR_fchmodat                          300
+__SYSCALL(300, sys_fchmodat, 4)
+#define __NR_faccessat                         301
+__SYSCALL(301, sys_faccessat, 4)
+#define __NR_available302                      302
+__SYSCALL(302, sys_ni_syscall, 0)
+#define __NR_available303                      303
+__SYSCALL(303, sys_ni_syscall, 0)
+
+#define __NR_signalfd                          304
+__SYSCALL(304, sys_signalfd, 3)
+/*  305 was __NR_timerfd  */
+__SYSCALL(305, sys_ni_syscall, 0)
+#define __NR_eventfd                           306
+__SYSCALL(306, sys_eventfd, 1)
+#define __NR_recvmmsg                          307
+__SYSCALL(307, sys_recvmmsg, 5)
+
+#define __NR_setns                             308
+__SYSCALL(308, sys_setns, 2)
+#define __NR_signalfd4                         309
+__SYSCALL(309, sys_signalfd4, 4)
+#define __NR_dup3                              310
+__SYSCALL(310, sys_dup3, 3)
+#define __NR_pipe2                             311
+__SYSCALL(311, sys_pipe2, 2)
+
+#define __NR_timerfd_create                    312
+__SYSCALL(312, sys_timerfd_create, 2)
+#define __NR_timerfd_settime                   313
+__SYSCALL(313, sys_timerfd_settime, 4)
+#define __NR_timerfd_gettime                   314
+__SYSCALL(314, sys_timerfd_gettime, 2)
+#define __NR_available315                      315
+__SYSCALL(315, sys_ni_syscall, 0)
+
+#define __NR_eventfd2                          316
+__SYSCALL(316, sys_eventfd2, 2)
+#define __NR_preadv                            317
+__SYSCALL(317, sys_preadv, 5)
+#define __NR_pwritev                           318
+__SYSCALL(318, sys_pwritev, 5)
+#define __NR_available319                      319
+__SYSCALL(319, sys_ni_syscall, 0)
+
+#define __NR_fanotify_init                     320
+__SYSCALL(320, sys_fanotify_init, 2)
+#define __NR_fanotify_mark                     321
+__SYSCALL(321, sys_fanotify_mark, 6)
+#define __NR_process_vm_readv                  322
+__SYSCALL(322, sys_process_vm_readv, 6)
+#define __NR_process_vm_writev                 323
+__SYSCALL(323, sys_process_vm_writev, 6)
+
+#define __NR_name_to_handle_at                 324
+__SYSCALL(324, sys_name_to_handle_at, 5)
+#define __NR_open_by_handle_at                 325
+__SYSCALL(325, sys_open_by_handle_at, 3)
+#define __NR_sync_file_range                   326
+__SYSCALL(326, sys_sync_file_range2, 6)
+#define __NR_perf_event_open                   327
+__SYSCALL(327, sys_perf_event_open, 5)
+
+#define __NR_rt_tgsigqueueinfo                 328
+__SYSCALL(328, sys_rt_tgsigqueueinfo, 4)
+#define __NR_clock_adjtime                     329
+__SYSCALL(329, sys_clock_adjtime, 2)
+#define __NR_prlimit64                         330
+__SYSCALL(330, sys_prlimit64, 4)
+#define __NR_kcmp                              331
+__SYSCALL(331, sys_kcmp, 5)
+
+
+#define __NR_syscall_count                     332
+
+/*
+ * sysxtensa syscall handler
+ *
+ * int sysxtensa (SYS_XTENSA_ATOMIC_SET,     ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_ADD,     ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_EXG_ADD, ptr, val,    unused);
+ * int sysxtensa (SYS_XTENSA_ATOMIC_CMP_SWP, ptr, oldval, newval);
+ *        a2            a6                   a3    a4      a5
+ */
+
+#define SYS_XTENSA_RESERVED               0     /* don't use this */
+#define SYS_XTENSA_ATOMIC_SET             1     /* set variable */
+#define SYS_XTENSA_ATOMIC_EXG_ADD         2     /* exchange memory and add */
+#define SYS_XTENSA_ATOMIC_ADD             3     /* add to memory */
+#define SYS_XTENSA_ATOMIC_CMP_SWP         4     /* compare and swap */
+
+#define SYS_XTENSA_COUNT                  5     /* count */
+
+#undef __SYSCALL
+
+#endif /* _UAPI_XTENSA_UNISTD_H */
index 33d6e9d2e83ca10ec0301689457727c27fb58ec7..934ae58e2c79766f46cba80ac12ed63649faae9b 100644 (file)
@@ -170,15 +170,15 @@ ENTRY(fast_unaligned)
        s32i    a7, a2, PT_AREG7
        s32i    a8, a2, PT_AREG8
 
-       rsr     a0, DEPC
-       xsr     a3, EXCSAVE_1
+       rsr     a0, depc
+       xsr     a3, excsave1
        s32i    a0, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
 
        /* Keep value of SAR in a0 */
 
-       rsr     a0, SAR
-       rsr     a8, EXCVADDR            # load unaligned memory address
+       rsr     a0, sar
+       rsr     a8, excvaddr            # load unaligned memory address
 
        /* Now, identify one of the following load/store instructions.
         *
@@ -197,7 +197,7 @@ ENTRY(fast_unaligned)
 
        /* Extract the instruction that caused the unaligned access. */
 
-       rsr     a7, EPC_1       # load exception address
+       rsr     a7, epc1        # load exception address
        movi    a3, ~3
        and     a3, a3, a7      # mask lower bits
 
@@ -275,16 +275,16 @@ ENTRY(fast_unaligned)
 1:
 
 #if XCHAL_HAVE_LOOPS
-       rsr     a5, LEND                # check if we reached LEND
+       rsr     a5, lend                # check if we reached LEND
        bne     a7, a5, 1f
-       rsr     a5, LCOUNT              # and LCOUNT != 0
+       rsr     a5, lcount              # and LCOUNT != 0
        beqz    a5, 1f
        addi    a5, a5, -1              # decrement LCOUNT and set
-       rsr     a7, LBEG                # set PC to LBEGIN
-       wsr     a5, LCOUNT
+       rsr     a7, lbeg                # set PC to LBEGIN
+       wsr     a5, lcount
 #endif
 
-1:     wsr     a7, EPC_1               # skip load instruction
+1:     wsr     a7, epc1                # skip load instruction
        extui   a4, a4, INSN_T, 4       # extract target register
        movi    a5, .Lload_table
        addx8   a4, a4, a5
@@ -355,16 +355,16 @@ ENTRY(fast_unaligned)
 
 1:
 #if XCHAL_HAVE_LOOPS
-       rsr     a4, LEND                # check if we reached LEND
+       rsr     a4, lend                # check if we reached LEND
        bne     a7, a4, 1f
-       rsr     a4, LCOUNT              # and LCOUNT != 0
+       rsr     a4, lcount              # and LCOUNT != 0
        beqz    a4, 1f
        addi    a4, a4, -1              # decrement LCOUNT and set
-       rsr     a7, LBEG                # set PC to LBEGIN
-       wsr     a4, LCOUNT
+       rsr     a7, lbeg                # set PC to LBEGIN
+       wsr     a4, lcount
 #endif
 
-1:     wsr     a7, EPC_1               # skip store instruction
+1:     wsr     a7, epc1                # skip store instruction
        movi    a4, ~3
        and     a4, a4, a8              # align memory address
 
@@ -406,7 +406,7 @@ ENTRY(fast_unaligned)
 
 .Lexit:
        movi    a4, 0
-       rsr     a3, EXCSAVE_1
+       rsr     a3, excsave1
        s32i    a4, a3, EXC_TABLE_FIXUP
 
        /* Restore working register */
@@ -420,7 +420,7 @@ ENTRY(fast_unaligned)
 
        /* restore SAR and return */
 
-       wsr     a0, SAR
+       wsr     a0, sar
        l32i    a0, a2, PT_AREG0
        l32i    a2, a2, PT_AREG2
        rfe
@@ -438,10 +438,10 @@ ENTRY(fast_unaligned)
        l32i    a6, a2, PT_AREG6
        l32i    a5, a2, PT_AREG5
        l32i    a4, a2, PT_AREG4
-       wsr     a0, SAR
+       wsr     a0, sar
        mov     a1, a2
 
-       rsr     a0, PS
+       rsr     a0, ps
         bbsi.l  a2, PS_UM_BIT, 1f     # jump if user mode
 
        movi    a0, _kernel_exception
index 2bc1e145c0a46d66512826db3bcf41aa65d92491..54c3be313bfa8141e79f84606f8f3d6093d6946f 100644 (file)
@@ -43,7 +43,7 @@
 /* IO protection is currently unsupported. */
 
 ENTRY(fast_io_protect)
-       wsr     a0, EXCSAVE_1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0
 
@@ -220,7 +220,7 @@ ENTRY(coprocessor_restore)
  */
 
 ENTRY(fast_coprocessor_double)
-       wsr     a0, EXCSAVE_1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0
 
@@ -229,13 +229,13 @@ ENTRY(fast_coprocessor)
 
        /* Save remaining registers a1-a3 and SAR */
 
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
        s32i    a3, a2, PT_AREG3
-       rsr     a3, SAR
+       rsr     a3, sar
        s32i    a1, a2, PT_AREG1
        s32i    a3, a2, PT_SAR
        mov     a1, a2
-       rsr     a2, DEPC
+       rsr     a2, depc
        s32i    a2, a1, PT_AREG2
 
        /*
@@ -248,17 +248,17 @@ ENTRY(fast_coprocessor)
 
        /* Find coprocessor number. Subtract first CP EXCCAUSE from EXCCAUSE */
 
-       rsr     a3, EXCCAUSE
+       rsr     a3, exccause
        addi    a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
 
        /* Set corresponding CPENABLE bit -> (sar:cp-index, a3: 1<<cp-index)*/
 
        ssl     a3                      # SAR: 32 - coprocessor_number
        movi    a2, 1
-       rsr     a0, CPENABLE
+       rsr     a0, cpenable
        sll     a2, a2
        or      a0, a0, a2
-       wsr     a0, CPENABLE
+       wsr     a0, cpenable
        rsync
 
        /* Retrieve previous owner. (a3 still holds CP number) */
@@ -291,7 +291,7 @@ ENTRY(fast_coprocessor)
 
        /* Note that only a0 and a1 were preserved. */
 
-2:     rsr     a3, EXCCAUSE
+2:     rsr     a3, exccause
        addi    a3, a3, -EXCCAUSE_COPROCESSOR0_DISABLED
        movi    a0, coprocessor_owner
        addx4   a0, a3, a0
@@ -321,7 +321,7 @@ ENTRY(fast_coprocessor)
        l32i    a0, a1, PT_SAR
        l32i    a3, a1, PT_AREG3
        l32i    a2, a1, PT_AREG2
-       wsr     a0, SAR
+       wsr     a0, sar
        l32i    a0, a1, PT_AREG0
        l32i    a1, a1, PT_AREG1
 
index 7e62360733971886161bfc80bd318a41cc21feb4..90bfc1dbc13dcf46992e4fb09bb7eab3cfe1bea3 100644 (file)
@@ -112,8 +112,8 @@ ENTRY(user_exception)
 
        /* Save a2, a3, and depc, restore excsave_1 and set SP. */
 
-       xsr     a3, EXCSAVE_1
-       rsr     a0, DEPC
+       xsr     a3, excsave1
+       rsr     a0, depc
        s32i    a1, a2, PT_AREG1
        s32i    a0, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
@@ -125,16 +125,16 @@ _user_exception:
        /* Save SAR and turn off single stepping */
 
        movi    a2, 0
-       rsr     a3, SAR
-       xsr     a2, ICOUNTLEVEL
+       rsr     a3, sar
+       xsr     a2, icountlevel
        s32i    a3, a1, PT_SAR
        s32i    a2, a1, PT_ICOUNTLEVEL
 
        /* Rotate ws so that the current windowbase is at bit0. */
        /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
 
-       rsr     a2, WINDOWBASE
-       rsr     a3, WINDOWSTART
+       rsr     a2, windowbase
+       rsr     a3, windowstart
        ssr     a2
        s32i    a2, a1, PT_WINDOWBASE
        s32i    a3, a1, PT_WINDOWSTART
@@ -205,12 +205,12 @@ _user_exception:
 
        /* WINDOWBASE still in SAR! */
 
-       rsr     a2, SAR                 # original WINDOWBASE
+       rsr     a2, sar                 # original WINDOWBASE
        movi    a3, 1
        ssl     a2
        sll     a3, a3
-       wsr     a3, WINDOWSTART         # set corresponding WINDOWSTART bit
-       wsr     a2, WINDOWBASE          # and WINDOWSTART
+       wsr     a3, windowstart         # set corresponding WINDOWSTART bit
+       wsr     a2, windowbase          # and WINDOWSTART
        rsync
 
        /* We are back to the original stack pointer (a1) */
@@ -252,8 +252,8 @@ ENTRY(kernel_exception)
 
        /* Save a0, a2, a3, DEPC and set SP. */
 
-       xsr     a3, EXCSAVE_1           # restore a3, excsave_1
-       rsr     a0, DEPC                # get a2
+       xsr     a3, excsave1            # restore a3, excsave_1
+       rsr     a0, depc                # get a2
        s32i    a1, a2, PT_AREG1
        s32i    a0, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
@@ -265,16 +265,16 @@ _kernel_exception:
        /* Save SAR and turn off single stepping */
 
        movi    a2, 0
-       rsr     a3, SAR
-       xsr     a2, ICOUNTLEVEL
+       rsr     a3, sar
+       xsr     a2, icountlevel
        s32i    a3, a1, PT_SAR
        s32i    a2, a1, PT_ICOUNTLEVEL
 
        /* Rotate ws so that the current windowbase is at bit0. */
        /* Assume ws = xxwww1yyyy. Rotate ws right, so that a2 = yyyyxxwww1 */
 
-       rsr     a2, WINDOWBASE          # don't need to save these, we only
-       rsr     a3, WINDOWSTART         # need shifted windowstart: windowmask
+       rsr     a2, windowbase          # don't need to save these, we only
+       rsr     a3, windowstart         # need shifted windowstart: windowmask
        ssr     a2
        slli    a2, a3, 32-WSBITS
        src     a2, a3, a2
@@ -323,24 +323,24 @@ common_exception:
 
        /* Save some registers, disable loops and clear the syscall flag. */
 
-       rsr     a2, DEBUGCAUSE
-       rsr     a3, EPC_1
+       rsr     a2, debugcause
+       rsr     a3, epc1
        s32i    a2, a1, PT_DEBUGCAUSE
        s32i    a3, a1, PT_PC
 
        movi    a2, -1
-       rsr     a3, EXCVADDR
+       rsr     a3, excvaddr
        s32i    a2, a1, PT_SYSCALL
        movi    a2, 0
        s32i    a3, a1, PT_EXCVADDR
-       xsr     a2, LCOUNT
+       xsr     a2, lcount
        s32i    a2, a1, PT_LCOUNT
 
        /* It is now save to restore the EXC_TABLE_FIXUP variable. */
 
-       rsr     a0, EXCCAUSE
+       rsr     a0, exccause
        movi    a3, 0
-       rsr     a2, EXCSAVE_1
+       rsr     a2, excsave1
        s32i    a0, a1, PT_EXCCAUSE
        s32i    a3, a2, EXC_TABLE_FIXUP
 
@@ -352,22 +352,22 @@ common_exception:
         *     (interrupts disabled) and if this exception is not an interrupt.
         */
 
-       rsr     a3, PS
+       rsr     a3, ps
        addi    a0, a0, -4
        movi    a2, 1
        extui   a3, a3, 0, 1            # a3 = PS.INTLEVEL[0]
        moveqz  a3, a2, a0              # a3 = 1 iff interrupt exception
        movi    a2, 1 << PS_WOE_BIT
        or      a3, a3, a2
-       rsr     a0, EXCCAUSE
-       xsr     a3, PS
+       rsr     a0, exccause
+       xsr     a3, ps
 
        s32i    a3, a1, PT_PS           # save ps
 
-       /* Save LBEG, LEND */
+       /* Save lbeg, lend */
 
-       rsr     a2, LBEG
-       rsr     a3, LEND
+       rsr     a2, lbeg
+       rsr     a3, lend
        s32i    a2, a1, PT_LBEG
        s32i    a3, a1, PT_LEND
 
@@ -432,7 +432,7 @@ common_exception_return:
 
        load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
 
-       wsr     a3, PS          /* disable interrupts */
+       wsr     a3, ps          /* disable interrupts */
 
        _bbci.l a3, PS_UM_BIT, kernel_exception_exit
 
@@ -444,12 +444,12 @@ user_exception_exit:
 
        l32i    a2, a1, PT_WINDOWBASE
        l32i    a3, a1, PT_WINDOWSTART
-       wsr     a1, DEPC                # use DEPC as temp storage
-       wsr     a3, WINDOWSTART         # restore WINDOWSTART
+       wsr     a1, depc                # use DEPC as temp storage
+       wsr     a3, windowstart         # restore WINDOWSTART
        ssr     a2                      # preserve user's WB in the SAR
-       wsr     a2, WINDOWBASE          # switch to user's saved WB
+       wsr     a2, windowbase          # switch to user's saved WB
        rsync
-       rsr     a1, DEPC                # restore stack pointer
+       rsr     a1, depc                # restore stack pointer
        l32i    a2, a1, PT_WMASK        # register frames saved (in bits 4...9)
        rotw    -1                      # we restore a4..a7
        _bltui  a6, 16, 1f              # only have to restore current window?
@@ -475,8 +475,8 @@ user_exception_exit:
 
        /* Clear unrestored registers (don't leak anything to user-land */
 
-1:     rsr     a0, WINDOWBASE
-       rsr     a3, SAR
+1:     rsr     a0, windowbase
+       rsr     a3, sar
        sub     a3, a0, a3
        beqz    a3, 2f
        extui   a3, a3, 0, WBBITS
@@ -556,7 +556,7 @@ kernel_exception_exit:
 
        /* Test WINDOWSTART now. If spilled, do the movsp */
 
-       rsr     a3, WINDOWSTART
+       rsr     a3, windowstart
        addi    a0, a3, -1
        and     a3, a3, a0
        _bnez   a3, common_exception_exit
@@ -604,24 +604,24 @@ common_exception_exit:
 
 1:     l32i    a2, a1, PT_PC
        l32i    a3, a1, PT_SAR
-       wsr     a2, EPC_1
-       wsr     a3, SAR
+       wsr     a2, epc1
+       wsr     a3, sar
 
        /* Restore LBEG, LEND, LCOUNT */
 
        l32i    a2, a1, PT_LBEG
        l32i    a3, a1, PT_LEND
-       wsr     a2, LBEG
+       wsr     a2, lbeg
        l32i    a2, a1, PT_LCOUNT
-       wsr     a3, LEND
-       wsr     a2, LCOUNT
+       wsr     a3, lend
+       wsr     a2, lcount
 
        /* We control single stepping through the ICOUNTLEVEL register. */
 
        l32i    a2, a1, PT_ICOUNTLEVEL
        movi    a3, -2
-       wsr     a2, ICOUNTLEVEL
-       wsr     a3, ICOUNT
+       wsr     a2, icountlevel
+       wsr     a3, icount
 
        /* Check if it was double exception. */
 
@@ -636,7 +636,7 @@ common_exception_exit:
        l32i    a1, a1, PT_AREG1
        rfe
 
-1:     wsr     a0, DEPC
+1:     wsr     a0, depc
        l32i    a0, a1, PT_AREG0
        l32i    a1, a1, PT_AREG1
        rfde
@@ -651,25 +651,25 @@ common_exception_exit:
 
 ENTRY(debug_exception)
 
-       rsr     a0, EPS + XCHAL_DEBUGLEVEL
+       rsr     a0, SREG_EPS + XCHAL_DEBUGLEVEL
        bbsi.l  a0, PS_EXCM_BIT, 1f     # exception mode
 
-       /* Set EPC_1 and EXCCAUSE */
+       /* Set EPC1 and EXCCAUSE */
 
-       wsr     a2, DEPC                # save a2 temporarily
-       rsr     a2, EPC + XCHAL_DEBUGLEVEL
-       wsr     a2, EPC_1
+       wsr     a2, depc                # save a2 temporarily
+       rsr     a2, SREG_EPC + XCHAL_DEBUGLEVEL
+       wsr     a2, epc1
 
        movi    a2, EXCCAUSE_MAPPED_DEBUG
-       wsr     a2, EXCCAUSE
+       wsr     a2, exccause
 
        /* Restore PS to the value before the debug exc but with PS.EXCM set.*/
 
        movi    a2, 1 << PS_EXCM_BIT
        or      a2, a0, a2
        movi    a0, debug_exception     # restore a3, debug jump vector
-       wsr     a2, PS
-       xsr     a0, EXCSAVE + XCHAL_DEBUGLEVEL
+       wsr     a2, ps
+       xsr     a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
 
        /* Switch to kernel/user stack, restore jump vector, and save a0 */
 
@@ -680,19 +680,19 @@ ENTRY(debug_exception)
        movi    a0, 0
        s32i    a1, a2, PT_AREG1
        s32i    a0, a2, PT_DEPC         # mark it as a regular exception
-       xsr     a0, DEPC
+       xsr     a0, depc
        s32i    a3, a2, PT_AREG3
        s32i    a0, a2, PT_AREG2
        mov     a1, a2
        j       _kernel_exception
 
-2:     rsr     a2, EXCSAVE_1
+2:     rsr     a2, excsave1
        l32i    a2, a2, EXC_TABLE_KSTK  # load kernel stack pointer
        s32i    a0, a2, PT_AREG0
        movi    a0, 0
        s32i    a1, a2, PT_AREG1
        s32i    a0, a2, PT_DEPC
-       xsr     a0, DEPC
+       xsr     a0, depc
        s32i    a3, a2, PT_AREG3
        s32i    a0, a2, PT_AREG2
        mov     a1, a2
@@ -732,12 +732,12 @@ ENTRY(unrecoverable_exception)
        movi    a0, 1
        movi    a1, 0
 
-       wsr     a0, WINDOWSTART
-       wsr     a1, WINDOWBASE
+       wsr     a0, windowstart
+       wsr     a1, windowbase
        rsync
 
        movi    a1, (1 << PS_WOE_BIT) | 1
-       wsr     a1, PS
+       wsr     a1, ps
        rsync
 
        movi    a1, init_task
@@ -793,7 +793,7 @@ ENTRY(fast_alloca)
        l32i    a0, a2, PT_DEPC
        _bgeui  a0, VALID_DOUBLE_EXCEPTION_ADDRESS, .Lunhandled_double
 
-       rsr     a0, DEPC                # get a2
+       rsr     a0, depc                # get a2
        s32i    a4, a2, PT_AREG4        # save a4 and
        s32i    a0, a2, PT_AREG2        # a2 to stack
 
@@ -804,8 +804,8 @@ ENTRY(fast_alloca)
 
        /* Restore a3, excsave_1 */
 
-       xsr     a3, EXCSAVE_1           # make sure excsave_1 is valid for dbl.
-       rsr     a4, EPC_1               # get exception address
+       xsr     a3, excsave1            # make sure excsave_1 is valid for dbl.
+       rsr     a4, epc1                # get exception address
        s32i    a3, a2, PT_AREG3        # save a3 to stack
 
 #ifdef ALLOCA_EXCEPTION_IN_IRAM
@@ -820,7 +820,7 @@ ENTRY(fast_alloca)
        jx      a3
 
 .Lunhandled_double:
-       wsr     a0, EXCSAVE_1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0
 
@@ -852,7 +852,7 @@ ENTRY(fast_alloca)
 #endif
        addi    a4, a4, 3               # step over movsp
        _EXTUI_MOVSP_DST(a0)            # extract destination register
-       wsr     a4, EPC_1               # save new epc_1
+       wsr     a4, epc1                # save new epc_1
 
        _bnei   a0, 1, 1f               # no 'movsp a1, ax': jump
 
@@ -953,14 +953,14 @@ ENTRY(fast_syscall_kernel)
 
        /* Skip syscall. */
 
-       rsr     a0, EPC_1
+       rsr     a0, epc1
        addi    a0, a0, 3
-       wsr     a0, EPC_1
+       wsr     a0, epc1
 
        l32i    a0, a2, PT_DEPC
        bgeui   a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
 
-       rsr     a0, DEPC                        # get syscall-nr
+       rsr     a0, depc                        # get syscall-nr
        _beqz   a0, fast_syscall_spill_registers
        _beqi   a0, __NR_xtensa, fast_syscall_xtensa
 
@@ -970,14 +970,14 @@ ENTRY(fast_syscall_user)
 
        /* Skip syscall. */
 
-       rsr     a0, EPC_1
+       rsr     a0, epc1
        addi    a0, a0, 3
-       wsr     a0, EPC_1
+       wsr     a0, epc1
 
        l32i    a0, a2, PT_DEPC
        bgeui   a0, VALID_DOUBLE_EXCEPTION_ADDRESS, fast_syscall_unrecoverable
 
-       rsr     a0, DEPC                        # get syscall-nr
+       rsr     a0, depc                        # get syscall-nr
        _beqz   a0, fast_syscall_spill_registers
        _beqi   a0, __NR_xtensa, fast_syscall_xtensa
 
@@ -988,10 +988,10 @@ ENTRY(fast_syscall_unrecoverable)
         /* Restore all states. */
 
         l32i    a0, a2, PT_AREG0        # restore a0
-        xsr     a2, DEPC                # restore a2, depc
-        rsr     a3, EXCSAVE_1
+        xsr     a2, depc                # restore a2, depc
+        rsr     a3, excsave1
 
-        wsr     a0, EXCSAVE_1
+        wsr     a0, excsave1
         movi    a0, unrecoverable_exception
         callx0  a0
 
@@ -1047,7 +1047,7 @@ ENTRY(fast_syscall_unrecoverable)
 
 ENTRY(fast_syscall_xtensa)
 
-       xsr     a3, EXCSAVE_1           # restore a3, excsave1
+       xsr     a3, excsave1            # restore a3, excsave1
 
        s32i    a7, a2, PT_AREG7        # we need an additional register
        movi    a7, 4                   # sizeof(unsigned int)
@@ -1124,13 +1124,13 @@ ENTRY(fast_syscall_spill_registers)
 
        movi    a0, fast_syscall_spill_registers_fixup
        s32i    a0, a3, EXC_TABLE_FIXUP
-       rsr     a0, WINDOWBASE
+       rsr     a0, windowbase
        s32i    a0, a3, EXC_TABLE_PARAM
 
        /* Save a3 and SAR on stack. */
 
-       rsr     a0, SAR
-       xsr     a3, EXCSAVE_1           # restore a3 and excsave_1
+       rsr     a0, sar
+       xsr     a3, excsave1            # restore a3 and excsave_1
        s32i    a3, a2, PT_AREG3
        s32i    a4, a2, PT_AREG4
        s32i    a0, a2, PT_AREG5        # store SAR to PT_AREG5
@@ -1148,7 +1148,7 @@ ENTRY(fast_syscall_spill_registers)
        l32i    a3, a2, PT_AREG5
        l32i    a4, a2, PT_AREG4
        l32i    a0, a2, PT_AREG0
-       wsr     a3, SAR
+       wsr     a3, sar
        l32i    a3, a2, PT_AREG3
 
        /* Restore clobbered registers. */
@@ -1173,8 +1173,8 @@ ENTRY(fast_syscall_spill_registers)
 
 fast_syscall_spill_registers_fixup:
 
-       rsr     a2, WINDOWBASE  # get current windowbase (a2 is saved)
-       xsr     a0, DEPC        # restore depc and a0
+       rsr     a2, windowbase  # get current windowbase (a2 is saved)
+       xsr     a0, depc        # restore depc and a0
        ssl     a2              # set shift (32 - WB)
 
        /* We need to make sure the current registers (a0-a3) are preserved.
@@ -1182,12 +1182,12 @@ fast_syscall_spill_registers_fixup:
         * in WS, so that the exception handlers save them to the task stack.
         */
 
-       rsr     a3, EXCSAVE_1   # get spill-mask
+       rsr     a3, excsave1    # get spill-mask
        slli    a2, a3, 1       # shift left by one
 
        slli    a3, a2, 32-WSBITS
        src     a2, a2, a3      # a1 = xxwww1yyxxxwww1yy......
-       wsr     a2, WINDOWSTART # set corrected windowstart
+       wsr     a2, windowstart # set corrected windowstart
 
        movi    a3, exc_table
        l32i    a2, a3, EXC_TABLE_DOUBLE_SAVE   # restore a2
@@ -1201,7 +1201,7 @@ fast_syscall_spill_registers_fixup:
         * excsave_1:   a3
         */
 
-       wsr     a3, WINDOWBASE
+       wsr     a3, windowbase
        rsync
 
        /* We are now in the original frame when we entered _spill_registers:
@@ -1227,7 +1227,7 @@ fast_syscall_spill_registers_fixup:
        /* Jump to the exception handler. */
 
        movi    a3, exc_table
-       rsr     a0, EXCCAUSE
+       rsr     a0, exccause
         addx4  a0, a0, a3                      # find entry in table
         l32i   a0, a0, EXC_TABLE_FAST_USER     # load handler
         jx     a0
@@ -1236,28 +1236,28 @@ fast_syscall_spill_registers_fixup_return:
 
        /* When we return here, all registers have been restored (a2: DEPC) */
 
-       wsr     a2, DEPC                # exception address
+       wsr     a2, depc                # exception address
 
        /* Restore fixup handler. */
 
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
        movi    a2, fast_syscall_spill_registers_fixup
        s32i    a2, a3, EXC_TABLE_FIXUP
-       rsr     a2, WINDOWBASE
+       rsr     a2, windowbase
        s32i    a2, a3, EXC_TABLE_PARAM
        l32i    a2, a3, EXC_TABLE_KSTK
 
        /* Load WB at the time the exception occurred. */
 
-       rsr     a3, SAR                 # WB is still in SAR
+       rsr     a3, sar                 # WB is still in SAR
        neg     a3, a3
-       wsr     a3, WINDOWBASE
+       wsr     a3, windowbase
        rsync
 
        /* Restore a3 and return. */
 
        movi    a3, exc_table
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
 
        rfde
 
@@ -1283,8 +1283,8 @@ ENTRY(_spill_registers)
         * Rotate ws right so that a4 = yyxxxwww1.
         */
 
-       rsr     a4, WINDOWBASE
-       rsr     a3, WINDOWSTART         # a3 = xxxwww1yy
+       rsr     a4, windowbase
+       rsr     a3, windowstart         # a3 = xxxwww1yy
        ssr     a4                      # holds WB
        slli    a4, a3, WSBITS
        or      a3, a3, a4              # a3 = xxxwww1yyxxxwww1yy
@@ -1302,7 +1302,7 @@ ENTRY(_spill_registers)
 
        /* Skip empty frames - get 'oldest' WINDOWSTART-bit. */
 
-       wsr     a3, WINDOWSTART         # save shifted windowstart
+       wsr     a3, windowstart         # save shifted windowstart
        neg     a4, a3
        and     a3, a4, a3              # first bit set from right: 000010000
 
@@ -1311,12 +1311,12 @@ ENTRY(_spill_registers)
        sub     a4, a3, a4              # WSBITS-a4:number of 0-bits from right
        ssr     a4                      # save in SAR for later.
 
-       rsr     a3, WINDOWBASE
+       rsr     a3, windowbase
        add     a3, a3, a4
-       wsr     a3, WINDOWBASE
+       wsr     a3, windowbase
        rsync
 
-       rsr     a3, WINDOWSTART
+       rsr     a3, windowstart
        srl     a3, a3                  # shift windowstart
 
        /* WB is now just one frame below the oldest frame in the register
@@ -1364,11 +1364,11 @@ ENTRY(_spill_registers)
 .Lexit: /* Done. Do the final rotation, set WS, and return. */
 
        rotw    1
-       rsr     a3, WINDOWBASE
+       rsr     a3, windowbase
        ssl     a3
        movi    a3, 1
        sll     a3, a3
-       wsr     a3, WINDOWSTART
+       wsr     a3, windowstart
        ret
 
 .Lc4:  s32e    a4, a9, -16
@@ -1429,7 +1429,7 @@ ENTRY(_spill_registers)
         * however, this condition is unrecoverable in kernel space.
         */
 
-       rsr     a0, PS
+       rsr     a0, ps
        _bbci.l a0, PS_UM_BIT, 1f
 
        /* User space: Setup a dummy frame and kill application.
@@ -1439,18 +1439,18 @@ ENTRY(_spill_registers)
        movi    a0, 1
        movi    a1, 0
 
-       wsr     a0, WINDOWSTART
-       wsr     a1, WINDOWBASE
+       wsr     a0, windowstart
+       wsr     a1, windowbase
        rsync
 
        movi    a0, 0
 
        movi    a3, exc_table
        l32i    a1, a3, EXC_TABLE_KSTK
-       wsr     a3, EXCSAVE_1
+       wsr     a3, excsave1
 
        movi    a4, (1 << PS_WOE_BIT) | 1
-       wsr     a4, PS
+       wsr     a4, ps
        rsync
 
        movi    a6, SIGSEGV
@@ -1459,7 +1459,7 @@ ENTRY(_spill_registers)
 
 1:     /* Kernel space: PANIC! */
 
-       wsr     a0, EXCSAVE_1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0              # should not return
 1:     j       1b
@@ -1524,7 +1524,7 @@ ENTRY(fast_second_level_miss)
 
        /* We deliberately destroy a3 that holds the exception table. */
 
-8:     rsr     a3, EXCVADDR            # fault address
+8:     rsr     a3, excvaddr            # fault address
        _PGD_OFFSET(a0, a3, a1)
        l32i    a0, a0, 0               # read pmdval
        beqz    a0, 2f
@@ -1542,7 +1542,7 @@ ENTRY(fast_second_level_miss)
         * pteval = ((pmdval - PAGE_OFFSET) & PAGE_MASK) | PAGE_DIRECTORY
         */
 
-       movi    a1, -PAGE_OFFSET
+       movi    a1, (-PAGE_OFFSET) & 0xffffffff
        add     a0, a0, a1              # pmdval - PAGE_OFFSET
        extui   a1, a0, 0, PAGE_SHIFT   # ... & PAGE_MASK
        xor     a0, a0, a1
@@ -1561,7 +1561,7 @@ ENTRY(fast_second_level_miss)
         */
 
        extui   a3, a3, 28, 2           # addr. bit 28 and 29   0,1,2,3
-       rsr     a1, PTEVADDR
+       rsr     a1, ptevaddr
        addx2   a3, a3, a3              # ->                    0,3,6,9
        srli    a1, a1, PAGE_SHIFT
        extui   a3, a3, 2, 2            # ->                    0,0,1,2
@@ -1583,18 +1583,18 @@ ENTRY(fast_second_level_miss)
        l32i    a0, a2, PT_AREG0
        l32i    a1, a2, PT_AREG1
        l32i    a2, a2, PT_DEPC
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
 
        bgeui   a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
        /* Restore excsave1 and return. */
 
-       rsr     a2, DEPC
+       rsr     a2, depc
        rfe
 
        /* Return from double exception. */
 
-1:     xsr     a2, DEPC
+1:     xsr     a2, depc
        esync
        rfde
 
@@ -1618,7 +1618,7 @@ ENTRY(fast_second_level_miss)
        /* Make sure the exception originated in the special functions */
 
        movi    a0, __tlbtemp_mapping_start
-       rsr     a3, EPC_1
+       rsr     a3, epc1
        bltu    a3, a0, 2f
        movi    a0, __tlbtemp_mapping_end
        bgeu    a3, a0, 2f
@@ -1626,7 +1626,7 @@ ENTRY(fast_second_level_miss)
        /* Check if excvaddr was in one of the TLBTEMP_BASE areas. */
 
        movi    a3, TLBTEMP_BASE_1
-       rsr     a0, EXCVADDR
+       rsr     a0, excvaddr
        bltu    a0, a3, 2f
 
        addi    a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT))
@@ -1635,7 +1635,7 @@ ENTRY(fast_second_level_miss)
        /* Check if we have to restore an ITLB mapping. */
 
        movi    a1, __tlbtemp_mapping_itlb
-       rsr     a3, EPC_1
+       rsr     a3, epc1
        sub     a3, a3, a1
 
        /* Calculate VPN */
@@ -1671,13 +1671,13 @@ ENTRY(fast_second_level_miss)
 2:     /* Invalid PGD, default exception handling */
 
        movi    a3, exc_table
-       rsr     a1, DEPC
-       xsr     a3, EXCSAVE_1
+       rsr     a1, depc
+       xsr     a3, excsave1
        s32i    a1, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
        mov     a1, a2
 
-       rsr     a2, PS
+       rsr     a2, ps
        bbsi.l  a2, PS_UM_BIT, 1f
        j       _kernel_exception
 1:     j       _user_exception
@@ -1712,7 +1712,7 @@ ENTRY(fast_store_prohibited)
        l32i    a0, a1, TASK_MM         # tsk->mm
        beqz    a0, 9f
 
-8:     rsr     a1, EXCVADDR            # fault address
+8:     rsr     a1, excvaddr            # fault address
        _PGD_OFFSET(a0, a1, a4)
        l32i    a0, a0, 0
        beqz    a0, 2f
@@ -1725,7 +1725,7 @@ ENTRY(fast_store_prohibited)
 
        movi    a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE
        or      a4, a4, a1
-       rsr     a1, EXCVADDR
+       rsr     a1, excvaddr
        s32i    a4, a0, 0
 
        /* We need to flush the cache if we have page coloring. */
@@ -1749,15 +1749,15 @@ ENTRY(fast_store_prohibited)
 
        /* Restore excsave1 and a3. */
 
-       xsr     a3, EXCSAVE_1
+       xsr     a3, excsave1
        bgeui   a2, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
 
-       rsr     a2, DEPC
+       rsr     a2, depc
        rfe
 
        /* Double exception. Restore FIXUP handler and return. */
 
-1:     xsr     a2, DEPC
+1:     xsr     a2, depc
        esync
        rfde
 
@@ -1766,14 +1766,14 @@ ENTRY(fast_store_prohibited)
 
 2:     /* If there was a problem, handle fault in C */
 
-       rsr     a4, DEPC        # still holds a2
-       xsr     a3, EXCSAVE_1
+       rsr     a4, depc        # still holds a2
+       xsr     a3, excsave1
        s32i    a4, a2, PT_AREG2
        s32i    a3, a2, PT_AREG3
        l32i    a4, a2, PT_AREG4
        mov     a1, a2
 
-       rsr     a2, PS
+       rsr     a2, ps
        bbsi.l  a2, PS_UM_BIT, 1f
        j       _kernel_exception
 1:     j       _user_exception
@@ -1832,50 +1832,6 @@ ENTRY(system_call)
        retw
 
 
-/*
- * Create a kernel thread
- *
- * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
- * a2                    a2                 a3             a4
- */
-
-ENTRY(kernel_thread)
-       entry   a1, 16
-
-       mov     a5, a2                  # preserve fn over syscall
-       mov     a7, a3                  # preserve args over syscall
-
-       movi    a3, _CLONE_VM | _CLONE_UNTRACED
-       movi    a2, __NR_clone
-       or      a6, a4, a3              # arg0: flags
-       mov     a3, a1                  # arg1: sp
-       syscall
-
-       beq     a3, a1, 1f              # branch if parent
-       mov     a6, a7                  # args
-       callx4  a5                      # fn(args)
-
-       movi    a2, __NR_exit
-       syscall                         # return value of fn(args) still in a6
-
-1:     retw
-
-/*
- * Do a system call from kernel instead of calling sys_execve, so we end up
- * with proper pt_regs.
- *
- * int kernel_execve(const char *fname, char *const argv[], charg *const envp[])
- * a2                        a2               a3                  a4
- */
-
-ENTRY(kernel_execve)
-       entry   a1, 16
-       mov     a6, a2                  # arg0 is in a6
-       movi    a2, __NR_execve
-       syscall
-
-       retw
-
 /*
  * Task switch.
  *
@@ -1901,8 +1857,8 @@ ENTRY(_switch_to)
        /* Disable ints while we manipulate the stack pointer. */
 
        movi    a14, (1 << PS_EXCM_BIT) | LOCKLEVEL
-       xsr     a14, PS
-       rsr     a3, EXCSAVE_1
+       xsr     a14, ps
+       rsr     a3, excsave1
        rsync
        s32i    a3, a3, EXC_TABLE_FIXUP /* enter critical section */
 
@@ -1910,7 +1866,7 @@ ENTRY(_switch_to)
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
        l32i    a3, a5, THREAD_CPENABLE
-       xsr     a3, CPENABLE
+       xsr     a3, cpenable
        s32i    a3, a4, THREAD_CPENABLE
 #endif
 
@@ -1924,7 +1880,7 @@ ENTRY(_switch_to)
         *       we return from kernel space.
         */
 
-       rsr     a3, EXCSAVE_1           # exc_table
+       rsr     a3, excsave1            # exc_table
        movi    a6, 0
        addi    a7, a5, PT_REGS_OFFSET
        s32i    a6, a3, EXC_TABLE_FIXUP
@@ -1937,7 +1893,7 @@ ENTRY(_switch_to)
 
        load_xtregs_user a5 a6 a8 a9 a10 a11 THREAD_XTREGS_USER
 
-       wsr     a14, PS
+       wsr     a14, ps
        mov     a2, a12                 # return 'prev'
        rsync
 
@@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)
 
        j       common_exception_return
 
+/*
+ * Kernel thread creation helper
+ * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg
+ *           left from _switch_to: a6 = prev
+ */
+ENTRY(ret_from_kernel_thread)
+
+       call4   schedule_tail
+       mov     a6, a3
+       callx4  a2
+       j       common_exception_return
+
+ENDPROC(ret_from_kernel_thread)
index 3ef91a73652d31bb943c4ca00949d05e270a8390..bdc50788f35e13e9e4d89b54e65af887f1a26610 100644 (file)
@@ -61,18 +61,18 @@ _startup:
        /* Disable interrupts and exceptions. */
 
        movi    a0, LOCKLEVEL
-       wsr     a0, PS
+       wsr     a0, ps
 
        /* Preserve the pointer to the boot parameter list in EXCSAVE_1 */
 
-       wsr     a2, EXCSAVE_1
+       wsr     a2, excsave1
 
        /* Start with a fresh windowbase and windowstart.  */
 
        movi    a1, 1
        movi    a0, 0
-       wsr     a1, WINDOWSTART
-       wsr     a0, WINDOWBASE
+       wsr     a1, windowstart
+       wsr     a0, windowbase
        rsync
 
        /* Set a0 to 0 for the remaining initialization. */
@@ -82,46 +82,46 @@ _startup:
        /* Clear debugging registers. */
 
 #if XCHAL_HAVE_DEBUG
-       wsr     a0, IBREAKENABLE
-       wsr     a0, ICOUNT
+       wsr     a0, ibreakenable
+       wsr     a0, icount
        movi    a1, 15
-       wsr     a0, ICOUNTLEVEL
+       wsr     a0, icountlevel
 
        .set    _index, 0
        .rept   XCHAL_NUM_DBREAK - 1
-       wsr     a0, DBREAKC + _index
+       wsr     a0, SREG_DBREAKC + _index
        .set    _index, _index + 1
        .endr
 #endif
 
        /* Clear CCOUNT (not really necessary, but nice) */
 
-       wsr     a0, CCOUNT      # not really necessary, but nice
+       wsr     a0, ccount      # not really necessary, but nice
 
        /* Disable zero-loops. */
 
 #if XCHAL_HAVE_LOOPS
-       wsr     a0, LCOUNT
+       wsr     a0, lcount
 #endif
 
        /* Disable all timers. */
 
        .set    _index, 0
        .rept   XCHAL_NUM_TIMERS - 1
-       wsr     a0, CCOMPARE + _index
+       wsr     a0, SREG_CCOMPARE + _index
        .set    _index, _index + 1
        .endr
 
        /* Interrupt initialization. */
 
        movi    a2, XCHAL_INTTYPE_MASK_SOFTWARE | XCHAL_INTTYPE_MASK_EXTERN_EDGE
-       wsr     a0, INTENABLE
-       wsr     a2, INTCLEAR
+       wsr     a0, intenable
+       wsr     a2, intclear
 
        /* Disable coprocessors. */
 
 #if XCHAL_CP_NUM > 0
-       wsr     a0, CPENABLE
+       wsr     a0, cpenable
 #endif
 
        /* Set PS.INTLEVEL=1, PS.WOE=0, kernel stack, PS.EXCM=0
@@ -132,7 +132,7 @@ _startup:
         */
 
        movi    a1, 1
-       wsr     a1, PS
+       wsr     a1, ps
        rsync
 
        /*  Initialize the caches.
@@ -206,18 +206,18 @@ _startup:
        addi    a1, a1, KERNEL_STACK_SIZE
 
        movi    a2, 0x00040001          # WOE=1, INTLEVEL=1, UM=0
-       wsr     a2, PS                  # (enable reg-windows; progmode stack)
+       wsr     a2, ps                  # (enable reg-windows; progmode stack)
        rsync
 
        /* Set up EXCSAVE[DEBUGLEVEL] to point to the Debug Exception Handler.*/
 
        movi    a2, debug_exception
-       wsr     a2, EXCSAVE + XCHAL_DEBUGLEVEL
+       wsr     a2, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
 
        /* Set up EXCSAVE[1] to point to the exc_table. */
 
        movi    a6, exc_table
-       xsr     a6, EXCSAVE_1
+       xsr     a6, excsave1
 
        /* init_arch kick-starts the linux kernel */
 
index 98e77c3ef1c38d9e1401b7238a7a4a4c51cea460..a6ce3e563739f1b56d34eea2a0c2f770159c9f46 100644 (file)
@@ -72,13 +72,13 @@ int arch_show_interrupts(struct seq_file *p, int prec)
 static void xtensa_irq_mask(struct irq_data *d)
 {
        cached_irq_mask &= ~(1 << d->irq);
-       set_sr (cached_irq_mask, INTENABLE);
+       set_sr (cached_irq_mask, intenable);
 }
 
 static void xtensa_irq_unmask(struct irq_data *d)
 {
        cached_irq_mask |= 1 << d->irq;
-       set_sr (cached_irq_mask, INTENABLE);
+       set_sr (cached_irq_mask, intenable);
 }
 
 static void xtensa_irq_enable(struct irq_data *d)
@@ -95,7 +95,7 @@ static void xtensa_irq_disable(struct irq_data *d)
 
 static void xtensa_irq_ack(struct irq_data *d)
 {
-       set_sr(1 << d->irq, INTCLEAR);
+       set_sr(1 << d->irq, intclear);
 }
 
 static int xtensa_irq_retrigger(struct irq_data *d)
index bc020825cce55197e6aaf7dfc127203a143e3553..09ae7bfab9a7a4a8ff2a6e2c55aadf07dda48024 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/regs.h>
 
 extern void ret_from_fork(void);
+extern void ret_from_kernel_thread(void);
 
 struct task_struct *current_set[NR_CPUS] = {&init_task, };
 
@@ -158,64 +159,123 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 /*
  * Copy thread.
  *
+ * There are two modes in which this function is called:
+ * 1) Userspace thread creation,
+ *    regs != NULL, usp_thread_fn is userspace stack pointer.
+ *    It is expected to copy parent regs (in case CLONE_VM is not set
+ *    in the clone_flags) and set up passed usp in the childregs.
+ * 2) Kernel thread creation,
+ *    regs == NULL, usp_thread_fn is the function to run in the new thread
+ *    and thread_fn_arg is its parameter.
+ *    childregs are not used for the kernel threads.
+ *
  * The stack layout for the new thread looks like this:
  *
- *     +------------------------+ <- sp in childregs (= tos)
+ *     +------------------------+
  *     |       childregs        |
  *     +------------------------+ <- thread.sp = sp in dummy-frame
  *     |      dummy-frame       |    (saved in dummy-frame spill-area)
  *     +------------------------+
  *
- * We create a dummy frame to return to ret_from_fork:
- *   a0 points to ret_from_fork (simulating a call4)
+ * We create a dummy frame to return to either ret_from_fork or
+ *   ret_from_kernel_thread:
+ *   a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)
  *   sp points to itself (thread.sp)
- *   a2, a3 are unused.
+ *   a2, a3 are unused for userspace threads,
+ *   a2 points to thread_fn, a3 holds thread_fn arg for kernel threads.
  *
  * Note: This is a pristine frame, so we don't need any spill region on top of
  *       childregs.
+ *
+ * The fun part:  if we're keeping the same VM (i.e. cloning a thread,
+ * not an entire process), we're normally given a new usp, and we CANNOT share
+ * any live address register windows.  If we just copy those live frames over,
+ * the two threads (parent and child) will overflow the same frames onto the
+ * parent stack at different times, likely corrupting the parent stack (esp.
+ * if the parent returns from functions that called clone() and calls new
+ * ones, before the child overflows its now old copies of its parent windows).
+ * One solution is to spill windows to the parent stack, but that's fairly
+ * involved.  Much simpler to just not copy those live frames across.
  */
 
-int copy_thread(unsigned long clone_flags, unsigned long usp,
-               unsigned long unused,
-                struct task_struct * p, struct pt_regs * regs)
+int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
+               unsigned long thread_fn_arg,
+               struct task_struct *p, struct pt_regs *unused)
 {
-       struct pt_regs *childregs;
-       struct thread_info *ti;
-       unsigned long tos;
-       int user_mode = user_mode(regs);
-
-       /* Set up new TSS. */
-       tos = (unsigned long)task_stack_page(p) + THREAD_SIZE;
-       if (user_mode)
-               childregs = (struct pt_regs*)(tos - PT_USER_SIZE);
-       else
-               childregs = (struct pt_regs*)tos - 1;
+       struct pt_regs *childregs = task_pt_regs(p);
 
-       *childregs = *regs;
+#if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
+       struct thread_info *ti;
+#endif
 
        /* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */
        *((int*)childregs - 3) = (unsigned long)childregs;
        *((int*)childregs - 4) = 0;
 
-       childregs->areg[1] = tos;
-       childregs->areg[2] = 0;
-       p->set_child_tid = p->clear_child_tid = NULL;
-       p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);
        p->thread.sp = (unsigned long)childregs;
 
-       if (user_mode(regs)) {
+       if (!(p->flags & PF_KTHREAD)) {
+               struct pt_regs *regs = current_pt_regs();
+               unsigned long usp = usp_thread_fn ?
+                       usp_thread_fn : regs->areg[1];
 
-               int len = childregs->wmask & ~0xf;
+               p->thread.ra = MAKE_RA_FOR_CALL(
+                               (unsigned long)ret_from_fork, 0x1);
+
+               /* This does not copy all the regs.
+                * In a bout of brilliance or madness,
+                * ARs beyond a0-a15 exist past the end of the struct.
+                */
+               *childregs = *regs;
                childregs->areg[1] = usp;
-               memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
-                      &regs->areg[XCHAL_NUM_AREGS - len/4], len);
+               childregs->areg[2] = 0;
+
+               /* When sharing memory with the parent thread, the child
+                  usually starts on a pristine stack, so we have to reset
+                  windowbase, windowstart and wmask.
+                  (Note that such a new thread is required to always create
+                  an initial call4 frame)
+                  The exception is vfork, where the new thread continues to
+                  run on the parent's stack until it calls execve. This could
+                  be a call8 or call12, which requires a legal stack frame
+                  of the previous caller for the overflow handlers to work.
+                  (Note that it's always legal to overflow live registers).
+                  In this case, ensure to spill at least the stack pointer
+                  of that frame. */
+
+               if (clone_flags & CLONE_VM) {
+                       /* check that caller window is live and same stack */
+                       int len = childregs->wmask & ~0xf;
+                       if (regs->areg[1] == usp && len != 0) {
+                               int callinc = (regs->areg[0] >> 30) & 3;
+                               int caller_ars = XCHAL_NUM_AREGS - callinc * 4;
+                               put_user(regs->areg[caller_ars+1],
+                                        (unsigned __user*)(usp - 12));
+                       }
+                       childregs->wmask = 1;
+                       childregs->windowstart = 1;
+                       childregs->windowbase = 0;
+               } else {
+                       int len = childregs->wmask & ~0xf;
+                       memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4],
+                              &regs->areg[XCHAL_NUM_AREGS - len/4], len);
+               }
 // FIXME: we need to set THREADPTR in thread_info...
                if (clone_flags & CLONE_SETTLS)
                        childregs->areg[2] = childregs->areg[6];
-
        } else {
-               /* In kernel space, we start a new thread with a new stack. */
-               childregs->wmask = 1;
+               p->thread.ra = MAKE_RA_FOR_CALL(
+                               (unsigned long)ret_from_kernel_thread, 1);
+
+               /* pass parameters to ret_from_kernel_thread:
+                * a2 = thread_fn, a3 = thread_fn arg
+                */
+               *((int *)childregs - 1) = thread_fn_arg;
+               *((int *)childregs - 2) = usp_thread_fn;
+
+               /* Childregs are only used when we're going to userspace
+                * in which case start_thread will set them up.
+                */
        }
 
 #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)
@@ -311,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,
                   void __user *child_tid, long a5,
                   struct pt_regs *regs)
 {
-        if (!newsp)
-                newsp = regs->areg[1];
         return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
-
-/*
- * xtensa_execve() executes a new program.
- */
-
-asmlinkage
-long xtensa_execve(const char __user *name,
-                  const char __user *const __user *argv,
-                   const char __user *const __user *envp,
-                   long a3, long a4, long a5,
-                   struct pt_regs *regs)
-{
-       long error;
-       struct filename *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename->name, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
-
index 270360d9806ca6832d0ff7d4aeeff62dfad910c7..b237988ba6d77b789ca2766509e66fd50985c840 100644 (file)
@@ -100,7 +100,7 @@ typedef struct tagtable {
 } tagtable_t;
 
 #define __tagtable(tag, fn) static tagtable_t __tagtable_##fn          \
-       __attribute__((unused, __section__(".taglist"))) = { tag, fn }
+       __attribute__((used, section(".taglist"))) = { tag, fn }
 
 /* parse current tag */
 
@@ -120,7 +120,7 @@ static int __init parse_tag_mem(const bp_tag_t *tag)
        }
        sysmem.bank[sysmem.nr_banks].type  = mi->type;
        sysmem.bank[sysmem.nr_banks].start = PAGE_ALIGN(mi->start);
-       sysmem.bank[sysmem.nr_banks].end   = mi->end & PAGE_SIZE;
+       sysmem.bank[sysmem.nr_banks].end   = mi->end & PAGE_MASK;
        sysmem.nr_banks++;
 
        return 0;
index 05b3f093d5d7cd09435c0395cf5a20e0a07e26ec..5702065f472a88bebc4df721dec0629208957395 100644 (file)
@@ -32,11 +32,8 @@ typedef void (*syscall_t)(void);
 syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {
        [0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall,
 
-#undef __SYSCALL
 #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol,
-#undef _XTENSA_UNISTD_H
-#undef  __KERNEL_SYSCALLS__
-#include <asm/unistd.h>
+#include <uapi/asm/unistd.h>
 };
 
 asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
@@ -50,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)
        return (long)ret;
 }
 
-asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len)
+asmlinkage long xtensa_fadvise64_64(int fd, int advice,
+               unsigned long long offset, unsigned long long len)
 {
        return sys_fadvise64_64(fd, offset, len, advice);
 }
index bc1e14cf93692b811c09c7440c83d9309cc00834..5caf2b64d43ac846c7a0c148166c54877dec8178 100644 (file)
@@ -97,7 +97,7 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
 /* EXCCAUSE_INTEGER_DIVIDE_BY_ZERO unhandled */
 /* EXCCAUSE_PRIVILEGED unhandled */
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
-#ifdef CONFIG_UNALIGNED_USER
+#ifdef CONFIG_XTENSA_UNALIGNED_USER
 { EXCCAUSE_UNALIGNED,          USER,      fast_unaligned },
 #else
 { EXCCAUSE_UNALIGNED,          0,         do_unaligned_user },
@@ -202,8 +202,8 @@ extern void do_IRQ(int, struct pt_regs *);
 
 void do_interrupt (struct pt_regs *regs)
 {
-       unsigned long intread = get_sr (INTREAD);
-       unsigned long intenable = get_sr (INTENABLE);
+       unsigned long intread = get_sr (interrupt);
+       unsigned long intenable = get_sr (intenable);
        int i, mask;
 
        /* Handle all interrupts (no priorities).
@@ -213,7 +213,7 @@ void do_interrupt (struct pt_regs *regs)
 
        for (i=0, mask = 1; i < XCHAL_NUM_INTERRUPTS; i++, mask <<= 1) {
                if (mask & (intread & intenable)) {
-                       set_sr (mask, INTCLEAR);
+                       set_sr (mask, intclear);
                        do_IRQ (i,regs);
                }
        }
@@ -244,7 +244,7 @@ do_illegal_instruction(struct pt_regs *regs)
  */
 
 #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
-#ifndef CONFIG_UNALIGNED_USER
+#ifndef CONFIG_XTENSA_UNALIGNED_USER
 void
 do_unaligned_user (struct pt_regs *regs)
 {
@@ -339,7 +339,7 @@ void __init trap_init(void)
        /* Initialize EXCSAVE_1 to hold the address of the exception table. */
 
        i = (unsigned long)exc_table;
-       __asm__ __volatile__("wsr  %0, "__stringify(EXCSAVE_1)"\n" : : "a" (i));
+       __asm__ __volatile__("wsr  %0, excsave1\n" : : "a" (i));
 }
 
 /*
@@ -386,16 +386,16 @@ static inline void spill_registers(void)
        unsigned int a0, ps;
 
        __asm__ __volatile__ (
-               "movi   a14," __stringify (PS_EXCM_BIT) " | 1\n\t"
+               "movi   a14, " __stringify(PS_EXCM_BIT | 1) "\n\t"
                "mov    a12, a0\n\t"
-               "rsr    a13," __stringify(SAR) "\n\t"
-               "xsr    a14," __stringify(PS) "\n\t"
+               "rsr    a13, sar\n\t"
+               "xsr    a14, ps\n\t"
                "movi   a0, _spill_registers\n\t"
                "rsync\n\t"
                "callx0 a0\n\t"
                "mov    a0, a12\n\t"
-               "wsr    a13," __stringify(SAR) "\n\t"
-               "wsr    a14," __stringify(PS) "\n\t"
+               "wsr    a13, sar\n\t"
+               "wsr    a14, ps\n\t"
                :: "a" (&a0), "a" (&ps)
                : "a2", "a3", "a4", "a7", "a11", "a12", "a13", "a14", "a15", "memory");
 }
index 70066e3582d0b878f427832f56d5f983fc5e11bb..4462c1e595c2b1ed87f772e11335561ed1885d6d 100644 (file)
 
 ENTRY(_UserExceptionVector)
 
-       xsr     a3, EXCSAVE_1           # save a3 and get dispatch table
-       wsr     a2, DEPC                # save a2
+       xsr     a3, excsave1            # save a3 and get dispatch table
+       wsr     a2, depc                # save a2
        l32i    a2, a3, EXC_TABLE_KSTK  # load kernel stack to a2
        s32i    a0, a2, PT_AREG0        # save a0 to ESF
-       rsr     a0, EXCCAUSE            # retrieve exception cause
+       rsr     a0, exccause            # retrieve exception cause
        s32i    a0, a2, PT_DEPC         # mark it as a regular exception
        addx4   a0, a0, a3              # find entry in table
        l32i    a0, a0, EXC_TABLE_FAST_USER     # load handler
@@ -93,11 +93,11 @@ ENTRY(_UserExceptionVector)
 
 ENTRY(_KernelExceptionVector)
 
-       xsr     a3, EXCSAVE_1           # save a3, and get dispatch table
-       wsr     a2, DEPC                # save a2
+       xsr     a3, excsave1            # save a3, and get dispatch table
+       wsr     a2, depc                # save a2
        addi    a2, a1, -16-PT_SIZE     # adjust stack pointer
        s32i    a0, a2, PT_AREG0        # save a0 to ESF
-       rsr     a0, EXCCAUSE            # retrieve exception cause
+       rsr     a0, exccause            # retrieve exception cause
        s32i    a0, a2, PT_DEPC         # mark it as a regular exception
        addx4   a0, a0, a3              # find entry in table
        l32i    a0, a0, EXC_TABLE_FAST_KERNEL   # load handler address
@@ -205,17 +205,17 @@ ENTRY(_DoubleExceptionVector)
 
        /* Deliberately destroy excsave (don't assume it's value was valid). */
 
-       wsr     a3, EXCSAVE_1           # save a3
+       wsr     a3, excsave1            # save a3
 
        /* Check for kernel double exception (usually fatal). */
 
-       rsr     a3, PS
+       rsr     a3, ps
        _bbci.l a3, PS_UM_BIT, .Lksp
 
        /* Check if we are currently handling a window exception. */
        /* Note: We don't need to indicate that we enter a critical section. */
 
-       xsr     a0, DEPC                # get DEPC, save a0
+       xsr     a0, depc                # get DEPC, save a0
 
        movi    a3, XCHAL_WINDOW_VECTORS_VADDR
        _bltu   a0, a3, .Lfixup
@@ -243,21 +243,21 @@ ENTRY(_DoubleExceptionVector)
         * Note: We can trash the current window frame (a0...a3) and depc!
         */
 
-       wsr     a2, DEPC                # save stack pointer temporarily
-       rsr     a0, PS
+       wsr     a2, depc                # save stack pointer temporarily
+       rsr     a0, ps
        extui   a0, a0, PS_OWB_SHIFT, 4
-       wsr     a0, WINDOWBASE
+       wsr     a0, windowbase
        rsync
 
        /* We are now in the previous window frame. Save registers again. */
 
-       xsr     a2, DEPC                # save a2 and get stack pointer
+       xsr     a2, depc                # save a2 and get stack pointer
        s32i    a0, a2, PT_AREG0
 
-       wsr     a3, EXCSAVE_1           # save a3
+       wsr     a3, excsave1            # save a3
        movi    a3, exc_table
 
-       rsr     a0, EXCCAUSE
+       rsr     a0, exccause
        s32i    a0, a2, PT_DEPC         # mark it as a regular exception
        addx4   a0, a0, a3
        l32i    a0, a0, EXC_TABLE_FAST_USER
@@ -290,14 +290,14 @@ ENTRY(_DoubleExceptionVector)
 
        /* a0: depc, a1: a1, a2: kstk, a3: a2, depc: a0, excsave: a3 */
 
-       xsr     a3, DEPC
+       xsr     a3, depc
        s32i    a0, a2, PT_DEPC
        s32i    a3, a2, PT_AREG0
 
        /* a0: avail, a1: a1, a2: kstk, a3: avail, depc: a2, excsave: a3 */
 
        movi    a3, exc_table
-       rsr     a0, EXCCAUSE
+       rsr     a0, exccause
        addx4   a0, a0, a3
        l32i    a0, a0, EXC_TABLE_FAST_USER
        jx      a0
@@ -312,7 +312,7 @@ ENTRY(_DoubleExceptionVector)
 
 .Lksp: /* a0: a0, a1: a1, a2: a2, a3: trashed, depc: depc, excsave: a3 */
 
-       rsr     a3, EXCCAUSE
+       rsr     a3, exccause
        beqi    a3, EXCCAUSE_ITLB_MISS, 1f
        addi    a3, a3, -EXCCAUSE_DTLB_MISS
        bnez    a3, .Lunrecoverable
@@ -328,11 +328,11 @@ ENTRY(_DoubleExceptionVector)
 
 .Lunrecoverable_fixup:
        l32i    a2, a3, EXC_TABLE_DOUBLE_SAVE
-       xsr     a0, DEPC
+       xsr     a0, depc
 
 .Lunrecoverable:
-       rsr     a3, EXCSAVE_1
-       wsr     a0, EXCSAVE_1
+       rsr     a3, excsave1
+       wsr     a0, excsave1
        movi    a0, unrecoverable_exception
        callx0  a0
 
@@ -349,7 +349,7 @@ ENTRY(_DoubleExceptionVector)
        .section .DebugInterruptVector.text, "ax"
 
 ENTRY(_DebugInterruptVector)
-       xsr     a0, EXCSAVE + XCHAL_DEBUGLEVEL
+       xsr     a0, SREG_EXCSAVE + XCHAL_DEBUGLEVEL
        jx      a0
 
 
index a8b9f1fd1e17f63573c74bdf8c06616c1abd7481..afe058b24e6e07c83d61f1a524b30e03340d6369 100644 (file)
@@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);
 EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(copy_page);
 
-EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(empty_zero_page);
 
 /*
index ea59dcd038666da7af3004c68da1eb7d9964d9dd..c48b80acb5f014813c9d509f425e95e4f3b872e0 100644 (file)
@@ -6,7 +6,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2002 - 2005 Tensilica Inc.
+ * Copyright (C) 2002 - 2012 Tensilica Inc.
  */
 
 #include <variant/core.h>
 #endif
        .endm
 
-
 /*
  * void *memcpy(void *dst, const void *src, size_t len);
- * void *memmove(void *dst, const void *src, size_t len);
- * void *bcopy(const void *src, void *dst, size_t len);
  *
  * This function is intended to do the same thing as the standard
- * library function memcpy() (or bcopy()) for most cases.
+ * library function memcpy() for most cases.
  * However, where the source and/or destination references
  * an instruction RAM or ROM or a data RAM or ROM, that
  * source and/or destination will always be accessed with
@@ -45,9 +42,6 @@
  * !!!!!!!  Handling of IRAM/IROM has not yet
  * !!!!!!!  been implemented.
  *
- * The bcopy version is provided here to avoid the overhead
- * of an extra call, for callers that require this convention.
- *
  * The (general case) algorithm is as follows:
  *   If destination is unaligned, align it by conditionally
  *     copying 1 and 2 bytes.
  */
 
        .text
-       .align  4
-       .global bcopy
-       .type   bcopy,@function
-bcopy:
-       entry   sp, 16          # minimal stack frame
-       # a2=src, a3=dst, a4=len
-       mov     a5, a3          # copy dst so that a2 is return value
-       mov     a3, a2
-       mov     a2, a5
-       j       .Lcommon        # go to common code for memcpy+bcopy
-
 
 /*
  * Byte by byte copy
@@ -107,7 +90,7 @@ bcopy:
        s8i     a6, a5, 0
        addi    a5, a5, 1
 #if !XCHAL_HAVE_LOOPS
-       blt     a3, a7, .Lnextbyte
+       bne     a3, a7, .Lnextbyte # continue loop if $a3:src != $a7:src_end
 #endif /* !XCHAL_HAVE_LOOPS */
 .Lbytecopydone:
        retw
@@ -144,9 +127,6 @@ bcopy:
        .global memcpy
        .type   memcpy,@function
 memcpy:
-       .global memmove
-       .type   memmove,@function
-memmove:
 
        entry   sp, 16          # minimal stack frame
        # a2/ dst, a3/ src, a4/ len
@@ -182,7 +162,7 @@ memmove:
        s32i    a7, a5, 12
        addi    a5, a5, 16
 #if !XCHAL_HAVE_LOOPS
-       blt     a3, a8, .Loop1
+       bne     a3, a8, .Loop1  # continue loop if a3:src != a8:src_end
 #endif /* !XCHAL_HAVE_LOOPS */
 .Loop1done:
        bbci.l  a4, 3, .L2
@@ -260,7 +240,7 @@ memmove:
        s32i    a9, a5, 12
        addi    a5, a5, 16
 #if !XCHAL_HAVE_LOOPS
-       blt     a3, a10, .Loop2
+       bne     a3, a10, .Loop2 # continue loop if a3:src != a10:src_end
 #endif /* !XCHAL_HAVE_LOOPS */
 .Loop2done:
        bbci.l  a4, 3, .L12
@@ -305,6 +285,285 @@ memmove:
        l8ui    a6, a3,  0
        s8i     a6, a5,  0
        retw
+
+
+/*
+ * void bcopy(const void *src, void *dest, size_t n);
+ */
+       .align  4
+       .global bcopy
+       .type   bcopy,@function
+bcopy:
+       entry   sp, 16          # minimal stack frame
+       # a2=src, a3=dst, a4=len
+       mov     a5, a3
+       mov     a3, a2
+       mov     a2, a5
+       j       .Lmovecommon    # go to common code for memmove+bcopy
+
+/*
+ * void *memmove(void *dst, const void *src, size_t len);
+ *
+ * This function is intended to do the same thing as the standard
+ * library function memmove() for most cases.
+ * However, where the source and/or destination references
+ * an instruction RAM or ROM or a data RAM or ROM, that
+ * source and/or destination will always be accessed with
+ * 32-bit load and store instructions (as required for these
+ * types of devices).
+ *
+ * !!!!!!!  XTFIXME:
+ * !!!!!!!  Handling of IRAM/IROM has not yet
+ * !!!!!!!  been implemented.
+ *
+ * The (general case) algorithm is as follows:
+ *   If end of source doesn't overlap destination then use memcpy.
+ *   Otherwise do memcpy backwards.
+ *
+ * Register use:
+ *     a0/ return address
+ *     a1/ stack pointer
+ *     a2/ return value
+ *     a3/ src
+ *     a4/ length
+ *     a5/ dst
+ *     a6/ tmp
+ *     a7/ tmp
+ *     a8/ tmp
+ *     a9/ tmp
+ *     a10/ tmp
+ *     a11/ tmp
+ */
+
+/*
+ * Byte by byte copy
+ */
+       .align  4
+       .byte   0               # 1 mod 4 alignment for LOOPNEZ
+                               # (0 mod 4 alignment for LBEG)
+.Lbackbytecopy:
+#if XCHAL_HAVE_LOOPS
+       loopnez a4, .Lbackbytecopydone
+#else /* !XCHAL_HAVE_LOOPS */
+       beqz    a4, .Lbackbytecopydone
+       sub     a7, a3, a4      # a7 = start address for source
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbacknextbyte:
+       addi    a3, a3, -1
+       l8ui    a6, a3, 0
+       addi    a5, a5, -1
+       s8i     a6, a5, 0
+#if !XCHAL_HAVE_LOOPS
+       bne     a3, a7, .Lbacknextbyte # continue loop if
+                                      # $a3:src != $a7:src_start
+#endif /* !XCHAL_HAVE_LOOPS */
+.Lbackbytecopydone:
+       retw
+
+/*
+ * Destination is unaligned
+ */
+
+       .align  4
+.Lbackdst1mod2:        # dst is only byte aligned
+       _bltui  a4, 7, .Lbackbytecopy   # do short copies byte by byte
+
+       # copy 1 byte
+       addi    a3, a3, -1
+       l8ui    a6, a3,  0
+       addi    a5, a5, -1
+       s8i     a6, a5,  0
+       addi    a4, a4, -1
+       _bbci.l a5, 1, .Lbackdstaligned # if dst is now aligned, then
+                                       # return to main algorithm
+.Lbackdst2mod4:        # dst 16-bit aligned
+       # copy 2 bytes
+       _bltui  a4, 6, .Lbackbytecopy   # do short copies byte by byte
+       addi    a3, a3, -2
+       l8ui    a6, a3,  0
+       l8ui    a7, a3,  1
+       addi    a5, a5, -2
+       s8i     a6, a5,  0
+       s8i     a7, a5,  1
+       addi    a4, a4, -2
+       j       .Lbackdstaligned        # dst is now aligned,
+                                       # return to main algorithm
+
+       .align  4
+       .global memmove
+       .type   memmove,@function
+memmove:
+
+       entry   sp, 16          # minimal stack frame
+       # a2/ dst, a3/ src, a4/ len
+       mov     a5, a2          # copy dst so that a2 is return value
+.Lmovecommon:
+       sub     a6, a5, a3
+       bgeu    a6, a4, .Lcommon
+
+       add     a5, a5, a4
+       add     a3, a3, a4
+
+       _bbsi.l a5, 0, .Lbackdst1mod2   # if dst is 1 mod 2
+       _bbsi.l a5, 1, .Lbackdst2mod4   # if dst is 2 mod 4
+.Lbackdstaligned:      # return here from .Lbackdst?mod? once dst is aligned
+       srli    a7, a4, 4       # number of loop iterations with 16B
+                               # per iteration
+       movi    a8, 3           # if source is not aligned,
+       _bany   a3, a8, .Lbacksrcunaligned      # then use shifting copy
+       /*
+        * Destination and source are word-aligned, use word copy.
+        */
+       # copy 16 bytes per iteration for word-aligned dst and word-aligned src
+#if XCHAL_HAVE_LOOPS
+       loopnez a7, .backLoop1done
+#else /* !XCHAL_HAVE_LOOPS */
+       beqz    a7, .backLoop1done
+       slli    a8, a7, 4
+       sub     a8, a3, a8      # a8 = start of first 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.backLoop1:
+       addi    a3, a3, -16
+       l32i    a7, a3, 12
+       l32i    a6, a3,  8
+       addi    a5, a5, -16
+       s32i    a7, a5, 12
+       l32i    a7, a3,  4
+       s32i    a6, a5,  8
+       l32i    a6, a3,  0
+       s32i    a7, a5,  4
+       s32i    a6, a5,  0
+#if !XCHAL_HAVE_LOOPS
+       bne     a3, a8, .backLoop1  # continue loop if a3:src != a8:src_start
+#endif /* !XCHAL_HAVE_LOOPS */
+.backLoop1done:
+       bbci.l  a4, 3, .Lback2
+       # copy 8 bytes
+       addi    a3, a3, -8
+       l32i    a6, a3,  0
+       l32i    a7, a3,  4
+       addi    a5, a5, -8
+       s32i    a6, a5,  0
+       s32i    a7, a5,  4
+.Lback2:
+       bbsi.l  a4, 2, .Lback3
+       bbsi.l  a4, 1, .Lback4
+       bbsi.l  a4, 0, .Lback5
+       retw
+.Lback3:
+       # copy 4 bytes
+       addi    a3, a3, -4
+       l32i    a6, a3,  0
+       addi    a5, a5, -4
+       s32i    a6, a5,  0
+       bbsi.l  a4, 1, .Lback4
+       bbsi.l  a4, 0, .Lback5
+       retw
+.Lback4:
+       # copy 2 bytes
+       addi    a3, a3, -2
+       l16ui   a6, a3,  0
+       addi    a5, a5, -2
+       s16i    a6, a5,  0
+       bbsi.l  a4, 0, .Lback5
+       retw
+.Lback5:
+       # copy 1 byte
+       addi    a3, a3, -1
+       l8ui    a6, a3,  0
+       addi    a5, a5, -1
+       s8i     a6, a5,  0
+       retw
+
+/*
+ * Destination is aligned, Source is unaligned
+ */
+
+       .align  4
+.Lbacksrcunaligned:
+       _beqz   a4, .Lbackdone  # avoid loading anything for zero-length copies
+       # copy 16 bytes per iteration for word-aligned dst and unaligned src
+       ssa8    a3              # set shift amount from byte offset
+#define SIM_CHECKS_ALIGNMENT   1       /* set to 1 when running on ISS with
+                                        * the lint or ferret client, or 0
+                                        * to save a few cycles */
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
+       and     a11, a3, a8     # save unalignment offset for below
+       sub     a3, a3, a11     # align a3
+#endif
+       l32i    a6, a3, 0       # load first word
+#if XCHAL_HAVE_LOOPS
+       loopnez a7, .backLoop2done
+#else /* !XCHAL_HAVE_LOOPS */
+       beqz    a7, .backLoop2done
+       slli    a10, a7, 4
+       sub     a10, a3, a10    # a10 = start of first 16B source chunk
+#endif /* !XCHAL_HAVE_LOOPS */
+.backLoop2:
+       addi    a3, a3, -16
+       l32i    a7, a3, 12
+       l32i    a8, a3,  8
+       addi    a5, a5, -16
+       src_b   a6, a7, a6
+       s32i    a6, a5, 12
+       l32i    a9, a3,  4
+       src_b   a7, a8, a7
+       s32i    a7, a5,  8
+       l32i    a6, a3,  0
+       src_b   a8, a9, a8
+       s32i    a8, a5,  4
+       src_b   a9, a6, a9
+       s32i    a9, a5,  0
+#if !XCHAL_HAVE_LOOPS
+       bne     a3, a10, .backLoop2 # continue loop if a3:src != a10:src_start
+#endif /* !XCHAL_HAVE_LOOPS */
+.backLoop2done:
+       bbci.l  a4, 3, .Lback12
+       # copy 8 bytes
+       addi    a3, a3, -8
+       l32i    a7, a3,  4
+       l32i    a8, a3,  0
+       addi    a5, a5, -8
+       src_b   a6, a7, a6
+       s32i    a6, a5,  4
+       src_b   a7, a8, a7
+       s32i    a7, a5,  0
+       mov     a6, a8
+.Lback12:
+       bbci.l  a4, 2, .Lback13
+       # copy 4 bytes
+       addi    a3, a3, -4
+       l32i    a7, a3,  0
+       addi    a5, a5, -4
+       src_b   a6, a7, a6
+       s32i    a6, a5,  0
+       mov     a6, a7
+.Lback13:
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || SIM_CHECKS_ALIGNMENT
+       add     a3, a3, a11     # readjust a3 with correct misalignment
+#endif
+       bbsi.l  a4, 1, .Lback14
+       bbsi.l  a4, 0, .Lback15
+.Lbackdone:
+       retw
+.Lback14:
+       # copy 2 bytes
+       addi    a3, a3, -2
+       l8ui    a6, a3,  0
+       l8ui    a7, a3,  1
+       addi    a5, a5, -2
+       s8i     a6, a5,  0
+       s8i     a7, a5,  1
+       bbsi.l  a4, 0, .Lback15
+       retw
+.Lback15:
+       # copy 1 byte
+       addi    a3, a3, -1
+       addi    a5, a5, -1
+       l8ui    a6, a3,  0
+       s8i     a6, a5,  0
+       retw
+
 \f
 /*
  * Local Variables:
index 2c2f710ed1dc905a8c9e0509d36cd76ed073e0ce..245b08f7eaf4bb98fd3a731c7f6d329214a5b55a 100644 (file)
@@ -6,7 +6,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2001 - 2010 Tensilica Inc.
  *
  * Chris Zankel <chris@zankel.net>
  * Joe Taylor  <joe@tensilica.com, joetylr@yahoo.com>
@@ -186,6 +186,7 @@ do_sigbus:
        /* Kernel mode? Handle exceptions or die */
        if (!user_mode(regs))
                bad_page_fault(regs, address, SIGBUS);
+       return;
 
 vmalloc_fault:
        {
index 8ab47edd7c82b677a5d893391d4f340454c1cb48..7e74895eee04c8e17333d159998ce0cc0b10cccb 100644 (file)
@@ -91,7 +91,7 @@ static int rs_write(struct tty_struct * tty,
 {
        /* see drivers/char/serialX.c to reference original version */
 
-       __simc (SYS_write, 1, (unsigned long)buf, count, 0, 0);
+       simc_write(1, buf, count);
        return count;
 }
 
@@ -122,12 +122,7 @@ static void rs_poll(unsigned long priv)
 
 static int rs_put_char(struct tty_struct *tty, unsigned char ch)
 {
-       char buf[2];
-
-       buf[0] = ch;
-       buf[1] = '\0';          /* Is this NULL necessary? */
-       __simc (SYS_write, 1, (unsigned long) buf, 1, 0, 0);
-       return 1;
+       return rs_write(tty, &ch, 1);
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
index 8c43bfea05e1e6257ad37f53f6eb12c4aaf45b85..bd78192e2fc9e61e72dbd8c38eda423598c6e2bb 100644 (file)
@@ -78,8 +78,9 @@ static inline int __simc(int a, int b, int c, int d, int e, int f)
        return ret;
 }
 
-static inline int simc_open(char *file, int flags, int mode)
+static inline int simc_open(const char *file, int flags, int mode)
 {
+       wmb();
        return __simc(SYS_open, (int) file, flags, mode, 0, 0);
 }
 
@@ -90,16 +91,19 @@ static inline int simc_close(int fd)
 
 static inline int simc_ioctl(int fd, int request, void *arg)
 {
+       wmb();
        return __simc(SYS_ioctl, fd, request, (int) arg, 0, 0);
 }
 
 static inline int simc_read(int fd, void *buf, size_t count)
 {
+       rmb();
        return __simc(SYS_read, fd, (int) buf, count, 0, 0);
 }
 
-static inline int simc_write(int fd, void *buf, size_t count)
+static inline int simc_write(int fd, const void *buf, size_t count)
 {
+       wmb();
        return __simc(SYS_write, fd, (int) buf, count, 0, 0);
 }
 
@@ -107,6 +111,7 @@ static inline int simc_poll(int fd)
 {
        struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
 
+       wmb();
        return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)&tv,
                        0, 0);
 }
index 927acf378ea35e3bb6364bfb78cfc1347f829ecb..e1700102f35ee8039d66661250f1a41ca26fc5d0 100644 (file)
@@ -61,13 +61,13 @@ void platform_restart(void)
         * jump to the reset vector. */
 
        __asm__ __volatile__("movi      a2, 15\n\t"
-                            "wsr       a2, " __stringify(ICOUNTLEVEL) "\n\t"
+                            "wsr       a2, icountlevel\n\t"
                             "movi      a2, 0\n\t"
-                            "wsr       a2, " __stringify(ICOUNT) "\n\t"
-                            "wsr       a2, " __stringify(IBREAKENABLE) "\n\t"
-                            "wsr       a2, " __stringify(LCOUNT) "\n\t"
+                            "wsr       a2, icount\n\t"
+                            "wsr       a2, ibreakenable\n\t"
+                            "wsr       a2, lcount\n\t"
                             "movi      a2, 0x1f\n\t"
-                            "wsr       a2, " __stringify(PS) "\n\t"
+                            "wsr       a2, ps\n\t"
                             "isync\n\t"
                             "jx        %0\n\t"
                             :
index 9e83940ac26577f3f60c92784b6bb482f98f736e..c7d90f17886e1fd86a1fc17df51bab8cbd2c939d 100644 (file)
@@ -66,13 +66,13 @@ void platform_restart(void)
         * jump to the reset vector. */
 
        __asm__ __volatile__ ("movi     a2, 15\n\t"
-                             "wsr      a2, " __stringify(ICOUNTLEVEL) "\n\t"
+                             "wsr      a2, icountlevel\n\t"
                              "movi     a2, 0\n\t"
-                             "wsr      a2, " __stringify(ICOUNT) "\n\t"
-                             "wsr      a2, " __stringify(IBREAKENABLE) "\n\t"
-                             "wsr      a2, " __stringify(LCOUNT) "\n\t"
+                             "wsr      a2, icount\n\t"
+                             "wsr      a2, ibreakenable\n\t"
+                             "wsr      a2, lcount\n\t"
                              "movi     a2, 0x1f\n\t"
-                             "wsr      a2, " __stringify(PS) "\n\t"
+                             "wsr      a2, ps\n\t"
                              "isync\n\t"
                              "jx       %0\n\t"
                              :
index 09acf1b39905ced3f08164c213a6d2aed7f29cae..a7e40a7c821427cd27f6c7019411030ea00e33e8 100644 (file)
@@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY
 
 config BLK_DEV_THROTTLING
        bool "Block layer bio throttling support"
-       depends on BLK_CGROUP=y && EXPERIMENTAL
+       depends on BLK_CGROUP=y
        default n
        ---help---
        Block layer bio throttling support. It can be used to limit
index cafcd743118969daec377f52f09e41594d188347..d0b770391ad400ad0312049c84a2b522bf985bf1 100644 (file)
@@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)
                blkg_destroy(blkg);
                spin_unlock(&blkcg->lock);
        }
+
+       /*
+        * root blkg is destroyed.  Just clear the pointer since
+        * root_rl does not take reference on root blkg.
+        */
+       q->root_blkg = NULL;
+       q->root_rl.blkg = NULL;
 }
 
 static void blkg_rcu_free(struct rcu_head *rcu_head)
@@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,
         */
        if (rl == &q->root_rl) {
                ent = &q->blkg_list;
+               /* There are no more block groups, hence no request lists */
+               if (list_empty(ent))
+                       return NULL;
        } else {
                blkg = container_of(rl, struct blkcg_gq, rl);
                ent = &blkg->q_node;
index a33870b1847bb70c6ef1937f7bef4e93bdf9c980..3c95c4d6e31afe057ebabeda36868682e8188329 100644 (file)
@@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
        struct request *rqa = container_of(a, struct request, queuelist);
        struct request *rqb = container_of(b, struct request, queuelist);
 
-       return !(rqa->q <= rqb->q);
+       return !(rqa->q < rqb->q ||
+               (rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb)));
 }
 
 /*
index 8b6dc5bd4dd061336172b144ae8c09da6bbc56f8..f71eac35c1b942005f3973fd9c919091b9b08bbd 100644 (file)
@@ -52,11 +52,17 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
                           rq_end_io_fn *done)
 {
        int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+       bool is_pm_resume;
 
        WARN_ON(irqs_disabled());
 
        rq->rq_disk = bd_disk;
        rq->end_io = done;
+       /*
+        * need to check this before __blk_run_queue(), because rq can
+        * be freed before that returns.
+        */
+       is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
 
        spin_lock_irq(q->queue_lock);
 
@@ -71,7 +77,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
        __elv_add_request(q, rq, where);
        __blk_run_queue(q);
        /* the queue is stopped so it won't be run */
-       if (rq->cmd_type == REQ_TYPE_PM_RESUME)
+       if (is_pm_resume)
                q->request_fn(q);
        spin_unlock_irq(q->queue_lock);
 }
index 671d4d6d14df106b3b0278364340ef3290d7a185..7bdd61b867c899901ed846ed5a229bc6ab31653b 100644 (file)
@@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work)
        struct crypto_async_request *req, *backlog;
 
        cpu_queue = container_of(work, struct cryptd_cpu_queue, work);
-       /* Only handle one request at a time to avoid hogging crypto
-        * workqueue. preempt_disable/enable is used to prevent
-        * being preempted by cryptd_enqueue_request() */
+       /*
+        * Only handle one request at a time to avoid hogging crypto workqueue.
+        * preempt_disable/enable is used to prevent being preempted by
+        * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent
+        * cryptd_enqueue_request() being accessed from software interrupts.
+        */
+       local_bh_disable();
        preempt_disable();
        backlog = crypto_get_backlog(&cpu_queue->queue);
        req = crypto_dequeue_request(&cpu_queue->queue);
        preempt_enable();
+       local_bh_enable();
 
        if (!req)
                return;
index 03da5b663aef8ea6c2991484b98cb315a16b87db..a16a8d001ae0c3fd0afd8cf3648cebe5c839d75b 100644 (file)
@@ -17,6 +17,10 @@ obj-$(CONFIG_PARISC)         += parisc/
 obj-$(CONFIG_RAPIDIO)          += rapidio/
 obj-y                          += video/
 obj-y                          += idle/
+
+# IPMI must come before ACPI in order to provide IPMI opregion support
+obj-$(CONFIG_IPMI_HANDLER)     += char/ipmi/
+
 obj-$(CONFIG_ACPI)             += acpi/
 obj-$(CONFIG_SFI)              += sfi/
 # PnP must come after ACPI since it will eventually need to check if acpi
index 47199e2a9130a6c929290e34917fc0fdc0714519..82422fe90f8192126ef25f02f1d7fe72fd2c9807 100644 (file)
@@ -47,6 +47,10 @@ acpi-y                               += video_detect.o
 endif
 
 # These are (potentially) separate modules
+
+# IPMI may be used by other drivers, so it has to initialise before them
+obj-$(CONFIG_ACPI_IPMI)                += acpi_ipmi.o
+
 obj-$(CONFIG_ACPI_AC)          += ac.o
 obj-$(CONFIG_ACPI_BUTTON)      += button.o
 obj-$(CONFIG_ACPI_FAN)         += fan.o
@@ -70,6 +74,5 @@ processor-y                   += processor_idle.o processor_thermal.o
 processor-$(CONFIG_CPU_FREQ)   += processor_perflib.o
 
 obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o
-obj-$(CONFIG_ACPI_IPMI)                += acpi_ipmi.o
 
 obj-$(CONFIG_ACPI_APEI)                += apei/
index d1a2d74033e945237afdef3fac02aea87cdebbdd..08373086cd7e883edeec356acb102bcac46147cf 100644 (file)
@@ -159,6 +159,7 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
        if (physical_node->node_id >= ACPI_MAX_PHYSICAL_NODE) {
                retval = -ENOSPC;
                mutex_unlock(&acpi_dev->physical_node_lock);
+               kfree(physical_node);
                goto err;
        }
 
index e78c2a52ea46665fe3ea31a7e79ba7f5cc5c38b2..bd4e5dca3ff7e81f4ce754cbaad3856bb4948a6a 100644 (file)
@@ -409,6 +409,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event)
                acpi_bus_generate_proc_event(device, event, 0);
                acpi_bus_generate_netlink_event(device->pnp.device_class,
                                                  dev_name(&device->dev), event, 0);
+               break;
        default:
                ACPI_DEBUG_PRINT((ACPI_DB_INFO,
                                  "Unsupported event [0x%x]\n", event));
index f94d4c818fc74dc9a076e8f67fe98d7bc6620a61..0230cb6cbb3a18eda2fd323763d6594205c0ed7f 100644 (file)
@@ -1345,12 +1345,15 @@ static int
 acpi_video_bus_get_devices(struct acpi_video_bus *video,
                           struct acpi_device *device)
 {
-       int status;
+       int status = 0;
        struct acpi_device *dev;
 
-       status = acpi_video_device_enumerate(video);
-       if (status)
-               return status;
+       /*
+        * There are systems where video module known to work fine regardless
+        * of broken _DOD and ignoring returned value here doesn't cause
+        * any issues later.
+        */
+       acpi_video_device_enumerate(video);
 
        list_for_each_entry(dev, &device->children, node) {
 
index b1ae48054dc5773eab42917d5e9d10f9764602ae..b7078afddb74fe91c403642cf4679beec06c0ef9 100644 (file)
@@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ahci_suspend(struct device *dev)
 {
        struct ahci_platform_data *pdata = dev_get_platdata(dev);
index fd9ecf74e631afc800e56927069d97bd61774862..5b0ba3f20edcfd4603538ce7505d69dd93f8bb29 100644 (file)
@@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
        struct acpi_device *acpi_dev;
        struct acpi_device_power_state *states;
 
-       if (ap->flags & ATA_FLAG_ACPI_SATA)
-               ata_dev = &ap->link.device[sdev->channel];
-       else
+       if (ap->flags & ATA_FLAG_ACPI_SATA) {
+               if (!sata_pmp_attached(ap))
+                       ata_dev = &ap->link.device[sdev->id];
+               else
+                       ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
+       }
+       else {
                ata_dev = &ap->link.device[sdev->id];
+       }
 
        *handle = ata_dev_acpi_handle(ata_dev);
 
index 3cc7096cfda758e9b3ffd514aaf6e70928ec7f8d..f46fbd3bd3fb6b4456032a0255bad894e8fc9cdb 100644 (file)
@@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
 
        if (xfer_mode == t->mode)
                return t;
+
+       WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n",
+                       __func__, xfer_mode);
+
        return NULL;
 }
 
index e3bda074fa12f59381f9e8911338c49a88611f36..a6df6a351d6e4ce263f717ad52bf1ebb72a1aae0 100644 (file)
@@ -1052,6 +1052,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
 {
        sdev->use_10_for_rw = 1;
        sdev->use_10_for_ms = 1;
+       sdev->no_report_opcodes = 1;
+       sdev->no_write_same = 1;
 
        /* Schedule policy is determined by ->qc_defer() callback and
         * it needs to see every deferred qc.  Set dev_blocked to 1 to
index 26201ebef3ca652a16c12c6719eae2127ed212ad..371fd2c698b70ce1b283672c0c2472f8ce6ac263 100644 (file)
@@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev)
                return ret;
        }
 
+       ret = clk_set_rate(acdev->clk, 166000000);
+       if (ret) {
+               dev_warn(acdev->host->dev, "clock set rate failed");
+               return ret;
+       }
+
        spin_lock_irqsave(&acdev->host->lock, flags);
        /* configure CF interface clock */
        writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk :
@@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int arasan_cf_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
index 0d7c4c2cd26fed3d81ecf2bfe78a1a4939588da9..400bf1c3e982eac392652d086358858ef903ca82 100644 (file)
@@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
 
-static int __init ahci_highbank_probe(struct platform_device *pdev)
+static int __devinit ahci_highbank_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ahci_host_priv *hpriv;
@@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ahci_highbank_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
index 44a4256533e1bd4e8aef978abdfc7e34361ad053..08608de87e4e6a971e9a36ef701f343a6982d5b7 100644 (file)
@@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link,
        return 0;
 }
 
+static int k2_sata_softreset(struct ata_link *link,
+                            unsigned int *class, unsigned long deadline)
+{
+       u8 dmactl;
+       void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+       dmactl = readb(mmio + ATA_DMA_CMD);
+
+       /* Clear the start bit */
+       if (dmactl & ATA_DMA_START) {
+               dmactl &= ~ATA_DMA_START;
+               writeb(dmactl, mmio + ATA_DMA_CMD);
+       }
+
+       return ata_sff_softreset(link, class, deadline);
+}
+
+static int k2_sata_hardreset(struct ata_link *link,
+                            unsigned int *class, unsigned long deadline)
+{
+       u8 dmactl;
+       void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+       dmactl = readb(mmio + ATA_DMA_CMD);
+
+       /* Clear the start bit */
+       if (dmactl & ATA_DMA_START) {
+               dmactl &= ~ATA_DMA_START;
+               writeb(dmactl, mmio + ATA_DMA_CMD);
+       }
+
+       return sata_sff_hardreset(link, class, deadline);
+}
 
 static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
@@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = {
 
 static struct ata_port_operations k2_sata_ops = {
        .inherits               = &ata_bmdma_port_ops,
+       .softreset              = k2_sata_softreset,
+       .hardreset              = k2_sata_hardreset,
        .sff_tf_load            = k2_sata_tf_load,
        .sff_tf_read            = k2_sata_tf_read,
        .sff_check_status       = k2_stat_check_status,
index 89b30f32ba68b4f1e5cd58fc5911a95213abf163..ff7bb8a42ed62b042bff5f786b94775f8bfb87bc 100644 (file)
@@ -1961,6 +1961,7 @@ static int __devinit ucode_init (loader_block * lb, amb_dev * dev) {
     res = loader_verify(lb, dev, rec);
     if (res)
       break;
+    rec = ihex_next_binrec(rec);
   }
   release_firmware(fw);
   if (!res)
index 98510931c8153110ee0617457fb63cafe652696a..6619a8a9607ce7be38bfe3cbc08e69215cfd4345 100644 (file)
@@ -164,7 +164,6 @@ static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
 static uint32_t fpga_tx(struct solos_card *);
 static irqreturn_t solos_irq(int irq, void *dev_id);
 static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
-static int list_vccs(int vci);
 static int atm_init(struct solos_card *, struct device *);
 static void atm_remove(struct solos_card *);
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
@@ -710,7 +709,8 @@ void solos_bh(unsigned long card_arg)
                                                dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
                                                         le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
                                                         port);
-                                       continue;
+                                       dev_kfree_skb_any(skb);
+                                       break;
                                }
                                atm_charge(vcc, skb->truesize);
                                vcc->push(vcc, skb);
@@ -790,44 +790,6 @@ static struct atm_vcc *find_vcc(struct atm_dev *dev, short vpi, int vci)
        return vcc;
 }
 
-static int list_vccs(int vci)
-{
-       struct hlist_head *head;
-       struct atm_vcc *vcc;
-       struct hlist_node *node;
-       struct sock *s;
-       int num_found = 0;
-       int i;
-
-       read_lock(&vcc_sklist_lock);
-       if (vci != 0){
-               head = &vcc_hash[vci & (VCC_HTABLE_SIZE -1)];
-               sk_for_each(s, node, head) {
-                       num_found ++;
-                       vcc = atm_sk(s);
-                       printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n",
-                              vcc->dev->number,
-                              vcc->vpi,
-                              vcc->vci);
-               }
-       } else {
-               for(i = 0; i < VCC_HTABLE_SIZE; i++){
-                       head = &vcc_hash[i];
-                       sk_for_each(s, node, head) {
-                               num_found ++;
-                               vcc = atm_sk(s);
-                               printk(KERN_DEBUG "Device: %d Vpi: %d Vci: %d\n",
-                                      vcc->dev->number,
-                                      vcc->vpi,
-                                      vcc->vci);
-                       }
-               }
-       }
-       read_unlock(&vcc_sklist_lock);
-       return num_found;
-}
-
-
 static int popen(struct atm_vcc *vcc)
 {
        struct solos_card *card = vcc->dev->dev_data;
@@ -840,7 +802,7 @@ static int popen(struct atm_vcc *vcc)
                return -EINVAL;
        }
 
-       skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+       skb = alloc_skb(sizeof(*header), GFP_KERNEL);
        if (!skb) {
                if (net_ratelimit())
                        dev_warn(&card->dev->dev, "Failed to allocate sk_buff in popen()\n");
@@ -857,8 +819,6 @@ static int popen(struct atm_vcc *vcc)
 
        set_bit(ATM_VF_ADDR, &vcc->flags);
        set_bit(ATM_VF_READY, &vcc->flags);
-       list_vccs(0);
-
 
        return 0;
 }
@@ -866,10 +826,21 @@ static int popen(struct atm_vcc *vcc)
 static void pclose(struct atm_vcc *vcc)
 {
        struct solos_card *card = vcc->dev->dev_data;
-       struct sk_buff *skb;
+       unsigned char port = SOLOS_CHAN(vcc->dev);
+       struct sk_buff *skb, *tmpskb;
        struct pkt_hdr *header;
 
-       skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+       /* Remove any yet-to-be-transmitted packets from the pending queue */
+       spin_lock(&card->tx_queue_lock);
+       skb_queue_walk_safe(&card->tx_queue[port], skb, tmpskb) {
+               if (SKB_CB(skb)->vcc == vcc) {
+                       skb_unlink(skb, &card->tx_queue[port]);
+                       solos_pop(vcc, skb);
+               }
+       }
+       spin_unlock(&card->tx_queue_lock);
+
+       skb = alloc_skb(sizeof(*header), GFP_KERNEL);
        if (!skb) {
                dev_warn(&card->dev->dev, "Failed to allocate sk_buff in pclose()\n");
                return;
@@ -881,15 +852,22 @@ static void pclose(struct atm_vcc *vcc)
        header->vci = cpu_to_le16(vcc->vci);
        header->type = cpu_to_le16(PKT_PCLOSE);
 
-       fpga_queue(card, SOLOS_CHAN(vcc->dev), skb, NULL);
+       skb_get(skb);
+       fpga_queue(card, port, skb, NULL);
 
-       clear_bit(ATM_VF_ADDR, &vcc->flags);
-       clear_bit(ATM_VF_READY, &vcc->flags);
+       if (!wait_event_timeout(card->param_wq, !skb_shared(skb), 5 * HZ))
+               dev_warn(&card->dev->dev,
+                        "Timeout waiting for VCC close on port %d\n", port);
+
+       dev_kfree_skb(skb);
 
        /* Hold up vcc_destroy_socket() (our caller) until solos_bh() in the
           tasklet has finished processing any incoming packets (and, more to
           the point, using the vcc pointer). */
        tasklet_unlock_wait(&card->tlet);
+
+       clear_bit(ATM_VF_ADDR, &vcc->flags);
+
        return;
 }
 
@@ -1011,9 +989,10 @@ static uint32_t fpga_tx(struct solos_card *card)
                        if (vcc) {
                                atomic_inc(&vcc->stats->tx);
                                solos_pop(vcc, oldskb);
-                       } else
+                       } else {
                                dev_kfree_skb_irq(oldskb);
-
+                               wake_up(&card->param_wq);
+                       }
                }
        }
        /* For non-DMA TX, write the 'TX start' bit for all four ports simultaneously */
@@ -1248,7 +1227,7 @@ static int atm_init(struct solos_card *card, struct device *parent)
                card->atmdev[i]->phy_data = (void *)(unsigned long)i;
                atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
 
-               skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
+               skb = alloc_skb(sizeof(*header), GFP_KERNEL);
                if (!skb) {
                        dev_warn(&card->dev->dev, "Failed to allocate sk_buff in atm_init()\n");
                        continue;
@@ -1345,6 +1324,8 @@ static struct pci_driver fpga_driver = {
 
 static int __init solos_pci_init(void)
 {
+       BUILD_BUG_ON(sizeof(struct solos_skb_cb) > sizeof(((struct sk_buff *)0)->cb));
+
        printk(KERN_INFO "Solos PCI Driver Version %s\n", VERSION);
        return pci_register_driver(&fpga_driver);
 }
index 08b4c520938463fd989bba879d791a3e418efd39..b34b5cda5ae110aeec980b6ec7c2ec608490a093 100644 (file)
@@ -236,7 +236,7 @@ config CMA_SIZE_PERCENTAGE
 
 choice
        prompt "Selected region size"
-       default CMA_SIZE_SEL_ABSOLUTE
+       default CMA_SIZE_SEL_MBYTES
 
 config CMA_SIZE_SEL_MBYTES
        bool "Use mega bytes value only"
index 560a7173f810015a9532d25395a8ad1a57366e6c..bc256b64102710039e208ec82c513e97b223a290 100644 (file)
@@ -191,9 +191,8 @@ EXPORT_SYMBOL(dma_release_from_coherent);
  * This checks whether the memory was allocated from the per-device
  * coherent memory pool and if so, maps that memory to the provided vma.
  *
- * Returns 1 if we correctly mapped the memory, or 0 if
- * dma_release_coherent() should proceed with mapping memory from
- * generic pools.
+ * Returns 1 if we correctly mapped the memory, or 0 if the caller should
+ * proceed with mapping memory from generic pools.
  */
 int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
                           void *vaddr, size_t size, int *ret)
index 9a1469474f55addaea1ae5be1f4499187297db06..612afcc5a938f45549ed877ebd6c8ac697315fe3 100644 (file)
 #include <linux/mm.h>
 #include <linux/mutex.h>
 #include <linux/page-isolation.h>
+#include <linux/sizes.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/mm_types.h>
 #include <linux/dma-contiguous.h>
 
-#ifndef SZ_1M
-#define SZ_1M (1 << 20)
-#endif
-
 struct cma {
        unsigned long   base_pfn;
        unsigned long   count;
index 81541452887bd3ce5d868909e3fb753fb3d6b124..8945f4e489ed70a03cb272f57064a69330409a60 100644 (file)
@@ -36,68 +36,6 @@ MODULE_AUTHOR("Manuel Estrada Sainz");
 MODULE_DESCRIPTION("Multi purpose firmware loading support");
 MODULE_LICENSE("GPL");
 
-static const char *fw_path[] = {
-       "/lib/firmware/updates/" UTS_RELEASE,
-       "/lib/firmware/updates",
-       "/lib/firmware/" UTS_RELEASE,
-       "/lib/firmware"
-};
-
-/* Don't inline this: 'struct kstat' is biggish */
-static noinline long fw_file_size(struct file *file)
-{
-       struct kstat st;
-       if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
-               return -1;
-       if (!S_ISREG(st.mode))
-               return -1;
-       if (st.size != (long)st.size)
-               return -1;
-       return st.size;
-}
-
-static bool fw_read_file_contents(struct file *file, struct firmware *fw)
-{
-       long size;
-       char *buf;
-
-       size = fw_file_size(file);
-       if (size < 0)
-               return false;
-       buf = vmalloc(size);
-       if (!buf)
-               return false;
-       if (kernel_read(file, 0, buf, size) != size) {
-               vfree(buf);
-               return false;
-       }
-       fw->data = buf;
-       fw->size = size;
-       return true;
-}
-
-static bool fw_get_filesystem_firmware(struct firmware *fw, const char *name)
-{
-       int i;
-       bool success = false;
-       char *path = __getname();
-
-       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
-               struct file *file;
-               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], name);
-
-               file = filp_open(path, O_RDONLY, 0);
-               if (IS_ERR(file))
-                       continue;
-               success = fw_read_file_contents(file, fw);
-               fput(file);
-               if (success)
-                       break;
-       }
-       __putname(path);
-       return success;
-}
-
 /* Builtin firmware support */
 
 #ifdef CONFIG_FW_LOADER
@@ -150,6 +88,11 @@ enum {
        FW_STATUS_ABORT,
 };
 
+enum fw_buf_fmt {
+       VMALLOC_BUF,    /* used in direct loading */
+       PAGE_BUF,       /* used in loading via userspace */
+};
+
 static int loading_timeout = 60;       /* In seconds */
 
 static inline long firmware_loading_timeout(void)
@@ -173,8 +116,6 @@ struct firmware_cache {
        spinlock_t name_lock;
        struct list_head fw_names;
 
-       wait_queue_head_t wait_queue;
-       int cnt;
        struct delayed_work work;
 
        struct notifier_block   pm_notify;
@@ -187,6 +128,7 @@ struct firmware_buf {
        struct completion completion;
        struct firmware_cache *fwc;
        unsigned long status;
+       enum fw_buf_fmt fmt;
        void *data;
        size_t size;
        struct page **pages;
@@ -240,6 +182,7 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
        strcpy(buf->fw_id, fw_name);
        buf->fwc = fwc;
        init_completion(&buf->completion);
+       buf->fmt = VMALLOC_BUF;
 
        pr_debug("%s: fw-%s buf=%p\n", __func__, fw_name, buf);
 
@@ -307,10 +250,14 @@ static void __fw_free_buf(struct kref *ref)
        list_del(&buf->list);
        spin_unlock(&fwc->lock);
 
-       vunmap(buf->data);
-       for (i = 0; i < buf->nr_pages; i++)
-               __free_page(buf->pages[i]);
-       kfree(buf->pages);
+
+       if (buf->fmt == PAGE_BUF) {
+               vunmap(buf->data);
+               for (i = 0; i < buf->nr_pages; i++)
+                       __free_page(buf->pages[i]);
+               kfree(buf->pages);
+       } else
+               vfree(buf->data);
        kfree(buf);
 }
 
@@ -319,6 +266,69 @@ static void fw_free_buf(struct firmware_buf *buf)
        kref_put(&buf->ref, __fw_free_buf);
 }
 
+/* direct firmware loading support */
+static const char *fw_path[] = {
+       "/lib/firmware/updates/" UTS_RELEASE,
+       "/lib/firmware/updates",
+       "/lib/firmware/" UTS_RELEASE,
+       "/lib/firmware"
+};
+
+/* Don't inline this: 'struct kstat' is biggish */
+static noinline long fw_file_size(struct file *file)
+{
+       struct kstat st;
+       if (vfs_getattr(file->f_path.mnt, file->f_path.dentry, &st))
+               return -1;
+       if (!S_ISREG(st.mode))
+               return -1;
+       if (st.size != (long)st.size)
+               return -1;
+       return st.size;
+}
+
+static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf)
+{
+       long size;
+       char *buf;
+
+       size = fw_file_size(file);
+       if (size < 0)
+               return false;
+       buf = vmalloc(size);
+       if (!buf)
+               return false;
+       if (kernel_read(file, 0, buf, size) != size) {
+               vfree(buf);
+               return false;
+       }
+       fw_buf->data = buf;
+       fw_buf->size = size;
+       return true;
+}
+
+static bool fw_get_filesystem_firmware(struct firmware_buf *buf)
+{
+       int i;
+       bool success = false;
+       char *path = __getname();
+
+       for (i = 0; i < ARRAY_SIZE(fw_path); i++) {
+               struct file *file;
+               snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id);
+
+               file = filp_open(path, O_RDONLY, 0);
+               if (IS_ERR(file))
+                       continue;
+               success = fw_read_file_contents(file, buf);
+               fput(file);
+               if (success)
+                       break;
+       }
+       __putname(path);
+       return success;
+}
+
 static struct firmware_priv *to_firmware_priv(struct device *dev)
 {
        return container_of(dev, struct firmware_priv, dev);
@@ -423,6 +433,21 @@ static void firmware_free_data(const struct firmware *fw)
 #ifndef PAGE_KERNEL_RO
 #define PAGE_KERNEL_RO PAGE_KERNEL
 #endif
+
+/* one pages buffer should be mapped/unmapped only once */
+static int fw_map_pages_buf(struct firmware_buf *buf)
+{
+       if (buf->fmt != PAGE_BUF)
+               return 0;
+
+       if (buf->data)
+               vunmap(buf->data);
+       buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
+       if (!buf->data)
+               return -ENOMEM;
+       return 0;
+}
+
 /**
  * firmware_loading_store - set value in the 'loading' control file
  * @dev: device pointer
@@ -467,6 +492,14 @@ static ssize_t firmware_loading_store(struct device *dev,
                if (test_bit(FW_STATUS_LOADING, &fw_buf->status)) {
                        set_bit(FW_STATUS_DONE, &fw_buf->status);
                        clear_bit(FW_STATUS_LOADING, &fw_buf->status);
+
+                       /*
+                        * Several loading requests may be pending on
+                        * one same firmware buf, so let all requests
+                        * see the mapped 'buf->data' once the loading
+                        * is completed.
+                        * */
+                       fw_map_pages_buf(fw_buf);
                        complete_all(&fw_buf->completion);
                        break;
                }
@@ -670,15 +703,6 @@ exit:
        return fw_priv;
 }
 
-/* one pages buffer is mapped/unmapped only once */
-static int fw_map_pages_buf(struct firmware_buf *buf)
-{
-       buf->data = vmap(buf->pages, buf->nr_pages, 0, PAGE_KERNEL_RO);
-       if (!buf->data)
-               return -ENOMEM;
-       return 0;
-}
-
 /* store the pages buffer info firmware from buf */
 static void fw_set_page_data(struct firmware_buf *buf, struct firmware *fw)
 {
@@ -778,11 +802,6 @@ _request_firmware_prepare(const struct firmware **firmware_p, const char *name,
                return NULL;
        }
 
-       if (fw_get_filesystem_firmware(firmware, name)) {
-               dev_dbg(device, "firmware: direct-loading firmware %s\n", name);
-               return NULL;
-       }
-
        ret = fw_lookup_and_allocate_buf(name, &fw_cache, &buf);
        if (!ret)
                fw_priv = fw_create_instance(firmware, name, device,
@@ -832,6 +851,21 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        struct device *f_dev = &fw_priv->dev;
        struct firmware_buf *buf = fw_priv->buf;
        struct firmware_cache *fwc = &fw_cache;
+       int direct_load = 0;
+
+       /* try direct loading from fs first */
+       if (fw_get_filesystem_firmware(buf)) {
+               dev_dbg(f_dev->parent, "firmware: direct-loading"
+                       " firmware %s\n", buf->fw_id);
+
+               set_bit(FW_STATUS_DONE, &buf->status);
+               complete_all(&buf->completion);
+               direct_load = 1;
+               goto handle_fw;
+       }
+
+       /* fall back on userspace loading */
+       buf->fmt = PAGE_BUF;
 
        dev_set_uevent_suppress(f_dev, true);
 
@@ -870,6 +904,7 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
 
        del_timer_sync(&fw_priv->timeout);
 
+handle_fw:
        mutex_lock(&fw_lock);
        if (!buf->size || test_bit(FW_STATUS_ABORT, &buf->status))
                retval = -ENOENT;
@@ -884,9 +919,6 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        if (!retval && f_dev->parent)
                fw_add_devm_name(f_dev->parent, buf->fw_id);
 
-       if (!retval)
-               retval = fw_map_pages_buf(buf);
-
        /*
         * After caching firmware image is started, let it piggyback
         * on request firmware.
@@ -902,6 +934,9 @@ static int _request_firmware_load(struct firmware_priv *fw_priv, bool uevent,
        fw_priv->buf = NULL;
        mutex_unlock(&fw_lock);
 
+       if (direct_load)
+               goto err_put_dev;
+
        device_remove_file(f_dev, &dev_attr_loading);
 err_del_bin_attr:
        device_remove_bin_file(f_dev, &firmware_attr_data);
@@ -1129,6 +1164,8 @@ int uncache_firmware(const char *fw_name)
 }
 
 #ifdef CONFIG_PM_SLEEP
+static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
+
 static struct fw_cache_entry *alloc_fw_cache_entry(const char *name)
 {
        struct fw_cache_entry *fce;
@@ -1142,17 +1179,27 @@ exit:
        return fce;
 }
 
-static int fw_cache_piggyback_on_request(const char *name)
+static int __fw_entry_found(const char *name)
 {
        struct firmware_cache *fwc = &fw_cache;
        struct fw_cache_entry *fce;
-       int ret = 0;
 
-       spin_lock(&fwc->name_lock);
        list_for_each_entry(fce, &fwc->fw_names, list) {
                if (!strcmp(fce->name, name))
-                       goto found;
+                       return 1;
        }
+       return 0;
+}
+
+static int fw_cache_piggyback_on_request(const char *name)
+{
+       struct firmware_cache *fwc = &fw_cache;
+       struct fw_cache_entry *fce;
+       int ret = 0;
+
+       spin_lock(&fwc->name_lock);
+       if (__fw_entry_found(name))
+               goto found;
 
        fce = alloc_fw_cache_entry(name);
        if (fce) {
@@ -1185,12 +1232,6 @@ static void __async_dev_cache_fw_image(void *fw_entry,
 
                free_fw_cache_entry(fce);
        }
-
-       spin_lock(&fwc->name_lock);
-       fwc->cnt--;
-       spin_unlock(&fwc->name_lock);
-
-       wake_up(&fwc->wait_queue);
 }
 
 /* called with dev->devres_lock held */
@@ -1229,11 +1270,19 @@ static void dev_cache_fw_image(struct device *dev, void *data)
                list_del(&fce->list);
 
                spin_lock(&fwc->name_lock);
-               fwc->cnt++;
-               list_add(&fce->list, &fwc->fw_names);
+               /* only one cache entry for one firmware */
+               if (!__fw_entry_found(fce->name)) {
+                       list_add(&fce->list, &fwc->fw_names);
+               } else {
+                       free_fw_cache_entry(fce);
+                       fce = NULL;
+               }
                spin_unlock(&fwc->name_lock);
 
-               async_schedule(__async_dev_cache_fw_image, (void *)fce);
+               if (fce)
+                       async_schedule_domain(__async_dev_cache_fw_image,
+                                             (void *)fce,
+                                             &fw_cache_domain);
        }
 }
 
@@ -1275,6 +1324,9 @@ static void device_cache_fw_images(void)
 
        pr_debug("%s\n", __func__);
 
+       /* cancel uncache work */
+       cancel_delayed_work_sync(&fwc->work);
+
        /*
         * use small loading timeout for caching devices' firmware
         * because all these firmware images have been loaded
@@ -1292,21 +1344,7 @@ static void device_cache_fw_images(void)
        mutex_unlock(&fw_lock);
 
        /* wait for completion of caching firmware for all devices */
-       spin_lock(&fwc->name_lock);
-       for (;;) {
-               prepare_to_wait(&fwc->wait_queue, &wait,
-                               TASK_UNINTERRUPTIBLE);
-               if (!fwc->cnt)
-                       break;
-
-               spin_unlock(&fwc->name_lock);
-
-               schedule();
-
-               spin_lock(&fwc->name_lock);
-       }
-       spin_unlock(&fwc->name_lock);
-       finish_wait(&fwc->wait_queue, &wait);
+       async_synchronize_full_domain(&fw_cache_domain);
 
        loading_timeout = old_timeout;
 }
@@ -1394,9 +1432,7 @@ static void __init fw_cache_init(void)
 #ifdef CONFIG_PM_SLEEP
        spin_lock_init(&fw_cache.name_lock);
        INIT_LIST_HEAD(&fw_cache.fw_names);
-       fw_cache.cnt = 0;
 
-       init_waitqueue_head(&fw_cache.wait_queue);
        INIT_DELAYED_WORK(&fw_cache.work,
                          device_uncache_fw_images_work);
 
index 8727e9c5eea47dd78170e091635f31d29fc7cb52..72c776f2a1f528db39398a0983ae86730ebf24c1 100644 (file)
@@ -83,9 +83,16 @@ EXPORT_SYMBOL_GPL(platform_get_resource);
  */
 int platform_get_irq(struct platform_device *dev, unsigned int num)
 {
+#ifdef CONFIG_SPARC
+       /* sparc does not have irqs represented as IORESOURCE_IRQ resources */
+       if (!dev || num >= dev->archdata.num_irqs)
+               return -ENXIO;
+       return dev->archdata.irqs[num];
+#else
        struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, num);
 
        return r ? r->start : -ENXIO;
+#endif
 }
 EXPORT_SYMBOL_GPL(platform_get_irq);
 
index c22b869245d9498e7052fdc42ceacf3aaa4e332e..96b71b6536d61cef381dab119533b4a0b13f542e 100644 (file)
@@ -1862,7 +1862,7 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
        cpuidle_drv = cpuidle_driver_ref();
        if (!cpuidle_drv) {
                ret = -ENODEV;
-               goto out;
+               goto err_drv;
        }
        if (cpuidle_drv->state_count <= state) {
                ret = -EINVAL;
@@ -1884,6 +1884,9 @@ int pm_genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
 
  err:
        cpuidle_driver_unref();
+
+ err_drv:
+       kfree(cpu_data);
        goto out;
 }
 
index 74a67e0019a2d246820ccb2858399bca193ff789..fbbd4ed2edf288318f8d165760c91ee420f1812c 100644 (file)
@@ -451,7 +451,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
        if (ancestor)
                error = dev_pm_qos_add_request(ancestor, req, value);
 
-       if (error)
+       if (error < 0)
                req->dev = NULL;
 
        return error;
index 6be390bd8bd1bc3f0fa1e3bfc38cd56f36bfa6be..f0d30543fcce0944d3e619031ea0a828a179e852 100644 (file)
@@ -3,7 +3,7 @@
 # subsystems should select the appropriate symbols.
 
 config REGMAP
-       default y if (REGMAP_I2C || REGMAP_SPI)
+       default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_MMIO || REGMAP_IRQ)
        select LZO_COMPRESS
        select LZO_DECOMPRESS
        select IRQ_DOMAIN if REGMAP_IRQ
index f529407db93ff74dbfa8b9dad13324815467fad2..824e09c4d0d7d1bcd83a00b87e37e1ca0115d5fb 100644 (file)
@@ -131,6 +131,7 @@ config BLK_CPQ_DA
 config BLK_CPQ_CISS_DA
        tristate "Compaq Smart Array 5xxx support"
        depends on PCI
+       select CHECK_SIGNATURE
        help
          This is the driver for Compaq Smart Array 5xxx controllers.
          Everyone using these boards should say Y here.
@@ -166,8 +167,8 @@ config BLK_DEV_DAC960
          module will be called DAC960.
 
 config BLK_DEV_UMEM
-       tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)"
-       depends on PCI && EXPERIMENTAL
+       tristate "Micro Memory MM5415 Battery Backed RAM support"
+       depends on PCI
        ---help---
          Saying Y here will include support for the MM5415 family of
          battery backed (Non-volatile) RAM cards.
@@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS
          a disc is opened for writing.
 
 config CDROM_PKTCDVD_WCACHE
-       bool "Enable write caching (EXPERIMENTAL)"
-       depends on CDROM_PKTCDVD && EXPERIMENTAL
+       bool "Enable write caching"
+       depends on CDROM_PKTCDVD
        help
          If enabled, write caching will be set for the CD-R/W device. For now
          this option is dangerous unless the CD-RW media is known good, as we
@@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND
 
 
 config VIRTIO_BLK
-       tristate "Virtio block driver (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && VIRTIO
+       tristate "Virtio block driver"
+       depends on VIRTIO
        ---help---
          This is the virtual block driver for virtio.  It can be used with
           lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M.
@@ -528,7 +529,7 @@ config BLK_DEV_HD
 
 config BLK_DEV_RBD
        tristate "Rados block device (RBD)"
-       depends on INET && EXPERIMENTAL && BLOCK
+       depends on INET && BLOCK
        select CEPH_LIB
        select LIBCRC32C
        select CRYPTO_AES
index 3804a0af3ef192c441643eee425d06f747b86d97..9fe4f1865558abce9ccd7ebf1ee10a56284caf61 100644 (file)
@@ -935,7 +935,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
 
        /* cf. http://lkml.org/lkml/2006/10/31/28 */
        if (!fastfail)
-               q->request_fn(q);
+               __blk_run_queue(q);
 }
 
 static void
index b0f553b26d0f8d00f86f768f93aad27ebcb0529e..ca83f96756ad86b2a339971050b7378f9a9752d9 100644 (file)
@@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)
                return;
        }
        /* write all data in the battery backed cache to disk */
-       memset(flush_buf, 0, 4);
        return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,
                4, 0, CTLR_LUNID, TYPE_CMD);
        kfree(flush_buf);
index 17c675c522954cc39a210e431603aac2a3a2d946..2ddd64a9ffdee43429653806be3262a80c372240 100644 (file)
@@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {
 
 static struct platform_device floppy_device[N_DRIVE];
 
+static bool floppy_available(int drive)
+{
+       if (!(allowed_drive_mask & (1 << drive)))
+               return false;
+       if (fdc_state[FDC(drive)].version == FDC_NONE)
+               return false;
+       return true;
+}
+
 static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 {
        int drive = (*part & 3) | ((*part & 0x80) >> 5);
-       if (drive >= N_DRIVE ||
-           !(allowed_drive_mask & (1 << drive)) ||
-           fdc_state[FDC(drive)].version == FDC_NONE)
+       if (drive >= N_DRIVE || !floppy_available(drive))
                return NULL;
        if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))
                return NULL;
@@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
 
 static int __init do_floppy_init(void)
 {
-       int i, unit, drive;
-       int err, dr;
+       int i, unit, drive, err;
 
        set_debugt();
        interruptjiffies = resultjiffies = jiffies;
@@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)
 
        raw_cmd = NULL;
 
-       for (dr = 0; dr < N_DRIVE; dr++) {
-               disks[dr] = alloc_disk(1);
-               if (!disks[dr]) {
-                       err = -ENOMEM;
-                       goto out_put_disk;
-               }
+       floppy_wq = alloc_ordered_workqueue("floppy", 0);
+       if (!floppy_wq)
+               return -ENOMEM;
 
-               floppy_wq = alloc_ordered_workqueue("floppy", 0);
-               if (!floppy_wq) {
+       for (drive = 0; drive < N_DRIVE; drive++) {
+               disks[drive] = alloc_disk(1);
+               if (!disks[drive]) {
                        err = -ENOMEM;
                        goto out_put_disk;
                }
 
-               disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock);
-               if (!disks[dr]->queue) {
+               disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock);
+               if (!disks[drive]->queue) {
                        err = -ENOMEM;
-                       goto out_destroy_workq;
+                       goto out_put_disk;
                }
 
-               blk_queue_max_hw_sectors(disks[dr]->queue, 64);
-               disks[dr]->major = FLOPPY_MAJOR;
-               disks[dr]->first_minor = TOMINOR(dr);
-               disks[dr]->fops = &floppy_fops;
-               sprintf(disks[dr]->disk_name, "fd%d", dr);
+               blk_queue_max_hw_sectors(disks[drive]->queue, 64);
+               disks[drive]->major = FLOPPY_MAJOR;
+               disks[drive]->first_minor = TOMINOR(drive);
+               disks[drive]->fops = &floppy_fops;
+               sprintf(disks[drive]->disk_name, "fd%d", drive);
 
-               init_timer(&motor_off_timer[dr]);
-               motor_off_timer[dr].data = dr;
-               motor_off_timer[dr].function = motor_off_callback;
+               init_timer(&motor_off_timer[drive]);
+               motor_off_timer[drive].data = drive;
+               motor_off_timer[drive].function = motor_off_callback;
        }
 
        err = register_blkdev(FLOPPY_MAJOR, "fd");
@@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)
        }
 
        for (drive = 0; drive < N_DRIVE; drive++) {
-               if (!(allowed_drive_mask & (1 << drive)))
-                       continue;
-               if (fdc_state[FDC(drive)].version == FDC_NONE)
+               if (!floppy_available(drive))
                        continue;
 
                floppy_device[drive].name = floppy_device_name;
@@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)
 
                err = platform_device_register(&floppy_device[drive]);
                if (err)
-                       goto out_release_dma;
+                       goto out_remove_drives;
 
                err = device_create_file(&floppy_device[drive].dev,
                                         &dev_attr_cmos);
@@ -4311,28 +4313,33 @@ static int __init do_floppy_init(void)
 
 out_unreg_platform_dev:
        platform_device_unregister(&floppy_device[drive]);
+out_remove_drives:
+       while (drive--) {
+               if (floppy_available(drive)) {
+                       del_gendisk(disks[drive]);
+                       device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
+                       platform_device_unregister(&floppy_device[drive]);
+               }
+       }
 out_release_dma:
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
 out_unreg_region:
        blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
        platform_driver_unregister(&floppy_driver);
-out_destroy_workq:
-       destroy_workqueue(floppy_wq);
 out_unreg_blkdev:
        unregister_blkdev(FLOPPY_MAJOR, "fd");
 out_put_disk:
-       while (dr--) {
-               del_timer_sync(&motor_off_timer[dr]);
-               if (disks[dr]->queue) {
-                       blk_cleanup_queue(disks[dr]->queue);
-                       /*
-                        * put_disk() is not paired with add_disk() and
-                        * will put queue reference one extra time. fix it.
-                        */
-                       disks[dr]->queue = NULL;
+       destroy_workqueue(floppy_wq);
+       for (drive = 0; drive < N_DRIVE; drive++) {
+               if (!disks[drive])
+                       break;
+               if (disks[drive]->queue) {
+                       del_timer_sync(&motor_off_timer[drive]);
+                       blk_cleanup_queue(disks[drive]->queue);
+                       disks[drive]->queue = NULL;
                }
-               put_disk(disks[dr]);
+               put_disk(disks[drive]);
        }
        return err;
 }
@@ -4548,11 +4555,12 @@ static void __exit floppy_module_exit(void)
        unregister_blkdev(FLOPPY_MAJOR, "fd");
        platform_driver_unregister(&floppy_driver);
 
+       destroy_workqueue(floppy_wq);
+
        for (drive = 0; drive < N_DRIVE; drive++) {
                del_timer_sync(&motor_off_timer[drive]);
 
-               if ((allowed_drive_mask & (1 << drive)) &&
-                   fdc_state[FDC(drive)].version != FDC_NONE) {
+               if (floppy_available(drive)) {
                        del_gendisk(disks[drive]);
                        device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);
                        platform_device_unregister(&floppy_device[drive]);
@@ -4572,7 +4580,6 @@ static void __exit floppy_module_exit(void)
 
        cancel_delayed_work_sync(&fd_timeout);
        cancel_delayed_work_sync(&fd_timer);
-       destroy_workqueue(floppy_wq);
 
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
index e9d594fd12cbee408251c4ead03d1b71183ff7ae..54046e51160aef28e3ee733797fa453a0403a02a 100644 (file)
@@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
 
-       if (lo->lo_refcnt > 1)  /* we needed one fd for the ioctl */
-               return -EBUSY;
+       /*
+        * If we've explicitly asked to tear down the loop device,
+        * and it has an elevated reference count, set it for auto-teardown when
+        * the last reference goes away. This stops $!~#$@ udev from
+        * preventing teardown because it decided that it needs to run blkid on
+        * the loopback device whenever they appear. xfstests is notorious for
+        * failing tests because blkid via udev races with a losetup
+        * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d
+        * command to fail with EBUSY.
+        */
+       if (lo->lo_refcnt > 1) {
+               lo->lo_flags |= LO_FLAGS_AUTOCLEAR;
+               mutex_unlock(&lo->lo_ctl_mutex);
+               return 0;
+       }
 
        if (filp == NULL)
                return -EINVAL;
index f946d31d6917e00aa0637df5d21cef35ebf82845..9694dd99bbbc7253af1c3626823899f985b1afc2 100644 (file)
@@ -559,7 +559,7 @@ static void mtip_timeout_function(unsigned long int data)
        struct mtip_cmd *command;
        int tag, cmdto_cnt = 0;
        unsigned int bit, group;
-       unsigned int num_command_slots = port->dd->slot_groups * 32;
+       unsigned int num_command_slots;
        unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
 
        if (unlikely(!port))
@@ -572,6 +572,7 @@ static void mtip_timeout_function(unsigned long int data)
        }
        /* clear the tag accumulator */
        memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+       num_command_slots = port->dd->slot_groups * 32;
 
        for (tag = 0; tag < num_command_slots; tag++) {
                /*
@@ -2035,8 +2036,9 @@ static unsigned int implicit_sector(unsigned char command,
        }
        return rv;
 }
-
-static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
+static void mtip_set_timeout(struct driver_data *dd,
+                                       struct host_to_dev_fis *fis,
+                                       unsigned int *timeout, u8 erasemode)
 {
        switch (fis->command) {
        case ATA_CMD_DOWNLOAD_MICRO:
@@ -2044,7 +2046,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
                break;
        case ATA_CMD_SEC_ERASE_UNIT:
        case 0xFC:
-               *timeout = 240000; /* 4 minutes */
+               if (erasemode)
+                       *timeout = ((*(dd->port->identify + 90) * 2) * 60000);
+               else
+                       *timeout = ((*(dd->port->identify + 89) * 2) * 60000);
                break;
        case ATA_CMD_STANDBYNOW1:
                *timeout = 120000;  /* 2 minutes */
@@ -2087,6 +2092,7 @@ static int exec_drive_taskfile(struct driver_data *dd,
        unsigned int transfer_size;
        unsigned long task_file_data;
        int intotal = outtotal + req_task->out_size;
+       int erasemode = 0;
 
        taskout = req_task->out_size;
        taskin = req_task->in_size;
@@ -2212,7 +2218,13 @@ static int exec_drive_taskfile(struct driver_data *dd,
                fis.lba_hi,
                fis.device);
 
-       mtip_set_timeout(&fis, &timeout);
+       /* check for erase mode support during secure erase.*/
+       if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) && outbuf &&
+                                       (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
+               erasemode = 1;
+       }
+
+       mtip_set_timeout(dd, &fis, &timeout, erasemode);
 
        /* Determine the correct transfer size.*/
        if (force_single_sector)
@@ -2428,7 +2440,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
  * return value
  *     None
  */
-static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
+static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
                              int nsect, int nents, int tag, void *callback,
                              void *data, int dir)
 {
@@ -2436,6 +2448,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        struct mtip_port *port = dd->port;
        struct mtip_cmd *command = &port->commands[tag];
        int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+       u64 start = sector;
 
        /* Map the scatter list for DMA access */
        nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
@@ -2454,8 +2467,12 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        fis->opts        = 1 << 7;
        fis->command     =
                (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE);
-       *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
-       *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
+       fis->lba_low     = start & 0xFF;
+       fis->lba_mid     = (start >> 8) & 0xFF;
+       fis->lba_hi      = (start >> 16) & 0xFF;
+       fis->lba_low_ex  = (start >> 24) & 0xFF;
+       fis->lba_mid_ex  = (start >> 32) & 0xFF;
+       fis->lba_hi_ex   = (start >> 40) & 0xFF;
        fis->device      = 1 << 6;
        fis->features    = nsect & 0xFF;
        fis->features_ex = (nsect >> 8) & 0xFF;
index 18627a1d04c59eff34f7cdd2313555b10a75b283..b1742640556a782cee77701c78c4ddf7e961591a 100644 (file)
@@ -33,6 +33,9 @@
 /* offset of Device Control register in PCIe extended capabilites space */
 #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET  0x48
 
+/* check for erase mode support during secure erase */
+#define MTIP_SEC_ERASE_MODE     0x2
+
 /* # of times to retry timed out/failed IOs */
 #define MTIP_MAX_RETRIES       2
 
@@ -152,14 +155,14 @@ enum {
        MTIP_DDF_REBUILD_FAILED_BIT = 8,
 };
 
-__packed struct smart_attr{
+struct smart_attr {
        u8 attr_id;
        u16 flags;
        u8 cur;
        u8 worst;
        u32 data;
        u8 res[3];
-};
+} __packed;
 
 /* Register Frame Information Structure (FIS), host to device. */
 struct host_to_dev_fis {
index 9ad3b5ec1dc1c521085db47a7928cc8cf1179701..9a54623e52d74ecc77953937bd923a9ecdb68d09 100644 (file)
@@ -158,8 +158,8 @@ struct xen_vbd {
        struct block_device     *bdev;
        /* Cached size parameter. */
        sector_t                size;
-       bool                    flush_support;
-       bool                    discard_secure;
+       unsigned int            flush_support:1;
+       unsigned int            discard_secure:1;
 };
 
 struct backend_info;
index 4f66171c668354b490f1284aec48278b8676bd84..f58434c2617cab4185b8c049804f1031f4226a6e 100644 (file)
@@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
 {
        struct xen_blkif *blkif;
 
-       blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL);
+       blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);
        if (!blkif)
                return ERR_PTR(-ENOMEM);
 
-       memset(blkif, 0, sizeof(*blkif));
        blkif->domid = domid;
        spin_lock_init(&blkif->blk_ring_lock);
        atomic_set(&blkif->refcnt, 1);
@@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)
        }
 }
 
-void xen_blkif_free(struct xen_blkif *blkif)
+static void xen_blkif_free(struct xen_blkif *blkif)
 {
        if (!atomic_dec_and_test(&blkif->refcnt))
                BUG();
@@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {
 VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);
 VBD_SHOW(mode, "%s\n", be->mode);
 
-int xenvbd_sysfs_addif(struct xenbus_device *dev)
+static int xenvbd_sysfs_addif(struct xenbus_device *dev)
 {
        int error;
 
@@ -281,7 +280,7 @@ fail1:      device_remove_file(&dev->dev, &dev_attr_physical_device);
        return error;
 }
 
-void xenvbd_sysfs_delif(struct xenbus_device *dev)
+static void xenvbd_sysfs_delif(struct xenbus_device *dev)
 {
        sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);
        device_remove_file(&dev->dev, &dev_attr_mode);
index ff63560b8467962ae781d5c3d6b64c122129a390..0c48b0e05ed6e7165a221399822e894e09c9fa18 100644 (file)
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/omap_ocp2scp.h>
+
+/**
+ * _count_resources - count for the number of resources
+ * @res: struct resource *
+ *
+ * Count and return the number of resources populated for the device that is
+ * connected to ocp2scp.
+ */
+static unsigned _count_resources(struct resource *res)
+{
+       int cnt = 0;
+
+       while (res->start != res->end) {
+               cnt++;
+               res++;
+       }
+
+       return cnt;
+}
 
 static int ocp2scp_remove_devices(struct device *dev, void *c)
 {
@@ -34,20 +54,62 @@ static int ocp2scp_remove_devices(struct device *dev, void *c)
 
 static int __devinit omap_ocp2scp_probe(struct platform_device *pdev)
 {
-       int                     ret;
-       struct device_node      *np = pdev->dev.of_node;
+       int ret;
+       unsigned res_cnt, i;
+       struct device_node *np = pdev->dev.of_node;
+       struct platform_device *pdev_child;
+       struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data;
+       struct omap_ocp2scp_dev *dev;
 
        if (np) {
                ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
                if (ret) {
-                       dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n");
+                       dev_err(&pdev->dev,
+                           "failed to add resources for ocp2scp child\n");
                        goto err0;
                }
+       } else if (pdata) {
+               for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++,
+                   dev++) {
+                       res_cnt = _count_resources(dev->res);
+
+                       pdev_child = platform_device_alloc(dev->drv_name,
+                           PLATFORM_DEVID_AUTO);
+                       if (!pdev_child) {
+                               dev_err(&pdev->dev,
+                                 "failed to allocate mem for ocp2scp child\n");
+                               goto err0;
+                       }
+
+                       ret = platform_device_add_resources(pdev_child,
+                           dev->res, res_cnt);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                "failed to add resources for ocp2scp child\n");
+                               goto err1;
+                       }
+
+                       pdev_child->dev.parent  = &pdev->dev;
+
+                       ret = platform_device_add(pdev_child);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                  "failed to register ocp2scp child device\n");
+                               goto err1;
+                       }
+               }
+       } else {
+               dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n");
+               return -EINVAL;
        }
+
        pm_runtime_enable(&pdev->dev);
 
        return 0;
 
+err1:
+       platform_device_put(pdev_child);
+
 err0:
        device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
 
index d0b27a39f1d48cee2c994797805bd33941a7e2e6..7ff1d0d208a7c3f89f6827fd3e9ba8815dad202d 100644 (file)
@@ -52,7 +52,6 @@ obj-$(CONFIG_TELCLOCK)                += tlclk.o
 obj-$(CONFIG_MWAVE)            += mwave/
 obj-$(CONFIG_AGP)              += agp/
 obj-$(CONFIG_PCMCIA)           += pcmcia/
-obj-$(CONFIG_IPMI_HANDLER)     += ipmi/
 
 obj-$(CONFIG_HANGCHECK_TIMER)  += hangcheck-timer.o
 obj-$(CONFIG_TCG_TPM)          += tpm/
index e01f5eaaec82a9317724c90337d9d8e45da1bb39..38390f7c6ab679ef3ed3ce0c4f9e28b7fa1e11b5 100644 (file)
@@ -667,7 +667,7 @@ static int intel_gtt_init(void)
        gtt_map_size = intel_private.base.gtt_total_entries * 4;
 
        intel_private.gtt = NULL;
-       if (INTEL_GTT_GEN < 6)
+       if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2)
                intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr,
                                               gtt_map_size);
        if (intel_private.gtt == NULL)
index 2c29942b132654747af55e6b70ea4857dc9e0de4..a0c84bb30856073aa7a46c52690f163789bbd9bc 100644 (file)
@@ -1880,7 +1880,7 @@ int ipmi_request_supply_msgs(ipmi_user_t          user,
                             struct ipmi_recv_msg *supplied_recv,
                             int                  priority)
 {
-       unsigned char saddr, lun;
+       unsigned char saddr = 0, lun = 0;
        int           rv;
 
        if (!user)
index 83f85cf7fb1b424afd4dde0b104af0ea21a51f7b..32a6c7e256bd82496f7461999a7ea3408342f423 100644 (file)
@@ -2424,6 +2424,38 @@ static void ipmi_pci_cleanup(struct smi_info *info)
        pci_disable_device(pdev);
 }
 
+static int __devinit ipmi_pci_probe_regspacing(struct smi_info *info)
+{
+       if (info->si_type == SI_KCS) {
+               unsigned char   status;
+               int             regspacing;
+
+               info->io.regsize = DEFAULT_REGSIZE;
+               info->io.regshift = 0;
+               info->io_size = 2;
+               info->handlers = &kcs_smi_handlers;
+
+               /* detect 1, 4, 16byte spacing */
+               for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) {
+                       info->io.regspacing = regspacing;
+                       if (info->io_setup(info)) {
+                               dev_err(info->dev,
+                                       "Could not setup I/O space\n");
+                               return DEFAULT_REGSPACING;
+                       }
+                       /* write invalid cmd */
+                       info->io.outputb(&info->io, 1, 0x10);
+                       /* read status back */
+                       status = info->io.inputb(&info->io, 1);
+                       info->io_cleanup(info);
+                       if (status)
+                               return regspacing;
+                       regspacing *= 4;
+               }
+       }
+       return DEFAULT_REGSPACING;
+}
+
 static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
 {
@@ -2476,8 +2508,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
        }
        info->io.addr_data = pci_resource_start(pdev, 0);
 
-       info->io.regspacing = DEFAULT_REGSPACING;
-       info->io.regsize = DEFAULT_REGSPACING;
+       info->io.regspacing = ipmi_pci_probe_regspacing(info);
+       info->io.regsize = DEFAULT_REGSIZE;
        info->io.regshift = 0;
 
        info->irq = pdev->irq;
index 320debbe32faf74032f5117cfaf461cbd65a63a3..9b4f0116ff21c95d73d2ad2da39d7fb40dc24ee8 100644 (file)
@@ -1456,7 +1456,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int old_camera_power;
 
 static int sonypi_suspend(struct device *dev)
index ca4a25ed844c379315c2834dcd239c4b9d50940d..e2c17d187d98b7bb09fe4252258641bbd424a1c5 100644 (file)
@@ -40,7 +40,7 @@ void u8500_clk_init(void)
                                CLK_IS_ROOT|CLK_IGNORE_UNUSED,
                                32768);
        clk_register_clkdev(clk, "clk32k", NULL);
-       clk_register_clkdev(clk, NULL, "rtc-pl031");
+       clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
 
        /* PRCMU clocks */
        fw_version = prcmu_get_fw_version();
@@ -228,10 +228,17 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE,
                                BIT(2), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
+
        clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE,
                                BIT(3), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp0");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0");
+
        clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE,
                                BIT(4), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp1");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1");
 
        clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE,
                                BIT(5), 0);
@@ -239,6 +246,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE,
                                BIT(6), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
 
        clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE,
                                BIT(7), 0);
@@ -246,6 +254,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE,
                                BIT(8), 0);
+       clk_register_clkdev(clk, "apb_pclk", "slimbus0");
 
        clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE,
                                BIT(9), 0);
@@ -255,11 +264,16 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE,
                                BIT(10), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
+
        clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE,
                                BIT(11), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp3");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3");
 
        clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE,
                                BIT(0), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
 
        clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE,
                                BIT(1), 0);
@@ -279,12 +293,13 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE,
                                BIT(5), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp2");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2");
 
        clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE,
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi1");
 
-
        clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE,
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi3");
@@ -316,10 +331,15 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE,
                                BIT(1), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ssp0");
+
        clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE,
                                BIT(2), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ssp1");
+
        clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE,
                                BIT(3), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
 
        clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE,
                                BIT(4), 0);
@@ -401,10 +421,17 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
+
        clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
                        U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp0");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0");
+
        clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
                        U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp1");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1");
 
        clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
                        U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE);
@@ -412,17 +439,25 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.2");
+
        clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
-       /* FIXME: Redefinition of BIT(3). */
+                       U8500_CLKRST1_BASE, BIT(8), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "slimbus0");
+
        clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.4");
+
        clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
                        U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp3");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3");
 
        /* Periph2 */
        clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
                        U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.3");
 
        clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
                        U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE);
@@ -430,6 +465,8 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
                        U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp2");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2");
 
        clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
                        U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE);
@@ -450,10 +487,15 @@ void u8500_clk_init(void)
        /* Periph3 */
        clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
                        U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ssp0");
+
        clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
                        U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ssp1");
+
        clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
                        U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
 
        clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
                        U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE);
index b40ee1403be9b657ffcabd5142650ddb926fb367..399831690fedc18a263636a89725ec7b9af7dadb 100644 (file)
@@ -328,6 +328,7 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
                cpufreq_update_policy(cpu);
                break;
        case CPU_DOWN_PREPARE:
+       case CPU_DOWN_PREPARE_FROZEN:
                cpufreq_stats_free_sysfs(cpu);
                break;
        case CPU_DEAD:
index 129e80bfff22e1d399fbe5320012f5721de1bcaf..e3ebb4fa2c3e5045c04f6b0b864a4499064fcbff 100644 (file)
@@ -5,7 +5,7 @@
  *  http://www.gnu.org/licenses/gpl.html
  *
  *  Maintainer:
- *  Andreas Herrmann <andreas.herrmann3@amd.com>
+ *  Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *  Based on the powernow-k7.c module written by Dave Jones.
  *  (C) 2003 Dave Jones on behalf of SuSE Labs
@@ -1052,14 +1052,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
        struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
                                             .relation = relation };
 
-       /*
-        * Must run on @pol->cpu.  cpufreq core is responsible for ensuring
-        * that we're bound to the current CPU and pol->cpu stays online.
-        */
-       if (smp_processor_id() == pol->cpu)
-               return powernowk8_target_fn(&pta);
-       else
-               return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
+       return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
 }
 
 /* Driver entry point to verify the policy and range of frequencies */
index 677cd6e4e1a1c1afb387217fdc9f0f363c3149cf..d4c12180c65416043dbbf3940374ad146daad881 100644 (file)
@@ -90,6 +90,17 @@ config DW_DMAC
          Support the Synopsys DesignWare AHB DMA controller.  This
          can be integrated in chips such as the Atmel AT32ap7000.
 
+config DW_DMAC_BIG_ENDIAN_IO
+       bool "Use big endian I/O register access"
+       default y if AVR32
+       depends on DW_DMAC
+       help
+         Say yes here to use big endian I/O access when reading and writing
+         to the DMA controller registers. This is needed on some platforms,
+         like the Atmel AVR32 architecture.
+
+         If unsure, use the default setting.
+
 config AT_HDMAC
        tristate "Atmel AHB DMA support"
        depends on ARCH_AT91
index ff39fa6cd2bc443a7d96fd9d85be015f643704f5..88965597b7d08c9e2b9987957f85284cc9851f4c 100644 (file)
@@ -98,9 +98,17 @@ struct dw_dma_regs {
        u32     DW_PARAMS;
 };
 
+#ifdef CONFIG_DW_DMAC_BIG_ENDIAN_IO
+#define dma_readl_native ioread32be
+#define dma_writel_native iowrite32be
+#else
+#define dma_readl_native readl
+#define dma_writel_native writel
+#endif
+
 /* To access the registers in early stage of probe */
 #define dma_read_byaddr(addr, name) \
-       readl((addr) + offsetof(struct dw_dma_regs, name))
+       dma_readl_native((addr) + offsetof(struct dw_dma_regs, name))
 
 /* Bitfields in DW_PARAMS */
 #define DW_PARAMS_NR_CHAN      8               /* number of channels */
@@ -216,9 +224,9 @@ __dwc_regs(struct dw_dma_chan *dwc)
 }
 
 #define channel_readl(dwc, name) \
-       readl(&(__dwc_regs(dwc)->name))
+       dma_readl_native(&(__dwc_regs(dwc)->name))
 #define channel_writel(dwc, name, val) \
-       writel((val), &(__dwc_regs(dwc)->name))
+       dma_writel_native((val), &(__dwc_regs(dwc)->name))
 
 static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
 {
@@ -246,9 +254,9 @@ static inline struct dw_dma_regs __iomem *__dw_regs(struct dw_dma *dw)
 }
 
 #define dma_readl(dw, name) \
-       readl(&(__dw_regs(dw)->name))
+       dma_readl_native(&(__dw_regs(dw)->name))
 #define dma_writel(dw, name, val) \
-       writel((val), &(__dw_regs(dw)->name))
+       dma_writel_native((val), &(__dw_regs(dw)->name))
 
 #define channel_set_bit(dw, reg, mask) \
        dma_writel(dw, reg, ((mask) << 8) | (mask))
index f11b5b2b1a1c1e41274ed7578ba197971e209f5a..7d9554cc4976313c90604eacecf4b78227a860f7 100644 (file)
@@ -474,8 +474,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d)
                        slot = i;
                        break;
                }
-               if (slot < 0)
+               if (slot < 0) {
+                       spin_unlock_irqrestore(&imxdma->lock, flags);
                        return -EBUSY;
+               }
 
                imxdma->slots_2d[slot].xsr = d->x;
                imxdma->slots_2d[slot].ysr = d->y;
index abd9038e06b1351ab7706c81fcbd96e8dbf2eebd..d6668071bd0d4cfca02996978818d65a62ce7630 100644 (file)
@@ -604,6 +604,23 @@ static int ioat3_dca_count_dca_slots(void *iobase, u16 dca_offset)
        return slots;
 }
 
+static inline int dca3_tag_map_invalid(u8 *tag_map)
+{
+       /*
+        * If the tag map is not programmed by the BIOS the default is:
+        * 0x80 0x80 0x80 0x80 0x80 0x00 0x00 0x00
+        *
+        * This an invalid map and will result in only 2 possible tags
+        * 0x1F and 0x00.  0x00 is an invalid DCA tag so we know that
+        * this entire definition is invalid.
+        */
+       return ((tag_map[0] == DCA_TAG_MAP_VALID) &&
+               (tag_map[1] == DCA_TAG_MAP_VALID) &&
+               (tag_map[2] == DCA_TAG_MAP_VALID) &&
+               (tag_map[3] == DCA_TAG_MAP_VALID) &&
+               (tag_map[4] == DCA_TAG_MAP_VALID));
+}
+
 struct dca_provider * __devinit
 ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
 {
@@ -674,6 +691,12 @@ ioat3_dca_init(struct pci_dev *pdev, void __iomem *iobase)
                ioatdca->tag_map[i] = bit & DCA_TAG_MAP_MASK;
        }
 
+       if (dca3_tag_map_invalid(ioatdca->tag_map)) {
+               dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, disabling DCA\n");
+               free_dca_provider(dca);
+               return NULL;
+       }
+
        err = register_dca_provider(dca, &pdev->dev);
        if (err) {
                free_dca_provider(dca);
index 64385cde044b3feefcc49001edbf0e9ee647bd0d..d451caace806445428c40d3f4d5678ada4a0925d 100644 (file)
@@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan)
        sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc,
                node);
        /* Move the first queued descriptor to active list */
-       list_move_tail(&schan->queued, &schan->active);
+       list_move_tail(&sdesc->node, &schan->active);
 
        /* Start the DMA transfer */
        writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 +
@@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved(
        unsigned long iflags;
        int ret;
 
-       if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) {
+       if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) {
                ret = -EINVAL;
                goto err_dir;
        }
index 5a297a26211d622b0f0ceedb0389fcbeb4223baf..cc8e7c78a23ca22972bfa570dc88d1fcf449e979 100644 (file)
@@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
         * memory controller and apply to register. Search for the first
         * bandwidth entry that is greater or equal than the setting requested
         * and program that. If at last entry, turn off DRAM scrubbing.
+        *
+        * If no suitable bandwidth is found, turn off DRAM scrubbing entirely
+        * by falling back to the last element in scrubrates[].
         */
-       for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
+       for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) {
                /*
                 * skip scrub rates which aren't recommended
                 * (see F10 BKDG, F3x58)
@@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate)
 
                if (scrubrates[i].bandwidth <= new_bw)
                        break;
-
-               /*
-                * if no suitable bandwidth found, turn off DRAM scrubbing
-                * entirely by falling back to the last element in the
-                * scrubrates array.
-                */
        }
 
        scrubval = scrubrates[i].scrubval;
index 8d4804732bacb77be17f07465e48f24ea513ab0c..8c4139647efc06acf50528a8d66f1e09995cc4cc 100644 (file)
@@ -33,7 +33,7 @@
  *             detection. The mods to Rev F required more family
  *             information detection.
  *
- *     Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>:
+ *     Changes/Fixes by Borislav Petkov <bp@alien8.de>:
  *             - misc fixes and code cleanups
  *
  * This module is based on the following documents
index 6c86f6e545587202d3a9f729457ef38314490f70..351945fa2ecdca3f59a691db38206a0f13795797 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 2007 (c) MontaVista Software, Inc.
  * 2010 (c) Advanced Micro Devices Inc.
- *         Borislav Petkov <borislav.petkov@amd.com>
+ *         Borislav Petkov <bp@alien8.de>
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
index 66b5151c10807083e1e724cb58cc384cdde2f11c..2ae78f20cc28f3850cc26a9156927c7b4e8b085e 100644 (file)
@@ -6,7 +6,7 @@
  * This file may be distributed under the terms of the GNU General Public
  * License version 2.
  *
- * Copyright (c) 2010:  Borislav Petkov <borislav.petkov@amd.com>
+ * Copyright (c) 2010:  Borislav Petkov <bp@alien8.de>
  *                     Advanced Micro Devices Inc.
  */
 
@@ -168,6 +168,6 @@ module_init(edac_init_mce_inject);
 module_exit(edac_exit_mce_inject);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>");
 MODULE_AUTHOR("AMD Inc.");
 MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
index 725eb5aa8d8cb670d0e104d48557fb866947a20a..e87196f6d2d2db43f945e6317b3d14fe09e680f4 100644 (file)
@@ -14,6 +14,7 @@
  *
  */
 
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
@@ -161,13 +162,12 @@ static int __devinit adc_jack_probe(struct platform_device *pdev)
        err = request_any_context_irq(data->irq, adc_jack_irq_thread,
                        pdata->irq_flags, pdata->name, data);
 
-       if (err) {
+       if (err < 0) {
                dev_err(&pdev->dev, "error: irq %d\n", data->irq);
-               err = -EINVAL;
                goto err_irq;
        }
 
-       goto out;
+       return 0;
 
 err_irq:
        extcon_dev_unregister(&data->edev);
@@ -196,3 +196,7 @@ static struct platform_driver adc_jack_driver = {
 };
 
 module_platform_driver(adc_jack_driver);
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("ADC Jack extcon driver");
+MODULE_LICENSE("GPL v2");
index 946a3188b2b78a4014f84e93588e8423c41501c0..d398821097f35f181c7ad554360a127de13496d5 100644 (file)
@@ -41,7 +41,7 @@
  * every single port-type of the following cable names. Please choose cable
  * names that are actually used in your extcon device.
  */
-const char *extcon_cable_name[] = {
+const char extcon_cable_name[][CABLE_NAME_MAX + 1] = {
        [EXTCON_USB]            = "USB",
        [EXTCON_USB_HOST]       = "USB-Host",
        [EXTCON_TA]             = "TA",
@@ -62,8 +62,6 @@ const char *extcon_cable_name[] = {
        [EXTCON_VIDEO_IN]       = "Video-in",
        [EXTCON_VIDEO_OUT]      = "Video-out",
        [EXTCON_MECHANICAL]     = "Mechanical",
-
-       NULL,
 };
 
 static struct class *extcon_class;
@@ -91,17 +89,13 @@ static int check_mutually_exclusive(struct extcon_dev *edev, u32 new_state)
                return 0;
 
        for (i = 0; edev->mutually_exclusive[i]; i++) {
-               int count = 0, j;
+               int weight;
                u32 correspondants = new_state & edev->mutually_exclusive[i];
-               u32 exp = 1;
-
-               for (j = 0; j < 32; j++) {
-                       if (exp & correspondants)
-                               count++;
-                       if (count > 1)
-                               return i + 1;
-                       exp <<= 1;
-               }
+
+               /* calculate the total number of bits set */
+               weight = hweight32(correspondants);
+               if (weight > 1)
+                       return i + 1;
        }
 
        return 0;
@@ -362,7 +356,7 @@ int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
 EXPORT_SYMBOL_GPL(extcon_get_cable_state);
 
 /**
- * extcon_get_cable_state_() - Set the status of a specific cable.
+ * extcon_set_cable_state_() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @index:     cable index that can be retrieved by extcon_find_cable_index().
  * @cable_state:       the new cable status. The default semantics is
@@ -382,7 +376,7 @@ int extcon_set_cable_state_(struct extcon_dev *edev,
 EXPORT_SYMBOL_GPL(extcon_set_cable_state_);
 
 /**
- * extcon_get_cable_state() - Set the status of a specific cable.
+ * extcon_set_cable_state() - Set the status of a specific cable.
  * @edev:      the extcon device that has the cable.
  * @cable_name:        cable name.
  * @cable_state:       the new cable status. The default semantics is
@@ -447,6 +441,8 @@ static int _call_per_cable(struct notifier_block *nb, unsigned long val,
  *                           extcon device.
  * @obj:       an empty extcon_specific_cable_nb object to be returned.
  * @extcon_name:       the name of extcon device.
+ *                     if NULL, extcon_register_interest will register
+ *                     every cable with the target cable_name given.
  * @cable_name:                the target cable name.
  * @nb:                the notifier block to get notified.
  *
@@ -466,22 +462,44 @@ int extcon_register_interest(struct extcon_specific_cable_nb *obj,
                             const char *extcon_name, const char *cable_name,
                             struct notifier_block *nb)
 {
-       if (!obj || !extcon_name || !cable_name || !nb)
+       if (!obj || !cable_name || !nb)
                return -EINVAL;
 
-       obj->edev = extcon_get_extcon_dev(extcon_name);
-       if (!obj->edev)
-               return -ENODEV;
+       if (extcon_name) {
+               obj->edev = extcon_get_extcon_dev(extcon_name);
+               if (!obj->edev)
+                       return -ENODEV;
 
-       obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
-       if (obj->cable_index < 0)
-               return -ENODEV;
+               obj->cable_index = extcon_find_cable_index(obj->edev, cable_name);
+               if (obj->cable_index < 0)
+                       return -ENODEV;
+
+               obj->user_nb = nb;
 
-       obj->user_nb = nb;
+               obj->internal_nb.notifier_call = _call_per_cable;
 
-       obj->internal_nb.notifier_call = _call_per_cable;
+               return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+       } else {
+               struct class_dev_iter iter;
+               struct extcon_dev *extd;
+               struct device *dev;
+
+               if (!extcon_class)
+                       return -ENODEV;
+               class_dev_iter_init(&iter, extcon_class, NULL, NULL);
+               while ((dev = class_dev_iter_next(&iter))) {
+                       extd = (struct extcon_dev *)dev_get_drvdata(dev);
+
+                       if (extcon_find_cable_index(extd, cable_name) < 0)
+                               continue;
+
+                       class_dev_iter_exit(&iter);
+                       return extcon_register_interest(obj, extd->name,
+                                               cable_name, nb);
+               }
 
-       return raw_notifier_chain_register(&obj->edev->nh, &obj->internal_nb);
+               return -ENODEV;
+       }
 }
 
 /**
@@ -551,43 +569,9 @@ static int create_extcon_class(void)
        return 0;
 }
 
-static void extcon_cleanup(struct extcon_dev *edev, bool skip)
-{
-       mutex_lock(&extcon_dev_list_lock);
-       list_del(&edev->entry);
-       mutex_unlock(&extcon_dev_list_lock);
-
-       if (!skip && get_device(edev->dev)) {
-               int index;
-
-               if (edev->mutually_exclusive && edev->max_supported) {
-                       for (index = 0; edev->mutually_exclusive[index];
-                            index++)
-                               kfree(edev->d_attrs_muex[index].attr.name);
-                       kfree(edev->d_attrs_muex);
-                       kfree(edev->attrs_muex);
-               }
-
-               for (index = 0; index < edev->max_supported; index++)
-                       kfree(edev->cables[index].attr_g.name);
-
-               if (edev->max_supported) {
-                       kfree(edev->extcon_dev_type.groups);
-                       kfree(edev->cables);
-               }
-
-               device_unregister(edev->dev);
-               put_device(edev->dev);
-       }
-
-       kfree(edev->dev);
-}
-
 static void extcon_dev_release(struct device *dev)
 {
-       struct extcon_dev *edev = (struct extcon_dev *) dev_get_drvdata(dev);
-
-       extcon_cleanup(edev, true);
+       kfree(dev);
 }
 
 static const char *muex_name = "mutually_exclusive";
@@ -813,7 +797,40 @@ EXPORT_SYMBOL_GPL(extcon_dev_register);
  */
 void extcon_dev_unregister(struct extcon_dev *edev)
 {
-       extcon_cleanup(edev, false);
+       int index;
+
+       mutex_lock(&extcon_dev_list_lock);
+       list_del(&edev->entry);
+       mutex_unlock(&extcon_dev_list_lock);
+
+       if (IS_ERR_OR_NULL(get_device(edev->dev))) {
+               dev_err(edev->dev, "Failed to unregister extcon_dev (%s)\n",
+                               dev_name(edev->dev));
+               return;
+       }
+
+       if (edev->mutually_exclusive && edev->max_supported) {
+               for (index = 0; edev->mutually_exclusive[index];
+                               index++)
+                       kfree(edev->d_attrs_muex[index].attr.name);
+               kfree(edev->d_attrs_muex);
+               kfree(edev->attrs_muex);
+       }
+
+       for (index = 0; index < edev->max_supported; index++)
+               kfree(edev->cables[index].attr_g.name);
+
+       if (edev->max_supported) {
+               kfree(edev->extcon_dev_type.groups);
+               kfree(edev->cables);
+       }
+
+#if defined(CONFIG_ANDROID)
+       if (switch_class)
+               class_compat_remove_link(switch_class, edev->dev, NULL);
+#endif
+       device_unregister(edev->dev);
+       put_device(edev->dev);
 }
 EXPORT_SYMBOL_GPL(extcon_dev_unregister);
 
@@ -825,6 +842,9 @@ module_init(extcon_class_init);
 
 static void __exit extcon_class_exit(void)
 {
+#if defined(CONFIG_ANDROID)
+       class_compat_unregister(switch_class);
+#endif
        class_destroy(extcon_class);
 }
 module_exit(extcon_class_exit);
index 3cc152e690b06087c8374bf35cb72106f9bfde32..71d3ab7b3d8d72c8c477250e25b8ec93ce7842e8 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/extcon.h>
 #include <linux/workqueue.h>
 #include <linux/gpio.h>
 #include <linux/extcon.h>
index e21387e2da5c25d2c9fdd19dae94108f9e9455da..a17d0d91ada26865d580768b293f2bbd936e4d10 100644 (file)
@@ -239,25 +239,19 @@ const char *max77693_extcon_cable[] = {
 static int max77693_muic_set_debounce_time(struct max77693_muic_info *info,
                enum max77693_muic_adc_debounce_time time)
 {
-       int ret = 0;
-       u8 ctrl3;
+       int ret;
 
        switch (time) {
        case ADC_DEBOUNCE_TIME_5MS:
        case ADC_DEBOUNCE_TIME_10MS:
        case ADC_DEBOUNCE_TIME_25MS:
        case ADC_DEBOUNCE_TIME_38_62MS:
-               ret = max77693_read_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, &ctrl3);
-               ctrl3 &= ~CONTROL3_ADCDBSET_MASK;
-               ctrl3 |= (time << CONTROL3_ADCDBSET_SHIFT);
-
-               ret = max77693_write_reg(info->max77693->regmap_muic,
-                               MAX77693_MUIC_REG_CTRL3, ctrl3);
-               if (ret) {
+               ret = max77693_update_reg(info->max77693->regmap_muic,
+                                         MAX77693_MUIC_REG_CTRL3,
+                                         time << CONTROL3_ADCDBSET_SHIFT,
+                                         CONTROL3_ADCDBSET_MASK);
+               if (ret)
                        dev_err(info->dev, "failed to set ADC debounce time\n");
-                       ret = -EINVAL;
-               }
                break;
        default:
                dev_err(info->dev, "invalid ADC debounce time\n");
@@ -657,6 +651,8 @@ out:
 static int __devinit max77693_muic_probe(struct platform_device *pdev)
 {
        struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
+       struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
+       struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
        struct max77693_muic_info *info;
        int ret, i;
        u8 id;
@@ -727,6 +723,31 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
                goto err_extcon;
        }
 
+       /* Initialize MUIC register by using platform data */
+       for (i = 0 ; i < muic_pdata->num_init_data ; i++) {
+               enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR;
+
+               max77693_write_reg(info->max77693->regmap_muic,
+                               muic_pdata->init_data[i].addr,
+                               muic_pdata->init_data[i].data);
+
+               switch (muic_pdata->init_data[i].addr) {
+               case MAX77693_MUIC_REG_INTMASK1:
+                       irq_src = MUIC_INT1;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK2:
+                       irq_src = MUIC_INT2;
+                       break;
+               case MAX77693_MUIC_REG_INTMASK3:
+                       irq_src = MUIC_INT3;
+                       break;
+               }
+
+               if (irq_src < MAX77693_IRQ_GROUP_NR)
+                       info->max77693->irq_masks_cur[irq_src]
+                               = muic_pdata->init_data[i].data;
+       }
+
        /* Check revision number of MUIC device*/
        ret = max77693_read_reg(info->max77693->regmap_muic,
                        MAX77693_MUIC_REG_ID, &id);
@@ -762,6 +783,7 @@ static int __devexit max77693_muic_remove(struct platform_device *pdev)
                free_irq(muic_irqs[i].virq, info);
        cancel_work_sync(&info->irq_work);
        extcon_dev_unregister(info->edev);
+       kfree(info->edev);
        kfree(info);
 
        return 0;
index ef9090a4271ddc00ee6d735c2c4b48051e5c09f3..77b66b0cc8f54b117280e951daf81b17d6d31c3c 100644 (file)
@@ -271,8 +271,6 @@ out:
 static int max8997_muic_handle_charger_type_detach(
                                struct max8997_muic_info *info)
 {
-       int ret = 0;
-
        switch (info->pre_charger_type) {
        case MAX8997_CHARGER_TYPE_USB:
                extcon_set_cable_state(info->edev, "USB", false);
@@ -290,11 +288,11 @@ static int max8997_muic_handle_charger_type_detach(
                extcon_set_cable_state(info->edev, "Fast-charger", false);
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
                break;
        }
 
-       return ret;
+       return 0;
 }
 
 static int max8997_muic_handle_charger_type(struct max8997_muic_info *info,
index 1162d6b3bf8561d6ed1cfe399643dff6deb4027b..bb1b392f5cdacd1194e9af1772469c834e4192dd 100644 (file)
@@ -1546,6 +1546,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
        struct sbp2_logical_unit *lu = sdev->hostdata;
 
        sdev->use_10_for_rw = 1;
+       sdev->no_report_opcodes = 1;
+       sdev->no_write_same = 1;
 
        if (sbp2_param_exclusive_login)
                sdev->manage_start_stop = 1;
index c1cdc9236666f60ee6891206f5a1f90bba2c4a0f..90723e65b08172ac49e67d01065aa79ca7f7ee54 100644 (file)
@@ -237,7 +237,7 @@ static ssize_t memmap_attr_show(struct kobject *kobj,
  * firmware_map_add() or firmware_map_add_early() afterwards, the entries
  * are not added to sysfs.
  */
-static int __init memmap_init(void)
+static int __init firmware_memmap_init(void)
 {
        struct firmware_map_entry *entry;
 
@@ -246,5 +246,5 @@ static int __init memmap_init(void)
 
        return 0;
 }
-late_initcall(memmap_init);
+late_initcall(firmware_memmap_init);
 
index d055cee36942d5e7aea8535b5f8d77b4ab34fe09..47150f5ded04ea4df13c14434fc3fa553141abaf 100644 (file)
@@ -47,7 +47,7 @@ if GPIOLIB
 
 config OF_GPIO
        def_bool y
-       depends on OF && !SPARC
+       depends on OF
 
 config DEBUG_GPIO
        bool "Debug GPIO calls"
@@ -466,7 +466,7 @@ config GPIO_ADP5588_IRQ
 
 config GPIO_ADNP
        tristate "Avionic Design N-bit GPIO expander"
-       depends on I2C && OF
+       depends on I2C && OF_GPIO
        help
          This option enables support for N GPIOs found on Avionic Design
          I2C GPIO expanders. The register space will be extended by powers
index ed3e55161bdc5bacbd0409a8a728f161872671c9..f05e54258ffb0a7c1b62eb54be11f2f8ed9486d8 100644 (file)
@@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)
        }
 
        chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers;
-       chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL);
+       chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);
        if (!chip->buffer) {
                ret = -ENOMEM;
                goto exit_destroy;
index 0f425189de11b3b5b8003a9c9abb330d9debd116..ce1c847600764602f568994f08167b8fc044dd9a 100644 (file)
@@ -77,7 +77,7 @@ struct mcp23s08_driver_data {
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
 {
@@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
                break;
 #endif /* CONFIG_SPI_MASTER */
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
        case MCP_TYPE_008:
                mcp->ops = &mcp23008_ops;
                mcp->chip.ngpio = 8;
@@ -473,7 +473,7 @@ fail:
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int __devinit mcp230xx_probe(struct i2c_client *client,
                                    const struct i2c_device_id *id)
index 902af437eaf26e9dc1b5c2cf3f1e902b70d5e237..be65c0451ad556e174b961f3542cc8d7b40e201c 100644 (file)
@@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
        return mvchip->membase + GPIO_OUT_OFF;
 }
 
+static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
+{
+       return mvchip->membase + GPIO_BLINK_EN_OFF;
+}
+
 static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
 {
        return mvchip->membase + GPIO_IO_CONF_OFF;
@@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
        return (u >> pin) & 1;
 }
 
+static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       unsigned long flags;
+       u32 u;
+
+       spin_lock_irqsave(&mvchip->lock, flags);
+       u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
+       if (value)
+               u |= 1 << pin;
+       else
+               u &= ~(1 << pin);
+       writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
+       spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
 static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
        struct mvebu_gpio_chip *mvchip =
@@ -244,6 +266,9 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
        if (ret)
                return ret;
 
+       mvebu_gpio_blink(chip, pin, 0);
+       mvebu_gpio_set(chip, pin, value);
+
        spin_lock_irqsave(&mvchip->lock, flags);
        u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));
        u &= ~(1 << pin);
@@ -381,11 +406,13 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
                u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
                u &= ~(1 << pin);
                writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+               break;
        case IRQ_TYPE_EDGE_FALLING:
        case IRQ_TYPE_LEVEL_LOW:
                u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip));
                u |= 1 << pin;
                writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+               break;
        case IRQ_TYPE_EDGE_BOTH: {
                u32 v;
 
@@ -401,6 +428,7 @@ static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type)
                else
                        u &= ~(1 << pin);       /* rising */
                writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip));
+               break;
        }
        }
        return 0;
@@ -641,7 +669,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
        ct->handler = handle_edge_irq;
        ct->chip.name = mvchip->chip.label;
 
-       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE,
+       irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
                               IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
 
        /* Setup irq domain on top of the generic chip. */
index 94cbc842fbc3a1363de61b8b7d08f2e4b56daeaf..d335af1d4d858da39b2825fd9144c01e76f877e5 100644 (file)
@@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,
        }
 }
 
+/**
+ * _clear_gpio_debounce - clear debounce settings for a gpio
+ * @bank: the gpio bank we're acting upon
+ * @gpio: the gpio number on this @gpio
+ *
+ * If a gpio is using debounce, then clear the debounce enable bit and if
+ * this is the only gpio in this bank using debounce, then clear the debounce
+ * time too. The debounce clock will also be disabled when calling this function
+ * if this is the only gpio in the bank using debounce.
+ */
+static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio)
+{
+       u32 gpio_bit = GPIO_BIT(bank, gpio);
+
+       if (!bank->dbck_flag)
+               return;
+
+       if (!(bank->dbck_enable_mask & gpio_bit))
+               return;
+
+       bank->dbck_enable_mask &= ~gpio_bit;
+       bank->context.debounce_en &= ~gpio_bit;
+       __raw_writel(bank->context.debounce_en,
+                    bank->base + bank->regs->debounce_en);
+
+       if (!bank->dbck_enable_mask) {
+               bank->context.debounce = 0;
+               __raw_writel(bank->context.debounce, bank->base +
+                            bank->regs->debounce);
+               clk_disable(bank->dbck);
+               bank->dbck_enabled = false;
+       }
+}
+
 static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,
                                                unsigned trigger)
 {
@@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)
        _set_gpio_irqenable(bank, gpio, 0);
        _clear_gpio_irqstatus(bank, gpio);
        _set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE);
+       _clear_gpio_debounce(bank, gpio);
 }
 
 /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */
index 031c6adf5b651542420ee819ad0810d537707222..1a3e2b9b4772f7e710c16dee60a48049a3ff5c6d 100644 (file)
@@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)
        unsigned long flags;
 
        spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier &= ~(1 << offset);
+       tgpio->last_ier &= ~(1UL << offset);
        iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
        spin_unlock_irqrestore(&tgpio->lock, flags);
 }
@@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)
        unsigned long flags;
 
        spin_lock_irqsave(&tgpio->lock, flags);
-       tgpio->last_ier |= 1 << offset;
+       tgpio->last_ier |= 1UL << offset;
        iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);
        spin_unlock_irqrestore(&tgpio->lock, flags);
 }
index 5d6c71edc73911c7765a7530e65352fda2478845..1c8d9e3380e17276e17e8f009659954e58d05bd1 100644 (file)
@@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,
         */
 
        status = gpio_request(gpio, "sysfs");
-       if (status < 0)
+       if (status < 0) {
+               if (status == -EPROBE_DEFER)
+                       status = -ENODEV;
                goto done;
-
+       }
        status = gpio_export(gpio, true);
        if (status < 0)
                gpio_free(gpio);
@@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)
 
        spin_lock_irqsave(&gpio_lock, flags);
 
-       if (!gpio_is_valid(gpio))
+       if (!gpio_is_valid(gpio)) {
+               status = -EINVAL;
                goto done;
+       }
        desc = &gpio_desc[gpio];
        chip = desc->chip;
        if (chip == NULL)
index 09e11a5d921a4487b273bcdc2c479e4a26f90301..fd9d0af4d5369bb7ebac13662a3d612188c87921 100644 (file)
@@ -206,7 +206,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
        size_t size;
        int ret;
 
-       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d\n",
+       DRM_DEBUG_KMS("surface width(%d), height(%d) and bpp(%d)\n",
                        sizes->surface_width, sizes->surface_height,
                        sizes->surface_bpp);
 
@@ -220,7 +220,7 @@ static int drm_fbdev_cma_create(struct drm_fb_helper *helper,
 
        size = mode_cmd.pitches[0] * mode_cmd.height;
        obj = drm_gem_cma_create(dev, size);
-       if (!obj)
+       if (IS_ERR(obj))
                return -ENOMEM;
 
        fbi = framebuffer_alloc(0, dev->dev);
index 7ef1b673e1be9ec2f82006ca3d8ea2519e13b231..133b4132983e35e366884301a443ff26f45a2a05 100644 (file)
@@ -121,6 +121,8 @@ int drm_open(struct inode *inode, struct file *filp)
        int minor_id = iminor(inode);
        struct drm_minor *minor;
        int retcode = 0;
+       int need_setup = 0;
+       struct address_space *old_mapping;
 
        minor = idr_find(&drm_minors_idr, minor_id);
        if (!minor)
@@ -132,23 +134,37 @@ int drm_open(struct inode *inode, struct file *filp)
        if (drm_device_is_unplugged(dev))
                return -ENODEV;
 
+       if (!dev->open_count++)
+               need_setup = 1;
+       mutex_lock(&dev->struct_mutex);
+       old_mapping = dev->dev_mapping;
+       if (old_mapping == NULL)
+               dev->dev_mapping = &inode->i_data;
+       /* ihold ensures nobody can remove inode with our i_data */
+       ihold(container_of(dev->dev_mapping, struct inode, i_data));
+       inode->i_mapping = dev->dev_mapping;
+       filp->f_mapping = dev->dev_mapping;
+       mutex_unlock(&dev->struct_mutex);
+
        retcode = drm_open_helper(inode, filp, dev);
-       if (!retcode) {
-               atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
-               if (!dev->open_count++)
-                       retcode = drm_setup(dev);
-       }
-       if (!retcode) {
-               mutex_lock(&dev->struct_mutex);
-               if (dev->dev_mapping == NULL)
-                       dev->dev_mapping = &inode->i_data;
-               /* ihold ensures nobody can remove inode with our i_data */
-               ihold(container_of(dev->dev_mapping, struct inode, i_data));
-               inode->i_mapping = dev->dev_mapping;
-               filp->f_mapping = dev->dev_mapping;
-               mutex_unlock(&dev->struct_mutex);
+       if (retcode)
+               goto err_undo;
+       atomic_inc(&dev->counts[_DRM_STAT_OPENS]);
+       if (need_setup) {
+               retcode = drm_setup(dev);
+               if (retcode)
+                       goto err_undo;
        }
+       return 0;
 
+err_undo:
+       mutex_lock(&dev->struct_mutex);
+       filp->f_mapping = old_mapping;
+       inode->i_mapping = old_mapping;
+       iput(container_of(dev->dev_mapping, struct inode, i_data));
+       dev->dev_mapping = old_mapping;
+       mutex_unlock(&dev->struct_mutex);
+       dev->open_count--;
        return retcode;
 }
 EXPORT_SYMBOL(drm_open);
index cdf8b1e7602db2fdd46891b88d7555f6cae7be3e..d4b20ceda3fbd8d183dc7e628683732590200f51 100644 (file)
@@ -205,8 +205,6 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data)
        struct drm_gem_object *obj = ptr;
        struct seq_file *m = data;
 
-       seq_printf(m, "name %d size %zd\n", obj->name, obj->size);
-
        seq_printf(m, "%6d %8zd %7d %8d\n",
                   obj->name, obj->size,
                   atomic_read(&obj->handle_count),
@@ -239,7 +237,7 @@ int drm_vma_info(struct seq_file *m, void *data)
        mutex_lock(&dev->struct_mutex);
        seq_printf(m, "vma use count: %d, high_memory = %pK, 0x%pK\n",
                   atomic_read(&dev->vma_count),
-                  high_memory, (void *)virt_to_phys(high_memory));
+                  high_memory, (void *)(unsigned long)virt_to_phys(high_memory));
 
        list_for_each_entry(pt, &dev->vmalist, head) {
                vma = pt->vma;
index aaeb6f8d69ce3502c569dda32d2d600117fb54c5..b8a282ea87515546695bc2965bce2b9f3e4f2f2d 100644 (file)
@@ -64,7 +64,6 @@ int drm_get_platform_dev(struct platform_device *platdev,
        }
 
        if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-               dev_set_drvdata(&platdev->dev, dev);
                ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
                if (ret)
                        goto err_g1;
index 59a26e577b57f423077d5a2c86d75364f14b6838..fc345d4ebb03acea266bfb100b4661cebf970f69 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_EXYNOS
        tristate "DRM Support for Samsung SoC EXYNOS Series"
-       depends on DRM && PLAT_SAMSUNG
+       depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)
        select DRM_KMS_HELPER
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
index 18c271862ca8468a8ce0d3d4b24d8a595d29ad44..0f68a28726739dd6b795ad066edb645799cfc6d2 100644 (file)
@@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
        exynos_connector->encoder_id = encoder->base.id;
        exynos_connector->manager = manager;
        exynos_connector->dpms = DRM_MODE_DPMS_OFF;
+       connector->dpms = DRM_MODE_DPMS_OFF;
        connector->encoder = encoder;
 
        err = drm_mode_connector_attach_encoder(connector, encoder);
index e51503fbaf2bcbf19edbdf423638a725b5703a6e..241ad1eeec64d2097a4416bd76026723d384a215 100644 (file)
  * @manager: specific encoder has its own manager to control a hardware
  *     appropriately and we can access a hardware drawing on this manager.
  * @dpms: store the encoder dpms value.
+ * @updated: indicate whether overlay data updating is needed or not.
  */
 struct exynos_drm_encoder {
        struct drm_crtc                 *old_crtc;
        struct drm_encoder              drm_encoder;
        struct exynos_drm_manager       *manager;
-       int dpms;
+       int                             dpms;
+       bool                            updated;
 };
 
 static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
@@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                if (manager_ops && manager_ops->apply)
-                       manager_ops->apply(manager->dev);
+                       if (!exynos_encoder->updated)
+                               manager_ops->apply(manager->dev);
+
                exynos_drm_connector_power(encoder, mode);
                exynos_encoder->dpms = mode;
                break;
@@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        case DRM_MODE_DPMS_OFF:
                exynos_drm_connector_power(encoder, mode);
                exynos_encoder->dpms = mode;
+               exynos_encoder->updated = false;
                break;
        default:
                DRM_ERROR("unspecified mode %d\n", mode);
@@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
 
 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
-       struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+       struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+       struct exynos_drm_manager *manager = exynos_encoder->manager;
        struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        if (manager_ops && manager_ops->commit)
                manager_ops->commit(manager->dev);
+
+       /*
+        * this will avoid one issue that overlay data is updated to
+        * real hardware two times.
+        * And this variable will be used to check if the data was
+        * already updated or not by exynos_drm_encoder_dpms function.
+        */
+       exynos_encoder->updated = true;
 }
 
 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
@@ -400,19 +414,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
        if (manager_ops && manager_ops->dpms)
                manager_ops->dpms(manager->dev, mode);
 
-       /*
-        * set current mode to new one so that data aren't updated into
-        * registers by drm_helper_connector_dpms two times.
-        *
-        * in case that drm_crtc_helper_set_mode() is called,
-        * overlay_ops->commit() and manager_ops->commit() callbacks
-        * can be called two times, first at drm_crtc_helper_set_mode()
-        * and second at drm_helper_connector_dpms().
-        * so with this setting, when drm_helper_connector_dpms() is called
-        * encoder->funcs->dpms() will be ignored.
-        */
-       exynos_encoder->dpms = mode;
-
        /*
         * if this condition is ok then it means that the crtc is already
         * detached from encoder and last function for detaching is properly
index 614b2e9ac462c9c402226324d9b12d38b996af14..e7fbb823fd8e5fe2fe97845a1b42a3d84efd50be 100644 (file)
@@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
                const struct of_device_id *match;
                match = of_match_node(of_match_ptr(mixer_match_types),
                                                          pdev->dev.of_node);
-               drv = match->data;
+               drv = (struct mixer_drv_data *)match->data;
        } else {
                drv = (struct mixer_drv_data *)
                        platform_get_device_id(pdev)->driver_data;
index 38f3a6cb8c7d72272c9cffae2466818b440282e9..3edd981e077013f780cc8d637b9a5ba60b0f2aa6 100644 (file)
@@ -303,10 +303,10 @@ static bool ch7xxx_get_hw_state(struct intel_dvo_device *dvo)
 
        ch7xxx_readb(dvo, CH7xxx_PM, &val);
 
-       if (val & CH7xxx_PM_FPD)
-               return false;
-       else
+       if (val & (CH7xxx_PM_DVIL | CH7xxx_PM_DVIP))
                return true;
+       else
+               return false;
 }
 
 static void ch7xxx_dump_regs(struct intel_dvo_device *dvo)
index c9bfd83dde64eb6d83cf181fb6c27b3cfcf0a038..61ae104dca8c0f5b9938f092b93f7eca70a06525 100644 (file)
@@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
                goto put_gmch;
        }
 
-       i915_kick_out_firmware_fb(dev_priv);
+       if (drm_core_check_feature(dev, DRIVER_MODESET))
+               i915_kick_out_firmware_fb(dev_priv);
 
        pci_set_master(dev->pdev);
 
index aac4e5e1a5b9b3533f36f801be7c553c2e60c8a1..6770ee6084b478475c3dde3a9bec72fff1e11a53 100644 (file)
@@ -118,6 +118,13 @@ module_param_named(i915_enable_ppgtt, i915_enable_ppgtt, int, 0600);
 MODULE_PARM_DESC(i915_enable_ppgtt,
                "Enable PPGTT (default: true)");
 
+unsigned int i915_preliminary_hw_support __read_mostly = 0;
+module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);
+MODULE_PARM_DESC(preliminary_hw_support,
+               "Enable preliminary hardware support. "
+               "Enable Haswell and ValleyView Support. "
+               "(default: false)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
@@ -826,6 +833,12 @@ i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct intel_device_info *intel_info =
                (struct intel_device_info *) ent->driver_data;
 
+       if (intel_info->is_haswell || intel_info->is_valleyview)
+               if(!i915_preliminary_hw_support) {
+                       DRM_ERROR("Preliminary hardware support disabled\n");
+                       return -ENODEV;
+               }
+
        /* Only bind to function 0 of the device. Early generations
         * used function 1 as a placeholder for multi-head. This causes
         * us confusion instead, especially on the systems where both
index 4f2831aa5fedd517a4f49189bc19b4803e69b71a..f511fa2f41687718494f2f1d9e2afb0c24f1fb70 100644 (file)
@@ -1217,6 +1217,7 @@ extern int i915_enable_rc6 __read_mostly;
 extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
+extern unsigned int i915_preliminary_hw_support __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
@@ -1341,9 +1342,14 @@ int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
 static inline struct page *i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
 {
        struct scatterlist *sg = obj->pages->sgl;
-       while (n >= SG_MAX_SINGLE_ALLOC) {
+       int nents = obj->pages->nents;
+       while (nents > SG_MAX_SINGLE_ALLOC) {
+               if (n < SG_MAX_SINGLE_ALLOC - 1)
+                       break;
+
                sg = sg_chain_ptr(sg + SG_MAX_SINGLE_ALLOC - 1);
                n -= SG_MAX_SINGLE_ALLOC - 1;
+               nents -= SG_MAX_SINGLE_ALLOC - 1;
        }
        return sg_page(sg+n);
 }
@@ -1427,7 +1433,7 @@ int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
 int i915_add_request(struct intel_ring_buffer *ring,
                     struct drm_file *file,
-                    struct drm_i915_gem_request *request);
+                    u32 *seqno);
 int __must_check i915_wait_seqno(struct intel_ring_buffer *ring,
                                 uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
index 19dbdd7dd5648e93b48062c54fd9bc3f6100e425..107f09befe929540e9ad801ff2bbdfe97a6b651d 100644 (file)
@@ -1407,8 +1407,10 @@ out:
                return VM_FAULT_NOPAGE;
        case -ENOMEM:
                return VM_FAULT_OOM;
+       case -ENOSPC:
+               return VM_FAULT_SIGBUS;
        default:
-               WARN_ON_ONCE(ret);
+               WARN_ONCE(ret, "unhandled error in i915_gem_fault: %i\n", ret);
                return VM_FAULT_SIGBUS;
        }
 }
@@ -1822,10 +1824,11 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
                sg_set_page(sg, page, PAGE_SIZE, 0);
        }
 
+       obj->pages = st;
+
        if (i915_gem_object_needs_bit17_swizzle(obj))
                i915_gem_object_do_bit_17_swizzle(obj);
 
-       obj->pages = st;
        return 0;
 
 err_pages:
@@ -1955,11 +1958,12 @@ i915_gem_next_request_seqno(struct intel_ring_buffer *ring)
 int
 i915_add_request(struct intel_ring_buffer *ring,
                 struct drm_file *file,
-                struct drm_i915_gem_request *request)
+                u32 *out_seqno)
 {
        drm_i915_private_t *dev_priv = ring->dev->dev_private;
-       uint32_t seqno;
+       struct drm_i915_gem_request *request;
        u32 request_ring_position;
+       u32 seqno;
        int was_empty;
        int ret;
 
@@ -1974,11 +1978,9 @@ i915_add_request(struct intel_ring_buffer *ring,
        if (ret)
                return ret;
 
-       if (request == NULL) {
-               request = kmalloc(sizeof(*request), GFP_KERNEL);
-               if (request == NULL)
-                       return -ENOMEM;
-       }
+       request = kmalloc(sizeof(*request), GFP_KERNEL);
+       if (request == NULL)
+               return -ENOMEM;
 
        seqno = i915_gem_next_request_seqno(ring);
 
@@ -2030,6 +2032,8 @@ i915_add_request(struct intel_ring_buffer *ring,
                }
        }
 
+       if (out_seqno)
+               *out_seqno = seqno;
        return 0;
 }
 
@@ -3959,6 +3963,9 @@ i915_gem_init_hw(struct drm_device *dev)
        if (!intel_enable_gtt())
                return -EIO;
 
+       if (IS_HASWELL(dev) && (I915_READ(0x120010) == 1))
+               I915_WRITE(0x9008, I915_READ(0x9008) | 0xf0000);
+
        i915_gem_l3_remap(dev);
 
        i915_gem_init_swizzling(dev);
@@ -4098,7 +4105,6 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
        }
 
        BUG_ON(!list_empty(&dev_priv->mm.active_list));
-       BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
        mutex_unlock(&dev->struct_mutex);
 
        ret = drm_irq_install(dev);
index 64c1be0a9cfdb033ab33e66da2463b8b28fc8ffb..a4162ddff6c5e0e38c3c7b298aa4806d02bcb992 100644 (file)
  */
 # define _3D_CHICKEN2_WM_READ_PIPELINED                        (1 << 14)
 #define _3D_CHICKEN3   0x02090
-#define  _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL          (1 << 5)
+#define  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL         (1 << 5)
 
 #define MI_MODE                0x0209c
 # define VS_TIMER_DISPATCH                             (1 << 6)
index 893f30164b7ec70a5cd2308db6db1e3e55222d6f..6345878ae1e73e260a9a3fdfcaaf760e6ec6e2c1 100644 (file)
@@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        int old_dpms;
 
        /* PCH platforms and VLV only support on/off. */
-       if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
+       if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON)
                mode = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
@@ -219,20 +219,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
                intel_encoder_to_crt(to_intel_encoder(encoder));
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
        struct drm_i915_private *dev_priv = dev->dev_private;
-       int dpll_md_reg;
-       u32 adpa, dpll_md;
-
-       dpll_md_reg = DPLL_MD(intel_crtc->pipe);
-
-       /*
-        * Disable separate mode multiplier used when cloning SDVO to CRT
-        * XXX this needs to be adjusted when we really are cloning
-        */
-       if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-               dpll_md = I915_READ(dpll_md_reg);
-               I915_WRITE(dpll_md_reg,
-                          dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
-       }
+       u32 adpa;
 
        adpa = ADPA_HOTPLUG_BITS;
        if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -742,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)
 
        crt->base.type = INTEL_OUTPUT_ANALOG;
        crt->base.cloneable = true;
-       if (IS_HASWELL(dev))
+       if (IS_HASWELL(dev) || IS_I830(dev))
                crt->base.crtc_mask = (1 << 0);
        else
                crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
index 2b6ce9b2674a9d899dd34a6e2b6e2622dc08c631..4154bcd7a0708b957d4b176607662933ac49fc0d 100644 (file)
@@ -3253,6 +3253,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
        if (HAS_PCH_CPT(dev))
                intel_cpt_verify_modeset(dev, intel_crtc->pipe);
+
+       /*
+        * There seems to be a race in PCH platform hw (at least on some
+        * outputs) where an enabled pipe still completes any pageflip right
+        * away (as if the pipe is off) instead of waiting for vblank. As soon
+        * as the first vblank happend, everything works as expected. Hence just
+        * wait for one vblank before returning to avoid strange things
+        * happening.
+        */
+       intel_wait_for_vblank(dev, intel_crtc->pipe);
 }
 
 static void ironlake_crtc_disable(struct drm_crtc *crtc)
@@ -3831,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        }
                }
 
+               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_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               display_bpc = edp_bpc;
+                       }
+                       continue;
+               }
+
                /*
                 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
                 * through, clamp it down.  (Note: >12bpc will be caught below.)
@@ -7882,6 +7903,34 @@ struct intel_quirk {
        void (*hook)(struct drm_device *dev);
 };
 
+/* For systems that don't have a meaningful PCI subdevice/subvendor ID */
+struct intel_dmi_quirk {
+       void (*hook)(struct drm_device *dev);
+       const struct dmi_system_id (*dmi_id_list)[];
+};
+
+static int intel_dmi_reverse_brightness(const struct dmi_system_id *id)
+{
+       DRM_INFO("Backlight polarity reversed on %s\n", id->ident);
+       return 1;
+}
+
+static const struct intel_dmi_quirk intel_dmi_quirks[] = {
+       {
+               .dmi_id_list = &(const struct dmi_system_id[]) {
+                       {
+                               .callback = intel_dmi_reverse_brightness,
+                               .ident = "NCR Corporation",
+                               .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"),
+                                           DMI_MATCH(DMI_PRODUCT_NAME, ""),
+                               },
+                       },
+                       { }  /* terminating entry */
+               },
+               .hook = quirk_invert_brightness,
+       },
+};
+
 static struct intel_quirk intel_quirks[] = {
        /* HP Mini needs pipe A force quirk (LP: #322104) */
        { 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
@@ -7892,8 +7941,7 @@ static struct intel_quirk intel_quirks[] = {
        /* ThinkPad T60 needs pipe A force quirk (bug #16494) */
        { 0x2782, 0x17aa, 0x201a, quirk_pipea_force },
 
-       /* 855 & before need to leave pipe A & dpll A up */
-       { 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
+       /* 830/845 need to leave pipe A & dpll A up */
        { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
        { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },
 
@@ -7922,6 +7970,10 @@ static void intel_init_quirks(struct drm_device *dev)
                     q->subsystem_device == PCI_ANY_ID))
                        q->hook(dev);
        }
+       for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) {
+               if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0)
+                       intel_dmi_quirks[i].hook(dev);
+       }
 }
 
 /* Disable the VGA plane that we never use */
@@ -8049,29 +8101,42 @@ static void intel_enable_pipe_a(struct drm_device *dev)
 
 }
 
+static bool
+intel_check_plane_mapping(struct intel_crtc *crtc)
+{
+       struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
+       u32 reg, val;
+
+       if (dev_priv->num_pipe == 1)
+               return true;
+
+       reg = DSPCNTR(!crtc->plane);
+       val = I915_READ(reg);
+
+       if ((val & DISPLAY_PLANE_ENABLE) &&
+           (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
+               return false;
+
+       return true;
+}
+
 static void intel_sanitize_crtc(struct intel_crtc *crtc)
 {
        struct drm_device *dev = crtc->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 reg, val;
+       u32 reg;
 
        /* Clear any frame start delays used for debugging left by the BIOS */
        reg = PIPECONF(crtc->pipe);
        I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK);
 
        /* We need to sanitize the plane -> pipe mapping first because this will
-        * disable the crtc (and hence change the state) if it is wrong. */
-       if (!HAS_PCH_SPLIT(dev)) {
+        * disable the crtc (and hence change the state) if it is wrong. Note
+        * that gen4+ has a fixed plane -> pipe mapping.  */
+       if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) {
                struct intel_connector *connector;
                bool plane;
 
-               reg = DSPCNTR(crtc->plane);
-               val = I915_READ(reg);
-
-               if ((val & DISPLAY_PLANE_ENABLE) == 0 &&
-                   (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe))
-                       goto ok;
-
                DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n",
                              crtc->base.base.id);
 
@@ -8095,7 +8160,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc)
                WARN_ON(crtc->active);
                crtc->base.enabled = false;
        }
-ok:
 
        if (dev_priv->quirks & QUIRK_PIPEA_FORCE &&
            crtc->pipe == PIPE_A && !crtc->active) {
index d1e8ddb2d6c0801e42a25c30e1eb66c29fb80150..368ed8ef1600233b6df90f32a591b46ea8fbdf88 100644 (file)
@@ -1797,7 +1797,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
                if (i == intel_dp->lane_count && voltage_tries == 5) {
-                       if (++loop_tries == 5) {
+                       ++loop_tries;
+                       if (loop_tries == 5) {
                                DRM_DEBUG_KMS("too many full retries, give up\n");
                                break;
                        }
@@ -1807,11 +1808,15 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                }
 
                /* Check to see if we've tried the same voltage 5 times */
-               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) {
-                       voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
-                       voltage_tries = 0;
-               } else
+               if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
                        ++voltage_tries;
+                       if (voltage_tries == 5) {
+                               DRM_DEBUG_KMS("too many voltage retries, give up\n");
+                               break;
+                       }
+               } else
+                       voltage_tries = 0;
+               voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
                /* Compute new intel_dp->train_set as requested by target */
                intel_get_adjust_train(intel_dp, link_status);
@@ -2369,8 +2374,9 @@ static void
 intel_dp_destroy(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
+       struct intel_dp *intel_dp = intel_attached_dp(connector);
 
-       if (intel_dpd_is_edp(dev))
+       if (is_edp(intel_dp))
                intel_panel_destroy_backlight(dev);
 
        drm_sysfs_connector_remove(connector);
index e3166df55daad03f4f5c144a5c0558aaa017fec6..edba93b3474b9540a5608f6acbd9eb75f7e53a33 100644 (file)
@@ -777,6 +777,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Supermicro X7SPA-H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
+               },
+       },
 
        { }     /* terminating entry */
 };
index ebff850a9ab6ff8f7b35c17fced205be45d84205..d7bc817f51a024b803986e76fa492146632da66d 100644 (file)
@@ -209,7 +209,6 @@ static void intel_overlay_unmap_regs(struct intel_overlay *overlay,
 }
 
 static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
-                                        struct drm_i915_gem_request *request,
                                         void (*tail)(struct intel_overlay *))
 {
        struct drm_device *dev = overlay->dev;
@@ -218,12 +217,10 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
        int ret;
 
        BUG_ON(overlay->last_flip_req);
-       ret = i915_add_request(ring, NULL, request);
-       if (ret) {
-           kfree(request);
-           return ret;
-       }
-       overlay->last_flip_req = request->seqno;
+       ret = i915_add_request(ring, NULL, &overlay->last_flip_req);
+       if (ret)
+               return ret;
+
        overlay->flip_tail = tail;
        ret = i915_wait_seqno(ring, overlay->last_flip_req);
        if (ret)
@@ -240,7 +237,6 @@ static int intel_overlay_on(struct intel_overlay *overlay)
        struct drm_device *dev = overlay->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
-       struct drm_i915_gem_request *request;
        int ret;
 
        BUG_ON(overlay->active);
@@ -248,17 +244,9 @@ static int intel_overlay_on(struct intel_overlay *overlay)
 
        WARN_ON(IS_I830(dev) && !(dev_priv->quirks & QUIRK_PIPEA_FORCE));
 
-       request = kzalloc(sizeof(*request), GFP_KERNEL);
-       if (request == NULL) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
        ret = intel_ring_begin(ring, 4);
-       if (ret) {
-               kfree(request);
-               goto out;
-       }
+       if (ret)
+               return ret;
 
        intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_ON);
        intel_ring_emit(ring, overlay->flip_addr | OFC_UPDATE);
@@ -266,9 +254,7 @@ static int intel_overlay_on(struct intel_overlay *overlay)
        intel_ring_emit(ring, MI_NOOP);
        intel_ring_advance(ring);
 
-       ret = intel_overlay_do_wait_request(overlay, request, NULL);
-out:
-       return ret;
+       return intel_overlay_do_wait_request(overlay, NULL);
 }
 
 /* overlay needs to be enabled in OCMD reg */
@@ -278,17 +264,12 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
        struct drm_device *dev = overlay->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
-       struct drm_i915_gem_request *request;
        u32 flip_addr = overlay->flip_addr;
        u32 tmp;
        int ret;
 
        BUG_ON(!overlay->active);
 
-       request = kzalloc(sizeof(*request), GFP_KERNEL);
-       if (request == NULL)
-               return -ENOMEM;
-
        if (load_polyphase_filter)
                flip_addr |= OFC_UPDATE;
 
@@ -298,22 +279,14 @@ static int intel_overlay_continue(struct intel_overlay *overlay,
                DRM_DEBUG("overlay underrun, DOVSTA: %x\n", tmp);
 
        ret = intel_ring_begin(ring, 2);
-       if (ret) {
-               kfree(request);
+       if (ret)
                return ret;
-       }
+
        intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
        intel_ring_emit(ring, flip_addr);
        intel_ring_advance(ring);
 
-       ret = i915_add_request(ring, NULL, request);
-       if (ret) {
-               kfree(request);
-               return ret;
-       }
-
-       overlay->last_flip_req = request->seqno;
-       return 0;
+       return i915_add_request(ring, NULL, &overlay->last_flip_req);
 }
 
 static void intel_overlay_release_old_vid_tail(struct intel_overlay *overlay)
@@ -349,15 +322,10 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring = &dev_priv->ring[RCS];
        u32 flip_addr = overlay->flip_addr;
-       struct drm_i915_gem_request *request;
        int ret;
 
        BUG_ON(!overlay->active);
 
-       request = kzalloc(sizeof(*request), GFP_KERNEL);
-       if (request == NULL)
-               return -ENOMEM;
-
        /* According to intel docs the overlay hw may hang (when switching
         * off) without loading the filter coeffs. It is however unclear whether
         * this applies to the disabling of the overlay or to the switching off
@@ -365,22 +333,28 @@ static int intel_overlay_off(struct intel_overlay *overlay)
        flip_addr |= OFC_UPDATE;
 
        ret = intel_ring_begin(ring, 6);
-       if (ret) {
-               kfree(request);
+       if (ret)
                return ret;
-       }
+
        /* wait for overlay to go idle */
        intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_CONTINUE);
        intel_ring_emit(ring, flip_addr);
        intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
        /* turn overlay off */
-       intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
-       intel_ring_emit(ring, flip_addr);
-       intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       if (IS_I830(dev)) {
+               /* Workaround: Don't disable the overlay fully, since otherwise
+                * it dies on the next OVERLAY_ON cmd. */
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_NOOP);
+               intel_ring_emit(ring, MI_NOOP);
+       } else {
+               intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF);
+               intel_ring_emit(ring, flip_addr);
+               intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
+       }
        intel_ring_advance(ring);
 
-       return intel_overlay_do_wait_request(overlay, request,
-                                            intel_overlay_off_tail);
+       return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail);
 }
 
 /* recover from an interruption due to a signal
@@ -425,24 +399,16 @@ static int intel_overlay_release_old_vid(struct intel_overlay *overlay)
                return 0;
 
        if (I915_READ(ISR) & I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT) {
-               struct drm_i915_gem_request *request;
-
                /* synchronous slowpath */
-               request = kzalloc(sizeof(*request), GFP_KERNEL);
-               if (request == NULL)
-                       return -ENOMEM;
-
                ret = intel_ring_begin(ring, 2);
-               if (ret) {
-                       kfree(request);
+               if (ret)
                        return ret;
-               }
 
                intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
                intel_ring_emit(ring, MI_NOOP);
                intel_ring_advance(ring);
 
-               ret = intel_overlay_do_wait_request(overlay, request,
+               ret = intel_overlay_do_wait_request(overlay,
                                                    intel_overlay_release_old_vid_tail);
                if (ret)
                        return ret;
index e019b236986128bae46c61bf49180f7ec2502a0d..e2aacd329545a1ff05a68dd4218f571c5208a2aa 100644 (file)
@@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)
        props.type = BACKLIGHT_RAW;
        props.max_brightness = _intel_panel_get_max_backlight(dev);
        if (props.max_brightness == 0) {
-               DRM_ERROR("Failed to get maximum backlight value\n");
+               DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");
                return -ENODEV;
        }
        dev_priv->backlight =
index b3b4b6cea8b001e4c31e79604fe56015a1bcae11..72f41aaa71ff330637bdc82d4ee8e0c04091bdf2 100644 (file)
@@ -3442,8 +3442,8 @@ static void gen6_init_clock_gating(struct drm_device *dev)
                   GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
 
        /* Bspec says we need to always set all mask bits. */
-       I915_WRITE(_3D_CHICKEN, (0xFFFF << 16) |
-                  _3D_CHICKEN_SF_DISABLE_FASTCLIP_CULL);
+       I915_WRITE(_3D_CHICKEN3, (0xFFFF << 16) |
+                  _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL);
 
        /*
         * According to the spec the following bits should be
index 0007a4d9bf6e5248effc509fd25f442b6d4e3164..c600fb06e25e6a4798cd7f7f5841593025d3f484 100644 (file)
@@ -139,6 +139,11 @@ struct intel_sdvo {
 
        /* DDC bus used by this SDVO encoder */
        uint8_t ddc_bus;
+
+       /*
+        * the sdvo flag gets lost in round trip: dtd->adjusted_mode->dtd
+        */
+       uint8_t dtd_sdvo_flags;
 };
 
 struct intel_sdvo_connector {
@@ -889,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)
 }
 #endif
 
+static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo,
+                                      unsigned if_index, uint8_t tx_rate,
+                                      uint8_t *data, unsigned length)
+{
+       uint8_t set_buf_index[2] = { if_index, 0 };
+       uint8_t hbuf_size, tmp[8];
+       int i;
+
+       if (!intel_sdvo_set_value(intel_sdvo,
+                                 SDVO_CMD_SET_HBUF_INDEX,
+                                 set_buf_index, 2))
+               return false;
+
+       if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO,
+                                 &hbuf_size, 1))
+               return false;
+
+       /* Buffer size is 0 based, hooray! */
+       hbuf_size++;
+
+       DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n",
+                     if_index, length, hbuf_size);
+
+       for (i = 0; i < hbuf_size; i += 8) {
+               memset(tmp, 0, 8);
+               if (i < length)
+                       memcpy(tmp, data + i, min_t(unsigned, 8, length - i));
+
+               if (!intel_sdvo_set_value(intel_sdvo,
+                                         SDVO_CMD_SET_HBUF_DATA,
+                                         tmp, 8))
+                       return false;
+       }
+
+       return intel_sdvo_set_value(intel_sdvo,
+                                   SDVO_CMD_SET_HBUF_TXRATE,
+                                   &tx_rate, 1);
+}
+
 static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
 {
        struct dip_infoframe avi_if = {
@@ -896,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
                .ver = DIP_VERSION_AVI,
                .len = DIP_LEN_AVI,
        };
-       uint8_t tx_rate = SDVO_HBUF_TX_VSYNC;
-       uint8_t set_buf_index[2] = { 1, 0 };
        uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)];
-       uint64_t *data = (uint64_t *)sdvo_data;
-       unsigned i;
 
        intel_dip_infoframe_csum(&avi_if);
 
@@ -910,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)
        sdvo_data[3] = avi_if.checksum;
        memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi));
 
-       if (!intel_sdvo_set_value(intel_sdvo,
-                                 SDVO_CMD_SET_HBUF_INDEX,
-                                 set_buf_index, 2))
-               return false;
-
-       for (i = 0; i < sizeof(sdvo_data); i += 8) {
-               if (!intel_sdvo_set_value(intel_sdvo,
-                                         SDVO_CMD_SET_HBUF_DATA,
-                                         data, 8))
-                       return false;
-               data++;
-       }
-
-       return intel_sdvo_set_value(intel_sdvo,
-                                   SDVO_CMD_SET_HBUF_TXRATE,
-                                   &tx_rate, 1);
+       return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF,
+                                         SDVO_HBUF_TX_VSYNC,
+                                         sdvo_data, sizeof(sdvo_data));
 }
 
 static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo)
@@ -984,6 +1011,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo,
                return false;
 
        intel_sdvo_get_mode_from_dtd(adjusted_mode, &input_dtd);
+       intel_sdvo->dtd_sdvo_flags = input_dtd.part2.sdvo_flags;
 
        return true;
 }
@@ -1092,6 +1120,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
         * adjusted_mode.
         */
        intel_sdvo_get_dtd_from_mode(&input_dtd, adjusted_mode);
+       if (intel_sdvo->is_tv || intel_sdvo->is_lvds)
+               input_dtd.part2.sdvo_flags = intel_sdvo->dtd_sdvo_flags;
        if (!intel_sdvo_set_input_timing(intel_sdvo, &input_dtd))
                DRM_INFO("Setting input timings on %s failed\n",
                         SDVO_NAME(intel_sdvo));
@@ -2277,10 +2307,8 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
                intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
        }
 
-       /* SDVO LVDS is cloneable because the SDVO encoder does the upscaling,
-        * as opposed to native LVDS, where we upscale with the panel-fitter
-        * (and hence only the native LVDS resolution could be cloned). */
-       intel_sdvo->base.cloneable = true;
+       /* SDVO LVDS is not cloneable because the input mode gets adjusted by the encoder */
+       intel_sdvo->base.cloneable = false;
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector))
@@ -2354,6 +2382,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
        return true;
 }
 
+static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
+{
+       struct drm_device *dev = intel_sdvo->base.base.dev;
+       struct drm_connector *connector, *tmp;
+
+       list_for_each_entry_safe(connector, tmp,
+                                &dev->mode_config.connector_list, head) {
+               if (intel_attached_encoder(connector) == &intel_sdvo->base)
+                       intel_sdvo_destroy(connector);
+       }
+}
+
 static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
                                          struct intel_sdvo_connector *intel_sdvo_connector,
                                          int type)
@@ -2677,7 +2717,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                                    intel_sdvo->caps.output_flags) != true) {
                DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
                              SDVO_NAME(intel_sdvo));
-               goto err;
+               /* Output_setup can leave behind connectors! */
+               goto err_output;
        }
 
        /* Only enable the hotplug irq if we need it, to work around noisy
@@ -2690,12 +2731,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
-               goto err;
+               goto err_output;
 
        if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,
                                                    &intel_sdvo->pixel_clock_min,
                                                    &intel_sdvo->pixel_clock_max))
-               goto err;
+               goto err_output;
 
        DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
                        "clock range %dMHz - %dMHz, "
@@ -2715,6 +2756,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                        (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
        return true;
 
+err_output:
+       intel_sdvo_output_cleanup(intel_sdvo);
+
 err:
        drm_encoder_cleanup(&intel_encoder->base);
        i2c_del_adapter(&intel_sdvo->ddc);
index 9d030142ee43476c89cf2769f0d8c75cf1697daa..770bdd6ecd9fb96b46365bbadd97ba3011c0ef96 100644 (file)
@@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {
 #define SDVO_CMD_SET_AUDIO_STAT                0x91
 #define SDVO_CMD_GET_AUDIO_STAT                0x92
 #define SDVO_CMD_SET_HBUF_INDEX                0x93
+  #define SDVO_HBUF_INDEX_ELD          0
+  #define SDVO_HBUF_INDEX_AVI_IF       1
 #define SDVO_CMD_GET_HBUF_INDEX                0x94
 #define SDVO_CMD_GET_HBUF_INFO         0x95
 #define SDVO_CMD_SET_HBUF_AV_SPLIT     0x96
index 1f34549aff18748758d4d72feed0eba5800734ab..70586fde69cf48018fd9786ccccacd4eef0900d4 100644 (file)
@@ -39,6 +39,11 @@ nouveau_gpuobj_destroy(struct nouveau_gpuobj *gpuobj)
                        nv_wo32(gpuobj, i, 0x00000000);
        }
 
+       if (gpuobj->node) {
+               nouveau_mm_free(&nv_gpuobj(gpuobj->parent)->heap,
+                               &gpuobj->node);
+       }
+
        if (gpuobj->heap.block_size)
                nouveau_mm_fini(&gpuobj->heap);
 
index bfddf87926dd8857a73df69cb26757836bd02f1f..a6d3cd6490f7fa97f171dff724f73430364af89f 100644 (file)
@@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)
        node = kzalloc(sizeof(*node), GFP_KERNEL);
        if (!node)
                return -ENOMEM;
-       node->offset = roundup(offset, mm->block_size);
-       node->length = rounddown(offset + length, mm->block_size) - node->offset;
+
+       if (length) {
+               node->offset  = roundup(offset, mm->block_size);
+               node->length  = rounddown(offset + length, mm->block_size);
+               node->length -= node->offset;
+       }
 
        list_add_tail(&node->nl_entry, &mm->nodes);
        list_add_tail(&node->fl_entry, &mm->free);
        mm->heap_nodes++;
-       mm->heap_size += length;
        return 0;
 }
 
@@ -236,7 +239,7 @@ nouveau_mm_fini(struct nouveau_mm *mm)
        int nodes = 0;
 
        list_for_each_entry(node, &mm->nodes, nl_entry) {
-               if (nodes++ == mm->heap_nodes)
+               if (WARN_ON(nodes++ == mm->heap_nodes))
                        return -EBUSY;
        }
 
index 16a9afb1060b72372ce4cd879870ec362dc9c0e8..15b182c84ce8b74b55f0cb1073c452a410329f6e 100644 (file)
@@ -22,6 +22,8 @@
  * Authors: Ben Skeggs
  */
 
+#include <subdev/bar.h>
+
 #include <engine/software.h>
 #include <engine/disp.h>
 
@@ -37,6 +39,7 @@ nv50_disp_sclass[] = {
 static void
 nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
 {
+       struct nouveau_bar *bar = nouveau_bar(priv);
        struct nouveau_disp *disp = &priv->base;
        struct nouveau_software_chan *chan, *temp;
        unsigned long flags;
@@ -46,19 +49,25 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
                if (chan->vblank.crtc != crtc)
                        continue;
 
-               nv_wr32(priv, 0x001704, chan->vblank.channel);
-               nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
-
-               if (nv_device(priv)->chipset == 0x50) {
-                       nv_wr32(priv, 0x001570, chan->vblank.offset);
-                       nv_wr32(priv, 0x001574, chan->vblank.value);
+               if (nv_device(priv)->chipset >= 0xc0) {
+                       nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
+                       bar->flush(bar);
+                       nv_wr32(priv, 0x06000c,
+                               upper_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x060010,
+                               lower_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x060014, chan->vblank.value);
                } else {
-                       if (nv_device(priv)->chipset >= 0xc0) {
-                               nv_wr32(priv, 0x06000c,
-                                       upper_32_bits(chan->vblank.offset));
+                       nv_wr32(priv, 0x001704, chan->vblank.channel);
+                       nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
+                       bar->flush(bar);
+                       if (nv_device(priv)->chipset == 0x50) {
+                               nv_wr32(priv, 0x001570, chan->vblank.offset);
+                               nv_wr32(priv, 0x001574, chan->vblank.value);
+                       } else {
+                               nv_wr32(priv, 0x060010, chan->vblank.offset);
+                               nv_wr32(priv, 0x060014, chan->vblank.value);
                        }
-                       nv_wr32(priv, 0x060010, chan->vblank.offset);
-                       nv_wr32(priv, 0x060014, chan->vblank.value);
                }
 
                list_del(&chan->vblank.head);
index e45035efb8ca084c37785ffd4a0ca789523d4a2b..7bbb1e1b7a8d1ebbeeb275dd38e27caaa7a1400c 100644 (file)
@@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem)
                           });
 }
 
-void
+int
 nv40_grctx_init(struct nouveau_device *device, u32 *size)
 {
-       u32 ctxprog[256], i;
+       u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i;
        struct nouveau_grctx ctx = {
                .device = device,
                .mode = NOUVEAU_GRCTX_PROG,
                .data = ctxprog,
-               .ctxprog_max = ARRAY_SIZE(ctxprog)
+               .ctxprog_max = 256,
        };
 
+       if (!ctxprog)
+               return -ENOMEM;
+
        nv40_grctx_generate(&ctx);
 
        nv_wr32(device, 0x400324, 0);
        for (i = 0; i < ctx.ctxprog_len; i++)
                nv_wr32(device, 0x400328, ctxprog[i]);
        *size = ctx.ctxvals_pos * 4;
+
+       kfree(ctxprog);
+       return 0;
 }
index 8d0021049ec09eeaf139b7797736965f52f8a7f2..cc6574eeb80e6459166224185a5bd81ce41e9aa4 100644 (file)
@@ -156,8 +156,8 @@ nv40_graph_context_ctor(struct nouveau_object *parent,
 static int
 nv40_graph_context_fini(struct nouveau_object *object, bool suspend)
 {
-       struct nv04_graph_priv *priv = (void *)object->engine;
-       struct nv04_graph_chan *chan = (void *)object;
+       struct nv40_graph_priv *priv = (void *)object->engine;
+       struct nv40_graph_chan *chan = (void *)object;
        u32 inst = 0x01000000 | nv_gpuobj(chan)->addr >> 4;
        int ret = 0;
 
@@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object)
                return ret;
 
        /* generate and upload context program */
-       nv40_grctx_init(nv_device(priv), &priv->size);
+       ret = nv40_grctx_init(nv_device(priv), &priv->size);
+       if (ret)
+               return ret;
 
        /* No context present currently */
        nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
index d2ac975afc2e8f46feff64c6be4c16e04faf73b3..7da35a4e7970d1684433f3fd036c60492a5ddb0d 100644 (file)
@@ -15,7 +15,7 @@ nv44_graph_class(void *priv)
        return !(0x0baf & (1 << (device->chipset & 0x0f)));
 }
 
-void nv40_grctx_init(struct nouveau_device *, u32 *size);
+int  nv40_grctx_init(struct nouveau_device *, u32 *size);
 void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *);
 
 #endif
index 12418574efeae389fa6fe3ee102379ae32b5fd19..f7c581ad1991b880b3abe6590f0250b68261a9d2 100644 (file)
@@ -38,7 +38,7 @@ struct nv40_mpeg_priv {
 };
 
 struct nv40_mpeg_chan {
-       struct nouveau_mpeg base;
+       struct nouveau_mpeg_chan base;
 };
 
 /*******************************************************************************
index 9ee9bf4028ca168800bc2c6fbcac96346aad9024..975137ba34a6faefb7d4121b8db2efd3464a28c6 100644 (file)
@@ -19,7 +19,6 @@ struct nouveau_mm {
 
        u32 block_size;
        int heap_nodes;
-       u32 heap_size;
 };
 
 int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block);
index 818feabbf4a0969f090f897852fe4476a422b1b6..486f1a9217fd6cd51dc2c5530d455eaa155c86b4 100644 (file)
@@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data)
        return temp;
 }
 
-static inline bool
-nv_strncmp(void *obj, u32 addr, u32 len, const char *str)
+static inline int
+nv_memcmp(void *obj, u32 addr, const char *str, u32 len)
 {
+       unsigned char c1, c2;
+
        while (len--) {
-               if (nv_ro08(obj, addr++) != *(str++))
-                       return false;
+               c1 = nv_ro08(obj, addr++);
+               c2 = *(str++);
+               if (c1 != c2)
+                       return c1 - c2;
        }
-       return true;
+       return 0;
 }
 
 #endif
index 39e73b91d360a3753dbcc3c210ca1e77f00332ec..41b7a6a76f1981ae3427278bacaf8d2c99edbe09 100644 (file)
@@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
                        int clk, struct nouveau_pll_vals *);
 int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,
                        struct nouveau_pll_vals *);
-
+int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
+                       int clk, struct nouveau_pll_vals *);
 
 #endif
index dcb5c2befc928a716425ace89149cec8a808c2e3..70ca7d5a1aa1aaa4e4302ab599ed5398d4f666eb 100644 (file)
@@ -72,7 +72,7 @@ nouveau_bios_shadow_of(struct nouveau_bios *bios)
        }
 
        data = of_get_property(dn, "NVDA,BMP", &size);
-       if (data) {
+       if (data && size) {
                bios->size = size;
                bios->data = kmalloc(bios->size, GFP_KERNEL);
                if (bios->data)
@@ -104,6 +104,9 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios)
                goto out;
 
        bios->size = nv_rd08(bios, 0x700002) * 512;
+       if (!bios->size)
+               goto out;
+
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
                for (i = 0; i < bios->size; i++)
@@ -155,6 +158,9 @@ nouveau_bios_shadow_prom(struct nouveau_bios *bios)
 
        /* read entire bios image to system memory */
        bios->size = nv_rd08(bios, 0x300002) * 512;
+       if (!bios->size)
+               goto out;
+
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        if (bios->data) {
                for (i = 0; i < bios->size; i++)
@@ -186,14 +192,22 @@ nouveau_bios_shadow_acpi(struct nouveau_bios *bios)
 {
        struct pci_dev *pdev = nv_device(bios)->pdev;
        int ret, cnt, i;
-       u8  data[3];
 
-       if (!nouveau_acpi_rom_supported(pdev))
+       if (!nouveau_acpi_rom_supported(pdev)) {
+               bios->data = NULL;
                return;
+       }
 
        bios->size = 0;
-       if (nouveau_acpi_get_bios_chunk(data, 0, 3) == 3)
-               bios->size = data[2] * 512;
+       bios->data = kmalloc(4096, GFP_KERNEL);
+       if (bios->data) {
+               if (nouveau_acpi_get_bios_chunk(bios->data, 0, 4096) == 4096)
+                       bios->size = bios->data[2] * 512;
+               kfree(bios->data);
+       }
+
+       if (!bios->size)
+               return;
 
        bios->data = kmalloc(bios->size, GFP_KERNEL);
        for (i = 0; bios->data && i < bios->size; i += cnt) {
@@ -229,12 +243,14 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
 static int
 nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
 {
-       if (!bios->data || bios->data[0] != 0x55 || bios->data[1] != 0xAA) {
+       if (bios->size < 3 || !bios->data || bios->data[0] != 0x55 ||
+                       bios->data[1] != 0xAA) {
                nv_info(bios, "... signature not found\n");
                return 0;
        }
 
-       if (nvbios_checksum(bios->data, bios->data[2] * 512)) {
+       if (nvbios_checksum(bios->data,
+                       min_t(u32, bios->data[2] * 512, bios->size))) {
                nv_info(bios, "... checksum invalid\n");
                /* if a ro image is somewhat bad, it's probably all rubbish */
                return writeable ? 2 : 1;
index 9ed6e728a94c920ef870ea35d516f0a79863309a..c511971577490499002426ed04087a517d8e0dab 100644 (file)
@@ -43,7 +43,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
        *ver = nv_ro08(bios, dcb);
 
        if (*ver >= 0x41) {
-               nv_warn(bios, "DCB *ver 0x%02x unknown\n", *ver);
+               nv_warn(bios, "DCB version 0x%02x unknown\n", *ver);
                return 0x0000;
        } else
        if (*ver >= 0x30) {
@@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
                }
        } else
        if (*ver >= 0x15) {
-               if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) {
+               if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) {
                        u16 i2c = nv_ro16(bios, dcb + 2);
                        *hdr = 4;
                        *cnt = (i2c - dcb) / 10;
index 5e5f4cddae3cc7248ed527c07b94e8d0c15e97e4..f835501203e552abb29b68425cb5b0a9b37e6bec 100644 (file)
@@ -157,11 +157,10 @@ pll_map_reg(struct nouveau_bios *bios, u32 reg, u32 *type, u8 *ver, u8 *len)
        while (map->reg) {
                if (map->reg == reg && *ver >= 0x20) {
                        u16 addr = (data += hdr);
+                       *type = map->type;
                        while (cnt--) {
-                               if (nv_ro32(bios, data) == map->reg) {
-                                       *type = map->type;
+                               if (nv_ro32(bios, data) == map->reg)
                                        return data;
-                               }
                                data += *len;
                        }
                        return addr;
@@ -200,11 +199,10 @@ pll_map_type(struct nouveau_bios *bios, u8 type, u32 *reg, u8 *ver, u8 *len)
        while (map->reg) {
                if (map->type == type && *ver >= 0x20) {
                        u16 addr = (data += hdr);
+                       *reg = map->reg;
                        while (cnt--) {
-                               if (nv_ro32(bios, data) == map->reg) {
-                                       *reg = map->reg;
+                               if (nv_ro32(bios, data) == map->reg)
                                        return data;
-                               }
                                data += *len;
                        }
                        return addr;
index cc8d7d162d7c348da6770d7404f195e9191d41e1..9068c98b96f64f2f8c0c5a18d478400d09855553 100644 (file)
@@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq)
        return ret;
 }
 
+int
+nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info,
+                   int clk, struct nouveau_pll_vals *pv)
+{
+       int ret, N, M, P;
+
+       ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P);
+
+       if (ret > 0) {
+               pv->refclk = info->refclk;
+               pv->N1 = N;
+               pv->M1 = M;
+               pv->log2P = P;
+       }
+       return ret;
+}
+
+
 static int
 nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                struct nouveau_oclass *oclass, void *data, u32 size,
@@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nva3_clock_pll_set;
+       priv->base.pll_calc = nva3_clock_pll_calc;
        return 0;
 }
 
index 5ccce0b17bf3dd209bde225486b41bab55fcdf79..f6962c9b6c36b6f00db2715287dedf1c3adb9f4e 100644 (file)
@@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nvc0_clock_pll_set;
+       priv->base.pll_calc = nva3_clock_pll_calc;
        return 0;
 }
 
index 436e9efe7ef5d862c047a308b77d394c10238118..5f570806143ad0fb35fcd67017acf07513b563e4 100644 (file)
@@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                             ((priv->base.ram.size & 0x000000ff) << 32);
 
        tags = nv_rd32(priv, 0x100320);
-       if (tags) {
-               ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
-               if (ret)
-                       return ret;
+       ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1);
+       if (ret)
+               return ret;
 
-               nv_debug(priv, "%d compression tags\n", tags);
-       }
+       nv_debug(priv, "%d compression tags\n", tags);
 
        size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;
        switch (device->chipset) {
@@ -237,6 +235,7 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                        return ret;
 
                priv->base.ram.stolen = (u64)nv_rd32(priv, 0x100e10) << 12;
+               priv->base.ram.type = NV_MEM_TYPE_STOLEN;
                break;
        default:
                ret = nouveau_mm_init(&priv->base.vram, rsvd_head, size,
@@ -277,7 +276,6 @@ nv50_fb_dtor(struct nouveau_object *object)
                __free_page(priv->r100c08_page);
        }
 
-       nouveau_mm_fini(&priv->base.vram);
        nouveau_fb_destroy(&priv->base);
 }
 
index 3d2c88310f982553380f19a7f89d5379a89a5d01..dbfc2abf0cfe1a98379a567fa8a7a90fcd409d5f 100644 (file)
@@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                case DCB_I2C_NVIO_BIT:
                        port->drive = info.drive & 0x0f;
                        if (device->card_type < NV_D0) {
-                               if (info.drive >= ARRAY_SIZE(nv50_i2c_port))
+                               if (port->drive >= ARRAY_SIZE(nv50_i2c_port))
                                        break;
                                port->drive = nv50_i2c_port[port->drive];
                                port->sense = port->drive;
index b29237970fa082ba3cdc5dcd9497e5d7bbe0714b..5231786851805da5e68840668a29db856f56cdb6 100644 (file)
@@ -134,7 +134,7 @@ nouveau_therm_fan_sense(struct nouveau_therm *therm)
        end = ptimer->read(ptimer);
 
        if (cycles == 5) {
-               tach = (u64)60000000000;
+               tach = (u64)60000000000ULL;
                do_div(tach, (end - start));
                return tach;
        } else
index 0203e1e12caaad34f4639ec3824a33d770a5d447..9474cfca6e4ccde36379d3dfa3426317be005741 100644 (file)
@@ -67,7 +67,7 @@ nv41_vm_unmap(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt)
 static void
 nv41_vm_flush(struct nouveau_vm *vm)
 {
-       struct nv04_vm_priv *priv = (void *)vm->vmm;
+       struct nv04_vmmgr_priv *priv = (void *)vm->vmm;
 
        mutex_lock(&nv_subdev(priv)->mutex);
        nv_wr32(priv, 0x100810, 0x00000022);
@@ -92,7 +92,8 @@ nv41_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
-       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
+           !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
                return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
                                           data, size, pobject);
        }
index 0ac18d05a146389b6d87e8c7898188fda5b5c5e3..aa8131436e3dced3d3d9ef894fec6d5ff21cee2d 100644 (file)
@@ -163,7 +163,8 @@ nv44_vmmgr_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
        struct nv04_vmmgr_priv *priv;
        int ret;
 
-       if (!nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
+       if (pci_find_capability(device->pdev, PCI_CAP_ID_AGP) ||
+           !nouveau_boolopt(device->cfgopt, "NvPCIE", true)) {
                return nouveau_object_ctor(parent, engine, &nv04_vmmgr_oclass,
                                           data, size, pobject);
        }
index cc79c796afee316cd810125b93dd86fbef940d5e..cbf1fc60a38682be197dc1bb1f0f15c8853a06e6 100644 (file)
@@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 
        if (unlikely(!abi16))
                return -ENOMEM;
+
+       if (!drm->channel)
+               return nouveau_abi16_put(abi16, -ENODEV);
+
        client = nv_client(abi16->client);
 
        if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
index 259e5f1adf4754ba270b22f8d32cc992695a28be..35ac57f0aab640c034b29cc15c8ca0315d1f8ec5 100644 (file)
@@ -456,6 +456,7 @@ static struct ttm_tt *
 nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size,
                      uint32_t page_flags, struct page *dummy_read)
 {
+#if __OS_HAS_AGP
        struct nouveau_drm *drm = nouveau_bdev(bdev);
        struct drm_device *dev = drm->dev;
 
@@ -463,6 +464,7 @@ nouveau_ttm_tt_create(struct ttm_bo_device *bdev, unsigned long size,
                return ttm_agp_tt_create(bdev, dev->agp->bridge, size,
                                         page_flags, dummy_read);
        }
+#endif
 
        return nouveau_sgdma_create_ttm(bdev, size, page_flags, dummy_read);
 }
index 9a6e2cb282dc4e38612845f41f224c5e2aa9b083..d3595b23434ace439cc2087e871f636e86e59867 100644 (file)
@@ -355,7 +355,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
         * valid - it's not (rh#613284)
         */
        if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
-               if (!(nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
+               if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) {
                        status = connector_status_connected;
                        goto out;
                }
index 8f98e5a8c488dba5c8e86d937aa26b5e65d78175..86124b131f4f31a2ca18e8c2416084ad6df1f585 100644 (file)
@@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_disp *pdisp = nouveau_disp(drm->device);
        struct nouveau_display *disp;
+       u32 pclass = dev->pdev->class >> 8;
        int ret, gen;
 
        disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL);
@@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)
        drm_kms_helper_poll_init(dev);
        drm_kms_helper_poll_disable(dev);
 
-       if (nv_device(drm->device)->card_type < NV_50)
-               ret = nv04_display_create(dev);
-       else
-       if (nv_device(drm->device)->card_type < NV_D0)
-               ret = nv50_display_create(dev);
-       else
-               ret = nvd0_display_create(dev);
-       if (ret)
-               goto disp_create_err;
-
-       if (dev->mode_config.num_crtc) {
-               ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+       if (nouveau_modeset == 1 ||
+           (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) {
+               if (nv_device(drm->device)->card_type < NV_50)
+                       ret = nv04_display_create(dev);
+               else
+               if (nv_device(drm->device)->card_type < NV_D0)
+                       ret = nv50_display_create(dev);
+               else
+                       ret = nvd0_display_create(dev);
                if (ret)
-                       goto vblank_err;
+                       goto disp_create_err;
+
+               if (dev->mode_config.num_crtc) {
+                       ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+                       if (ret)
+                               goto vblank_err;
+               }
+
+               nouveau_backlight_init(dev);
        }
 
-       nouveau_backlight_init(dev);
        return 0;
 
 vblank_err:
@@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)
        nouveau_backlight_exit(dev);
        drm_vblank_cleanup(dev);
 
-       disp->dtor(dev);
+       if (disp->dtor)
+               disp->dtor(dev);
 
        drm_kms_helper_poll_fini(dev);
        drm_mode_config_cleanup(dev);
@@ -530,9 +536,11 @@ nouveau_page_flip_reserve(struct nouveau_bo *old_bo,
        if (ret)
                goto fail;
 
-       ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
-       if (ret)
-               goto fail_unreserve;
+       if (likely(old_bo != new_bo)) {
+               ret = ttm_bo_reserve(&old_bo->bo, false, false, false, 0);
+               if (ret)
+                       goto fail_unreserve;
+       }
 
        return 0;
 
@@ -551,8 +559,10 @@ nouveau_page_flip_unreserve(struct nouveau_bo *old_bo,
        nouveau_bo_fence(new_bo, fence);
        ttm_bo_unreserve(&new_bo->bo);
 
-       nouveau_bo_fence(old_bo, fence);
-       ttm_bo_unreserve(&old_bo->bo);
+       if (likely(old_bo != new_bo)) {
+               nouveau_bo_fence(old_bo, fence);
+               ttm_bo_unreserve(&old_bo->bo);
+       }
 
        nouveau_bo_unpin(old_bo);
 }
index ccae8c26ae2b34ecc25e8312ee6d57c0d14f06e3..8503b2ea570a0616234e409c524593f37a98648e 100644 (file)
@@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");
 static int nouveau_noaccel = 0;
 module_param_named(noaccel, nouveau_noaccel, int, 0400);
 
-MODULE_PARM_DESC(modeset, "enable driver");
-static int nouveau_modeset = -1;
+MODULE_PARM_DESC(modeset, "enable driver (default: auto, "
+                         "0 = disabled, 1 = enabled, 2 = headless)");
+int nouveau_modeset = -1;
 module_param_named(modeset, nouveau_modeset, int, 0400);
 
 static struct drm_driver driver;
@@ -128,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
 
        /* initialise synchronisation routines */
        if      (device->card_type < NV_10) ret = nv04_fence_create(drm);
-       else if (device->chipset   <  0x84) ret = nv10_fence_create(drm);
+       else if (device->card_type < NV_50) ret = nv10_fence_create(drm);
+       else if (device->chipset   <  0x84) ret = nv50_fence_create(drm);
        else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
        else                                ret = nvc0_fence_create(drm);
        if (ret) {
@@ -363,7 +365,8 @@ nouveau_drm_unload(struct drm_device *dev)
 
        nouveau_pm_fini(dev);
 
-       nouveau_display_fini(dev);
+       if (dev->mode_config.num_crtc)
+               nouveau_display_fini(dev);
        nouveau_display_destroy(dev);
 
        nouveau_irq_fini(dev);
@@ -403,13 +406,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)
            pm_state.event == PM_EVENT_PRETHAW)
                return 0;
 
-       NV_INFO(drm, "suspending fbcon...\n");
-       nouveau_fbcon_set_suspend(dev, 1);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "suspending fbcon...\n");
+               nouveau_fbcon_set_suspend(dev, 1);
 
-       NV_INFO(drm, "suspending display...\n");
-       ret = nouveau_display_suspend(dev);
-       if (ret)
-               return ret;
+               NV_INFO(drm, "suspending display...\n");
+               ret = nouveau_display_suspend(dev);
+               if (ret)
+                       return ret;
+       }
 
        NV_INFO(drm, "evicting buffers...\n");
        ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM);
@@ -445,8 +450,10 @@ fail_client:
                nouveau_client_init(&cli->base);
        }
 
-       NV_INFO(drm, "resuming display...\n");
-       nouveau_display_resume(dev);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "resuming display...\n");
+               nouveau_display_resume(dev);
+       }
        return ret;
 }
 
@@ -486,8 +493,10 @@ nouveau_drm_resume(struct pci_dev *pdev)
        nouveau_irq_postinstall(dev);
        nouveau_pm_resume(dev);
 
-       NV_INFO(drm, "resuming display...\n");
-       nouveau_display_resume(dev);
+       if (dev->mode_config.num_crtc) {
+               NV_INFO(drm, "resuming display...\n");
+               nouveau_display_resume(dev);
+       }
        return 0;
 }
 
@@ -662,9 +671,7 @@ nouveau_drm_init(void)
 #ifdef CONFIG_VGA_CONSOLE
                if (vgacon_text_force())
                        nouveau_modeset = 0;
-               else
 #endif
-                       nouveau_modeset = 1;
        }
 
        if (!nouveau_modeset)
index 819471217546b23cb867e3e583ed856d5d810ea2..a10169927086dfea6c826dac0378ae1d2c82ffb3 100644 (file)
@@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);
                nv_info((cli), fmt, ##args);                                   \
 } while (0)
 
+extern int nouveau_modeset;
+
 #endif
index 9ca8afdb5549777c7a2b25e64de9b63f700260bc..1d8cb506a28ae5159ebe4c9df362f3f0d92d7758 100644 (file)
@@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
 
        nv_subdev(pmc)->intr(nv_subdev(pmc));
 
-       if (device->card_type >= NV_D0) {
-               if (nv_rd32(device, 0x000100) & 0x04000000)
-                       nvd0_display_intr(dev);
-       } else
-       if (device->card_type >= NV_50) {
-               if (nv_rd32(device, 0x000100) & 0x04000000)
-                       nv50_display_intr(dev);
+       if (dev->mode_config.num_crtc) {
+               if (device->card_type >= NV_D0) {
+                       if (nv_rd32(device, 0x000100) & 0x04000000)
+                               nvd0_display_intr(dev);
+               } else
+               if (device->card_type >= NV_50) {
+                       if (nv_rd32(device, 0x000100) & 0x04000000)
+                               nv50_display_intr(dev);
+               }
        }
 
        return IRQ_HANDLED;
index 0bf64c90aa206cc42879e2621a8da1f5481e7f4d..5566172774df4b2ff891db4745483b8655754a5b 100644 (file)
@@ -52,7 +52,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl,
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_pm *pm = nouveau_pm(dev);
-       struct nouveau_therm *therm = nouveau_therm(drm);
+       struct nouveau_therm *therm = nouveau_therm(drm->device);
        int ret;
 
        /*XXX: not on all boards, we should control based on temperature
@@ -64,7 +64,6 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl,
                ret = therm->fan_set(therm, perflvl->fanspeed);
                if (ret && ret != -ENODEV) {
                        NV_ERROR(drm, "fanspeed set failed: %d\n", ret);
-                       return ret;
                }
        }
 
@@ -706,8 +705,7 @@ nouveau_hwmon_init(struct drm_device *dev)
        struct device *hwmon_dev;
        int ret = 0;
 
-       if (!therm || !therm->temp_get || !therm->attr_get ||
-               !therm->attr_set || therm->temp_get(therm) < 0)
+       if (!therm || !therm->temp_get || !therm->attr_get || !therm->attr_set)
                return -ENODEV;
 
        hwmon_dev = hwmon_device_register(&dev->pdev->dev);
index 347a3bd78d0486f1fed24f11d8183f9382d822dd..64f7020fb605dcaff92163aa161d174ad0d77a23 100644 (file)
@@ -220,7 +220,7 @@ out:
        NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);
 
        if (blue == 0x18) {
-               NV_INFO(drm, "Load detected on head A\n");
+               NV_DEBUG(drm, "Load detected on head A\n");
                return connector_status_connected;
        }
 
@@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 
        if (nv17_dac_sample_load(encoder) &
            NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
-               NV_INFO(drm, "Load detected on output %c\n",
-                       '@' + ffs(dcb->or));
+               NV_DEBUG(drm, "Load detected on output %c\n",
+                        '@' + ffs(dcb->or));
                return connector_status_connected;
        } else {
                return connector_status_disconnected;
@@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
@@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
 }
index da55d7642c8cdd325ccca35bd8a1d1b1c1bda8f5..184cdf806761c0bc0cefb52af00a8799ae8e6393 100644 (file)
@@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-               drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-               nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
+                nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode)
@@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        if (was_powersaving && is_powersaving_dpms(mode))
                return;
@@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)
                return;
        nv_encoder->last_dpms = mode;
 
-       NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
-                    mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        nv04_dfp_update_backlight(encoder, mode);
        nv04_dfp_update_fp_control(encoder, mode);
index 099fbeda6e2e18f85b7dedbc961582516729b50a..62e826a139b3bd4b08d00a0ca46e0efc59c62d63 100644 (file)
@@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)
        struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;
        uint8_t crtc1A;
 
-       NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
-               mode, nv_encoder->dcb->index);
+       NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n",
+                mode, nv_encoder->dcb->index);
 
        state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK);
 
@@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
 
        helper->dpms(encoder, DRM_MODE_DPMS_ON);
 
-       NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n",
-                     drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index,
-                     '@' + ffs(nv_encoder->dcb->or));
+       NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n",
+                drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
 }
 
 static void nv04_tv_destroy(struct drm_encoder *encoder)
index 96184d02c8d924969527c307d137a55664c6f96c..3bce0299f64a664f9d1de78a6f452c907221694f 100644 (file)
@@ -1690,41 +1690,49 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
                }
                /* all other cases */
                pll_in_use = radeon_get_pll_use_mask(crtc);
-               if (!(pll_in_use & (1 << ATOM_PPLL2)))
-                       return ATOM_PPLL2;
                if (!(pll_in_use & (1 << ATOM_PPLL1)))
                        return ATOM_PPLL1;
+               if (!(pll_in_use & (1 << ATOM_PPLL2)))
+                       return ATOM_PPLL2;
                DRM_ERROR("unable to allocate a PPLL\n");
                return ATOM_PPLL_INVALID;
-       } else {
-               if (ASIC_IS_AVIVO(rdev)) {
-                       /* in DP mode, the DP ref clock can come from either PPLL
-                        * depending on the asic:
-                        * DCE3: PPLL1 or PPLL2
-                        */
-                       if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
-                               /* use the same PPLL for all DP monitors */
-                               pll = radeon_get_shared_dp_ppll(crtc);
-                               if (pll != ATOM_PPLL_INVALID)
-                                       return pll;
-                       } else {
-                               /* use the same PPLL for all monitors with the same clock */
-                               pll = radeon_get_shared_nondp_ppll(crtc);
-                               if (pll != ATOM_PPLL_INVALID)
-                                       return pll;
-                       }
-                       /* all other cases */
-                       pll_in_use = radeon_get_pll_use_mask(crtc);
+       } else if (ASIC_IS_AVIVO(rdev)) {
+               /* in DP mode, the DP ref clock can come from either PPLL
+                * depending on the asic:
+                * DCE3: PPLL1 or PPLL2
+                */
+               if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(radeon_crtc->encoder))) {
+                       /* use the same PPLL for all DP monitors */
+                       pll = radeon_get_shared_dp_ppll(crtc);
+                       if (pll != ATOM_PPLL_INVALID)
+                               return pll;
+               } else {
+                       /* use the same PPLL for all monitors with the same clock */
+                       pll = radeon_get_shared_nondp_ppll(crtc);
+                       if (pll != ATOM_PPLL_INVALID)
+                               return pll;
+               }
+               /* all other cases */
+               pll_in_use = radeon_get_pll_use_mask(crtc);
+               /* the order shouldn't matter here, but we probably
+                * need this until we have atomic modeset
+                */
+               if (rdev->flags & RADEON_IS_IGP) {
+                       if (!(pll_in_use & (1 << ATOM_PPLL1)))
+                               return ATOM_PPLL1;
+                       if (!(pll_in_use & (1 << ATOM_PPLL2)))
+                               return ATOM_PPLL2;
+               } else {
                        if (!(pll_in_use & (1 << ATOM_PPLL2)))
                                return ATOM_PPLL2;
                        if (!(pll_in_use & (1 << ATOM_PPLL1)))
                                return ATOM_PPLL1;
-                       DRM_ERROR("unable to allocate a PPLL\n");
-                       return ATOM_PPLL_INVALID;
-               } else {
-                       /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
-                       return radeon_crtc->crtc_id;
                }
+               DRM_ERROR("unable to allocate a PPLL\n");
+               return ATOM_PPLL_INVALID;
+       } else {
+               /* on pre-R5xx asics, the crtc to pll mapping is hardcoded */
+               return radeon_crtc->crtc_id;
        }
 }
 
index 49cbb3795a102e755337a3c2105f03caedc0f2ee..010bae19554ad204537a31a5e02584d130086ff3 100644 (file)
@@ -184,6 +184,7 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        struct radeon_backlight_privdata *pdata;
        struct radeon_encoder_atom_dig *dig;
        u8 backlight_level;
+       char bl_name[16];
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -203,7 +204,9 @@ void radeon_atom_backlight_init(struct radeon_encoder *radeon_encoder,
        memset(&props, 0, sizeof(props));
        props.max_brightness = RADEON_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+       snprintf(bl_name, sizeof(bl_name),
+                "radeon_bl%d", dev->primary->index);
+       bd = backlight_device_register(bl_name, &drm_connector->kdev,
                                       pdata, &radeon_atom_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
@@ -1622,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                        /* some early dce3.2 boards have a bug in their transmitter control table */
-                       if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
+                       if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
                                atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
index a1f49c5fd74b2ce287f0fe2786434853779fa033..219942c660d7d2129e7c21ac375761dcd5309c9f 100644 (file)
@@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                                        break;
                                udelay(1);
                        }
+               } else {
+                       save->crtc_enabled[i] = false;
                }
        }
 
@@ -1372,7 +1374,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
        WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN);
 
        for (i = 0; i < rdev->num_crtc; i++) {
-               if (save->crtc_enabled) {
+               if (save->crtc_enabled[i]) {
                        if (ASIC_IS_DCE6(rdev)) {
                                tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]);
                                tmp |= EVERGREEN_CRTC_BLANK_DATA_EN;
@@ -3431,9 +3433,14 @@ void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
        if (!(mask & DRM_PCIE_SPEED_50))
                return;
 
+       speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+       if (speed_cntl & LC_CURRENT_DATA_RATE) {
+               DRM_INFO("PCIE gen 2 link speeds already enabled\n");
+               return;
+       }
+
        DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
 
-       speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
        if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) ||
            (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
 
index 573ed1bc6cf7d36ffd1a3385cc05350fd7a3d3a0..c042e497e4507eaebfd91bb477acbc7520f0143d 100644 (file)
@@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,
        /* macro tile width & height */
        palign = (8 * surf->bankw * track->npipes) * surf->mtilea;
        halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea;
-       mtileb = (palign / 8) * (halign / 8) * tileb;;
+       mtileb = (palign / 8) * (halign / 8) * tileb;
        mtile_pr = surf->nbx / palign;
        mtile_ps = (mtile_pr * surf->nby) / halign;
        surf->layer_size = mtile_ps * mtileb * slice_pt;
@@ -2725,6 +2725,9 @@ static bool evergreen_vm_reg_valid(u32 reg)
        /* check config regs */
        switch (reg) {
        case GRBM_GFX_INDEX:
+       case CP_STRMOUT_CNTL:
+       case CP_COHER_CNTL:
+       case CP_COHER_SIZE:
        case VGT_VTX_VECT_EJECT_REG:
        case VGT_CACHE_INVALIDATION:
        case VGT_GS_VERTEX_REUSE:
@@ -2829,6 +2832,7 @@ static bool evergreen_vm_reg_valid(u32 reg)
        case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS:
                return true;
        default:
+               DRM_ERROR("Invalid register 0x%x in CS\n", reg);
                return false;
        }
 }
index df542f1a5dfbf38198d6bfbe329fd6964eacf352..2bc0f6a1b428ab8151b2a7fa57d5f7848ab0dda6 100644 (file)
 #define                FB_READ_EN                                      (1 << 0)
 #define                FB_WRITE_EN                                     (1 << 1)
 
+#define        CP_STRMOUT_CNTL                                 0x84FC
+
+#define        CP_COHER_CNTL                                   0x85F0
+#define        CP_COHER_SIZE                                   0x85F4
 #define        CP_COHER_BASE                                   0x85F8
 #define        CP_STALLED_STAT1                        0x8674
 #define        CP_STALLED_STAT2                        0x8678
index 8bcb554ea0c527126d7b4a618c2b53d504ecf7ff..81e6a568c29debcf49bb915c5d3aa19bcc88324e 100644 (file)
@@ -770,9 +770,13 @@ static int cayman_pcie_gart_enable(struct radeon_device *rdev)
        WREG32(0x15DC, 0);
 
        /* empty context1-7 */
+       /* Assign the pt base to something valid for now; the pts used for
+        * the VMs are determined by the application and setup and assigned
+        * on the fly in the vm part of radeon_gart.c
+        */
        for (i = 1; i < 8; i++) {
                WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0);
-               WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), 0);
+               WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn);
                WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
                        rdev->gart.table_addr >> 12);
        }
@@ -1534,26 +1538,31 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe,
 {
        struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
-       int i;
 
-       radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, 1 + count * 2));
-       radeon_ring_write(ring, pe);
-       radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
-       for (i = 0; i < count; ++i) {
-               uint64_t value = 0;
-               if (flags & RADEON_VM_PAGE_SYSTEM) {
-                       value = radeon_vm_map_gart(rdev, addr);
-                       value &= 0xFFFFFFFFFFFFF000ULL;
-                       addr += incr;
-
-               } else if (flags & RADEON_VM_PAGE_VALID) {
-                       value = addr;
-                       addr += incr;
-               }
+       while (count) {
+               unsigned ndw = 1 + count * 2;
+               if (ndw > 0x3FFF)
+                       ndw = 0x3FFF;
+
+               radeon_ring_write(ring, PACKET3(PACKET3_ME_WRITE, ndw));
+               radeon_ring_write(ring, pe);
+               radeon_ring_write(ring, upper_32_bits(pe) & 0xff);
+               for (; ndw > 1; ndw -= 2, --count, pe += 8) {
+                       uint64_t value = 0;
+                       if (flags & RADEON_VM_PAGE_SYSTEM) {
+                               value = radeon_vm_map_gart(rdev, addr);
+                               value &= 0xFFFFFFFFFFFFF000ULL;
+                               addr += incr;
+
+                       } else if (flags & RADEON_VM_PAGE_VALID) {
+                               value = addr;
+                               addr += incr;
+                       }
 
-               value |= r600_flags;
-               radeon_ring_write(ring, value);
-               radeon_ring_write(ring, upper_32_bits(value));
+                       value |= r600_flags;
+                       radeon_ring_write(ring, value);
+                       radeon_ring_write(ring, upper_32_bits(value));
+               }
        }
 }
 
@@ -1572,12 +1581,6 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        if (vm == NULL)
                return;
 
-       radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (vm->id << 2), 0));
-       radeon_ring_write(ring, 0);
-
-       radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (vm->id << 2), 0));
-       radeon_ring_write(ring, vm->last_pfn);
-
        radeon_ring_write(ring, PACKET0(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (vm->id << 2), 0));
        radeon_ring_write(ring, vm->pd_gpu_addr >> 12);
 
@@ -1588,4 +1591,8 @@ void cayman_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        /* bits 0-7 are the VM contexts0-7 */
        radeon_ring_write(ring, PACKET0(VM_INVALIDATE_REQUEST, 0));
        radeon_ring_write(ring, 1 << vm->id);
+
+       /* sync PFP to ME, otherwise we might get invalid PFP reads */
+       radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+       radeon_ring_write(ring, 0x0);
 }
index 2423d1b5d385938f2445706abc97ab74198e1b0f..cbef6815907a13c83efff8b9e863568b1e625980 100644 (file)
 #define        PACKET3_MPEG_INDEX                              0x3A
 #define        PACKET3_WAIT_REG_MEM                            0x3C
 #define        PACKET3_MEM_WRITE                               0x3D
+#define        PACKET3_PFP_SYNC_ME                             0x42
 #define        PACKET3_SURFACE_SYNC                            0x43
 #              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
 #              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
index 70c800ff61901ba6a30d0e714491cc9ccc190d3b..cda280d157da95725b414f54ebcc5cce9f78b7fc 100644 (file)
@@ -3703,6 +3703,12 @@ static void r600_pcie_gen2_enable(struct radeon_device *rdev)
        if (!(mask & DRM_PCIE_SPEED_50))
                return;
 
+       speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
+       if (speed_cntl & LC_CURRENT_DATA_RATE) {
+               DRM_INFO("PCIE gen 2 link speeds already enabled\n");
+               return;
+       }
+
        DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
 
        /* 55 nm r6xx asics */
index b04c06444d8b13b21107e87a842603714f569001..8c42d54c2e26ad56ce7d0c7873128f466e60b801 100644 (file)
@@ -663,9 +663,14 @@ struct radeon_vm {
        struct list_head                list;
        struct list_head                va;
        unsigned                        id;
-       unsigned                        last_pfn;
-       u64                             pd_gpu_addr;
-       struct radeon_sa_bo             *sa_bo;
+
+       /* contains the page directory */
+       struct radeon_sa_bo             *page_directory;
+       uint64_t                        pd_gpu_addr;
+
+       /* array of page tables, one for each page directory entry */
+       struct radeon_sa_bo             **page_tables;
+
        struct mutex                    mutex;
        /* last fence for cs using this vm */
        struct radeon_fence             *fence;
@@ -1843,9 +1848,10 @@ extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size
  */
 int radeon_vm_manager_init(struct radeon_device *rdev);
 void radeon_vm_manager_fini(struct radeon_device *rdev);
-int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm);
+void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm);
 void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm);
 int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm);
+void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm);
 struct radeon_fence *radeon_vm_grab_id(struct radeon_device *rdev,
                                       struct radeon_vm *vm, int ring);
 void radeon_vm_fence(struct radeon_device *rdev,
index b0a5688c67f8c98d91340551207979b810a33fed..196d28d995705f408fe817a08093abad3e370626 100644 (file)
@@ -201,7 +201,7 @@ static int radeon_atif_verify_interface(acpi_handle handle,
 
        size = *(u16 *) info->buffer.pointer;
        if (size < 12) {
-               DRM_INFO("ATIF buffer is too small: %lu\n", size);
+               DRM_INFO("ATIF buffer is too small: %zu\n", size);
                err = -EINVAL;
                goto out;
        }
@@ -370,6 +370,7 @@ int radeon_atif_handler(struct radeon_device *rdev,
 
                        radeon_set_backlight_level(rdev, enc, req.backlight_level);
 
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
                        if (rdev->is_atom_bios) {
                                struct radeon_encoder_atom_dig *dig = enc->enc_priv;
                                backlight_force_update(dig->bl_dev,
@@ -379,6 +380,7 @@ int radeon_atif_handler(struct radeon_device *rdev,
                                backlight_force_update(dig->bl_dev,
                                                       BACKLIGHT_UPDATE_HOTKEY);
                        }
+#endif
                }
        }
        /* TODO: check other events */
@@ -485,7 +487,7 @@ static int radeon_atcs_verify_interface(acpi_handle handle,
 
        size = *(u16 *) info->buffer.pointer;
        if (size < 8) {
-               DRM_INFO("ATCS buffer is too small: %lu\n", size);
+               DRM_INFO("ATCS buffer is too small: %zu\n", size);
                err = -EINVAL;
                goto out;
        }
index 10ea17a6b2a6edfae76955f7e8f2ccd08ea7b1fe..42433344cb1b24860998067fe7c96baf332c1ece 100644 (file)
@@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
        /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/
        { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59,
                PCI_VENDOR_ID_DELL, 0x00e3, 2},
-       /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */
+       /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */
        { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66,
                PCI_VENDOR_ID_DELL, 0x0149, 1},
+       /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */
+       { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66,
+               PCI_VENDOR_ID_IBM, 0x0531, 1},
        /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */
        { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
                0x1025, 0x0061, 1},
index 582e99449c12f28a01482dfc3138bf2ec1ead2d8..15f5ded65e0c290e431a73d4d2c950c9fd9d2687 100644 (file)
@@ -87,7 +87,7 @@ static union acpi_object *radeon_atpx_call(acpi_handle handle, int function,
                atpx_arg_elements[1].integer.value = 0;
        }
 
-       status = acpi_evaluate_object(handle, "ATPX", &atpx_arg, &buffer);
+       status = acpi_evaluate_object(handle, NULL, &atpx_arg, &buffer);
 
        /* Fail only if calling the method fails and ATPX is supported */
        if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
@@ -148,7 +148,7 @@ static int radeon_atpx_verify_interface(struct radeon_atpx *atpx)
 
        size = *(u16 *) info->buffer.pointer;
        if (size < 8) {
-               printk("ATPX buffer is too small: %lu\n", size);
+               printk("ATPX buffer is too small: %zu\n", size);
                err = -EINVAL;
                goto out;
        }
@@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
 }
 
 /**
- * radeon_atpx_switchto - switch to the requested GPU
+ * radeon_atpx_power_state - power down/up the requested GPU
  *
- * @id: GPU to switch to
+ * @id: GPU to power down/up
  * @state: requested power state (0 = off, 1 = on)
  *
  * Execute the necessary ATPX function to power down/up the discrete GPU
@@ -373,11 +373,11 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
 }
 
 /**
- * radeon_atpx_pci_probe_handle - look up the ATRM and ATPX handles
+ * radeon_atpx_pci_probe_handle - look up the ATPX handle
  *
  * @pdev: pci device
  *
- * Look up the ATPX and ATRM handles (all asics).
+ * Look up the ATPX handles (all asics).
  * Returns true if the handles are found, false if not.
  */
 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
index 67cfc1795ecdd4560ac720cc85b0e5a17335a507..b884c362a8c2c0770c02ecb09100d1f9440b55ab 100644 (file)
@@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
        struct drm_mode_object *obj;
        int i;
        enum drm_connector_status ret = connector_status_disconnected;
-       bool dret = false;
+       bool dret = false, broken_edid = false;
 
        if (!force && radeon_check_hpd_status_unchanged(connector))
                return connector->status;
@@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                                ret = connector_status_disconnected;
                                DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
                                radeon_connector->ddc_bus = NULL;
+                       } else {
+                               ret = connector_status_connected;
+                               broken_edid = true; /* defer use_digital to later */
                        }
                } else {
                        radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
@@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
 
                        encoder_funcs = encoder->helper_private;
                        if (encoder_funcs->detect) {
-                               if (ret != connector_status_connected) {
-                                       ret = encoder_funcs->detect(encoder, connector);
-                                       if (ret == connector_status_connected) {
-                                               radeon_connector->use_digital = false;
+                               if (!broken_edid) {
+                                       if (ret != connector_status_connected) {
+                                               /* deal with analog monitors without DDC */
+                                               ret = encoder_funcs->detect(encoder, connector);
+                                               if (ret == connector_status_connected) {
+                                                       radeon_connector->use_digital = false;
+                                               }
+                                               if (ret != connector_status_disconnected)
+                                                       radeon_connector->detected_by_load = true;
                                        }
-                                       if (ret != connector_status_disconnected)
-                                               radeon_connector->detected_by_load = true;
+                               } else {
+                                       enum drm_connector_status lret;
+                                       /* assume digital unless load detected otherwise */
+                                       radeon_connector->use_digital = true;
+                                       lret = encoder_funcs->detect(encoder, connector);
+                                       DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret);
+                                       if (lret == connector_status_connected)
+                                               radeon_connector->use_digital = false;
                                }
                                break;
                        }
index cb7b7c062fef407d0dbbb0a1e6c0c50e7d930690..41672cc563fb13005bc732d581844d9811473047 100644 (file)
@@ -478,6 +478,7 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
        }
 
 out:
+       radeon_vm_add_to_lru(rdev, vm);
        mutex_unlock(&vm->mutex);
        mutex_unlock(&rdev->vm_manager.lock);
        return r;
index 64a42647f08a43cacdabd7a76bc7b52dde6c762b..e2f5f888c374cc29b2f8658a5e0ba9d91325827d 100644 (file)
@@ -355,6 +355,8 @@ int radeon_wb_init(struct radeon_device *rdev)
  */
 void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64 base)
 {
+       uint64_t limit = (uint64_t)radeon_vram_limit << 20;
+
        mc->vram_start = base;
        if (mc->mc_vram_size > (0xFFFFFFFF - base + 1)) {
                dev_warn(rdev->dev, "limiting VRAM to PCI aperture size\n");
@@ -368,8 +370,8 @@ void radeon_vram_location(struct radeon_device *rdev, struct radeon_mc *mc, u64
                mc->mc_vram_size = mc->aper_size;
        }
        mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
-       if (radeon_vram_limit && radeon_vram_limit < mc->real_vram_size)
-               mc->real_vram_size = radeon_vram_limit;
+       if (limit && limit < mc->real_vram_size)
+               mc->real_vram_size = limit;
        dev_info(rdev->dev, "VRAM: %lluM 0x%016llX - 0x%016llX (%lluM used)\n",
                        mc->mc_vram_size >> 20, mc->vram_start,
                        mc->vram_end, mc->real_vram_size >> 20);
@@ -834,6 +836,19 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
                return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }
 
+/**
+ * radeon_check_pot_argument - check that argument is a power of two
+ *
+ * @arg: value to check
+ *
+ * Validates that a certain argument is a power of two (all asics).
+ * Returns true if argument is valid.
+ */
+static bool radeon_check_pot_argument(int arg)
+{
+       return (arg & (arg - 1)) == 0;
+}
+
 /**
  * radeon_check_arguments - validate module params
  *
@@ -845,52 +860,25 @@ static unsigned int radeon_vga_set_decode(void *cookie, bool state)
 static void radeon_check_arguments(struct radeon_device *rdev)
 {
        /* vramlimit must be a power of two */
-       switch (radeon_vram_limit) {
-       case 0:
-       case 4:
-       case 8:
-       case 16:
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-               break;
-       default:
+       if (!radeon_check_pot_argument(radeon_vram_limit)) {
                dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n",
                                radeon_vram_limit);
                radeon_vram_limit = 0;
-               break;
        }
-       radeon_vram_limit = radeon_vram_limit << 20;
+
        /* gtt size must be power of two and greater or equal to 32M */
-       switch (radeon_gart_size) {
-       case 4:
-       case 8:
-       case 16:
+       if (radeon_gart_size < 32) {
                dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n",
                                radeon_gart_size);
                radeon_gart_size = 512;
-               break;
-       case 32:
-       case 64:
-       case 128:
-       case 256:
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-               break;
-       default:
+
+       } else if (!radeon_check_pot_argument(radeon_gart_size)) {
                dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n",
                                radeon_gart_size);
                radeon_gart_size = 512;
-               break;
        }
-       rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
+       rdev->mc.gtt_size = (uint64_t)radeon_gart_size << 20;
+
        /* AGP mode can only be -1, 1, 2, 4, 8 */
        switch (radeon_agpmode) {
        case -1:
@@ -1018,6 +1006,10 @@ int radeon_device_init(struct radeon_device *rdev,
                return r;
        /* initialize vm here */
        mutex_init(&rdev->vm_manager.lock);
+       /* Adjust VM size here.
+        * Currently set to 4GB ((1 << 20) 4k pages).
+        * Max GPUVM size for cayman and SI is 40 bits.
+        */
        rdev->vm_manager.max_pfn = 1 << 20;
        INIT_LIST_HEAD(&rdev->vm_manager.lru_vm);
 
index f0c06d196b752379712acaefb44f0aa537fa0cee..4debd60e5aa63390f0f386ee236bfc42fe4f8cf3 100644 (file)
@@ -355,14 +355,13 @@ int radeon_gart_init(struct radeon_device *rdev)
        DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
                 rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
        /* Allocate pages table */
-       rdev->gart.pages = kzalloc(sizeof(void *) * rdev->gart.num_cpu_pages,
-                                  GFP_KERNEL);
+       rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages);
        if (rdev->gart.pages == NULL) {
                radeon_gart_fini(rdev);
                return -ENOMEM;
        }
-       rdev->gart.pages_addr = kzalloc(sizeof(dma_addr_t) *
-                                       rdev->gart.num_cpu_pages, GFP_KERNEL);
+       rdev->gart.pages_addr = vzalloc(sizeof(dma_addr_t) *
+                                       rdev->gart.num_cpu_pages);
        if (rdev->gart.pages_addr == NULL) {
                radeon_gart_fini(rdev);
                return -ENOMEM;
@@ -388,8 +387,8 @@ void radeon_gart_fini(struct radeon_device *rdev)
                radeon_gart_unbind(rdev, 0, rdev->gart.num_cpu_pages);
        }
        rdev->gart.ready = false;
-       kfree(rdev->gart.pages);
-       kfree(rdev->gart.pages_addr);
+       vfree(rdev->gart.pages);
+       vfree(rdev->gart.pages_addr);
        rdev->gart.pages = NULL;
        rdev->gart.pages_addr = NULL;
 
@@ -422,6 +421,18 @@ void radeon_gart_fini(struct radeon_device *rdev)
  * TODO bind a default page at vm initialization for default address
  */
 
+/**
+ * radeon_vm_num_pde - return the number of page directory entries
+ *
+ * @rdev: radeon_device pointer
+ *
+ * Calculate the number of page directory entries (cayman+).
+ */
+static unsigned radeon_vm_num_pdes(struct radeon_device *rdev)
+{
+       return rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE;
+}
+
 /**
  * radeon_vm_directory_size - returns the size of the page directory in bytes
  *
@@ -431,7 +442,7 @@ void radeon_gart_fini(struct radeon_device *rdev)
  */
 static unsigned radeon_vm_directory_size(struct radeon_device *rdev)
 {
-       return (rdev->vm_manager.max_pfn >> RADEON_VM_BLOCK_SIZE) * 8;
+       return RADEON_GPU_PAGE_ALIGN(radeon_vm_num_pdes(rdev) * 8);
 }
 
 /**
@@ -451,11 +462,11 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
 
        if (!rdev->vm_manager.enabled) {
                /* allocate enough for 2 full VM pts */
-               size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev));
-               size += RADEON_GPU_PAGE_ALIGN(rdev->vm_manager.max_pfn * 8);
+               size = radeon_vm_directory_size(rdev);
+               size += rdev->vm_manager.max_pfn * 8;
                size *= 2;
                r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager,
-                                             size,
+                                             RADEON_GPU_PAGE_ALIGN(size),
                                              RADEON_GEM_DOMAIN_VRAM);
                if (r) {
                        dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n",
@@ -476,7 +487,7 @@ int radeon_vm_manager_init(struct radeon_device *rdev)
 
        /* restore page table */
        list_for_each_entry(vm, &rdev->vm_manager.lru_vm, list) {
-               if (vm->sa_bo == NULL)
+               if (vm->page_directory == NULL)
                        continue;
 
                list_for_each_entry(bo_va, &vm->va, vm_list) {
@@ -500,16 +511,25 @@ static void radeon_vm_free_pt(struct radeon_device *rdev,
                                    struct radeon_vm *vm)
 {
        struct radeon_bo_va *bo_va;
+       int i;
 
-       if (!vm->sa_bo)
+       if (!vm->page_directory)
                return;
 
        list_del_init(&vm->list);
-       radeon_sa_bo_free(rdev, &vm->sa_bo, vm->fence);
+       radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence);
 
        list_for_each_entry(bo_va, &vm->va, vm_list) {
                bo_va->valid = false;
        }
+
+       if (vm->page_tables == NULL)
+               return;
+
+       for (i = 0; i < radeon_vm_num_pdes(rdev); i++)
+               radeon_sa_bo_free(rdev, &vm->page_tables[i], vm->fence);
+
+       kfree(vm->page_tables);
 }
 
 /**
@@ -545,6 +565,35 @@ void radeon_vm_manager_fini(struct radeon_device *rdev)
        rdev->vm_manager.enabled = false;
 }
 
+/**
+ * radeon_vm_evict - evict page table to make room for new one
+ *
+ * @rdev: radeon_device pointer
+ * @vm: VM we want to allocate something for
+ *
+ * Evict a VM from the lru, making sure that it isn't @vm. (cayman+).
+ * Returns 0 for success, -ENOMEM for failure.
+ *
+ * Global and local mutex must be locked!
+ */
+static int radeon_vm_evict(struct radeon_device *rdev, struct radeon_vm *vm)
+{
+       struct radeon_vm *vm_evict;
+
+       if (list_empty(&rdev->vm_manager.lru_vm))
+               return -ENOMEM;
+
+       vm_evict = list_first_entry(&rdev->vm_manager.lru_vm,
+                                   struct radeon_vm, list);
+       if (vm_evict == vm)
+               return -ENOMEM;
+
+       mutex_lock(&vm_evict->mutex);
+       radeon_vm_free_pt(rdev, vm_evict);
+       mutex_unlock(&vm_evict->mutex);
+       return 0;
+}
+
 /**
  * radeon_vm_alloc_pt - allocates a page table for a VM
  *
@@ -552,57 +601,71 @@ void radeon_vm_manager_fini(struct radeon_device *rdev)
  * @vm: vm to bind
  *
  * Allocate a page table for the requested vm (cayman+).
- * Also starts to populate the page table.
  * Returns 0 for success, error for failure.
  *
  * Global and local mutex must be locked!
  */
 int radeon_vm_alloc_pt(struct radeon_device *rdev, struct radeon_vm *vm)
 {
-       struct radeon_vm *vm_evict;
-       int r;
+       unsigned pd_size, pts_size;
        u64 *pd_addr;
-       int tables_size;
+       int r;
 
        if (vm == NULL) {
                return -EINVAL;
        }
 
-       /* allocate enough to cover the current VM size */
-       tables_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev));
-       tables_size += RADEON_GPU_PAGE_ALIGN(vm->last_pfn * 8);
-
-       if (vm->sa_bo != NULL) {
-               /* update lru */
-               list_del_init(&vm->list);
-               list_add_tail(&vm->list, &rdev->vm_manager.lru_vm);
+       if (vm->page_directory != NULL) {
                return 0;
        }
 
 retry:
-       r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager, &vm->sa_bo,
-                            tables_size, RADEON_GPU_PAGE_SIZE, false);
+       pd_size = RADEON_GPU_PAGE_ALIGN(radeon_vm_directory_size(rdev));
+       r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
+                            &vm->page_directory, pd_size,
+                            RADEON_GPU_PAGE_SIZE, false);
        if (r == -ENOMEM) {
-               if (list_empty(&rdev->vm_manager.lru_vm)) {
+               r = radeon_vm_evict(rdev, vm);
+               if (r)
                        return r;
-               }
-               vm_evict = list_first_entry(&rdev->vm_manager.lru_vm, struct radeon_vm, list);
-               mutex_lock(&vm_evict->mutex);
-               radeon_vm_free_pt(rdev, vm_evict);
-               mutex_unlock(&vm_evict->mutex);
                goto retry;
 
        } else if (r) {
                return r;
        }
 
-       pd_addr = radeon_sa_bo_cpu_addr(vm->sa_bo);
-       vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->sa_bo);
-       memset(pd_addr, 0, tables_size);
+       vm->pd_gpu_addr = radeon_sa_bo_gpu_addr(vm->page_directory);
+
+       /* Initially clear the page directory */
+       pd_addr = radeon_sa_bo_cpu_addr(vm->page_directory);
+       memset(pd_addr, 0, pd_size);
+
+       pts_size = radeon_vm_num_pdes(rdev) * sizeof(struct radeon_sa_bo *);
+       vm->page_tables = kzalloc(pts_size, GFP_KERNEL);
+
+       if (vm->page_tables == NULL) {
+               DRM_ERROR("Cannot allocate memory for page table array\n");
+               radeon_sa_bo_free(rdev, &vm->page_directory, vm->fence);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
 
+/**
+ * radeon_vm_add_to_lru - add VMs page table to LRU list
+ *
+ * @rdev: radeon_device pointer
+ * @vm: vm to add to LRU
+ *
+ * Add the allocated page table to the LRU list (cayman+).
+ *
+ * Global mutex must be locked!
+ */
+void radeon_vm_add_to_lru(struct radeon_device *rdev, struct radeon_vm *vm)
+{
+       list_del_init(&vm->list);
        list_add_tail(&vm->list, &rdev->vm_manager.lru_vm);
-       return radeon_vm_bo_update_pte(rdev, vm, rdev->ring_tmp_bo.bo,
-                                      &rdev->ring_tmp_bo.bo->tbo.mem);
 }
 
 /**
@@ -793,20 +856,6 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev,
        }
 
        mutex_lock(&vm->mutex);
-       if (last_pfn > vm->last_pfn) {
-               /* release mutex and lock in right order */
-               mutex_unlock(&vm->mutex);
-               mutex_lock(&rdev->vm_manager.lock);
-               mutex_lock(&vm->mutex);
-               /* and check again */
-               if (last_pfn > vm->last_pfn) {
-                       /* grow va space 32M by 32M */
-                       unsigned align = ((32 << 20) >> 12) - 1;
-                       radeon_vm_free_pt(rdev, vm);
-                       vm->last_pfn = (last_pfn + align) & ~align;
-               }
-               mutex_unlock(&rdev->vm_manager.lock);
-       }
        head = &vm->va;
        last_offset = 0;
        list_for_each_entry(tmp, &vm->va, vm_list) {
@@ -864,6 +913,154 @@ uint64_t radeon_vm_map_gart(struct radeon_device *rdev, uint64_t addr)
        return result;
 }
 
+/**
+ * radeon_vm_update_pdes - make sure that page directory is valid
+ *
+ * @rdev: radeon_device pointer
+ * @vm: requested vm
+ * @start: start of GPU address range
+ * @end: end of GPU address range
+ *
+ * Allocates new page tables if necessary
+ * and updates the page directory (cayman+).
+ * Returns 0 for success, error for failure.
+ *
+ * Global and local mutex must be locked!
+ */
+static int radeon_vm_update_pdes(struct radeon_device *rdev,
+                                struct radeon_vm *vm,
+                                uint64_t start, uint64_t end)
+{
+       static const uint32_t incr = RADEON_VM_PTE_COUNT * 8;
+
+       uint64_t last_pde = ~0, last_pt = ~0;
+       unsigned count = 0;
+       uint64_t pt_idx;
+       int r;
+
+       start = (start / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE;
+       end = (end / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE;
+
+       /* walk over the address space and update the page directory */
+       for (pt_idx = start; pt_idx <= end; ++pt_idx) {
+               uint64_t pde, pt;
+
+               if (vm->page_tables[pt_idx])
+                       continue;
+
+retry:
+               r = radeon_sa_bo_new(rdev, &rdev->vm_manager.sa_manager,
+                                    &vm->page_tables[pt_idx],
+                                    RADEON_VM_PTE_COUNT * 8,
+                                    RADEON_GPU_PAGE_SIZE, false);
+
+               if (r == -ENOMEM) {
+                       r = radeon_vm_evict(rdev, vm);
+                       if (r)
+                               return r;
+                       goto retry;
+               } else if (r) {
+                       return r;
+               }
+
+               pde = vm->pd_gpu_addr + pt_idx * 8;
+
+               pt = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);
+
+               if (((last_pde + 8 * count) != pde) ||
+                   ((last_pt + incr * count) != pt)) {
+
+                       if (count) {
+                               radeon_asic_vm_set_page(rdev, last_pde,
+                                                       last_pt, count, incr,
+                                                       RADEON_VM_PAGE_VALID);
+                       }
+
+                       count = 1;
+                       last_pde = pde;
+                       last_pt = pt;
+               } else {
+                       ++count;
+               }
+       }
+
+       if (count) {
+               radeon_asic_vm_set_page(rdev, last_pde, last_pt, count,
+                                       incr, RADEON_VM_PAGE_VALID);
+
+       }
+
+       return 0;
+}
+
+/**
+ * radeon_vm_update_ptes - make sure that page tables are valid
+ *
+ * @rdev: radeon_device pointer
+ * @vm: requested vm
+ * @start: start of GPU address range
+ * @end: end of GPU address range
+ * @dst: destination address to map to
+ * @flags: mapping flags
+ *
+ * Update the page tables in the range @start - @end (cayman+).
+ *
+ * Global and local mutex must be locked!
+ */
+static void radeon_vm_update_ptes(struct radeon_device *rdev,
+                                 struct radeon_vm *vm,
+                                 uint64_t start, uint64_t end,
+                                 uint64_t dst, uint32_t flags)
+{
+       static const uint64_t mask = RADEON_VM_PTE_COUNT - 1;
+
+       uint64_t last_pte = ~0, last_dst = ~0;
+       unsigned count = 0;
+       uint64_t addr;
+
+       start = start / RADEON_GPU_PAGE_SIZE;
+       end = end / RADEON_GPU_PAGE_SIZE;
+
+       /* walk over the address space and update the page tables */
+       for (addr = start; addr < end; ) {
+               uint64_t pt_idx = addr >> RADEON_VM_BLOCK_SIZE;
+               unsigned nptes;
+               uint64_t pte;
+
+               if ((addr & ~mask) == (end & ~mask))
+                       nptes = end - addr;
+               else
+                       nptes = RADEON_VM_PTE_COUNT - (addr & mask);
+
+               pte = radeon_sa_bo_gpu_addr(vm->page_tables[pt_idx]);
+               pte += (addr & mask) * 8;
+
+               if ((last_pte + 8 * count) != pte) {
+
+                       if (count) {
+                               radeon_asic_vm_set_page(rdev, last_pte,
+                                                       last_dst, count,
+                                                       RADEON_GPU_PAGE_SIZE,
+                                                       flags);
+                       }
+
+                       count = nptes;
+                       last_pte = pte;
+                       last_dst = dst;
+               } else {
+                       count += nptes;
+               }
+
+               addr += nptes;
+               dst += nptes * RADEON_GPU_PAGE_SIZE;
+       }
+
+       if (count) {
+               radeon_asic_vm_set_page(rdev, last_pte, last_dst, count,
+                                       RADEON_GPU_PAGE_SIZE, flags);
+       }
+}
+
 /**
  * radeon_vm_bo_update_pte - map a bo into the vm page table
  *
@@ -887,12 +1084,11 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
        struct radeon_semaphore *sem = NULL;
        struct radeon_bo_va *bo_va;
        unsigned nptes, npdes, ndw;
-       uint64_t pe, addr;
-       uint64_t pfn;
+       uint64_t addr;
        int r;
 
        /* nothing to do if vm isn't bound */
-       if (vm->sa_bo == NULL)
+       if (vm->page_directory == NULL)
                return 0;
 
        bo_va = radeon_vm_bo_find(vm, bo);
@@ -939,25 +1135,29 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                }
        }
 
-       /* estimate number of dw needed */
-       /* reserve space for 32-bit padding */
-       ndw = 32;
-
        nptes = radeon_bo_ngpu_pages(bo);
 
-       pfn = (bo_va->soffset / RADEON_GPU_PAGE_SIZE);
+       /* assume two extra pdes in case the mapping overlaps the borders */
+       npdes = (nptes >> RADEON_VM_BLOCK_SIZE) + 2;
 
-       /* handle cases where a bo spans several pdes  */
-       npdes = (ALIGN(pfn + nptes, RADEON_VM_PTE_COUNT) -
-                (pfn & ~(RADEON_VM_PTE_COUNT - 1))) >> RADEON_VM_BLOCK_SIZE;
+       /* estimate number of dw needed */
+       /* semaphore, fence and padding */
+       ndw = 32;
+
+       if (RADEON_VM_BLOCK_SIZE > 11)
+               /* reserve space for one header for every 2k dwords */
+               ndw += (nptes >> 11) * 4;
+       else
+               /* reserve space for one header for
+                   every (1 << BLOCK_SIZE) entries */
+               ndw += (nptes >> RADEON_VM_BLOCK_SIZE) * 4;
 
-       /* reserve space for one header for every 2k dwords */
-       ndw += (nptes >> 11) * 3;
        /* reserve space for pte addresses */
        ndw += nptes * 2;
 
        /* reserve space for one header for every 2k dwords */
-       ndw += (npdes >> 11) * 3;
+       ndw += (npdes >> 11) * 4;
+
        /* reserve space for pde addresses */
        ndw += npdes * 2;
 
@@ -971,22 +1171,14 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
                radeon_fence_note_sync(vm->fence, ridx);
        }
 
-       /* update page table entries */
-       pe = vm->pd_gpu_addr;
-       pe += radeon_vm_directory_size(rdev);
-       pe += (bo_va->soffset / RADEON_GPU_PAGE_SIZE) * 8;
-
-       radeon_asic_vm_set_page(rdev, pe, addr, nptes,
-                               RADEON_GPU_PAGE_SIZE, bo_va->flags);
-
-       /* update page directory entries */
-       addr = pe;
-
-       pe = vm->pd_gpu_addr;
-       pe += ((bo_va->soffset / RADEON_GPU_PAGE_SIZE) >> RADEON_VM_BLOCK_SIZE) * 8;
+       r = radeon_vm_update_pdes(rdev, vm, bo_va->soffset, bo_va->eoffset);
+       if (r) {
+               radeon_ring_unlock_undo(rdev, ring);
+               return r;
+       }
 
-       radeon_asic_vm_set_page(rdev, pe, addr, npdes,
-                               RADEON_VM_PTE_COUNT * 8, RADEON_VM_PAGE_VALID);
+       radeon_vm_update_ptes(rdev, vm, bo_va->soffset, bo_va->eoffset,
+                             addr, bo_va->flags);
 
        radeon_fence_unref(&vm->fence);
        r = radeon_fence_emit(rdev, &vm->fence, ridx);
@@ -997,6 +1189,7 @@ int radeon_vm_bo_update_pte(struct radeon_device *rdev,
        radeon_ring_unlock_commit(rdev, ring);
        radeon_semaphore_free(rdev, &sem, vm->fence);
        radeon_fence_unref(&vm->last_flush);
+
        return 0;
 }
 
@@ -1056,31 +1249,15 @@ void radeon_vm_bo_invalidate(struct radeon_device *rdev,
  * @rdev: radeon_device pointer
  * @vm: requested vm
  *
- * Init @vm (cayman+).
- * Map the IB pool and any other shared objects into the VM
- * by default as it's used by all VMs.
- * Returns 0 for success, error for failure.
+ * Init @vm fields (cayman+).
  */
-int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
+void radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
 {
-       struct radeon_bo_va *bo_va;
-       int r;
-
        vm->id = 0;
        vm->fence = NULL;
-       vm->last_pfn = 0;
        mutex_init(&vm->mutex);
        INIT_LIST_HEAD(&vm->list);
        INIT_LIST_HEAD(&vm->va);
-
-       /* map the ib pool buffer at 0 in virtual address space, set
-        * read only
-        */
-       bo_va = radeon_vm_bo_add(rdev, vm, rdev->ring_tmp_bo.bo);
-       r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
-                                 RADEON_VM_PAGE_READABLE |
-                                 RADEON_VM_PAGE_SNOOPED);
-       return r;
 }
 
 /**
@@ -1102,17 +1279,6 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm)
        radeon_vm_free_pt(rdev, vm);
        mutex_unlock(&rdev->vm_manager.lock);
 
-       /* remove all bo at this point non are busy any more because unbind
-        * waited for the last vm fence to signal
-        */
-       r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
-       if (!r) {
-               bo_va = radeon_vm_bo_find(vm, rdev->ring_tmp_bo.bo);
-               list_del_init(&bo_va->bo_list);
-               list_del_init(&bo_va->vm_list);
-               radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
-               kfree(bo_va);
-       }
        if (!list_empty(&vm->va)) {
                dev_err(rdev->dev, "still active bo inside vm\n");
        }
index f38fbcc469358a2144791d40f910d4d900d99202..fe5c1f6b795795530075939d39c06486ce42d29d 100644 (file)
@@ -53,6 +53,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
                                struct drm_gem_object **obj)
 {
        struct radeon_bo *robj;
+       unsigned long max_size;
        int r;
 
        *obj = NULL;
@@ -60,11 +61,26 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
        if (alignment < PAGE_SIZE) {
                alignment = PAGE_SIZE;
        }
+
+       /* maximun bo size is the minimun btw visible vram and gtt size */
+       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
+       if (size > max_size) {
+               printk(KERN_WARNING "%s:%d alloc size %dMb bigger than %ldMb limit\n",
+                      __func__, __LINE__, size >> 20, max_size >> 20);
+               return -ENOMEM;
+       }
+
+retry:
        r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, NULL, &robj);
        if (r) {
-               if (r != -ERESTARTSYS)
+               if (r != -ERESTARTSYS) {
+                       if (initial_domain == RADEON_GEM_DOMAIN_VRAM) {
+                               initial_domain |= RADEON_GEM_DOMAIN_GTT;
+                               goto retry;
+                       }
                        DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
                                  size, initial_domain, alignment, r);
+               }
                return r;
        }
        *obj = &robj->gem_base;
index 83b8d8aa71c0daf541a8da98c28dee949a5d98d4..dc781c49b96b3848c116cb6fe013dd8abd669ddc 100644 (file)
@@ -419,6 +419,7 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
        /* new gpu have virtual address space support */
        if (rdev->family >= CHIP_CAYMAN) {
                struct radeon_fpriv *fpriv;
+               struct radeon_bo_va *bo_va;
                int r;
 
                fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
@@ -426,7 +427,15 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                        return -ENOMEM;
                }
 
-               r = radeon_vm_init(rdev, &fpriv->vm);
+               radeon_vm_init(rdev, &fpriv->vm);
+
+               /* map the ib pool buffer read only into
+                * virtual address space */
+               bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
+                                        rdev->ring_tmp_bo.bo);
+               r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
+                                         RADEON_VM_PAGE_READABLE |
+                                         RADEON_VM_PAGE_SNOOPED);
                if (r) {
                        radeon_vm_fini(rdev, &fpriv->vm);
                        kfree(fpriv);
@@ -454,6 +463,17 @@ void radeon_driver_postclose_kms(struct drm_device *dev,
        /* new gpu have virtual address space support */
        if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) {
                struct radeon_fpriv *fpriv = file_priv->driver_priv;
+               struct radeon_bo_va *bo_va;
+               int r;
+
+               r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
+               if (!r) {
+                       bo_va = radeon_vm_bo_find(&fpriv->vm,
+                                                 rdev->ring_tmp_bo.bo);
+                       if (bo_va)
+                               radeon_vm_bo_rmv(rdev, bo_va);
+                       radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
+               }
 
                radeon_vm_fini(rdev, &fpriv->vm);
                kfree(fpriv);
index 5677a424b58535e2bffb0422856e9385182b649c..6857cb4efb768c932f23d4645c3969fd9c792f18 100644 (file)
@@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
+       uint32_t crtc_ext_cntl = 0;
        uint32_t mask;
 
        if (radeon_crtc->crtc_id)
@@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                        RADEON_CRTC_VSYNC_DIS |
                        RADEON_CRTC_HSYNC_DIS);
 
+       /*
+        * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC.
+        * Therefore it is set in the DAC DMPS function.
+        * This is different for GPU's with a single CRTC but a primary and a
+        * TV DAC: here it controls the single CRTC no matter where it is
+        * routed. Therefore we set it here.
+        */
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               crtc_ext_cntl = RADEON_CRTC_CRT_ON;
+       
        switch (mode) {
        case DRM_MODE_DPMS_ON:
                radeon_crtc->enabled = true;
@@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
                                                                         RADEON_CRTC_DISP_REQ_EN_B));
-                       WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask);
+                       WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));
                }
                drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
                radeon_crtc_load_lut(crtc);
@@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
                else {
                        WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
                                                                                    RADEON_CRTC_DISP_REQ_EN_B));
-                       WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask);
+                       WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));
                }
                radeon_crtc->enabled = false;
                /* adjust pm to dpms changes AFTER disabling crtcs */
index 92487e614778a93e40d253689ccaf085f019f291..f5ba2241dacc6cfd2bb6b55fead51a7ae2c395e8 100644 (file)
@@ -269,27 +269,6 @@ static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
        .disable = radeon_legacy_encoder_disable,
 };
 
-#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
-
-static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
-{
-       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
-       uint8_t level;
-
-       /* Convert brightness to hardware level */
-       if (bd->props.brightness < 0)
-               level = 0;
-       else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
-               level = RADEON_MAX_BL_LEVEL;
-       else
-               level = bd->props.brightness;
-
-       if (pdata->negative)
-               level = RADEON_MAX_BL_LEVEL - level;
-
-       return level;
-}
-
 u8
 radeon_legacy_get_backlight_level(struct radeon_encoder *radeon_encoder)
 {
@@ -331,6 +310,27 @@ radeon_legacy_set_backlight_level(struct radeon_encoder *radeon_encoder, u8 leve
        radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
 }
 
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
+{
+       struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+       uint8_t level;
+
+       /* Convert brightness to hardware level */
+       if (bd->props.brightness < 0)
+               level = 0;
+       else if (bd->props.brightness > RADEON_MAX_BL_LEVEL)
+               level = RADEON_MAX_BL_LEVEL;
+       else
+               level = bd->props.brightness;
+
+       if (pdata->negative)
+               level = RADEON_MAX_BL_LEVEL - level;
+
+       return level;
+}
+
 static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
 {
        struct radeon_backlight_privdata *pdata = bl_get_data(bd);
@@ -370,6 +370,7 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        struct backlight_properties props;
        struct radeon_backlight_privdata *pdata;
        uint8_t backlight_level;
+       char bl_name[16];
 
        if (!radeon_encoder->enc_priv)
                return;
@@ -389,7 +390,9 @@ void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
        memset(&props, 0, sizeof(props));
        props.max_brightness = RADEON_MAX_BL_LEVEL;
        props.type = BACKLIGHT_RAW;
-       bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+       snprintf(bl_name, sizeof(bl_name),
+                "radeon_bl%d", dev->primary->index);
+       bd = backlight_device_register(bl_name, &drm_connector->kdev,
                                       pdata, &radeon_backlight_ops, &props);
        if (IS_ERR(bd)) {
                DRM_ERROR("Backlight registration failed\n");
@@ -534,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode
                break;
        }
 
-       WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
+       /* handled in radeon_crtc_dpms() */
+       if (!(rdev->flags & RADEON_SINGLE_CRTC))
+               WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
        WREG32(RADEON_DAC_CNTL, dac_cntl);
        WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl);
 
@@ -659,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
 
        if (ASIC_IS_R300(rdev))
                tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT);
+       else if (ASIC_IS_RV100(rdev))
+               tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);
        else
                tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT);
 
@@ -668,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
        tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;
        WREG32(RADEON_DAC_CNTL, tmp);
 
+       tmp = dac_macro_cntl;
        tmp &= ~(RADEON_DAC_PDWN_R |
                 RADEON_DAC_PDWN_G |
                 RADEON_DAC_PDWN_B);
@@ -991,11 +999,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
 static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
-       if (tmds) {
-               if (tmds->i2c_bus)
-                       radeon_i2c_destroy(tmds->i2c_bus);
-       }
+       /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */
        kfree(radeon_encoder->enc_priv);
        drm_encoder_cleanup(encoder);
        kfree(radeon_encoder);
@@ -1093,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
        } else {
                if (is_tv)
                        WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl);
-               else
+               /* handled in radeon_crtc_dpms() */
+               else if (!(rdev->flags & RADEON_SINGLE_CRTC))
                        WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
                WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
        }
@@ -1417,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,
        return found;
 }
 
+static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder,
+                                        struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl;
+       uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c;
+       uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f;
+       uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp;
+       uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid;
+       bool found = false;
+       int i;
+
+       /* save the regs we need */
+       gpio_monid = RREG32(RADEON_GPIO_MONID);
+       fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL);
+       disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+       crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+       disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A);
+       disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B);
+       disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C);
+       disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D);
+       disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E);
+       disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F);
+       crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP);
+       crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP);
+       crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID);
+       crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID);
+
+       tmp = RREG32(RADEON_GPIO_MONID);
+       tmp &= ~RADEON_GPIO_A_0;
+       WREG32(RADEON_GPIO_MONID, tmp);
+
+       WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON |
+                                    RADEON_FP2_PANEL_FORMAT |
+                                    R200_FP2_SOURCE_SEL_TRANS_UNIT |
+                                    RADEON_FP2_DVO_EN |
+                                    R200_FP2_DVO_RATE_SEL_SDR));
+
+       WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX |
+                                        RADEON_DISP_TRANS_MATRIX_GRAPHICS));
+
+       WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN |
+                                      RADEON_CRTC2_DISP_REQ_EN_B));
+
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0);
+
+       WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008);
+       WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800);
+       WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001);
+       WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080);
+
+       for (i = 0; i < 200; i++) {
+               tmp = RREG32(RADEON_GPIO_MONID);
+               if (tmp & RADEON_GPIO_Y_0)
+                       found = true;
+
+               if (found)
+                       break;
+
+               if (!drm_can_sleep())
+                       mdelay(1);
+               else
+                       msleep(1);
+       }
+
+       /* restore the regs we used */
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e);
+       WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f);
+       WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp);
+       WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp);
+       WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid);
+       WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid);
+       WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+       WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+       WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl);
+       WREG32(RADEON_GPIO_MONID, gpio_monid);
+
+       return found;
+}
+
 static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,
                                                             struct drm_connector *connector)
 {
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
-       uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
-       uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp;
+       uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl;
+       uint32_t gpiopad_a = 0, pixclks_cntl, tmp;
+       uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;
        enum drm_connector_status found = connector_status_disconnected;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv;
@@ -1460,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
                return connector_status_disconnected;
        }
 
+       /* R200 uses an external DAC for secondary DAC */
+       if (rdev->family == CHIP_R200) {
+               if (radeon_legacy_ext_dac_detect(encoder, connector))
+                       found = connector_status_connected;
+               return found;
+       }
+
        /* save the regs we need */
        pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL);
-       gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0;
-       disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0;
-       disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG);
-       crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
+       } else {
+               if (ASIC_IS_R300(rdev)) {
+                       gpiopad_a = RREG32(RADEON_GPIOPAD_A);
+                       disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL);
+               } else {
+                       disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG);
+               }
+               crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL);
+       }
        tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
        dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);
        dac_cntl2 = RREG32(RADEON_DAC_CNTL2);
@@ -1474,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
                               | RADEON_PIX2CLK_DAC_ALWAYS_ONb);
        WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp);
 
-       if (ASIC_IS_R300(rdev))
-               WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
-
-       tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
-       tmp |= RADEON_CRTC2_CRT2_ON |
-               (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
-
-       WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
-
-       if (ASIC_IS_R300(rdev)) {
-               tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
-               tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
-               WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON;
+               WREG32(RADEON_CRTC_EXT_CNTL, tmp);
        } else {
-               tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
-               WREG32(RADEON_DISP_HW_DEBUG, tmp);
+               tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK;
+               tmp |= RADEON_CRTC2_CRT2_ON |
+                       (2 << RADEON_CRTC2_PIX_WIDTH_SHIFT);
+               WREG32(RADEON_CRTC2_GEN_CNTL, tmp);
+
+               if (ASIC_IS_R300(rdev)) {
+                       WREG32_P(RADEON_GPIOPAD_A, 1, ~1);
+                       tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK;
+                       tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2;
+                       WREG32(RADEON_DISP_OUTPUT_CNTL, tmp);
+               } else {
+                       tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL;
+                       WREG32(RADEON_DISP_HW_DEBUG, tmp);
+               }
        }
 
        tmp = RADEON_TV_DAC_NBLANK |
@@ -1531,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
        WREG32(RADEON_DAC_CNTL2, dac_cntl2);
        WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);
        WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);
-       WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
 
-       if (ASIC_IS_R300(rdev)) {
-               WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
-               WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+       if (rdev->flags & RADEON_SINGLE_CRTC) {
+               WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);
        } else {
-               WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+               WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);
+               if (ASIC_IS_R300(rdev)) {
+                       WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl);
+                       WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1);
+               } else {
+                       WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug);
+               }
        }
+
        WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);
 
        return found;
index 8b27dd6e3144566bf9cfcb218f4697cd92dbbb95..b91118ccef867f5b59effd78d0ee93d65a932f8b 100644 (file)
@@ -105,7 +105,6 @@ int radeon_bo_create(struct radeon_device *rdev,
        struct radeon_bo *bo;
        enum ttm_bo_type type;
        unsigned long page_align = roundup(byte_align, PAGE_SIZE) >> PAGE_SHIFT;
-       unsigned long max_size = 0;
        size_t acc_size;
        int r;
 
@@ -121,18 +120,9 @@ int radeon_bo_create(struct radeon_device *rdev,
        }
        *bo_ptr = NULL;
 
-       /* maximun bo size is the minimun btw visible vram and gtt size */
-       max_size = min(rdev->mc.visible_vram_size, rdev->mc.gtt_size);
-       if ((page_align << PAGE_SHIFT) >= max_size) {
-               printk(KERN_WARNING "%s:%d alloc size %ldM bigger than %ldMb limit\n",
-                       __func__, __LINE__, page_align  >> (20 - PAGE_SHIFT), max_size >> 20);
-               return -ENOMEM;
-       }
-
        acc_size = ttm_bo_dma_acc_size(&rdev->mman.bdev, size,
                                       sizeof(struct radeon_bo));
 
-retry:
        bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
        if (bo == NULL)
                return -ENOMEM;
@@ -154,15 +144,6 @@ retry:
                        acc_size, sg, &radeon_ttm_bo_destroy);
        up_read(&rdev->pm.mclk_lock);
        if (unlikely(r != 0)) {
-               if (r != -ERESTARTSYS) {
-                       if (domain == RADEON_GEM_DOMAIN_VRAM) {
-                               domain |= RADEON_GEM_DOMAIN_GTT;
-                               goto retry;
-                       }
-                       dev_err(rdev->dev,
-                               "object_init failed for (%lu, 0x%08X)\n",
-                               size, domain);
-               }
                return r;
        }
        *bo_ptr = bo;
index bba66902c83b6ada2e3a475572fa5f7101a05a6b..47634f27f2e5eca62cc6335d95fc246e13a6deb2 100644 (file)
@@ -305,7 +305,7 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v)
 {
 #if DRM_DEBUG_CODE
        if (ring->count_dw <= 0) {
-               DRM_ERROR("radeon: writting more dword to ring than expected !\n");
+               DRM_ERROR("radeon: writing more dwords to the ring than expected!\n");
        }
 #endif
        ring->ring[ring->wptr++] = v;
index f79633a036c394f22d81182fc56036aa830e190e..4422d630b33bc4052ddfdc311ea37944f9d87051 100644 (file)
@@ -2407,12 +2407,13 @@ static int si_pcie_gart_enable(struct radeon_device *rdev)
        WREG32(0x15DC, 0);
 
        /* empty context1-15 */
-       /* FIXME start with 4G, once using 2 level pt switch to full
-        * vm size space
-        */
        /* set vm size, must be a multiple of 4 */
        WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
        WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn);
+       /* Assign the pt base to something valid for now; the pts used for
+        * the VMs are determined by the application and setup and assigned
+        * on the fly in the vm part of radeon_gart.c
+        */
        for (i = 1; i < 16; i++) {
                if (i < 8)
                        WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
@@ -2473,6 +2474,7 @@ static bool si_vm_reg_valid(u32 reg)
        /* check config regs */
        switch (reg) {
        case GRBM_GFX_INDEX:
+       case CP_STRMOUT_CNTL:
        case VGT_VTX_VECT_EJECT_REG:
        case VGT_CACHE_INVALIDATION:
        case VGT_ESGS_RING_SIZE:
@@ -2807,26 +2809,31 @@ void si_vm_set_page(struct radeon_device *rdev, uint64_t pe,
 {
        struct radeon_ring *ring = &rdev->ring[rdev->asic->vm.pt_ring_index];
        uint32_t r600_flags = cayman_vm_page_flags(rdev, flags);
-       int i;
-       uint64_t value;
 
-       radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 2 + count * 2));
-       radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
-                                WRITE_DATA_DST_SEL(1)));
-       radeon_ring_write(ring, pe);
-       radeon_ring_write(ring, upper_32_bits(pe));
-       for (i = 0; i < count; ++i) {
-               if (flags & RADEON_VM_PAGE_SYSTEM) {
-                       value = radeon_vm_map_gart(rdev, addr);
-                       value &= 0xFFFFFFFFFFFFF000ULL;
-               } else if (flags & RADEON_VM_PAGE_VALID)
-                       value = addr;
-               else
-                       value = 0;
-               addr += incr;
-               value |= r600_flags;
-               radeon_ring_write(ring, value);
-               radeon_ring_write(ring, upper_32_bits(value));
+       while (count) {
+               unsigned ndw = 2 + count * 2;
+               if (ndw > 0x3FFE)
+                       ndw = 0x3FFE;
+
+               radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, ndw));
+               radeon_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) |
+                                        WRITE_DATA_DST_SEL(1)));
+               radeon_ring_write(ring, pe);
+               radeon_ring_write(ring, upper_32_bits(pe));
+               for (; ndw > 2; ndw -= 2, --count, pe += 8) {
+                       uint64_t value;
+                       if (flags & RADEON_VM_PAGE_SYSTEM) {
+                               value = radeon_vm_map_gart(rdev, addr);
+                               value &= 0xFFFFFFFFFFFFF000ULL;
+                       } else if (flags & RADEON_VM_PAGE_VALID)
+                               value = addr;
+                       else
+                               value = 0;
+                       addr += incr;
+                       value |= r600_flags;
+                       radeon_ring_write(ring, value);
+                       radeon_ring_write(ring, upper_32_bits(value));
+               }
        }
 }
 
@@ -2867,6 +2874,10 @@ void si_vm_flush(struct radeon_device *rdev, int ridx, struct radeon_vm *vm)
        radeon_ring_write(ring, VM_INVALIDATE_REQUEST >> 2);
        radeon_ring_write(ring, 0);
        radeon_ring_write(ring, 1 << vm->id);
+
+       /* sync PFP to ME, otherwise we might get invalid PFP reads */
+       radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0));
+       radeon_ring_write(ring, 0x0);
 }
 
 /*
index 7d2a20e565771366a09124386a3ac513b66f8613..a8871afc5b4e6af2f13599bbed34a2cfd05eec36 100644 (file)
 #       define RDERR_INT_ENABLE                         (1 << 0)
 #       define GUI_IDLE_INT_ENABLE                      (1 << 19)
 
+#define        CP_STRMOUT_CNTL                                 0x84FC
 #define        SCRATCH_REG0                                    0x8500
 #define        SCRATCH_REG1                                    0x8504
 #define        SCRATCH_REG2                                    0x8508
index c71d493fd0c54fc184023428bdcbfb286d2d1109..1c350fc4e449715edd5ef997e6eb791722d0f604 100644 (file)
@@ -201,6 +201,8 @@ static int shmob_drm_load(struct drm_device *dev, unsigned long flags)
                goto done;
        }
 
+       platform_set_drvdata(pdev, sdev);
+
 done:
        if (ret)
                shmob_drm_unload(dev);
@@ -299,11 +301,9 @@ static struct drm_driver shmob_drm_driver = {
 #if CONFIG_PM_SLEEP
 static int shmob_drm_pm_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-       struct shmob_drm_device *sdev = ddev->dev_private;
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
-       drm_kms_helper_poll_disable(ddev);
+       drm_kms_helper_poll_disable(sdev->ddev);
        shmob_drm_crtc_suspend(&sdev->crtc);
 
        return 0;
@@ -311,9 +311,7 @@ static int shmob_drm_pm_suspend(struct device *dev)
 
 static int shmob_drm_pm_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct drm_device *ddev = platform_get_drvdata(pdev);
-       struct shmob_drm_device *sdev = ddev->dev_private;
+       struct shmob_drm_device *sdev = dev_get_drvdata(dev);
 
        mutex_lock(&sdev->ddev->mode_config.mutex);
        shmob_drm_crtc_resume(&sdev->crtc);
index 402ab69f9f991c64d149841cc154d6ea86ae9a96..bf6e4b5a73b509a73d06873c213335158b5fff89 100644 (file)
@@ -580,6 +580,7 @@ retry:
        if (unlikely(ret != 0))
                return ret;
 
+retry_reserve:
        spin_lock(&glob->lru_lock);
 
        if (unlikely(list_empty(&bo->ddestroy))) {
@@ -587,14 +588,20 @@ retry:
                return 0;
        }
 
-       ret = ttm_bo_reserve_locked(bo, interruptible,
-                                   no_wait_reserve, false, 0);
+       ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
-       if (unlikely(ret != 0)) {
+       if (unlikely(ret == -EBUSY)) {
                spin_unlock(&glob->lru_lock);
-               return ret;
+               if (likely(!no_wait_reserve))
+                       ret = ttm_bo_wait_unreserved(bo, interruptible);
+               if (unlikely(ret != 0))
+                       return ret;
+
+               goto retry_reserve;
        }
 
+       BUG_ON(ret != 0);
+
        /**
         * We can re-check for sync object without taking
         * the bo::lock since setting the sync object requires
@@ -811,17 +818,14 @@ retry:
                                          no_wait_reserve, no_wait_gpu);
                kref_put(&bo->list_kref, ttm_bo_release_list);
 
-               if (likely(ret == 0 || ret == -ERESTARTSYS))
-                       return ret;
-
-               goto retry;
+               return ret;
        }
 
-       ret = ttm_bo_reserve_locked(bo, false, no_wait_reserve, false, 0);
+       ret = ttm_bo_reserve_locked(bo, false, true, false, 0);
 
        if (unlikely(ret == -EBUSY)) {
                spin_unlock(&glob->lru_lock);
-               if (likely(!no_wait_gpu))
+               if (likely(!no_wait_reserve))
                        ret = ttm_bo_wait_unreserved(bo, interruptible);
 
                kref_put(&bo->list_kref, ttm_bo_release_list);
index 860dc4813e9991fe67754333ad487686605a7b26..bd2a3b40cd129b30d4445a8cdca8adec2eb492f9 100644 (file)
@@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
        /* clear the pages coming from the pool if requested */
        if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) {
                list_for_each_entry(p, &plist, lru) {
-                       clear_page(page_address(p));
+                       if (PageHighMem(p))
+                               clear_highpage(p);
+                       else
+                               clear_page(page_address(p));
                }
        }
 
index bf8260133ea9dc2cd6058118864cd481fbe8dcff..7d759a4302943bb6c5904356dd9e81dec6d4588f 100644 (file)
@@ -308,9 +308,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
                if (unlikely(to_page == NULL))
                        goto out_err;
 
-               preempt_disable();
                copy_highpage(to_page, from_page);
-               preempt_enable();
                page_cache_release(from_page);
        }
 
@@ -358,9 +356,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                        ret = PTR_ERR(to_page);
                        goto out_err;
                }
-               preempt_disable();
                copy_highpage(to_page, from_page);
-               preempt_enable();
                set_page_dirty(to_page);
                mark_page_accessed(to_page);
                page_cache_release(to_page);
index fccd361f7b50b4e4d4bd072afac3f32869da3da7..87aa5f5d3c88657b8c55055608a65baa271c4c94 100644 (file)
@@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,
 
 int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
                     const char *front, char **urb_buf_ptr,
-                    u32 byte_offset, u32 byte_width,
+                    u32 byte_offset, u32 device_byte_offset, u32 byte_width,
                     int *ident_ptr, int *sent_ptr);
 
 int udl_dumb_create(struct drm_file *file_priv,
index 69a2b16f42a60284d2d8eecb8ae1fe01fe8e2ced..d4ab3beaada027825d6182a1330b79bd75d220d4 100644 (file)
@@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,
        list_for_each_entry(cur, &fbdefio->pagelist, lru) {
 
                if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
-                                 &urb, (char *) info->fix.smem_start,
-                                 &cmd, cur->index << PAGE_SHIFT,
-                                 PAGE_SIZE, &bytes_identical, &bytes_sent))
+                                    &urb, (char *) info->fix.smem_start,
+                                    &cmd, cur->index << PAGE_SHIFT,
+                                    cur->index << PAGE_SHIFT,
+                                    PAGE_SIZE, &bytes_identical, &bytes_sent))
                        goto error;
                bytes_rendered += PAGE_SIZE;
        }
@@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
        for (i = y; i < y + height ; i++) {
                const int line_offset = fb->base.pitches[0] * i;
                const int byte_offset = line_offset + (x * bpp);
-
+               const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
                if (udl_render_hline(dev, bpp, &urb,
                                     (char *) fb->obj->vmapping,
-                                    &cmd, byte_offset, width * bpp,
+                                    &cmd, byte_offset, dev_byte_offset,
+                                    width * bpp,
                                     &bytes_identical, &bytes_sent))
                        goto error;
        }
index dc095526ffb750124573b9c2a9e472a4bbe82101..142fee5f983f9aa36c8fff99b3ddaf4d4eba78cd 100644 (file)
@@ -213,11 +213,12 @@ static void udl_compress_hline16(
  */
 int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,
                     const char *front, char **urb_buf_ptr,
-                    u32 byte_offset, u32 byte_width,
+                    u32 byte_offset, u32 device_byte_offset,
+                    u32 byte_width,
                     int *ident_ptr, int *sent_ptr)
 {
        const u8 *line_start, *line_end, *next_pixel;
-       u32 base16 = 0 + (byte_offset / bpp) * 2;
+       u32 base16 = 0 + (device_byte_offset / bpp) * 2;
        struct urb *urb = *urb_ptr;
        u8 *cmd = *urb_buf_ptr;
        u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
index 3ce68a2e312dbba2e588a3e52595b0d7f060ef44..d1498bfd78732ef519f50d6fea726d502cffd824 100644 (file)
@@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin)
 
        BUG_ON(!atomic_read(&bo->reserved));
        BUG_ON(old_mem_type != TTM_PL_VRAM &&
-              old_mem_type != VMW_PL_FLAG_GMR);
+              old_mem_type != VMW_PL_GMR);
 
        pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED;
        if (pin)
index ed3c1e7ddde94cde6db31c1e09b3174364eb9d22..2dd185e42f2129c8492021050e8ba149890cfbfd 100644 (file)
@@ -1098,6 +1098,11 @@ static void vmw_pm_complete(struct device *kdev)
        struct drm_device *dev = pci_get_drvdata(pdev);
        struct vmw_private *dev_priv = vmw_priv(dev);
 
+       mutex_lock(&dev_priv->hw_mutex);
+       vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
+       (void) vmw_read(dev_priv, SVGA_REG_ID);
+       mutex_unlock(&dev_priv->hw_mutex);
+
        /**
         * Reclaim 3d reference held by fbdev and potentially
         * start fifo.
index b07ca2e4d04b5852c6b59438aaae27bbe478acd2..7290811f89bef5956019f90acc59f543206e49e7 100644 (file)
@@ -110,6 +110,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
        memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
 
        ret = copy_to_user(buffer, bounce, size);
+       if (ret)
+               ret = -EFAULT;
        vfree(bounce);
 
        if (unlikely(ret != 0))
index 06ebdbb6ea0207f8d92d691d15c00434f4fab21a..fd7722aecf77929eea158263af6cc1b601287408 100644 (file)
@@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {
                .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
                .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+               .driver_data = APPLE_HAS_FN },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+               .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
+               .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
                .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
index bd3971bf31bf7bc4369911a648b02c8729a3004d..f4109fd657ff7a337761f9029969dde8ee71e3cc 100644 (file)
@@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { }
index 269b50912a4ae9207d1d04f2e014b3c950f20324..9d7a42857ea190a9b9fbc12582582b8ae97ebd2a 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI  0x0252
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO   0x0253
 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS   0x0254
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI  0x0249
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO   0x024a
 #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS   0x024b
index 3acdcfcc17df24f696ed7b440f6a29540456e33e..6fcd466d082512f675d027aafd7600eb34edebaf 100644 (file)
 #define MS_RDESC               0x08
 #define MS_NOGET               0x10
 #define MS_DUPLICATE_USAGES    0x20
+#define MS_RDESC_3K            0x40
 
-/*
- * Microsoft Wireless Desktop Receiver (Model 1028) has
- * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
- */
 static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
        unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
 
+       /*
+        * Microsoft Wireless Desktop Receiver (Model 1028) has
+        * 'Usage Min/Max' where it ought to have 'Physical Min/Max'
+        */
        if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&
                        rdesc[559] == 0x29) {
                hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");
                rdesc[557] = 0x35;
                rdesc[559] = 0x45;
        }
+       /* the same as above (s/usage/physical/) */
+       if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 &&
+                       rdesc[95] == 0x00 && rdesc[96] == 0x29 &&
+                       rdesc[97] == 0xff) {
+               rdesc[94] = 0x35;
+               rdesc[96] = 0x45;
+       }
        return rdesc;
 }
 
@@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {
        { 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 },
+               .driver_data = MS_ERGONOMY | MS_RDESC_3K },
        { 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),
index 3eb02b94fc87c8a3bc903474db7c3b55efd5ead5..7867d69f0efe1cd734c57e7e4627eb9aaf7a367e 100644 (file)
@@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {
        },
        { .name = MT_CLS_GENERALTOUCH_PWT_TENFINGERS,
                .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP |
-                       MT_QUIRK_SLOT_IS_CONTACTNUMBER,
-               .maxcontacts = 10
+                       MT_QUIRK_SLOT_IS_CONTACTNUMBER
        },
 
        { .name = MT_CLS_FLATFROG,
@@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                         * contact max are global to the report */
                        td->last_field_index = field->index;
                        return -1;
-               }
                case HID_DG_TOUCH:
                        /* Legacy devices use TIPSWITCH and not TOUCH.
                         * Let's just ignore this field. */
                        return -1;
+               }
                /* let hid-input decide for the others */
                return 0;
 
index 17d15bb610d15ac4b544e11af3007cd5b6357fd8..7c47fc3f7b2b0b28f27021c75bb3b8d8f3771c4d 100644 (file)
@@ -42,7 +42,6 @@ static struct cdev hidraw_cdev;
 static struct class *hidraw_class;
 static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES];
 static DEFINE_MUTEX(minors_lock);
-static void drop_ref(struct hidraw *hid, int exists_bit);
 
 static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 {
@@ -114,7 +113,7 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
        __u8 *buf;
        int ret = 0;
 
-       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+       if (!hidraw_table[minor]) {
                ret = -ENODEV;
                goto out;
        }
@@ -262,7 +261,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
        }
 
        mutex_lock(&minors_lock);
-       if (!hidraw_table[minor] || !hidraw_table[minor]->exist) {
+       if (!hidraw_table[minor]) {
                err = -ENODEV;
                goto out_unlock;
        }
@@ -299,12 +298,36 @@ out:
 static int hidraw_release(struct inode * inode, struct file * file)
 {
        unsigned int minor = iminor(inode);
+       struct hidraw *dev;
        struct hidraw_list *list = file->private_data;
+       int ret;
+       int i;
+
+       mutex_lock(&minors_lock);
+       if (!hidraw_table[minor]) {
+               ret = -ENODEV;
+               goto unlock;
+       }
 
-       drop_ref(hidraw_table[minor], 0);
        list_del(&list->node);
+       dev = hidraw_table[minor];
+       if (!--dev->open) {
+               if (list->hidraw->exist) {
+                       hid_hw_power(dev->hid, PM_HINT_NORMAL);
+                       hid_hw_close(dev->hid);
+               } else {
+                       kfree(list->hidraw);
+               }
+       }
+
+       for (i = 0; i < HIDRAW_BUFFER_SIZE; ++i)
+               kfree(list->buffer[i].value);
        kfree(list);
-       return 0;
+       ret = 0;
+unlock:
+       mutex_unlock(&minors_lock);
+
+       return ret;
 }
 
 static long hidraw_ioctl(struct file *file, unsigned int cmd,
@@ -506,7 +529,21 @@ EXPORT_SYMBOL_GPL(hidraw_connect);
 void hidraw_disconnect(struct hid_device *hid)
 {
        struct hidraw *hidraw = hid->hidraw;
-       drop_ref(hidraw, 1);
+
+       mutex_lock(&minors_lock);
+       hidraw->exist = 0;
+
+       device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+
+       hidraw_table[hidraw->minor] = NULL;
+
+       if (hidraw->open) {
+               hid_hw_close(hid);
+               wake_up_interruptible(&hidraw->wait);
+       } else {
+               kfree(hidraw);
+       }
+       mutex_unlock(&minors_lock);
 }
 EXPORT_SYMBOL_GPL(hidraw_disconnect);
 
@@ -555,23 +592,3 @@ void hidraw_exit(void)
        unregister_chrdev_region(dev_id, HIDRAW_MAX_DEVICES);
 
 }
-
-static void drop_ref(struct hidraw *hidraw, int exists_bit)
-{
-       mutex_lock(&minors_lock);
-       if (exists_bit) {
-               hid_hw_close(hidraw->hid);
-               hidraw->exist = 0;
-               if (hidraw->open)
-                       wake_up_interruptible(&hidraw->wait);
-       } else {
-               --hidraw->open;
-       }
-
-       if (!hidraw->open && !hidraw->exist) {
-               device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
-               hidraw_table[hidraw->minor] = NULL;
-               kfree(hidraw);
-       }
-       mutex_unlock(&minors_lock);
-}
index 406537420fffdc0b90c008dad53205bd19f2acfe..f4c3d28cd1fcc96ed76720433104aa21bd0b08a6 100644 (file)
@@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        ret = hv_ringbuffer_init(
                &newchannel->inbound, in, recv_ringbuffer_size);
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
 
@@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (ret != 0) {
                err = ret;
-               goto errorout;
+               goto error0;
        }
 
        /* Create and init the channel open message */
@@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                           GFP_KERNEL);
        if (!open_info) {
                err = -ENOMEM;
-               goto errorout;
+               goto error0;
        }
 
        init_completion(&open_info->waitevent);
@@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
 
        if (userdatalen > MAX_USER_DEFINED_BYTES) {
                err = -EINVAL;
-               goto errorout;
+               goto error0;
        }
 
        if (userdatalen)
@@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size,
                               sizeof(struct vmbus_channel_open_channel));
 
        if (ret != 0)
-               goto cleanup;
+               goto error1;
 
        t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ);
        if (t == 0) {
                err = -ETIMEDOUT;
-               goto errorout;
+               goto error1;
        }
 
 
        if (open_info->response.open_result.status)
                err = open_info->response.open_result.status;
 
-cleanup:
        spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
        list_del(&open_info->msglistentry);
        spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
@@ -228,9 +227,12 @@ cleanup:
        kfree(open_info);
        return err;
 
-errorout:
-       hv_ringbuffer_cleanup(&newchannel->outbound);
-       hv_ringbuffer_cleanup(&newchannel->inbound);
+error1:
+       spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags);
+       list_del(&open_info->msglistentry);
+       spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags);
+
+error0:
        free_pages((unsigned long)out,
                get_order(send_ringbuffer_size + recv_ringbuffer_size));
        kfree(open_info);
index a227be47149f473bfd6fc2d41a8de99f842056fd..520e5bf4f76d9f8cd1b16edf5610554fde103181 100644 (file)
@@ -32,7 +32,7 @@
  * ASB100-A supports pwm1, while plain ASB100 does not.  There is no known
  * way for the driver to tell which one is there.
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * asb100      7       3       1       4       0x31    0x0694  yes     no
  */
 
index 984a3f13923b615b7c6849cd59b396689680ed20..47b8d84b489ddb748bd0a3fea2b1aa2582be1002 100644 (file)
@@ -205,8 +205,11 @@ static const struct tjmax __cpuinitconst tjmax_table[] = {
        { "CPU N455", 100000 },
        { "CPU N470", 100000 },
        { "CPU N475", 100000 },
-       { "CPU  230", 100000 },
-       { "CPU  330", 125000 },
+       { "CPU  230", 100000 },         /* Model 0x1c, stepping 2       */
+       { "CPU  330", 125000 },         /* Model 0x1c, stepping 2       */
+       { "CPU CE4110", 110000 },       /* Model 0x1c, stepping 10      */
+       { "CPU CE4150", 110000 },       /* Model 0x1c, stepping 10      */
+       { "CPU CE4170", 110000 },       /* Model 0x1c, stepping 10      */
 };
 
 static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id,
index 68ad7d2555124a45f2d9008374d973d4b6de3b04..4f4110407387fce21c4e58cdc76dfec6093b6183 100644 (file)
@@ -2,7 +2,7 @@
  * fam15h_power.c - AMD Family 15h processor power monitoring
  *
  * Copyright (c) 2011 Advanced Micro Devices, Inc.
- * Author: Andreas Herrmann <andreas.herrmann3@amd.com>
+ * Author: Andreas Herrmann <herrmann.der.user@googlemail.com>
  *
  *
  * This driver is free software; you can redistribute it and/or
@@ -28,7 +28,7 @@
 #include <asm/processor.h>
 
 MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor");
-MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>");
+MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");
 MODULE_LICENSE("GPL");
 
 /* D18F3 */
index 36509ae32083d2b3e48ec894768c504e1179577c..1381a2e3bbd4dc09dca9e74c87dd4ad2ce5ebc50 100644 (file)
@@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {
        .driver = {
                .name   = "gpio-fan",
                .pm     = GPIO_FAN_PM,
+#ifdef CONFIG_OF_GPIO
                .of_match_table = of_match_ptr(of_gpio_fan_match),
+#endif
        },
 };
 
index 2ca6a5a4f5a795a23721467581ff9e02cc5baf5a..60745a535821d3b787af31a00cfcecd41743c7ec 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig PMBUS
        tristate "PMBus support"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        default n
        help
          Say yes here if you want to enable PMBus support.
index 1821b7423d5b77ae5a9e6cdd2794a7e1b9a2c173..de3c7e04c3b5b21ae095f6f91308d1fb97eb6e64 100644 (file)
@@ -2083,6 +2083,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev)
        mutex_init(&data->lock);
        mutex_init(&data->update_lock);
        data->name = w83627ehf_device_names[sio_data->kind];
+       data->bank = 0xff;              /* Force initial bank selection */
        platform_set_drvdata(pdev, data);
 
        /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
index 5b1a6a666441f242ac63f21d9b9359464ced3f97..af15899087095044c623b4ddf0aeadbb15ed8801 100644 (file)
@@ -25,7 +25,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83627hf    9       3       2       3       0x20    0x5ca3  no      yes(LPC)
  * w83627thf   7       3       3       3       0x90    0x5ca3  no      yes(LPC)
  * w83637hf    7       3       3       3       0x80    0x5ca3  no      yes(LPC)
index 5a5046d94c3eee8288cf5871655fffa973d97977..20f11d31da407f5545af8b7082187c518721522a 100644 (file)
@@ -24,7 +24,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * as99127f    7       3       0       3       0x31    0x12c3  yes     no
  * as99127f rev.2 (type_name = as99127f)       0x31    0x5ca3  yes     no
  * w83781d     7       3       0       3       0x10-1  0x5ca3  yes     yes
index 39ab7bcc616e7a9e8733ce9bbbcc7e3cf6b0b970..ed397c6451983473b9ca7d1dbac399194a746fb3 100644 (file)
@@ -22,7 +22,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83791d     10      5       5       3       0x71    0x5ca3  yes     no
  *
  * The w83791d chip appears to be part way between the 83781d and the
index 053645279f381b453396053dfb71294346604717..301942d084534ef748f1917b1fa3dccde1b8beed 100644 (file)
@@ -31,7 +31,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83792d     9       7       7       3       0x7a    0x5ca3  yes     no
  */
 
index f0e8286c3c70ed7c1c2a57a73b19cc06fec8a193..79710bcac2f724233746b9c416fd53384dd52e52 100644 (file)
@@ -20,7 +20,7 @@
 /*
  * Supports following chips:
  *
- * Chip        #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+ * Chip                #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
  * w83l786ng   3       2       2       2       0x7b    0x5ca3  yes     no
  */
 
index beee6b2d361db458a1336a48bd13b5166d6d013c..1722f50f247385e0247c98e5dee91c97f18203ee 100644 (file)
@@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS)         += i2c-smbus.o
 obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
 obj-$(CONFIG_I2C_MUX)          += i2c-mux.o
 obj-y                          += algos/ busses/ muxes/
+obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 
 ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
 CFLAGS_i2c-core.o := -Wno-deprecated-declarations
index 65dd599a02620211b8db7a1ef6bfd1d8f9cdda30..e9df4612b7ebc9710db24290b159b4bd77d5d625 100644 (file)
@@ -81,7 +81,6 @@ config I2C_I801
        tristate "Intel 82801 (ICH/PCH)"
        depends on PCI
        select CHECK_SIGNATURE if X86 && DMI
-       select GPIOLIB if I2C_MUX
        help
          If you say yes to this option, support will be included for the Intel
          801 family of mainboard I2C interfaces.  Specifically, the following
index 2d33d62952c112adfb62bde5f08a342a37466c78..395b516ffa08cddbf5fdc2cbc5e2c34a558e356c 100644 (file)
@@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN)               += i2c-acorn.o
 obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
 obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
-obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
 
index aa59a254be2c3e3755a377d0c0c1f02dfa6c797d..c02bf208084f0a52cbb08548a36cece9c0ca3fb9 100644 (file)
@@ -39,6 +39,7 @@
 #define        AT91_TWI_STOP           0x0002  /* Send a Stop Condition */
 #define        AT91_TWI_MSEN           0x0004  /* Master Transfer Enable */
 #define        AT91_TWI_SVDIS          0x0020  /* Slave Transfer Disable */
+#define        AT91_TWI_QUICK          0x0040  /* SMBus quick command */
 #define        AT91_TWI_SWRST          0x0080  /* Software Reset */
 
 #define        AT91_TWI_MMR            0x0004  /* Master Mode Register */
@@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 
        INIT_COMPLETION(dev->cmd_complete);
        dev->transfer_status = 0;
-       if (dev->msg->flags & I2C_M_RD) {
+
+       if (!dev->buf_len) {
+               at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK);
+               at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
+       } else if (dev->msg->flags & I2C_M_RD) {
                unsigned start_flags = AT91_TWI_START;
 
                if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
index 37793156bd936202a10362e7910d88708c4a9248..6abc00d59881c921e14ab460f8bb477995c4ea44 100644 (file)
@@ -82,7 +82,8 @@
 #include <linux/wait.h>
 #include <linux/err.h>
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
 #include <linux/gpio.h>
 #include <linux/i2c-mux-gpio.h>
 #include <linux/platform_device.h>
@@ -192,7 +193,8 @@ struct i801_priv {
        int len;
        u8 *data;
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
        const struct i801_mux_config *mux_drvdata;
        struct platform_device *mux_pdev;
 #endif
@@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}
 static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
 #endif /* CONFIG_X86 && CONFIG_DMI */
 
-#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
+#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \
+               defined CONFIG_DMI
 static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
        .gpio_chip = "gpio_ich",
        .values = { 0x02, 0x03 },
@@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
 
        id = dmi_first_match(mux_dmi_table);
        if (id) {
-               /* Remove from branch classes from trunk */
+               /* Remove branch classes from trunk */
                mux_config = id->driver_data;
                for (i = 0; i < mux_config->n_values; i++)
                        class &= ~mux_config->classes[i];
index 1f58197062cfe120b8987236044afbeec5e397df..0670da79ee5e53cd0682dbdc1e7b311a196f73e1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Freescale MXS I2C bus driver
  *
- * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.
  *
  * based on a (non-working) driver which was:
  *
 
 #define DRIVER_NAME "mxs-i2c"
 
-static bool use_pioqueue;
-module_param(use_pioqueue, bool, 0);
-MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
-
 #define MXS_I2C_CTRL0          (0x00)
 #define MXS_I2C_CTRL0_SET      (0x04)
 
@@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");
                                 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
                                 MXS_I2C_CTRL1_SLAVE_IRQ)
 
-#define MXS_I2C_QUEUECTRL      (0x60)
-#define MXS_I2C_QUEUECTRL_SET  (0x64)
-#define MXS_I2C_QUEUECTRL_CLR  (0x68)
-
-#define MXS_I2C_QUEUECTRL_QUEUE_RUN            0x20
-#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE       0x04
-
-#define MXS_I2C_QUEUESTAT      (0x70)
-#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY        0x00002000
-#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F
-
-#define MXS_I2C_QUEUECMD       (0x80)
-
-#define MXS_I2C_QUEUEDATA      (0x90)
-
-#define MXS_I2C_DATA           (0xa0)
-
 
 #define MXS_CMD_I2C_SELECT     (MXS_I2C_CTRL0_RETAIN_CLOCK |   \
                                 MXS_I2C_CTRL0_PRE_SEND_START | \
@@ -153,7 +132,6 @@ struct mxs_i2c_dev {
        const struct mxs_i2c_speed_config *speed;
 
        /* DMA support components */
-       bool                            dma_mode;
        int                             dma_channel;
        struct dma_chan                 *dmach;
        struct mxs_dma_data             dma_data;
@@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
        writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);
 
        writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
-       if (i2c->dma_mode)
-               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
-                       i2c->regs + MXS_I2C_QUEUECTRL_CLR);
-       else
-               writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
-                       i2c->regs + MXS_I2C_QUEUECTRL_SET);
-}
-
-static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
-                                       int flags)
-{
-       u32 data;
-
-       writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
-
-       data = (addr << 1) | I2C_SMBUS_READ;
-       writel(data, i2c->regs + MXS_I2C_DATA);
-
-       data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
-       writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-}
-
-static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
-                                   u8 addr, u8 *buf, int len, int flags)
-{
-       u32 data;
-       int i, shifts_left;
-
-       data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
-       writel(data, i2c->regs + MXS_I2C_QUEUECMD);
-
-       /*
-        * We have to copy the slave address (u8) and buffer (arbitrary number
-        * of u8) into the data register (u32). To achieve that, the u8 are put
-        * into the MSBs of 'data' which is then shifted for the next u8. When
-        * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
-        * looks like this:
-        *
-        *  3          2          1          0
-        * 10987654|32109876|54321098|76543210
-        * --------+--------+--------+--------
-        * buffer+2|buffer+1|buffer+0|slave_addr
-        */
-
-       data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
-
-       for (i = 0; i < len; i++) {
-               data >>= 8;
-               data |= buf[i] << 24;
-               if ((i & 3) == 2)
-                       writel(data, i2c->regs + MXS_I2C_DATA);
-       }
-
-       /* Write out the remaining bytes if any */
-       shifts_left = 24 - (i & 3) * 8;
-       if (shifts_left)
-               writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
-}
-
-/*
- * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
- * rd_threshold to 1). Couldn't get this to work, though.
- */
-static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
-{
-       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
-       while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
-                       & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
-                       if (time_after(jiffies, timeout))
-                               return -ETIMEDOUT;
-                       cond_resched();
-       }
-
-       return 0;
-}
-
-static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
-{
-       u32 uninitialized_var(data);
-       int i;
-
-       for (i = 0; i < len; i++) {
-               if ((i & 3) == 0) {
-                       if (mxs_i2c_wait_for_data(i2c))
-                               return -ETIMEDOUT;
-                       data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
-               }
-               buf[i] = data & 0xff;
-               data >>= 8;
-       }
-
-       return 0;
 }
 
 static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c)
@@ -402,12 +287,14 @@ read_init_dma_fail:
 select_init_dma_fail:
        dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
 select_init_pio_fail:
+       dmaengine_terminate_all(i2c->dmach);
        return -EINVAL;
 
 /* Write failpath. */
 write_init_dma_fail:
        dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
 write_init_pio_fail:
+       dmaengine_terminate_all(i2c->dmach);
        return -EINVAL;
 }
 
@@ -432,39 +319,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
        init_completion(&i2c->cmd_complete);
        i2c->cmd_err = 0;
 
-       if (i2c->dma_mode) {
-               ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
-               if (ret)
-                       return ret;
-       } else {
-               if (msg->flags & I2C_M_RD) {
-                       mxs_i2c_pioq_setup_read(i2c, msg->addr,
-                                               msg->len, flags);
-               } else {
-                       mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf,
-                                               msg->len, flags);
-               }
-
-               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                       i2c->regs + MXS_I2C_QUEUECTRL_SET);
-       }
+       ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
+       if (ret)
+               return ret;
 
        ret = wait_for_completion_timeout(&i2c->cmd_complete,
                                                msecs_to_jiffies(1000));
        if (ret == 0)
                goto timeout;
 
-       if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) {
-               ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
-               if (ret)
-                       goto timeout;
-       }
-
        if (i2c->cmd_err == -ENXIO)
                mxs_i2c_reset(i2c);
-       else
-               writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
-                               i2c->regs + MXS_I2C_QUEUECTRL_CLR);
 
        dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
 
@@ -472,8 +337,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
 
 timeout:
        dev_dbg(i2c->dev, "Timeout!\n");
-       if (i2c->dma_mode)
-               mxs_i2c_dma_finish(i2c);
+       mxs_i2c_dma_finish(i2c);
        mxs_i2c_reset(i2c);
        return -ETIMEDOUT;
 }
@@ -502,7 +366,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
 {
        struct mxs_i2c_dev *i2c = dev_id;
        u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
-       bool is_last_cmd;
 
        if (!stat)
                return IRQ_NONE;
@@ -515,14 +378,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
                /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
                i2c->cmd_err = -EIO;
 
-       if (!i2c->dma_mode) {
-               is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) &
-                       MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0;
-
-               if (is_last_cmd || i2c->cmd_err)
-                       complete(&i2c->cmd_complete);
-       }
-
        writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
 
        return IRQ_HANDLED;
@@ -555,15 +410,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        struct device_node *node = dev->of_node;
        int ret;
 
-       /*
-        * The MXS I2C DMA mode is prefered and enabled by default.
-        * The PIO mode is still supported, but should be used only
-        * for debuging purposes etc.
-        */
-       i2c->dma_mode = !use_pioqueue;
-       if (!i2c->dma_mode)
-               dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n");
-
        /*
         * TODO: This is a temporary solution and should be changed
         * to use generic DMA binding later when the helpers get in.
@@ -571,8 +417,8 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        ret = of_property_read_u32(node, "fsl,i2c-dma-channel",
                                   &i2c->dma_channel);
        if (ret) {
-               dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n");
-               i2c->dma_mode = 0;
+               dev_err(dev, "Failed to get DMA channel!\n");
+               return -ENODEV;
        }
 
        ret = of_property_read_u32(node, "clock-frequency", &speed);
@@ -634,15 +480,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
        }
 
        /* Setup the DMA */
-       if (i2c->dma_mode) {
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_SLAVE, mask);
-               i2c->dma_data.chan_irq = dmairq;
-               i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
-               if (!i2c->dmach) {
-                       dev_err(dev, "Failed to request dma\n");
-                       return -ENODEV;
-               }
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       i2c->dma_data.chan_irq = dmairq;
+       i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c);
+       if (!i2c->dmach) {
+               dev_err(dev, "Failed to request dma\n");
+               return -ENODEV;
        }
 
        platform_set_drvdata(pdev, i2c);
index 698d7acb0f083c10ea2028ad895e58043105f44e..02c3115a2dfa11c0aecf5a5c7e6bc24566539c8b 100644 (file)
@@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
 
        pm_runtime_get_sync(&dev->adev->dev);
 
-       clk_enable(dev->clk);
+       status = clk_prepare_enable(dev->clk);
+       if (status) {
+               dev_err(&dev->adev->dev, "can't prepare_enable clock\n");
+               goto out_clk;
+       }
 
        status = init_hw(dev);
        if (status)
@@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
 
 out:
-       clk_disable(dev->clk);
+       clk_disable_unprepare(dev->clk);
+out_clk:
        pm_runtime_put_sync(&dev->adev->dev);
 
        dev->busy = false;
index db31eaed6ea59b32083df49f757c1fc949c60303..3525c9e62cb0f9bf23f47705fd86d3bba9707b45 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2           0x20
@@ -187,8 +186,9 @@ struct omap_i2c_dev {
        int                     reg_shift;      /* bit shift for I2C register addresses */
        struct completion       cmd_complete;
        struct resource         *ioarea;
-       u32                     latency;        /* maximum MPU wkup latency */
-       struct pm_qos_request   pm_qos_request;
+       u32                     latency;        /* maximum mpu wkup latency */
+       void                    (*set_mpu_wkup_lat)(struct device *dev,
+                                                   long latency);
        u32                     speed;          /* Speed of bus in kHz */
        u32                     dtrev;          /* extra revision from DT */
        u32                     flags;
@@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
                dev->b_hw = 1; /* Enable hardware fixes */
 
        /* calculate wakeup latency constraint for MPU */
-       dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->latency = (1000000 * dev->threshold) /
+                       (1000 * dev->speed / 8);
 }
 
 /*
@@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
        dev->buf = msg->buf;
        dev->buf_len = msg->len;
 
+       /* make sure writes to dev->buf_len are ordered */
+       barrier();
+
        omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
 
        /* Clear the FIFO Buffers */
@@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
         */
        timeout = wait_for_completion_timeout(&dev->cmd_complete,
                                                OMAP_I2C_TIMEOUT);
-       dev->buf_len = 0;
        if (timeout == 0) {
                dev_err(dev->dev, "controller timed out\n");
                omap_i2c_init(dev);
@@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        if (r < 0)
                goto out;
 
-       /*
-        * When waiting for completion of a i2c transfer, we need to
-        * set a wake up latency constraint for the MPU. This is to
-        * ensure quick enough wakeup from idle, when transfer
-        * completes.
-        */
-       if (dev->latency)
-               pm_qos_add_request(&dev->pm_qos_request,
-                                  PM_QOS_CPU_DMA_LATENCY,
-                                  dev->latency);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->set_mpu_wkup_lat(dev->dev, dev->latency);
 
        for (i = 0; i < num; i++) {
                r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
                        break;
        }
 
-       if (dev->latency)
-               pm_qos_remove_request(&dev->pm_qos_request);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->set_mpu_wkup_lat(dev->dev, -1);
 
        if (r == 0)
                r = num;
@@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev)
        } else if (pdata != NULL) {
                dev->speed = pdata->clkrate;
                dev->flags = pdata->flags;
+               dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
                dev->dtrev = pdata->rev;
        }
 
@@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev)
                        dev->b_hw = 1; /* Enable hardware fixes */
 
                /* calculate wakeup latency constraint for MPU */
-               dev->latency = (1000000 * dev->fifo_size) /
-                              (1000 * dev->speed / 8);
+               if (dev->set_mpu_wkup_lat != NULL)
+                       dev->latency = (1000000 * dev->fifo_size) /
+                                      (1000 * dev->speed / 8);
        }
 
        /* reset ASAP, clearing any IRQs */
index 3e0335f1fc60df8b78ce50c7a4e5284e82ad432f..9d902725bac94f28c91aa26ec57615988cd96e77 100644 (file)
@@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
                        dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
                        goto free_gpio;
                }
+               i2c->gpios[idx] = gpio;
 
                ret = gpio_request(gpio, "i2c-bus");
                if (ret) {
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
deleted file mode 100644 (file)
index b1b3447..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
-    i2c-stub.c - I2C/SMBus chip emulator
-
-    Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
-    Copyright (C) 2007 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
-    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 DEBUG 1
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/i2c.h>
-
-#define MAX_CHIPS 10
-#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
-                  I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
-                  I2C_FUNC_SMBUS_I2C_BLOCK)
-
-static unsigned short chip_addr[MAX_CHIPS];
-module_param_array(chip_addr, ushort, NULL, S_IRUGO);
-MODULE_PARM_DESC(chip_addr,
-                "Chip addresses (up to 10, between 0x03 and 0x77)");
-
-static unsigned long functionality = STUB_FUNC;
-module_param(functionality, ulong, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(functionality, "Override functionality bitfield");
-
-struct stub_chip {
-       u8 pointer;
-       u16 words[256];         /* Byte operations use the LSB as per SMBus
-                                  specification */
-};
-
-static struct stub_chip *stub_chips;
-
-/* Return negative errno on error. */
-static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
-       char read_write, u8 command, int size, union i2c_smbus_data * data)
-{
-       s32 ret;
-       int i, len;
-       struct stub_chip *chip = NULL;
-
-       /* Search for the right chip */
-       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
-               if (addr == chip_addr[i]) {
-                       chip = stub_chips + i;
-                       break;
-               }
-       }
-       if (!chip)
-               return -ENODEV;
-
-       switch (size) {
-
-       case I2C_SMBUS_QUICK:
-               dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr);
-               ret = 0;
-               break;
-
-       case I2C_SMBUS_BYTE:
-               if (read_write == I2C_SMBUS_WRITE) {
-                       chip->pointer = command;
-                       dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
-                                       "wrote 0x%02x.\n",
-                                       addr, command);
-               } else {
-                       data->byte = chip->words[chip->pointer++] & 0xff;
-                       dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, "
-                                       "read  0x%02x.\n",
-                                       addr, data->byte);
-               }
-
-               ret = 0;
-               break;
-
-       case I2C_SMBUS_BYTE_DATA:
-               if (read_write == I2C_SMBUS_WRITE) {
-                       chip->words[command] &= 0xff00;
-                       chip->words[command] |= data->byte;
-                       dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
-                                       "wrote 0x%02x at 0x%02x.\n",
-                                       addr, data->byte, command);
-               } else {
-                       data->byte = chip->words[command] & 0xff;
-                       dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, "
-                                       "read  0x%02x at 0x%02x.\n",
-                                       addr, data->byte, command);
-               }
-               chip->pointer = command + 1;
-
-               ret = 0;
-               break;
-
-       case I2C_SMBUS_WORD_DATA:
-               if (read_write == I2C_SMBUS_WRITE) {
-                       chip->words[command] = data->word;
-                       dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
-                                       "wrote 0x%04x at 0x%02x.\n",
-                                       addr, data->word, command);
-               } else {
-                       data->word = chip->words[command];
-                       dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, "
-                                       "read  0x%04x at 0x%02x.\n",
-                                       addr, data->word, command);
-               }
-
-               ret = 0;
-               break;
-
-       case I2C_SMBUS_I2C_BLOCK_DATA:
-               len = data->block[0];
-               if (read_write == I2C_SMBUS_WRITE) {
-                       for (i = 0; i < len; i++) {
-                               chip->words[command + i] &= 0xff00;
-                               chip->words[command + i] |= data->block[1 + i];
-                       }
-                       dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
-                                       "wrote %d bytes at 0x%02x.\n",
-                                       addr, len, command);
-               } else {
-                       for (i = 0; i < len; i++) {
-                               data->block[1 + i] =
-                                       chip->words[command + i] & 0xff;
-                       }
-                       dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
-                                       "read  %d bytes at 0x%02x.\n",
-                                       addr, len, command);
-               }
-
-               ret = 0;
-               break;
-
-       default:
-               dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
-               ret = -EOPNOTSUPP;
-               break;
-       } /* switch (size) */
-
-       return ret;
-}
-
-static u32 stub_func(struct i2c_adapter *adapter)
-{
-       return STUB_FUNC & functionality;
-}
-
-static const struct i2c_algorithm smbus_algorithm = {
-       .functionality  = stub_func,
-       .smbus_xfer     = stub_xfer,
-};
-
-static struct i2c_adapter stub_adapter = {
-       .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
-       .algo           = &smbus_algorithm,
-       .name           = "SMBus stub driver",
-};
-
-static int __init i2c_stub_init(void)
-{
-       int i, ret;
-
-       if (!chip_addr[0]) {
-               printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
-               return -ENODEV;
-       }
-
-       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
-               if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
-                       printk(KERN_ERR "i2c-stub: Invalid chip address "
-                              "0x%02x\n", chip_addr[i]);
-                       return -EINVAL;
-               }
-
-               printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n",
-                      chip_addr[i]);
-       }
-
-       /* Allocate memory for all chips at once */
-       stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
-       if (!stub_chips) {
-               printk(KERN_ERR "i2c-stub: Out of memory\n");
-               return -ENOMEM;
-       }
-
-       ret = i2c_add_adapter(&stub_adapter);
-       if (ret)
-               kfree(stub_chips);
-       return ret;
-}
-
-static void __exit i2c_stub_exit(void)
-{
-       i2c_del_adapter(&stub_adapter);
-       kfree(stub_chips);
-}
-
-MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
-MODULE_DESCRIPTION("I2C stub driver");
-MODULE_LICENSE("GPL");
-
-module_init(i2c_stub_init);
-module_exit(i2c_stub_exit);
-
index f981ac4e6783104ee8586e2631fc58f788d49be6..dcea77bf6f50ff2cc1c198e7850bbbe138128238 100644 (file)
@@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
        }
 
        ret = devm_request_irq(&pdev->dev, i2c_dev->irq,
-                       tegra_i2c_isr, 0, pdev->name, i2c_dev);
+                       tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);
        if (ret) {
                dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
                return ret;
diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c
new file mode 100644 (file)
index 0000000..d0a9c59
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+    i2c-stub.c - I2C/SMBus chip emulator
+
+    Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
+    Copyright (C) 2007, 2012 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
+    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 DEBUG 1
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/i2c.h>
+
+#define MAX_CHIPS 10
+#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \
+                  I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \
+                  I2C_FUNC_SMBUS_I2C_BLOCK)
+
+static unsigned short chip_addr[MAX_CHIPS];
+module_param_array(chip_addr, ushort, NULL, S_IRUGO);
+MODULE_PARM_DESC(chip_addr,
+                "Chip addresses (up to 10, between 0x03 and 0x77)");
+
+static unsigned long functionality = STUB_FUNC;
+module_param(functionality, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(functionality, "Override functionality bitfield");
+
+struct stub_chip {
+       u8 pointer;
+       u16 words[256];         /* Byte operations use the LSB as per SMBus
+                                  specification */
+};
+
+static struct stub_chip *stub_chips;
+
+/* Return negative errno on error. */
+static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags,
+       char read_write, u8 command, int size, union i2c_smbus_data *data)
+{
+       s32 ret;
+       int i, len;
+       struct stub_chip *chip = NULL;
+
+       /* Search for the right chip */
+       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
+               if (addr == chip_addr[i]) {
+                       chip = stub_chips + i;
+                       break;
+               }
+       }
+       if (!chip)
+               return -ENODEV;
+
+       switch (size) {
+
+       case I2C_SMBUS_QUICK:
+               dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr);
+               ret = 0;
+               break;
+
+       case I2C_SMBUS_BYTE:
+               if (read_write == I2C_SMBUS_WRITE) {
+                       chip->pointer = command;
+                       dev_dbg(&adap->dev,
+                               "smbus byte - addr 0x%02x, wrote 0x%02x.\n",
+                               addr, command);
+               } else {
+                       data->byte = chip->words[chip->pointer++] & 0xff;
+                       dev_dbg(&adap->dev,
+                               "smbus byte - addr 0x%02x, read  0x%02x.\n",
+                               addr, data->byte);
+               }
+
+               ret = 0;
+               break;
+
+       case I2C_SMBUS_BYTE_DATA:
+               if (read_write == I2C_SMBUS_WRITE) {
+                       chip->words[command] &= 0xff00;
+                       chip->words[command] |= data->byte;
+                       dev_dbg(&adap->dev,
+                               "smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n",
+                               addr, data->byte, command);
+               } else {
+                       data->byte = chip->words[command] & 0xff;
+                       dev_dbg(&adap->dev,
+                               "smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n",
+                               addr, data->byte, command);
+               }
+               chip->pointer = command + 1;
+
+               ret = 0;
+               break;
+
+       case I2C_SMBUS_WORD_DATA:
+               if (read_write == I2C_SMBUS_WRITE) {
+                       chip->words[command] = data->word;
+                       dev_dbg(&adap->dev,
+                               "smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n",
+                               addr, data->word, command);
+               } else {
+                       data->word = chip->words[command];
+                       dev_dbg(&adap->dev,
+                               "smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\n",
+                               addr, data->word, command);
+               }
+
+               ret = 0;
+               break;
+
+       case I2C_SMBUS_I2C_BLOCK_DATA:
+               len = data->block[0];
+               if (read_write == I2C_SMBUS_WRITE) {
+                       for (i = 0; i < len; i++) {
+                               chip->words[command + i] &= 0xff00;
+                               chip->words[command + i] |= data->block[1 + i];
+                       }
+                       dev_dbg(&adap->dev,
+                               "i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n",
+                               addr, len, command);
+               } else {
+                       for (i = 0; i < len; i++) {
+                               data->block[1 + i] =
+                                       chip->words[command + i] & 0xff;
+                       }
+                       dev_dbg(&adap->dev,
+                               "i2c block data - addr 0x%02x, read  %d bytes at 0x%02x.\n",
+                               addr, len, command);
+               }
+
+               ret = 0;
+               break;
+
+       default:
+               dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
+               ret = -EOPNOTSUPP;
+               break;
+       } /* switch (size) */
+
+       return ret;
+}
+
+static u32 stub_func(struct i2c_adapter *adapter)
+{
+       return STUB_FUNC & functionality;
+}
+
+static const struct i2c_algorithm smbus_algorithm = {
+       .functionality  = stub_func,
+       .smbus_xfer     = stub_xfer,
+};
+
+static struct i2c_adapter stub_adapter = {
+       .owner          = THIS_MODULE,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+       .algo           = &smbus_algorithm,
+       .name           = "SMBus stub driver",
+};
+
+static int __init i2c_stub_init(void)
+{
+       int i, ret;
+
+       if (!chip_addr[0]) {
+               pr_err("i2c-stub: Please specify a chip address\n");
+               return -ENODEV;
+       }
+
+       for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {
+               if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) {
+                       pr_err("i2c-stub: Invalid chip address 0x%02x\n",
+                              chip_addr[i]);
+                       return -EINVAL;
+               }
+
+               pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);
+       }
+
+       /* Allocate memory for all chips at once */
+       stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);
+       if (!stub_chips) {
+               pr_err("i2c-stub: Out of memory\n");
+               return -ENOMEM;
+       }
+
+       ret = i2c_add_adapter(&stub_adapter);
+       if (ret)
+               kfree(stub_chips);
+       return ret;
+}
+
+static void __exit i2c_stub_exit(void)
+{
+       i2c_del_adapter(&stub_adapter);
+       kfree(stub_chips);
+}
+
+MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
+MODULE_DESCRIPTION("I2C stub driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_stub_init);
+module_exit(i2c_stub_exit);
index 5f097f309b9f9e92c59a5525db04283ab699fc74..7fa5b24b16db9a4a1c4c1a360f16dd01b018a215 100644 (file)
@@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
        mux->busses = devm_kzalloc(&pdev->dev,
                                   sizeof(mux->busses) * mux->pdata->bus_count,
                                   GFP_KERNEL);
-       if (!mux->states) {
+       if (!mux->busses) {
                dev_err(&pdev->dev, "Cannot allocate busses\n");
                ret = -ENOMEM;
                goto err;
index 6e3f143fc71d146c786a550162216be2200d0f4f..fc937aca71fbb2f7bb8a53fac55e2ae9b0cec048 100644 (file)
@@ -62,7 +62,6 @@ source "drivers/iio/frequency/Kconfig"
 source "drivers/iio/dac/Kconfig"
 source "drivers/iio/common/Kconfig"
 source "drivers/iio/gyro/Kconfig"
-source "drivers/iio/light/Kconfig"
 source "drivers/iio/magnetometer/Kconfig"
 
 endif # IIO
index f7fa3c0867b4c29026b2821cf793c352972741ce..761f2b65ac52865f4d16a99db3a1f6e7e1b61fbb 100644 (file)
@@ -18,5 +18,4 @@ obj-y += frequency/
 obj-y += dac/
 obj-y += common/
 obj-y += gyro/
-obj-y += light/
 obj-y += magnetometer/
index 57e07c61ace2e8147badfcd87e7f19fa211e4746..afd81790ab3c3e818c73b26fb6856e4f327c133a 100644 (file)
@@ -468,7 +468,7 @@ struct ib_mr *c4iw_register_phys_mem(struct ib_pd *pd,
        ret = alloc_pbl(mhp, npages);
        if (ret) {
                kfree(page_list);
-               goto err_pbl;
+               goto err;
        }
 
        ret = write_pbl(&mhp->rhp->rdev, page_list, mhp->attr.pbl_addr,
index d2fb38d43571d9f5ebba2dbc33e94ff5fc4cf737..2f215b93db6ba5a68b6d7e6fc38d21c91ff0cfa9 100644 (file)
@@ -107,7 +107,7 @@ static __be64 get_cached_alias_guid(struct mlx4_ib_dev *dev, int port, int index
 {
        if (index >= NUM_ALIAS_GUID_PER_PORT) {
                pr_err("%s: ERROR: asked for index:%d\n", __func__, index);
-               return  (__force __be64) ((u64) 0xFFFFFFFFFFFFFFFFUL);
+               return (__force __be64) -1;
        }
        return *(__be64 *)&dev->sriov.demux[port - 1].guid_cache[index];
 }
index 21a794152d15acea2a2e450258f4aaa915bce03a..0a903c129f0a19bfd0175de7aaea382dddec6d88 100644 (file)
@@ -409,38 +409,45 @@ int mlx4_ib_find_real_gid(struct ib_device *ibdev, u8 port, __be64 guid)
 }
 
 
-static int get_pkey_phys_indices(struct mlx4_ib_dev *ibdev, u8 port, u8 ph_pkey_ix,
-                                u8 *full_pk_ix, u8 *partial_pk_ix,
-                                int *is_full_member)
+static int find_slave_port_pkey_ix(struct mlx4_ib_dev *dev, int slave,
+                                  u8 port, u16 pkey, u16 *ix)
 {
-       u16 search_pkey;
-       int fm;
-       int err = 0;
-       u16 pk;
+       int i, ret;
+       u8 unassigned_pkey_ix, pkey_ix, partial_ix = 0xFF;
+       u16 slot_pkey;
 
-       err = ib_get_cached_pkey(&ibdev->ib_dev, port, ph_pkey_ix, &search_pkey);
-       if (err)
-               return err;
+       if (slave == mlx4_master_func_num(dev->dev))
+               return ib_find_cached_pkey(&dev->ib_dev, port, pkey, ix);
 
-       fm = (search_pkey & 0x8000) ? 1 : 0;
-       if (fm) {
-               *full_pk_ix = ph_pkey_ix;
-               search_pkey &= 0x7FFF;
-       } else {
-               *partial_pk_ix = ph_pkey_ix;
-               search_pkey |= 0x8000;
-       }
+       unassigned_pkey_ix = dev->dev->phys_caps.pkey_phys_table_len[port] - 1;
 
-       if (ib_find_exact_cached_pkey(&ibdev->ib_dev, port, search_pkey, &pk))
-               pk = 0xFFFF;
+       for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
+               if (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == unassigned_pkey_ix)
+                       continue;
 
-       if (fm)
-               *partial_pk_ix = (pk & 0xFF);
-       else
-               *full_pk_ix = (pk & 0xFF);
+               pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][i];
 
-       *is_full_member = fm;
-       return err;
+               ret = ib_get_cached_pkey(&dev->ib_dev, port, pkey_ix, &slot_pkey);
+               if (ret)
+                       continue;
+               if ((slot_pkey & 0x7FFF) == (pkey & 0x7FFF)) {
+                       if (slot_pkey & 0x8000) {
+                               *ix = (u16) pkey_ix;
+                               return 0;
+                       } else {
+                               /* take first partial pkey index found */
+                               if (partial_ix == 0xFF)
+                                       partial_ix = pkey_ix;
+                       }
+               }
+       }
+
+       if (partial_ix < 0xFF) {
+               *ix = (u16) partial_ix;
+               return 0;
+       }
+
+       return -EINVAL;
 }
 
 int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
@@ -458,10 +465,8 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        unsigned tun_tx_ix = 0;
        int dqpn;
        int ret = 0;
-       int i;
-       int is_full_member = 0;
        u16 tun_pkey_ix;
-       u8 ph_pkey_ix, full_pk_ix = 0, partial_pk_ix = 0;
+       u16 cached_pkey;
 
        if (dest_qpt > IB_QPT_GSI)
                return -EINVAL;
@@ -481,27 +486,17 @@ int mlx4_ib_send_to_slave(struct mlx4_ib_dev *dev, int slave, u8 port,
        else
                tun_qp = &tun_ctx->qp[1];
 
-       /* compute pkey index for slave */
-       /* get physical pkey -- virtualized Dom0 pkey to phys*/
+       /* compute P_Key index to put in tunnel header for slave */
        if (dest_qpt) {
-               ph_pkey_ix =
-                       dev->pkeys.virt2phys_pkey[mlx4_master_func_num(dev->dev)][port - 1][wc->pkey_index];
-
-               /* now, translate this to the slave pkey index */
-               ret = get_pkey_phys_indices(dev, port, ph_pkey_ix, &full_pk_ix,
-                                           &partial_pk_ix, &is_full_member);
+               u16 pkey_ix;
+               ret = ib_get_cached_pkey(&dev->ib_dev, port, wc->pkey_index, &cached_pkey);
                if (ret)
                        return -EINVAL;
 
-               for (i = 0; i < dev->dev->caps.pkey_table_len[port]; i++) {
-                       if ((dev->pkeys.virt2phys_pkey[slave][port - 1][i] == full_pk_ix) ||
-                           (is_full_member &&
-                            (dev->pkeys.virt2phys_pkey[slave][port - 1][i] == partial_pk_ix)))
-                               break;
-               }
-               if (i == dev->dev->caps.pkey_table_len[port])
+               ret = find_slave_port_pkey_ix(dev, slave, port, cached_pkey, &pkey_ix);
+               if (ret)
                        return -EINVAL;
-               tun_pkey_ix = i;
+               tun_pkey_ix = pkey_ix;
        } else
                tun_pkey_ix = dev->pkeys.virt2phys_pkey[slave][port - 1][0];
 
index 3c3b54c3fdd93206e60b85c421bc313d952c9655..25b2cdff00f8e4bcd76044e8916b2aa257a7276e 100644 (file)
@@ -233,7 +233,8 @@ static int send_mad_to_slave(int slave, struct mlx4_ib_demux_ctx *ctx,
 
        ib_query_ah(dev->sm_ah[ctx->port - 1], &ah_attr);
 
-       wc.pkey_index = 0;
+       if (ib_find_cached_pkey(&dev->ib_dev, ctx->port, IB_DEFAULT_PKEY_FULL, &wc.pkey_index))
+               return -EINVAL;
        wc.sl = 0;
        wc.dlid_path_bits = 0;
        wc.port_num = ctx->port;
@@ -1074,10 +1075,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
        unsigned long end;
        int count;
 
-       if (ctx->flushing)
-               return;
-
-       ctx->flushing = 1;
        for (i = 0; i < MAX_VFS; ++i)
                clean_vf_mcast(ctx, i);
 
@@ -1107,9 +1104,6 @@ static void _mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy
                force_clean_group(group);
        }
        mutex_unlock(&ctx->mcg_table_lock);
-
-       if (!destroy_wq)
-               ctx->flushing = 0;
 }
 
 struct clean_work {
@@ -1123,6 +1117,7 @@ static void mcg_clean_task(struct work_struct *work)
        struct clean_work *cw = container_of(work, struct clean_work, work);
 
        _mlx4_ib_mcg_port_cleanup(cw->ctx, cw->destroy_wq);
+       cw->ctx->flushing = 0;
        kfree(cw);
 }
 
@@ -1130,13 +1125,20 @@ void mlx4_ib_mcg_port_cleanup(struct mlx4_ib_demux_ctx *ctx, int destroy_wq)
 {
        struct clean_work *work;
 
+       if (ctx->flushing)
+               return;
+
+       ctx->flushing = 1;
+
        if (destroy_wq) {
                _mlx4_ib_mcg_port_cleanup(ctx, destroy_wq);
+               ctx->flushing = 0;
                return;
        }
 
        work = kmalloc(sizeof *work, GFP_KERNEL);
        if (!work) {
+               ctx->flushing = 0;
                mcg_warn("failed allocating work for cleanup\n");
                return;
        }
index 6ae2ac47c9c806ecf5224e2eb02c49a704b40432..f0f8928b3c8a2902295ccfdf4803b43e00f3a0c9 100644 (file)
@@ -292,7 +292,6 @@ static int evdev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        evdev_close_device(evdev);
-       put_device(&evdev->dev);
 
        return 0;
 }
@@ -331,7 +330,6 @@ static int evdev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&evdev->dev);
        return 0;
 
  err_free_client:
@@ -1001,6 +999,7 @@ static int evdev_connect(struct input_handler *handler, struct input_dev *dev,
                goto err_free_evdev;
 
        cdev_init(&evdev->cdev, &evdev_fops);
+       evdev->cdev.kobj.parent = &evdev->dev.kobj;
        error = cdev_add(&evdev->cdev, evdev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index c0ec7d42c3be05ffd574daec1870d44d560ed15a..1abbc170d8b77f302154323a0ea944474bfd5d37 100644 (file)
@@ -26,10 +26,14 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
  * input_mt_init_slots() - initialize MT input slots
  * @dev: input device supporting MT events and finger tracking
  * @num_slots: number of slots used by the device
+ * @flags: mt tasks to handle in core
  *
  * This function allocates all necessary memory for MT slot handling
  * in the input device, prepares the ABS_MT_SLOT and
  * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
+ * Depending on the flags set, it also performs pointer emulation and
+ * frame synchronization.
+ *
  * May be called repeatedly. Returns -EINVAL if attempting to
  * reinitialize with a different number of slots.
  */
index b62b5891f3999573893c732297ecd0467a094147..f362883c94e37ce828d18938b7d25790135cf2d1 100644 (file)
@@ -243,7 +243,6 @@ static int joydev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        joydev_close_device(joydev);
-       put_device(&joydev->dev);
 
        return 0;
 }
@@ -270,7 +269,6 @@ static int joydev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&joydev->dev);
        return 0;
 
  err_free_client:
@@ -858,6 +856,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev,
                goto err_free_joydev;
 
        cdev_init(&joydev->cdev, &joydev_fops);
+       joydev->cdev.kobj.parent = &joydev->dev.kobj;
        error = cdev_add(&joydev->cdev, joydev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index b4b65af8612a3f03a79ea19422873cd777f39b76..de0874054e9faebde97690fdb23986d268cbf95d 100644 (file)
@@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO
 config KEYBOARD_LPC32XX
        tristate "LPC32XX matrix key scanner support"
        depends on ARCH_LPC32XX && OF
+       select INPUT_MATRIXKMAP
        help
          Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
          connected to a key matrix.
index 803ff6fe021ec001393a5a9844dd825cbcb6235d..cad9d5dd597330b2eaa523b046f33edddb3641bb 100644 (file)
@@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
        unsigned int mask = 0, direct_key_num = 0;
        unsigned long kpc = 0;
 
+       /* clear pending interrupt bit */
+       keypad_readl(KPC);
+
        /* enable matrix keys with automatic scan */
        if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
                kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
index 02ca8680ea5b8f68393cecc3925792fc74236614..6f7d99013031b66f16d2c4e25f06dd3c352a622c 100644 (file)
@@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -350,6 +349,10 @@ InitWait:
 
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 3a78f235fa3e70b8057b929a2c4e2e763141cd9f..2baff1b79a5596eb33eaaaa31577c193d80f099e 100644 (file)
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI   0x0262
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO    0x0263
 #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS    0x0264
+/* MacbookPro10,2 (unibody, October 2012) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI  0x0259
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO   0x025a
+#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS   0x025b
 
 #define BCM5974_DEVICE(prod) {                                 \
        .match_flags = (USB_DEVICE_ID_MATCH_DEVICE |            \
@@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = {
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),
        BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),
+       /* MacbookPro10,2 */
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO),
+       BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),
        /* Terminating entry */
        {}
 };
@@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {
                { SN_COORD, -150, 6730 },
                { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
        },
+       {
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI,
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO,
+               USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
+               HAS_INTEGRATED_BUTTON,
+               0x84, sizeof(struct bt_data),
+               0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+               { SN_PRESSURE, 0, 300 },
+               { SN_WIDTH, 0, 2048 },
+               { SN_COORD, -4750, 5280 },
+               { SN_COORD, -150, 6730 },
+               { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
+       },
        {}
 };
 
index a1b4c37956b2ef3af055e5c66ccd7753225cabeb..4c842c320c2ede9f2bf42d507ee5c91f00eef7e3 100644 (file)
@@ -12,8 +12,8 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #define MOUSEDEV_MINOR_BASE    32
-#define MOUSEDEV_MINORS                32
-#define MOUSEDEV_MIX           31
+#define MOUSEDEV_MINORS                31
+#define MOUSEDEV_MIX           63
 
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -523,7 +523,6 @@ static int mousedev_release(struct inode *inode, struct file *file)
        kfree(client);
 
        mousedev_close_device(mousedev);
-       put_device(&mousedev->dev);
 
        return 0;
 }
@@ -558,7 +557,6 @@ static int mousedev_open(struct inode *inode, struct file *file)
        file->private_data = client;
        nonseekable_open(inode, file);
 
-       get_device(&mousedev->dev);
        return 0;
 
  err_free_client:
@@ -892,6 +890,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
        }
 
        cdev_init(&mousedev->cdev, &mousedev_fops);
+       mousedev->cdev.kobj.parent = &mousedev->dev.kobj;
        error = cdev_add(&mousedev->cdev, mousedev->dev.devt, 1);
        if (error)
                goto err_unregister_handle;
index 9edf9806cff9db6350e4e25677fb74177364251a..858ad446de91b338553d6577bb6d1ac886c1fbb5 100644 (file)
@@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
                                                }
 
-                                               if (features->type == MTSCREEN)
+                                               if (features->type == MTSCREEN || features->type == WACOM_24HDT)
                                                        features->pktlen = WACOM_PKGLEN_MTOUCH;
 
                                                if (features->type == BAMBOO_PT) {
@@ -402,6 +402,14 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->x_max =
                                                                get_unaligned_le16(&report[i + 8]);
                                                        i += 15;
+                                               } else if (features->type == WACOM_24HDT) {
+                                                       features->x_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->x_phy =
+                                                               get_unaligned_le16(&report[i + 8]);
+                                                       features->unit = report[i - 1];
+                                                       features->unitExpo = report[i - 3];
+                                                       i += 12;
                                                } else {
                                                        features->x_max =
                                                                get_unaligned_le16(&report[i + 3]);
@@ -434,6 +442,12 @@ static int wacom_parse_hid(struct usb_interface *intf,
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 6]);
                                                        i += 7;
+                                               } else if (type == WACOM_24HDT) {
+                                                       features->y_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->y_phy =
+                                                               get_unaligned_le16(&report[i - 2]);
+                                                       i += 7;
                                                } else if (type == BAMBOO_PT) {
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 3]);
@@ -541,6 +555,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
                        /* MT Tablet PC touch */
                        return wacom_set_device_mode(intf, 3, 4, 4);
                }
+               else if (features->type == WACOM_24HDT) {
+                       return wacom_set_device_mode(intf, 18, 3, 2);
+               }
        } else if (features->device_type == BTN_TOOL_PEN) {
                if (features->type <= BAMBOO_PT && features->type != WIRELESS) {
                        return wacom_set_device_mode(intf, 2, 2, 2);
@@ -613,6 +630,30 @@ struct wacom_usbdev_data {
 static LIST_HEAD(wacom_udev_list);
 static DEFINE_MUTEX(wacom_udev_list_lock);
 
+static struct usb_device *wacom_get_sibling(struct usb_device *dev, int vendor, int product)
+{
+       int port1;
+       struct usb_device *sibling;
+
+       if (vendor == 0 && product == 0)
+               return dev;
+
+       if (dev->parent == NULL)
+               return NULL;
+
+       usb_hub_for_each_child(dev->parent, port1, sibling) {
+               struct usb_device_descriptor *d;
+               if (sibling == NULL)
+                       continue;
+
+               d = &sibling->descriptor;
+               if (d->idVendor == vendor && d->idProduct == product)
+                       return sibling;
+       }
+
+       return NULL;
+}
+
 static struct wacom_usbdev_data *wacom_get_usbdev_data(struct usb_device *dev)
 {
        struct wacom_usbdev_data *data;
@@ -1257,13 +1298,19 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
 
        if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
+               struct usb_device *other_dev;
+
                /* Append the device type to the name */
                strlcat(wacom_wac->name,
                        features->device_type == BTN_TOOL_PEN ?
                                " Pen" : " Finger",
                        sizeof(wacom_wac->name));
 
-               error = wacom_add_shared_data(wacom_wac, dev);
+
+               other_dev = wacom_get_sibling(dev, features->oVid, features->oPid);
+               if (other_dev == NULL || wacom_get_usbdev_data(other_dev) == NULL)
+                       other_dev = dev;
+               error = wacom_add_shared_data(wacom_wac, other_dev);
                if (error)
                        goto fail3;
        }
index c3468c8dbd891865b0fd2b4a8159f499ea8df1f1..0a67031ffc131a2559d6573d5c3cf65173edd9c6 100644 (file)
@@ -806,6 +806,70 @@ static int find_slot_from_contactid(struct wacom_wac *wacom, int contactid)
        return -1;
 }
 
+static int int_dist(int x1, int y1, int x2, int y2)
+{
+       int x = x2 - x1;
+       int y = y2 - y1;
+
+       return int_sqrt(x*x + y*y);
+}
+
+static int wacom_24hdt_irq(struct wacom_wac *wacom)
+{
+       struct input_dev *input = wacom->input;
+       char *data = wacom->data;
+       int i;
+       int current_num_contacts = data[61];
+       int contacts_to_send = 0;
+
+       /*
+        * First packet resets the counter since only the first
+        * packet in series will have non-zero current_num_contacts.
+        */
+       if (current_num_contacts)
+               wacom->num_contacts_left = current_num_contacts;
+
+       /* There are at most 4 contacts per packet */
+       contacts_to_send = min(4, wacom->num_contacts_left);
+
+       for (i = 0; i < contacts_to_send; i++) {
+               int offset = (WACOM_BYTES_PER_24HDT_PACKET * i) + 1;
+               bool touch = data[offset] & 0x1 && !wacom->shared->stylus_in_proximity;
+               int id = data[offset + 1];
+               int slot = find_slot_from_contactid(wacom, id);
+
+               if (slot < 0)
+                       continue;
+               input_mt_slot(input, slot);
+               input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+
+               if (touch) {
+                       int t_x = le16_to_cpup((__le16 *)&data[offset + 2]);
+                       int c_x = le16_to_cpup((__le16 *)&data[offset + 4]);
+                       int t_y = le16_to_cpup((__le16 *)&data[offset + 6]);
+                       int c_y = le16_to_cpup((__le16 *)&data[offset + 8]);
+                       int w = le16_to_cpup((__le16 *)&data[offset + 10]);
+                       int h = le16_to_cpup((__le16 *)&data[offset + 12]);
+
+                       input_report_abs(input, ABS_MT_POSITION_X, t_x);
+                       input_report_abs(input, ABS_MT_POSITION_Y, t_y);
+                       input_report_abs(input, ABS_MT_TOUCH_MAJOR, min(w,h));
+                       input_report_abs(input, ABS_MT_WIDTH_MAJOR, min(w, h) + int_dist(t_x, t_y, c_x, c_y));
+                       input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
+                       input_report_abs(input, ABS_MT_ORIENTATION, w > h);
+               }
+               wacom->slots[slot] = touch ? id : -1;
+       }
+
+       input_mt_report_pointer_emulation(input, true);
+
+       wacom->num_contacts_left -= contacts_to_send;
+       if (wacom->num_contacts_left <= 0)
+               wacom->num_contacts_left = 0;
+
+       return 1;
+}
+
 static int wacom_mt_touch(struct wacom_wac *wacom)
 {
        struct input_dev *input = wacom->input;
@@ -1255,6 +1319,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                sync = wacom_intuos_irq(wacom_wac);
                break;
 
+       case WACOM_24HDT:
+               sync = wacom_24hdt_irq(wacom_wac);
+               break;
+
        case INTUOS5S:
        case INTUOS5:
        case INTUOS5L:
@@ -1340,7 +1408,8 @@ void wacom_setup_device_quirks(struct wacom_features *features)
 
        /* these device have multiple inputs */
        if (features->type >= WIRELESS ||
-           (features->type >= INTUOS5S && features->type <= INTUOS5L))
+           (features->type >= INTUOS5S && features->type <= INTUOS5L) ||
+           (features->oVid && features->oPid))
                features->quirks |= WACOM_QUIRK_MULTI_INPUT;
 
        /* quirk for bamboo touch with 2 low res touches */
@@ -1449,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
 
                input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
                input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0);
+
+               __set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
                wacom_setup_cintiq(wacom_wac);
                break;
 
@@ -1575,6 +1647,15 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(INPUT_PROP_POINTER, input_dev->propbit);
                break;
 
+       case WACOM_24HDT:
+               if (features->device_type == BTN_TOOL_FINGER) {
+                       input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0);
+                       input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0);
+               }
+               /* fall through */
+
        case MTSCREEN:
                if (features->device_type == BTN_TOOL_FINGER) {
                        wacom_wac->slots = kmalloc(features->touch_max *
@@ -1869,8 +1950,11 @@ static const struct wacom_features wacom_features_0xF4 =
        { "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
          63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xF8 =
-       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
-         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047, /* Pen */
+         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 };
+static const struct wacom_features wacom_features_0xF6 =
+       { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */
+         .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf8, .touch_max = 10 };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
          63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
@@ -2113,6 +2197,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
        { USB_DEVICE_WACOM(0xF8) },
+       { USB_DEVICE_WACOM(0xF6) },
        { USB_DEVICE_WACOM(0xFA) },
        { USB_DEVICE_LENOVO(0x6004) },
        { }
index 96c185cc301eb95bf062440e59c49114458c0028..345f1e76975ef76ef6b251ae772a7c2b807c21ff 100644 (file)
@@ -29,6 +29,7 @@
 
 /* wacom data size per MT contact */
 #define WACOM_BYTES_PER_MT_PACKET      11
+#define WACOM_BYTES_PER_24HDT_PACKET   14
 
 /* device IDs */
 #define STYLUS_DEVICE_ID       0x02
@@ -49,6 +50,7 @@
 #define WACOM_REPORT_TPCHID            15
 #define WACOM_REPORT_TPCST             16
 #define WACOM_REPORT_TPC1FGE           18
+#define WACOM_REPORT_24HDT             1
 
 /* device quirks */
 #define WACOM_QUIRK_MULTI_INPUT                0x0001
@@ -81,6 +83,7 @@ enum {
        WACOM_MO,
        WIRELESS,
        BAMBOO_PT,
+       WACOM_24HDT,
        TABLETPC,   /* add new TPC below */
        TABLETPCE,
        TABLETPC2FG,
@@ -109,6 +112,8 @@ struct wacom_features {
        int distance_fuzz;
        unsigned quirks;
        unsigned touch_max;
+       int oVid;
+       int oPid;
 };
 
 struct wacom_shared {
index 1ba232cbc09d4e8744e1a827c3939ad7292e85a6..f7668b24c378aeed3b4ca4fc1c09d025255eccc1 100644 (file)
@@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI
 
 config TOUCHSCREEN_EGALAX
        tristate "EETI eGalax multi-touch panel support"
-       depends on I2C
+       depends on I2C && OF
        help
          Say Y here to enable support for I2C connected EETI
          eGalax multi-touch panels.
index f02028ec3db6a6384dc194e7633ee12e8bbb7685..78e5d9ab0ba7fd991e55cff240257248f42b7ba1 100644 (file)
@@ -955,7 +955,8 @@ static int ads7846_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
-static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+static int __devinit ads7846_setup_pendown(struct spi_device *spi,
+                                          struct ads7846 *ts)
 {
        struct ads7846_platform_data *pdata = spi->dev.platform_data;
        int err;
@@ -981,6 +982,9 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
 
                ts->gpio_pendown = pdata->gpio_pendown;
 
+               if (pdata->gpio_pendown_debounce)
+                       gpio_set_debounce(pdata->gpio_pendown,
+                                         pdata->gpio_pendown_debounce);
        } else {
                dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
                return -EINVAL;
index c1e3460f1195aed3953c0e09542c9718d8664421..13fa62fdfb0b4160f76484bd2aadc92151597ab8 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/input/mt.h>
+#include <linux/of_gpio.h>
 
 /*
  * Mouse Mode: some panel may configure the controller to mouse mode,
@@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)
 /* wake up controller by an falling edge of interrupt gpio.  */
 static int egalax_wake_up_device(struct i2c_client *client)
 {
-       int gpio = irq_to_gpio(client->irq);
+       struct device_node *np = client->dev.of_node;
+       int gpio;
        int ret;
 
+       if (!np)
+               return -ENODEV;
+
+       gpio = of_get_named_gpio(np, "wakeup-gpios", 0);
+       if (!gpio_is_valid(gpio))
+               return -ENODEV;
+
        ret = gpio_request(gpio, "egalax_irq");
        if (ret < 0) {
                dev_err(&client->dev,
@@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,
        ts->input_dev = input_dev;
 
        /* controller may be in sleep, wake it up. */
-       egalax_wake_up_device(client);
+       error = egalax_wake_up_device(client);
+       if (error) {
+               dev_err(&client->dev, "Failed to wake up the controller\n");
+               goto err_free_dev;
+       }
 
        ret = egalax_firmware_version(client);
        if (ret < 0) {
@@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume);
 
+static struct of_device_id egalax_ts_dt_ids[] = {
+       { .compatible = "eeti,egalax_ts" },
+       { /* sentinel */ }
+};
+
 static struct i2c_driver egalax_ts_driver = {
        .driver = {
                .name   = "egalax_ts",
                .owner  = THIS_MODULE,
                .pm     = &egalax_ts_pm_ops,
+               .of_match_table = of_match_ptr(egalax_ts_dt_ids),
        },
        .id_table       = egalax_ts_id,
        .probe          = egalax_ts_probe,
index 63209aaa55f01f1baf65a8a1632c8c2ce4056870..eb96f168fb9d53c68032c172faec9d2652dcfa70 100644 (file)
@@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)
        __set_bit(BTN_TOUCH, input_dev->keybit);
        input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);
        input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0);
-       input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);
 
        serio_set_drvdata(serio, ptsc);
 
index 18b0d99bd4d6686b3727f83896769d0a116dcf1f..81837b0710a9ba0240b1eba3c1b3f8b51d997e2f 100644 (file)
@@ -1599,21 +1599,46 @@ static void __init free_on_init_error(void)
 #endif
 }
 
+/* SB IOAPIC is always on this device in AMD systems */
+#define IOAPIC_SB_DEVID                ((0x00 << 8) | PCI_DEVFN(0x14, 0))
+
 static bool __init check_ioapic_information(void)
 {
+       bool ret, has_sb_ioapic;
        int idx;
 
-       for (idx = 0; idx < nr_ioapics; idx++) {
-               int id = mpc_ioapic_id(idx);
+       has_sb_ioapic = false;
+       ret           = false;
 
-               if (get_ioapic_devid(id) < 0) {
-                       pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id);
-                       pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n");
-                       return false;
+       for (idx = 0; idx < nr_ioapics; idx++) {
+               int devid, id = mpc_ioapic_id(idx);
+
+               devid = get_ioapic_devid(id);
+               if (devid < 0) {
+                       pr_err(FW_BUG "AMD-Vi: IOAPIC[%d] not in IVRS table\n", id);
+                       ret = false;
+               } else if (devid == IOAPIC_SB_DEVID) {
+                       has_sb_ioapic = true;
+                       ret           = true;
                }
        }
 
-       return true;
+       if (!has_sb_ioapic) {
+               /*
+                * We expect the SB IOAPIC to be listed in the IVRS
+                * table. The system timer is connected to the SB IOAPIC
+                * and if we don't have it in the list the system will
+                * panic at boot time.  This situation usually happens
+                * when the BIOS is buggy and provides us the wrong
+                * device id for the IOAPIC in the system.
+                */
+               pr_err(FW_BUG "AMD-Vi: No southbridge IOAPIC found in IVRS table\n");
+       }
+
+       if (!ret)
+               pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug(s)\n");
+
+       return ret;
 }
 
 static void __init free_dma_resources(void)
index d4a4cd445cabb40504bd2a1c7d5300656feceaff..0badfa48b32b7e84a16449ebc8804e461529c8b9 100644 (file)
@@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
 static int intel_iommu_add_device(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct pci_dev *bridge, *dma_pdev;
+       struct pci_dev *bridge, *dma_pdev = NULL;
        struct iommu_group *group;
        int ret;
 
@@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev)
                        dma_pdev = pci_get_domain_bus_and_slot(
                                                pci_domain_nr(pdev->bus),
                                                bridge->subordinate->number, 0);
-               else
+               if (!dma_pdev)
                        dma_pdev = pci_dev_get(bridge);
        } else
                dma_pdev = pci_dev_get(pdev);
index 0b4d62e0c64573cea96dc38f237436a036aa74cf..c0f7a42662635a288fc8c98fabe3d8f1b35f1141 100644 (file)
@@ -200,7 +200,7 @@ enum {
 
 #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12)
 #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22)
-#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22)
+#define SMMU_PDN_TO_ADDR(pdn)  ((pdn) << 22)
 
 #define _READABLE      (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT)
 #define _WRITABLE      (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT)
@@ -1054,6 +1054,7 @@ static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
                        stats[i], val, offs);
        }
        seq_printf(s, "\n");
+       dput(dent);
 
        return 0;
 }
index dc670ccc6978614330a85fa4138c0df47febcfba..16c78f1c5ef25ad4121b1ee7e2b7fab30cedce95 100644 (file)
@@ -168,7 +168,8 @@ static int __init armctrl_of_init(struct device_node *node,
 }
 
 static struct of_device_id irq_of_match[] __initconst = {
-       { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }
+       { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init },
+       { }
 };
 
 void __init bcm2835_init_irq(void)
index a233ed53913a67bb67150ce9d35abf6f8aa42297..86cd75a0e84da69469ef10b5712285f4ce4e84f2 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig ISDN
        bool "ISDN support"
-       depends on NET
+       depends on NET && NETDEVICES
        depends on !S390 && !UML
        ---help---
          ISDN ("Integrated Services Digital Network", called RNIS in France)
index 5275887089483b6b8ff8ffdc1e9fad46ac1f81fb..c44950d3eb7b48f8a81fd16db9e46ecd15343a39 100644 (file)
@@ -617,7 +617,13 @@ static void int_in_work(struct work_struct *work)
        if (rc == 0)
                /* success, resubmit interrupt read URB */
                rc = usb_submit_urb(urb, GFP_ATOMIC);
-       if (rc != 0 && rc != -ENODEV) {
+
+       switch (rc) {
+       case 0:         /* success */
+       case -ENODEV:   /* device gone */
+       case -EINVAL:   /* URB already resubmitted, or terminal badness */
+               break;
+       default:        /* failure: try to recover by resetting the device */
                dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc));
                rc = usb_lock_device_for_reset(ucs->udev, ucs->interface);
                if (rc == 0) {
@@ -2442,7 +2448,9 @@ static void gigaset_disconnect(struct usb_interface *interface)
 }
 
 /* gigaset_suspend
- * This function is called before the USB connection is suspended.
+ * This function is called before the USB connection is suspended
+ * or before the USB device is reset.
+ * In the latter case, message == PMSG_ON.
  */
 static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
 {
@@ -2498,7 +2506,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message)
        del_timer_sync(&ucs->timer_atrdy);
        del_timer_sync(&ucs->timer_cmd_in);
        del_timer_sync(&ucs->timer_int_in);
-       cancel_work_sync(&ucs->int_in_wq);
+
+       /* don't try to cancel int_in_wq from within reset as it
+        * might be the one requesting the reset
+        */
+       if (message.event != PM_EVENT_ON)
+               cancel_work_sync(&ucs->int_in_wq);
 
        gig_dbg(DEBUG_SUSPEND, "suspend complete");
        return 0;
index 81363ffa5357f11213c6b87b3dc4b0d80786d6ae..6e99d73563b8abbe8b5c6931b741ab15a5536a33 100644 (file)
@@ -490,7 +490,7 @@ receive_dmsg(struct hfc_pci *hc)
                    (df->data[le16_to_cpu(zp->z1)])) {
                        if (dch->debug & DEBUG_HW)
                                printk(KERN_DEBUG
-                                      "empty_fifo hfcpci paket inv. len "
+                                      "empty_fifo hfcpci packet inv. len "
                                       "%d or crc %d\n",
                                       rcnt,
                                       df->data[le16_to_cpu(zp->z1)]);
index 182ecf0626c2098e3c38c4da0eeea54a1197ce7d..feafa91c2ed99088c0958059e0de6c04dd832128 100644 (file)
@@ -1302,7 +1302,7 @@ modeisar(struct isar_ch *ch, u32 bprotocol)
                                                   &ch->is->Flags))
                                ch->dpath = 1;
                        else {
-                               pr_info("modeisar both pathes in use\n");
+                               pr_info("modeisar both paths in use\n");
                                return -EBUSY;
                        }
                        if (bprotocol == ISDN_P_B_HDLC)
index a47637be0cc558c0b2ea4ccd6209e42445ff80e5..ddec47a911a0df6ea74c1a9f5e926fbbacc54a2a 100644 (file)
@@ -35,7 +35,7 @@ static int chancount;
 /* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */
 #define ALERT_REJECT 0
 
-/* Value to delay the sending of the first B-channel paket after CONNECT
+/* Value to delay the sending of the first B-channel packet after CONNECT
  * here is no value given by ITU, but experience shows that 300 ms will
  * work on many networks, if you or your other side is behind local exchanges
  * a greater value may be recommented. If the delay is to short the first paket
index 334fa90bed8ec73a348fcc29d85a7db8324b1ca5..f60d4be589414149f1ca7e6f9157d37012ef2d24 100644 (file)
@@ -354,7 +354,7 @@ receive_dmsg(struct IsdnCardState *cs)
                if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
                    (df->data[zp->z1])) {
                        if (cs->debug & L1_DEB_WARN)
-                               debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]);
+                               debugl1(cs, "empty_fifo hfcpci packet inv. len %d or crc %d", rcnt, df->data[zp->z1]);
 #ifdef ERROR_STATISTIC
                        cs->err_rx++;
 #endif
index 4db846be4369b1bd7b894e8a590437b81597ee82..4ec279ce052f0fc64f2d822b46a463fb562717fa 100644 (file)
@@ -270,7 +270,7 @@ read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max)
 
                if ((count > fifo_size) || (count < 4)) {
                        if (cs->debug & L1_DEB_WARN)
-                               debugl1(cs, "hfcsx_read_fifo %d paket inv. len %d ", fifo , count);
+                               debugl1(cs, "hfcsx_read_fifo %d packet inv. len %d ", fifo , count);
                        while (count) {
                                count--; /* empty fifo */
                                Read_hfc(cs, HFCSX_FIF_DRD);
index 2302fbe70ac62badd292a5e455a24042687f2b09..9c6650ea848ece07f2a369cbc0e7a17b26fc035b 100644 (file)
@@ -6,7 +6,7 @@ if ISDN_I4L
 
 config ISDN_PPP
        bool "Support synchronous PPP"
-       depends on INET && NETDEVICES
+       depends on INET
        select SLHC
        help
          Over digital connections such as ISDN, there is no need to
index 8c610fa6782b67925e4c286f651e044a37a53b62..e2a945ee9f05c558eec64ee6a18df91beee318c2 100644 (file)
@@ -1312,7 +1312,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                        } else
                                return -EINVAL;
                        break;
-#ifdef CONFIG_NETDEVICES
                case IIOCNETGPN:
                        /* Get peer phone number of a connected
                         * isdn network interface */
@@ -1322,7 +1321,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                                return isdn_net_getpeer(&phone, argp);
                        } else
                                return -EINVAL;
-#endif
                default:
                        return -EINVAL;
                }
@@ -1352,7 +1350,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                case IIOCNETLCR:
                        printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
                        return -ENODEV;
-#ifdef CONFIG_NETDEVICES
                case IIOCNETAIF:
                        /* Add a network-interface */
                        if (arg) {
@@ -1491,7 +1488,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
                                return -EFAULT;
                        return isdn_net_force_hangup(name);
                        break;
-#endif                          /* CONFIG_NETDEVICES */
                case IIOCSETVER:
                        dev->net_verbose = arg;
                        printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
index db50f788855db4f41de7f35e3aee4abe4da87253..f8e405c383a0774948c464f415ac94f77d7a5679 100644 (file)
@@ -277,7 +277,6 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
                  u16 timebase, u8 *buf, int len)
 {
        u8 *p;
-       int multi = 0;
        u8 frame[len + 32];
        struct socket *socket = NULL;
 
@@ -317,9 +316,7 @@ l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask,
                *p++ = hc->id >> 8;
                *p++ = hc->id;
        }
-       *p++ = (multi == 1) ? 0x80 : 0x00 + channel; /* m-flag, channel */
-       if (multi == 1)
-               *p++ = len; /* length */
+       *p++ =  0x00 + channel; /* m-flag, channel */
        *p++ = timebase >> 8; /* time base */
        *p++ = timebase;
 
index be88728f110643dbaef2794b8ad64143a7224b08..592f597d895181d0ce1e5dd697a7d37ab09f2ef3 100644 (file)
@@ -250,7 +250,7 @@ tei_debug(struct FsmInst *fi, char *fmt, ...)
 static int
 get_free_id(struct manager *mgr)
 {
-       u64             ids = 0;
+       DECLARE_BITMAP(ids, 64) = { [0 ... BITS_TO_LONGS(64) - 1] = 0 };
        int             i;
        struct layer2   *l2;
 
@@ -261,11 +261,11 @@ get_free_id(struct manager *mgr)
                               __func__);
                        return -EBUSY;
                }
-               test_and_set_bit(l2->ch.nr, (u_long *)&ids);
+               __set_bit(l2->ch.nr, ids);
        }
-       for (i = 1; i < 64; i++)
-               if (!test_bit(i, (u_long *)&ids))
-                       return i;
+       i = find_next_zero_bit(ids, 64, 1);
+       if (i < 64)
+               return i;
        printk(KERN_WARNING "%s: more as 63 layer2 for one device\n",
               __func__);
        return -EBUSY;
@@ -274,7 +274,7 @@ get_free_id(struct manager *mgr)
 static int
 get_free_tei(struct manager *mgr)
 {
-       u64             ids = 0;
+       DECLARE_BITMAP(ids, 64) = { [0 ... BITS_TO_LONGS(64) - 1] = 0 };
        int             i;
        struct layer2   *l2;
 
@@ -288,11 +288,11 @@ get_free_tei(struct manager *mgr)
                        continue;
                i -= 64;
 
-               test_and_set_bit(i, (u_long *)&ids);
+               __set_bit(i, ids);
        }
-       for (i = 0; i < 64; i++)
-               if (!test_bit(i, (u_long *)&ids))
-                       return i + 64;
+       i = find_first_zero_bit(ids, 64);
+       if (i < 64)
+               return i + 64;
        printk(KERN_WARNING "%s: more as 63 dynamic tei for one device\n",
               __func__);
        return -1;
index a18e639b40d7e4c354812092c494e46f98618235..42ecfef80132b098735ab2a4d96bc9ec2094eece 100644 (file)
@@ -508,7 +508,7 @@ pcbit_irq_handler(int interrupt, void *devptr)
                return IRQ_NONE;
        }
        if (dev->interrupt) {
-               printk(KERN_DEBUG "pcbit: reentering interrupt hander\n");
+               printk(KERN_DEBUG "pcbit: reentering interrupt handler\n");
                return IRQ_HANDLED;
        }
        dev->interrupt = 1;
index b312056da14d3c5f9ef602a455d8bbc80fc8c125..4239b3955ff08f27edacbc4311bb09f93231bd69 100644 (file)
@@ -33,8 +33,6 @@
 struct led_trigger_cpu {
        char name[MAX_NAME_LEN];
        struct led_trigger *_trig;
-       struct mutex lock;
-       int lock_is_inited;
 };
 
 static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
@@ -50,12 +48,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
 {
        struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig);
 
-       /* mutex lock should be initialized before calling mutex_call() */
-       if (!trig->lock_is_inited)
-               return;
-
-       mutex_lock(&trig->lock);
-
        /* Locate the correct CPU LED */
        switch (ledevt) {
        case CPU_LED_IDLE_END:
@@ -75,8 +67,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
                /* Will leave the LED as it is */
                break;
        }
-
-       mutex_unlock(&trig->lock);
 }
 EXPORT_SYMBOL(ledtrig_cpu);
 
@@ -117,14 +107,9 @@ static int __init ledtrig_cpu_init(void)
        for_each_possible_cpu(cpu) {
                struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-               mutex_init(&trig->lock);
-
                snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
 
-               mutex_lock(&trig->lock);
                led_trigger_register_simple(trig->name, &trig->_trig);
-               trig->lock_is_inited = 1;
-               mutex_unlock(&trig->lock);
        }
 
        register_syscore_ops(&ledtrig_cpu_syscore_ops);
@@ -142,15 +127,9 @@ static void __exit ledtrig_cpu_exit(void)
        for_each_possible_cpu(cpu) {
                struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-               mutex_lock(&trig->lock);
-
                led_trigger_unregister_simple(trig->_trig);
                trig->_trig = NULL;
                memset(trig->name, 0, MAX_NAME_LEN);
-               trig->lock_is_inited = 0;
-
-               mutex_unlock(&trig->lock);
-               mutex_destroy(&trig->lock);
        }
 
        unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
index 02db9183ca01e8b64ce54a649dacc943c883f38f..77e6eff41cae9bb7c693aac363c509f65c44251d 100644 (file)
@@ -740,8 +740,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue)
        if (!md_in_flight(md))
                wake_up(&md->wait);
 
+       /*
+        * Run this off this callpath, as drivers could invoke end_io while
+        * inside their request_fn (and holding the queue lock). Calling
+        * back into ->request_fn() could deadlock attempting to grab the
+        * queue lock again.
+        */
        if (run_queue)
-               blk_run_queue(md->queue);
+               blk_run_queue_async(md->queue);
 
        /*
         * dm_put() must be at the end of this function. See the comment above
index 45135f69509c89e83b6cc7190f1f25972ae28076..5e7dc772f5deca223ea9142d073cc66785f54b27 100644 (file)
@@ -315,8 +315,11 @@ static int run(struct mddev *mddev)
        }
        conf->nfaults = 0;
 
-       rdev_for_each(rdev, mddev)
+       rdev_for_each(rdev, mddev) {
                conf->rdev = rdev;
+               disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                 rdev->data_offset << 9);
+       }
 
        md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));
        mddev->private = conf;
index 9ab768acfb623f8bbb13870e5f65150a60ecad07..61200717687b85b3fed040f9599ffd1987b8842d 100644 (file)
@@ -1817,10 +1817,10 @@ retry:
                        memset(bbp, 0xff, PAGE_SIZE);
 
                        for (i = 0 ; i < bb->count ; i++) {
-                               u64 internal_bb = *p++;
+                               u64 internal_bb = p[i];
                                u64 store_bb = ((BB_OFFSET(internal_bb) << 10)
                                                | BB_LEN(internal_bb));
-                               *bbp++ = cpu_to_le64(store_bb);
+                               bbp[i] = cpu_to_le64(store_bb);
                        }
                        bb->changed = 0;
                        if (read_seqretry(&bb->lock, seq))
@@ -5294,7 +5294,7 @@ void md_stop_writes(struct mddev *mddev)
 }
 EXPORT_SYMBOL_GPL(md_stop_writes);
 
-void md_stop(struct mddev *mddev)
+static void __md_stop(struct mddev *mddev)
 {
        mddev->ready = 0;
        mddev->pers->stop(mddev);
@@ -5304,6 +5304,18 @@ void md_stop(struct mddev *mddev)
        mddev->pers = NULL;
        clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 }
+
+void md_stop(struct mddev *mddev)
+{
+       /* stop the array and free an attached data structures.
+        * This is called from dm-raid
+        */
+       __md_stop(mddev);
+       bitmap_destroy(mddev);
+       if (mddev->bio_set)
+               bioset_free(mddev->bio_set);
+}
+
 EXPORT_SYMBOL_GPL(md_stop);
 
 static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
@@ -5364,7 +5376,7 @@ static int do_md_stop(struct mddev * mddev, int mode,
                        set_disk_ro(disk, 0);
 
                __md_stop_writes(mddev);
-               md_stop(mddev);
+               __md_stop(mddev);
                mddev->queue->merge_bvec_fn = NULL;
                mddev->queue->backing_dev_info.congested_fn = NULL;
 
@@ -7936,9 +7948,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
                   sector_t *first_bad, int *bad_sectors)
 {
        int hi;
-       int lo = 0;
+       int lo;
        u64 *p = bb->page;
-       int rv = 0;
+       int rv;
        sector_t target = s + sectors;
        unsigned seq;
 
@@ -7953,7 +7965,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
 
 retry:
        seq = read_seqbegin(&bb->lock);
-
+       lo = 0;
+       rv = 0;
        hi = bb->count;
 
        /* Binary search between lo and hi for 'target'
index 8034fbd6190ce647ec2feb6a281e4bb32b406f8e..636bae0405e8167edcec328e5759b3f949dd0876 100644 (file)
@@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)
                    || disk_idx < 0)
                        continue;
                if (test_bit(Replacement, &rdev->flags))
-                       disk = conf->mirrors + conf->raid_disks + disk_idx;
+                       disk = conf->mirrors + mddev->raid_disks + disk_idx;
                else
                        disk = conf->mirrors + disk_idx;
 
index 906ccbd0f7dcdc6710869c5b990f9375d020d370..0d5d0ff2c0f7beb47a02bd4692273b31369b2bc5 100644 (file)
@@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error)
         */
        one_write_done(r10_bio);
        if (dec_rdev)
-               rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+               rdev_dec_pending(rdev, conf->mddev);
 }
 
 /*
@@ -1334,18 +1334,21 @@ retry_write:
                        blocked_rdev = rrdev;
                        break;
                }
+               if (rdev && (test_bit(Faulty, &rdev->flags)
+                            || test_bit(Unmerged, &rdev->flags)))
+                       rdev = NULL;
                if (rrdev && (test_bit(Faulty, &rrdev->flags)
                              || test_bit(Unmerged, &rrdev->flags)))
                        rrdev = NULL;
 
                r10_bio->devs[i].bio = NULL;
                r10_bio->devs[i].repl_bio = NULL;
-               if (!rdev || test_bit(Faulty, &rdev->flags) ||
-                   test_bit(Unmerged, &rdev->flags)) {
+
+               if (!rdev && !rrdev) {
                        set_bit(R10BIO_Degraded, &r10_bio->state);
                        continue;
                }
-               if (test_bit(WriteErrorSeen, &rdev->flags)) {
+               if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) {
                        sector_t first_bad;
                        sector_t dev_sector = r10_bio->devs[i].addr;
                        int bad_sectors;
@@ -1387,8 +1390,10 @@ retry_write:
                                        max_sectors = good_sectors;
                        }
                }
-               r10_bio->devs[i].bio = bio;
-               atomic_inc(&rdev->nr_pending);
+               if (rdev) {
+                       r10_bio->devs[i].bio = bio;
+                       atomic_inc(&rdev->nr_pending);
+               }
                if (rrdev) {
                        r10_bio->devs[i].repl_bio = bio;
                        atomic_inc(&rrdev->nr_pending);
@@ -1444,69 +1449,71 @@ retry_write:
        for (i = 0; i < conf->copies; i++) {
                struct bio *mbio;
                int d = r10_bio->devs[i].devnum;
-               if (!r10_bio->devs[i].bio)
-                       continue;
+               if (r10_bio->devs[i].bio) {
+                       struct md_rdev *rdev = conf->mirrors[d].rdev;
+                       mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+                       md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+                                   max_sectors);
+                       r10_bio->devs[i].bio = mbio;
+
+                       mbio->bi_sector = (r10_bio->devs[i].addr+
+                                          choose_data_offset(r10_bio,
+                                                             rdev));
+                       mbio->bi_bdev = rdev->bdev;
+                       mbio->bi_end_io = raid10_end_write_request;
+                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_private = r10_bio;
 
-               mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
-                           max_sectors);
-               r10_bio->devs[i].bio = mbio;
+                       atomic_inc(&r10_bio->remaining);
 
-               mbio->bi_sector = (r10_bio->devs[i].addr+
-                                  choose_data_offset(r10_bio,
-                                                     conf->mirrors[d].rdev));
-               mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
-               mbio->bi_end_io = raid10_end_write_request;
-               mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
-               mbio->bi_private = r10_bio;
+                       cb = blk_check_plugged(raid10_unplug, mddev,
+                                              sizeof(*plug));
+                       if (cb)
+                               plug = container_of(cb, struct raid10_plug_cb,
+                                                   cb);
+                       else
+                               plug = NULL;
+                       spin_lock_irqsave(&conf->device_lock, flags);
+                       if (plug) {
+                               bio_list_add(&plug->pending, mbio);
+                               plug->pending_cnt++;
+                       } else {
+                               bio_list_add(&conf->pending_bio_list, mbio);
+                               conf->pending_count++;
+                       }
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       if (!plug)
+                               md_wakeup_thread(mddev->thread);
+               }
 
-               atomic_inc(&r10_bio->remaining);
+               if (r10_bio->devs[i].repl_bio) {
+                       struct md_rdev *rdev = conf->mirrors[d].replacement;
+                       if (rdev == NULL) {
+                               /* Replacement just got moved to main 'rdev' */
+                               smp_mb();
+                               rdev = conf->mirrors[d].rdev;
+                       }
+                       mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+                       md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+                                   max_sectors);
+                       r10_bio->devs[i].repl_bio = mbio;
+
+                       mbio->bi_sector = (r10_bio->devs[i].addr +
+                                          choose_data_offset(
+                                                  r10_bio, rdev));
+                       mbio->bi_bdev = rdev->bdev;
+                       mbio->bi_end_io = raid10_end_write_request;
+                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_private = r10_bio;
 
-               cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug));
-               if (cb)
-                       plug = container_of(cb, struct raid10_plug_cb, cb);
-               else
-                       plug = NULL;
-               spin_lock_irqsave(&conf->device_lock, flags);
-               if (plug) {
-                       bio_list_add(&plug->pending, mbio);
-                       plug->pending_cnt++;
-               } else {
+                       atomic_inc(&r10_bio->remaining);
+                       spin_lock_irqsave(&conf->device_lock, flags);
                        bio_list_add(&conf->pending_bio_list, mbio);
                        conf->pending_count++;
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       if (!mddev_check_plugged(mddev))
+                               md_wakeup_thread(mddev->thread);
                }
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!plug)
-                       md_wakeup_thread(mddev->thread);
-
-               if (!r10_bio->devs[i].repl_bio)
-                       continue;
-
-               mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
-                           max_sectors);
-               r10_bio->devs[i].repl_bio = mbio;
-
-               /* We are actively writing to the original device
-                * so it cannot disappear, so the replacement cannot
-                * become NULL here
-                */
-               mbio->bi_sector = (r10_bio->devs[i].addr +
-                                  choose_data_offset(
-                                          r10_bio,
-                                          conf->mirrors[d].replacement));
-               mbio->bi_bdev = conf->mirrors[d].replacement->bdev;
-               mbio->bi_end_io = raid10_end_write_request;
-               mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
-               mbio->bi_private = r10_bio;
-
-               atomic_inc(&r10_bio->remaining);
-               spin_lock_irqsave(&conf->device_lock, flags);
-               bio_list_add(&conf->pending_bio_list, mbio);
-               conf->pending_count++;
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!mddev_check_plugged(mddev))
-                       md_wakeup_thread(mddev->thread);
        }
 
        /* Don't remove the bias on 'remaining' (one_write_done) until
@@ -1783,7 +1790,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
                clear_bit(Unmerged, &rdev->flags);
        }
        md_integrity_add_rdev(rdev, mddev);
-       if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
+       if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
                queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
 
        print_conf(conf);
@@ -3613,11 +3620,14 @@ static int run(struct mddev *mddev)
                        discard_supported = true;
        }
 
-       if (discard_supported)
-               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-       else
-               queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
-
+       if (mddev->queue) {
+               if (discard_supported)
+                       queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
+                                               mddev->queue);
+               else
+                       queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD,
+                                                 mddev->queue);
+       }
        /* need to check that every block has at least one working mirror */
        if (!enough(conf, -1)) {
                printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
index c5439dce0295078ecf82094af5474a649284ce61..a4502686e7a8763fb5aeded988f026b2a9dd1c99 100644 (file)
@@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                        dev = &sh->dev[i];
                        if (!test_bit(R5_LOCKED, &dev->flags) &&
                            (test_bit(R5_UPTODATE, &dev->flags) ||
-                            test_and_clear_bit(R5_Discard, &dev->flags))) {
+                            test_bit(R5_Discard, &dev->flags))) {
                                /* We can return any write requests */
                                struct bio *wbi, *wbi2;
                                pr_debug("Return write for disc %d\n", i);
+                               if (test_and_clear_bit(R5_Discard, &dev->flags))
+                                       clear_bit(R5_UPTODATE, &dev->flags);
                                wbi = dev->written;
                                dev->written = NULL;
                                while (wbi && wbi->bi_sector <
@@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                                         !test_bit(STRIPE_DEGRADED, &sh->state),
                                                0);
                        }
-               }
+               } else if (test_bit(R5_Discard, &sh->dev[i].flags))
+                       clear_bit(R5_Discard, &sh->dev[i].flags);
 
        if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
                if (atomic_dec_and_test(&conf->pending_full_writes))
@@ -3490,40 +3493,6 @@ static void handle_stripe(struct stripe_head *sh)
                        handle_failed_sync(conf, sh, &s);
        }
 
-       /*
-        * might be able to return some write requests if the parity blocks
-        * are safe, or on a failed drive
-        */
-       pdev = &sh->dev[sh->pd_idx];
-       s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
-               || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
-       qdev = &sh->dev[sh->qd_idx];
-       s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
-               || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
-               || conf->level < 6;
-
-       if (s.written &&
-           (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
-                            && !test_bit(R5_LOCKED, &pdev->flags)
-                            && (test_bit(R5_UPTODATE, &pdev->flags) ||
-                                test_bit(R5_Discard, &pdev->flags))))) &&
-           (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
-                            && !test_bit(R5_LOCKED, &qdev->flags)
-                            && (test_bit(R5_UPTODATE, &qdev->flags) ||
-                                test_bit(R5_Discard, &qdev->flags))))))
-               handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
-
-       /* Now we might consider reading some blocks, either to check/generate
-        * parity, or to satisfy requests
-        * or to load a block that is being partially written.
-        */
-       if (s.to_read || s.non_overwrite
-           || (conf->level == 6 && s.to_write && s.failed)
-           || (s.syncing && (s.uptodate + s.compute < disks))
-           || s.replacing
-           || s.expanding)
-               handle_stripe_fill(sh, &s, disks);
-
        /* Now we check to see if any write operations have recently
         * completed
         */
@@ -3561,6 +3530,40 @@ static void handle_stripe(struct stripe_head *sh)
                        s.dec_preread_active = 1;
        }
 
+       /*
+        * might be able to return some write requests if the parity blocks
+        * are safe, or on a failed drive
+        */
+       pdev = &sh->dev[sh->pd_idx];
+       s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
+               || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
+       qdev = &sh->dev[sh->qd_idx];
+       s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
+               || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
+               || conf->level < 6;
+
+       if (s.written &&
+           (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
+                            && !test_bit(R5_LOCKED, &pdev->flags)
+                            && (test_bit(R5_UPTODATE, &pdev->flags) ||
+                                test_bit(R5_Discard, &pdev->flags))))) &&
+           (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
+                            && !test_bit(R5_LOCKED, &qdev->flags)
+                            && (test_bit(R5_UPTODATE, &qdev->flags) ||
+                                test_bit(R5_Discard, &qdev->flags))))))
+               handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
+
+       /* Now we might consider reading some blocks, either to check/generate
+        * parity, or to satisfy requests
+        * or to load a block that is being partially written.
+        */
+       if (s.to_read || s.non_overwrite
+           || (conf->level == 6 && s.to_write && s.failed)
+           || (s.syncing && (s.uptodate + s.compute < disks))
+           || s.replacing
+           || s.expanding)
+               handle_stripe_fill(sh, &s, disks);
+
        /* Now to consider new write requests and what else, if anything
         * should be read.  We do not handle new writes when:
         * 1/ A 'write' operation (copy+xor) is already in flight.
@@ -5529,6 +5532,10 @@ static int run(struct mddev *mddev)
                 * discard data disk but write parity disk
                 */
                stripe = stripe * PAGE_SIZE;
+               /* Round up to power of 2, as discard handling
+                * currently assumes that */
+               while ((stripe-1) & stripe)
+                       stripe = (stripe | (stripe-1)) + 1;
                mddev->queue->limits.discard_alignment = stripe;
                mddev->queue->limits.discard_granularity = stripe;
                /*
index dd13e3a4c272965bf23cde32b3409bd28dda6f62..4ef0d80b57f412cb32b5da897a71e5cbff4e1d0b 100644 (file)
@@ -163,19 +163,21 @@ source "drivers/media/common/Kconfig"
 #
 
 config MEDIA_SUBDRV_AUTOSELECT
-       bool "Autoselect analog and hybrid tuner modules to build"
-       depends on MEDIA_TUNER
+       bool "Autoselect tuners and i2c modules to build"
+       depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT
        default y
        help
-         By default, a TV driver auto-selects all possible tuners
-         thar could be used by the driver.
+         By default, a media driver auto-selects all possible i2c
+         devices that are used by any of the supported devices.
 
          This is generally the right thing to do, except when there
-         are strict constraints with regards to the kernel size.
+         are strict constraints with regards to the kernel size,
+         like on embedded systems.
 
-         Use this option with care, as deselecting tuner drivers which
-         are in fact necessary will result in TV devices which cannot
-         be tuned due to lack of the tuning driver.
+         Use this option with care, as deselecting ancillary drivers which
+         are, in fact, necessary will result in the lack of the needed
+         functionality for your device (it may not tune or may not have
+         the need demodulers).
 
          If unsure say Y.
 
index 262dfa503c2a3e2db6cca50a5028d57ca46736df..b551ca350e00005bdcf93637a5e8b153f66e844a 100644 (file)
@@ -300,15 +300,15 @@ static enum fe_stv0900_error stv0900_set_mclk(struct stv0900_internal *intp, u32
 {
        u32 m_div, clk_sel;
 
-       dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
-                       intp->quartz);
-
        if (intp == NULL)
                return STV0900_INVALID_HANDLE;
 
        if (intp->errs)
                return STV0900_I2C_ERROR;
 
+       dprintk("%s: Mclk set to %d, Quartz = %d\n", __func__, mclk,
+                       intp->quartz);
+
        clk_sel = ((stv0900_get_bits(intp, F0900_SELX1RATIO) == 1) ? 4 : 6);
        m_div = ((clk_sel * mclk) / intp->quartz) - 1;
        stv0900_write_bits(intp, F0900_M_DIV, m_div);
index 109bc9b12e740eec80dda9e0eb9dea30a530fb5e..05f8950f6f91b54cbad5f195fcfecd3cc6a784c1 100644 (file)
@@ -53,8 +53,7 @@ MODULE_LICENSE("GPL");
 /* ADV7604 system clock frequency */
 #define ADV7604_fsc (28636360)
 
-#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \
-                       (state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR))
+#define DIGITAL_INPUT (state->mode == ADV7604_MODE_HDMI)
 
 /*
  **********************************************************************
@@ -68,7 +67,7 @@ struct adv7604_state {
        struct v4l2_subdev sd;
        struct media_pad pad;
        struct v4l2_ctrl_handler hdl;
-       enum adv7604_prim_mode prim_mode;
+       enum adv7604_mode mode;
        struct v4l2_dv_timings timings;
        u8 edid[256];
        unsigned edid_blocks;
@@ -77,6 +76,7 @@ struct adv7604_state {
        struct workqueue_struct *work_queues;
        struct delayed_work delayed_work_enable_hotplug;
        bool connector_hdmi;
+       bool restart_stdi_once;
 
        /* i2c clients */
        struct i2c_client *i2c_avlink;
@@ -106,7 +106,6 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
        V4L2_DV_BT_CEA_720X576P50,
        V4L2_DV_BT_CEA_1280X720P24,
        V4L2_DV_BT_CEA_1280X720P25,
-       V4L2_DV_BT_CEA_1280X720P30,
        V4L2_DV_BT_CEA_1280X720P50,
        V4L2_DV_BT_CEA_1280X720P60,
        V4L2_DV_BT_CEA_1920X1080P24,
@@ -115,6 +114,7 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
        V4L2_DV_BT_CEA_1920X1080P50,
        V4L2_DV_BT_CEA_1920X1080P60,
 
+       /* sorted by DMT ID */
        V4L2_DV_BT_DMT_640X350P85,
        V4L2_DV_BT_DMT_640X400P85,
        V4L2_DV_BT_DMT_720X400P85,
@@ -164,6 +164,89 @@ static const struct v4l2_dv_timings adv7604_timings[] = {
        { },
 };
 
+struct adv7604_video_standards {
+       struct v4l2_dv_timings timings;
+       u8 vid_std;
+       u8 v_freq;
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_comp[] = {
+       /* { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 }, TODO flickering */
+       { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
+       { V4L2_DV_BT_CEA_1280X720P50, 0x19, 0x01 },
+       { V4L2_DV_BT_CEA_1280X720P60, 0x19, 0x00 },
+       { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
+       { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
+       { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
+       { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
+       { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
+       /* TODO add 1920x1080P60_RB (CVT timing) */
+       { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_gr[] = {
+       { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
+       { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
+       { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
+       { V4L2_DV_BT_DMT_1360X768P60, 0x12, 0x00 },
+       { V4L2_DV_BT_DMT_1366X768P60, 0x13, 0x00 },
+       { V4L2_DV_BT_DMT_1400X1050P60, 0x14, 0x00 },
+       { V4L2_DV_BT_DMT_1400X1050P75, 0x15, 0x00 },
+       { V4L2_DV_BT_DMT_1600X1200P60, 0x16, 0x00 }, /* TODO not tested */
+       /* TODO add 1600X1200P60_RB (not a DMT timing) */
+       { V4L2_DV_BT_DMT_1680X1050P60, 0x18, 0x00 },
+       { V4L2_DV_BT_DMT_1920X1200P60_RB, 0x19, 0x00 }, /* TODO not tested */
+       { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_hdmi_comp[] = {
+       { V4L2_DV_BT_CEA_720X480P59_94, 0x0a, 0x00 },
+       { V4L2_DV_BT_CEA_720X576P50, 0x0b, 0x00 },
+       { V4L2_DV_BT_CEA_1280X720P50, 0x13, 0x01 },
+       { V4L2_DV_BT_CEA_1280X720P60, 0x13, 0x00 },
+       { V4L2_DV_BT_CEA_1920X1080P24, 0x1e, 0x04 },
+       { V4L2_DV_BT_CEA_1920X1080P25, 0x1e, 0x03 },
+       { V4L2_DV_BT_CEA_1920X1080P30, 0x1e, 0x02 },
+       { V4L2_DV_BT_CEA_1920X1080P50, 0x1e, 0x01 },
+       { V4L2_DV_BT_CEA_1920X1080P60, 0x1e, 0x00 },
+       { },
+};
+
+/* sorted by number of lines */
+static const struct adv7604_video_standards adv7604_prim_mode_hdmi_gr[] = {
+       { V4L2_DV_BT_DMT_640X480P60, 0x08, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P72, 0x09, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P75, 0x0a, 0x00 },
+       { V4L2_DV_BT_DMT_640X480P85, 0x0b, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P56, 0x00, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P60, 0x01, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P72, 0x02, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P75, 0x03, 0x00 },
+       { V4L2_DV_BT_DMT_800X600P85, 0x04, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P60, 0x0c, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P70, 0x0d, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P75, 0x0e, 0x00 },
+       { V4L2_DV_BT_DMT_1024X768P85, 0x0f, 0x00 },
+       { V4L2_DV_BT_DMT_1280X1024P60, 0x05, 0x00 },
+       { V4L2_DV_BT_DMT_1280X1024P75, 0x06, 0x00 },
+       { },
+};
+
 /* ----------------------------------------------------------------------- */
 
 static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
@@ -672,64 +755,144 @@ static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
                                ((io_read(sd, 0x6f) & 0x10) >> 4));
 }
 
-static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings)
+static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd,
+               u8 prim_mode,
+               const struct adv7604_video_standards *predef_vid_timings,
+               const struct v4l2_dv_timings *timings)
+{
+       struct adv7604_state *state = to_state(sd);
+       int i;
+
+       for (i = 0; predef_vid_timings[i].timings.bt.width; i++) {
+               if (!v4l_match_dv_timings(timings, &predef_vid_timings[i].timings,
+                                       DIGITAL_INPUT ? 250000 : 1000000))
+                       continue;
+               io_write(sd, 0x00, predef_vid_timings[i].vid_std); /* video std */
+               io_write(sd, 0x01, (predef_vid_timings[i].v_freq << 4) +
+                               prim_mode); /* v_freq and prim mode */
+               return 0;
+       }
+
+       return -1;
+}
+
+static int configure_predefined_video_timings(struct v4l2_subdev *sd,
+               struct v4l2_dv_timings *timings)
 {
+       struct adv7604_state *state = to_state(sd);
+       int err;
+
+       v4l2_dbg(1, debug, sd, "%s", __func__);
+
+       /* reset to default values */
+       io_write(sd, 0x16, 0x43);
+       io_write(sd, 0x17, 0x5a);
+       /* disable embedded syncs for auto graphics mode */
+       cp_write_and_or(sd, 0x81, 0xef, 0x00);
+       cp_write(sd, 0x8f, 0x00);
+       cp_write(sd, 0x90, 0x00);
+       cp_write(sd, 0xa2, 0x00);
+       cp_write(sd, 0xa3, 0x00);
+       cp_write(sd, 0xa4, 0x00);
+       cp_write(sd, 0xa5, 0x00);
+       cp_write(sd, 0xa6, 0x00);
+       cp_write(sd, 0xa7, 0x00);
+       cp_write(sd, 0xab, 0x00);
+       cp_write(sd, 0xac, 0x00);
+
+       switch (state->mode) {
+       case ADV7604_MODE_COMP:
+       case ADV7604_MODE_GR:
+               err = find_and_set_predefined_video_timings(sd,
+                               0x01, adv7604_prim_mode_comp, timings);
+               if (err)
+                       err = find_and_set_predefined_video_timings(sd,
+                                       0x02, adv7604_prim_mode_gr, timings);
+               break;
+       case ADV7604_MODE_HDMI:
+               err = find_and_set_predefined_video_timings(sd,
+                               0x05, adv7604_prim_mode_hdmi_comp, timings);
+               if (err)
+                       err = find_and_set_predefined_video_timings(sd,
+                                       0x06, adv7604_prim_mode_hdmi_gr, timings);
+               break;
+       default:
+               v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+                               __func__, state->mode);
+               err = -1;
+               break;
+       }
+
+
+       return err;
+}
+
+static void configure_custom_video_timings(struct v4l2_subdev *sd,
+               const struct v4l2_bt_timings *bt)
+{
+       struct adv7604_state *state = to_state(sd);
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       u32 width = htotal(timings);
-       u32 height = vtotal(timings);
-       u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ?
-               ((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0;
+       u32 width = htotal(bt);
+       u32 height = vtotal(bt);
+       u16 cp_start_sav = bt->hsync + bt->hbackporch - 4;
+       u16 cp_start_eav = width - bt->hfrontporch;
+       u16 cp_start_vbi = height - bt->vfrontporch;
+       u16 cp_end_vbi = bt->vsync + bt->vbackporch;
+       u16 ch1_fr_ll = (((u32)bt->pixelclock / 100) > 0) ?
+               ((width * (ADV7604_fsc / 100)) / ((u32)bt->pixelclock / 100)) : 0;
+       const u8 pll[2] = {
+               0xc0 | ((width >> 8) & 0x1f),
+               width & 0xff
+       };
 
        v4l2_dbg(2, debug, sd, "%s\n", __func__);
 
-       cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);     /* CH1_FR_LL */
-       cp_write(sd, 0x90, ch1_fr_ll & 0xff);           /* CH1_FR_LL */
-       cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */
-       cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */
-       /* TODO support interlaced */
-       cp_write(sd, 0x91, 0x10);       /* INTERLACED */
-
-       /* Should only be set in auto-graphics mode [REF_02 p. 91-92] */
-       if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) {
-               u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi;
-               const u8 pll[2] = {
-                       (0xc0 | ((width >> 8) & 0x1f)),
-                       (width & 0xff)
-               };
+       switch (state->mode) {
+       case ADV7604_MODE_COMP:
+       case ADV7604_MODE_GR:
+               /* auto graphics */
+               io_write(sd, 0x00, 0x07); /* video std */
+               io_write(sd, 0x01, 0x02); /* prim mode */
+               /* enable embedded syncs for auto graphics mode */
+               cp_write_and_or(sd, 0x81, 0xef, 0x10);
 
+               /* Should only be set in auto-graphics mode [REF_02, p. 91-92] */
                /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
                /* IO-map reg. 0x16 and 0x17 should be written in sequence */
                if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
                        v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
-                       return;
+                       break;
                }
 
                /* active video - horizontal timing */
-               cp_start_sav = timings->hsync + timings->hbackporch - 4;
-               cp_start_eav = width - timings->hfrontporch;
                cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
-               cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f));
+               cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) |
+                                       ((cp_start_eav >> 8) & 0x0f));
                cp_write(sd, 0xa4, cp_start_eav & 0xff);
 
                /* active video - vertical timing */
-               cp_start_vbi = height - timings->vfrontporch;
-               cp_end_vbi = timings->vsync + timings->vbackporch;
                cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
-               cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf));
+               cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) |
+                                       ((cp_end_vbi >> 8) & 0xf));
                cp_write(sd, 0xa7, cp_end_vbi & 0xff);
-       } else {
-               /* reset to default values */
-               io_write(sd, 0x16, 0x43);
-               io_write(sd, 0x17, 0x5a);
-               cp_write(sd, 0xa2, 0x00);
-               cp_write(sd, 0xa3, 0x00);
-               cp_write(sd, 0xa4, 0x00);
-               cp_write(sd, 0xa5, 0x00);
-               cp_write(sd, 0xa6, 0x00);
-               cp_write(sd, 0xa7, 0x00);
+               break;
+       case ADV7604_MODE_HDMI:
+               /* set default prim_mode/vid_std for HDMI
+                  accoring to [REF_03, c. 4.2] */
+               io_write(sd, 0x00, 0x02); /* video std */
+               io_write(sd, 0x01, 0x06); /* prim mode */
+               break;
+       default:
+               v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+                               __func__, state->mode);
+               break;
        }
-}
 
+       cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);
+       cp_write(sd, 0x90, ch1_fr_ll & 0xff);
+       cp_write(sd, 0xab, (height >> 4) & 0xff);
+       cp_write(sd, 0xac, (height & 0x0f) << 4);
+}
 
 static void set_rgb_quantization_range(struct v4l2_subdev *sd)
 {
@@ -738,12 +901,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
        switch (state->rgb_quantization_range) {
        case V4L2_DV_RGB_RANGE_AUTO:
                /* automatic */
-               if ((hdmi_read(sd, 0x05) & 0x80) ||
-                               (state->prim_mode == ADV7604_PRIM_MODE_COMP) ||
-                               (state->prim_mode == ADV7604_PRIM_MODE_RGB)) {
-                       /* receiving HDMI or analog signal */
-                       io_write_and_or(sd, 0x02, 0x0f, 0xf0);
-               } else {
+               if (DIGITAL_INPUT && !(hdmi_read(sd, 0x05) & 0x80)) {
                        /* receiving DVI-D signal */
 
                        /* ADV7604 selects RGB limited range regardless of
@@ -756,6 +914,9 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd)
                                /* RGB full range (0-255) */
                                io_write_and_or(sd, 0x02, 0x0f, 0x10);
                        }
+               } else {
+                       /* receiving HDMI or analog signal, set automode */
+                       io_write_and_or(sd, 0x02, 0x0f, 0xf0);
                }
                break;
        case V4L2_DV_RGB_RANGE_LIMITED:
@@ -967,8 +1128,10 @@ static int stdi2dv_timings(struct v4l2_subdev *sd,
                        state->aspect_ratio, timings))
                return 0;
 
-       v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n",
-                       __func__, stdi->lcf, stdi->bl);
+       v4l2_dbg(2, debug, sd,
+               "%s: No format candidate found for lcvs = %d, lcf=%d, bl = %d, %chsync, %cvsync\n",
+               __func__, stdi->lcvs, stdi->lcf, stdi->bl,
+               stdi->hs_pol, stdi->vs_pol);
        return -1;
 }
 
@@ -1123,7 +1286,7 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
                adv7604_fill_optional_dv_timings_fields(sd, timings);
        } else {
                /* find format
-                * Since LCVS values are inaccurate (REF_03, page 275-276),
+                * Since LCVS values are inaccurate [REF_03, p. 275-276],
                 * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
                 */
                if (!stdi2dv_timings(sd, &stdi, timings))
@@ -1135,9 +1298,31 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
                stdi.lcvs -= 2;
                v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
                if (stdi2dv_timings(sd, &stdi, timings)) {
+                       /*
+                        * The STDI block may measure wrong values, especially
+                        * for lcvs and lcf. If the driver can not find any
+                        * valid timing, the STDI block is restarted to measure
+                        * the video timings again. The function will return an
+                        * error, but the restart of STDI will generate a new
+                        * STDI interrupt and the format detection process will
+                        * restart.
+                        */
+                       if (state->restart_stdi_once) {
+                               v4l2_dbg(1, debug, sd, "%s: restart STDI\n", __func__);
+                               /* TODO restart STDI for Sync Channel 2 */
+                               /* enter one-shot mode */
+                               cp_write_and_or(sd, 0x86, 0xf9, 0x00);
+                               /* trigger STDI restart */
+                               cp_write_and_or(sd, 0x86, 0xf9, 0x04);
+                               /* reset to continuous mode */
+                               cp_write_and_or(sd, 0x86, 0xf9, 0x02);
+                               state->restart_stdi_once = false;
+                               return -ENOLINK;
+                       }
                        v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
                        return -ERANGE;
                }
+               state->restart_stdi_once = true;
        }
 found:
 
@@ -1166,6 +1351,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
 {
        struct adv7604_state *state = to_state(sd);
        struct v4l2_bt_timings *bt;
+       int err;
 
        if (!timings)
                return -EINVAL;
@@ -1178,12 +1364,20 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
                                __func__, (u32)bt->pixelclock);
                return -ERANGE;
        }
+
        adv7604_fill_optional_dv_timings_fields(sd, timings);
 
        state->timings = *timings;
 
-       /* freerun */
-       configure_free_run(sd, bt);
+       cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10);
+
+       /* Use prim_mode and vid_std when available */
+       err = configure_predefined_video_timings(sd, timings);
+       if (err) {
+               /* custom settings when the video format
+                does not have prim_mode/vid_std */
+               configure_custom_video_timings(sd, bt);
+       }
 
        set_rgb_quantization_range(sd);
 
@@ -1203,24 +1397,25 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
        return 0;
 }
 
-static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+static void enable_input(struct v4l2_subdev *sd)
 {
-       switch (prim_mode) {
-       case ADV7604_PRIM_MODE_COMP:
-       case ADV7604_PRIM_MODE_RGB:
+       struct adv7604_state *state = to_state(sd);
+
+       switch (state->mode) {
+       case ADV7604_MODE_COMP:
+       case ADV7604_MODE_GR:
                /* enable */
                io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
                break;
-       case ADV7604_PRIM_MODE_HDMI_COMP:
-       case ADV7604_PRIM_MODE_HDMI_GR:
+       case ADV7604_MODE_HDMI:
                /* enable */
                hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
                hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
                io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
                break;
        default:
-               v4l2_err(sd, "%s: reserved primary mode 0x%0x\n",
-                               __func__, prim_mode);
+               v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+                               __func__, state->mode);
                break;
        }
 }
@@ -1233,17 +1428,13 @@ static void disable_input(struct v4l2_subdev *sd)
        hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
 }
 
-static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+static void select_input(struct v4l2_subdev *sd)
 {
-       switch (prim_mode) {
-       case ADV7604_PRIM_MODE_COMP:
-       case ADV7604_PRIM_MODE_RGB:
-               /* set mode and select free run resolution */
-               io_write(sd, 0x00, 0x07); /* video std */
-               io_write(sd, 0x01, 0x02); /* prim mode */
-               /* enable embedded syncs for auto graphics mode */
-               cp_write_and_or(sd, 0x81, 0xef, 0x10);
+       struct adv7604_state *state = to_state(sd);
 
+       switch (state->mode) {
+       case ADV7604_MODE_COMP:
+       case ADV7604_MODE_GR:
                /* reset ADI recommended settings for HDMI: */
                /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
                hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
@@ -1271,16 +1462,7 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
                cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
                break;
 
-       case ADV7604_PRIM_MODE_HDMI_COMP:
-       case ADV7604_PRIM_MODE_HDMI_GR:
-               /* set mode and select free run resolution */
-               /* video std */
-               io_write(sd, 0x00,
-                       (prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e);
-               io_write(sd, 0x01, prim_mode); /* prim mode */
-               /* disable embedded syncs for auto graphics mode */
-               cp_write_and_or(sd, 0x81, 0xef, 0x00);
-
+       case ADV7604_MODE_HDMI:
                /* set ADI recommended settings for HDMI: */
                /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
                hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
@@ -1309,7 +1491,8 @@ static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mod
 
                break;
        default:
-               v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode);
+               v4l2_dbg(2, debug, sd, "%s: Unknown mode %d\n",
+                               __func__, state->mode);
                break;
        }
 }
@@ -1321,26 +1504,13 @@ static int adv7604_s_routing(struct v4l2_subdev *sd,
 
        v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
 
-       switch (input) {
-       case 0:
-               /* TODO select HDMI_COMP or HDMI_GR */
-               state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP;
-               break;
-       case 1:
-               state->prim_mode = ADV7604_PRIM_MODE_RGB;
-               break;
-       case 2:
-               state->prim_mode = ADV7604_PRIM_MODE_COMP;
-               break;
-       default:
-               return -EINVAL;
-       }
+       state->mode = input;
 
        disable_input(sd);
 
-       select_input(sd, state->prim_mode);
+       select_input(sd);
 
-       enable_input(sd, state->prim_mode);
+       enable_input(sd);
 
        return 0;
 }
@@ -1549,8 +1719,9 @@ static int adv7604_log_status(struct v4l2_subdev *sd)
        v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
        v4l2_info(sd, "CP free run: %s\n",
                        (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
-       v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n",
-                       io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f);
+       v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x, v_freq = 0x%x\n",
+                       io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f,
+                       (io_read(sd, 0x01) & 0x70) >> 4);
 
        v4l2_info(sd, "-----Video Timings-----\n");
        if (read_stdi(sd, &stdi))
@@ -1712,9 +1883,9 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
        cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
        cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
        cp_write(sd, 0xf9, 0x23); /*  STDI ch. 1 - LCVS change threshold -
-                                     ADI recommended setting [REF_01 c. 2.3.3] */
+                                     ADI recommended setting [REF_01, c. 2.3.3] */
        cp_write(sd, 0x45, 0x23); /*  STDI ch. 2 - LCVS change threshold -
-                                     ADI recommended setting [REF_01 c. 2.3.3] */
+                                     ADI recommended setting [REF_01, c. 2.3.3] */
        cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
                                     for digital formats */
 
@@ -1724,11 +1895,6 @@ static int adv7604_core_init(struct v4l2_subdev *sd)
        afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
        io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
 
-       state->prim_mode = pdata->prim_mode;
-       select_input(sd, pdata->prim_mode);
-
-       enable_input(sd, pdata->prim_mode);
-
        /* interrupts */
        io_write(sd, 0x40, 0xc2); /* Configure INT1 */
        io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
@@ -1883,6 +2049,7 @@ static int adv7604_probe(struct i2c_client *client,
                v4l2_err(sd, "failed to create all i2c clients\n");
                goto err_i2c;
        }
+       state->restart_stdi_once = true;
 
        /* work queues */
        state->work_queues = create_singlethread_workqueue(client->name);
index 13057b966ee9abe10b7d4e29331ec80ba52fa20a..333ef178d6fbfe1d5622fd161c01856182b01871 100644 (file)
@@ -263,9 +263,14 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
                if (ret & 1) /* Autoexposure */
                        ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
                                        rect.height + mt9v022->y_skip_top + 43);
-               else
-                       ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
-                                       rect.height + mt9v022->y_skip_top + 43);
+               /*
+                * If autoexposure is off, there is no need to set
+                * MT9V022_TOTAL_SHUTTER_WIDTH here. Autoexposure can be off
+                * only if the user has set exposure manually, using the
+                * V4L2_CID_EXPOSURE_AUTO with the value V4L2_EXPOSURE_MANUAL.
+                * In this case the register MT9V022_TOTAL_SHUTTER_WIDTH
+                * already contains the correct value.
+                */
        }
        /* Setup frame format: defaults apart from width and height */
        if (!ret)
index bfec9e65aefbd78cca43638f7ffe5bdbc339c3ae..19cbb12a12a2c814424a32b8db8ae2b30074d687 100644 (file)
@@ -965,8 +965,10 @@ static struct platform_device_id gsc_driver_ids[] = {
 MODULE_DEVICE_TABLE(platform, gsc_driver_ids);
 
 static const struct of_device_id exynos_gsc_match[] = {
-       { .compatible = "samsung,exynos5250-gsc",
-       .data = &gsc_v_100_drvdata, },
+       {
+               .compatible = "samsung,exynos5-gsc",
+               .data = &gsc_v_100_drvdata,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, exynos_gsc_match);
index 60181ab96063ea12be4f0a10f6b02e5a86e29991..aa9df9d71a7b0a455544446ed3e79e7c83ac7218 100644 (file)
@@ -1706,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 }
 
 static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
-                               const struct v4l2_event_subscription *sub)
+                               struct v4l2_event_subscription *sub)
 {
        if (sub->type != V4L2_EVENT_FRAME_SYNC)
                return -EINVAL;
@@ -1719,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
 }
 
 static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
-                                 const struct v4l2_event_subscription *sub)
+                                 struct v4l2_event_subscription *sub)
 {
        return v4l2_event_unsubscribe(fh, sub);
 }
index d7ac76b5c2aee4d38916057b1757d2366b27b188..b8640be692f1aef7f093b6364ddb62c15a881504 100644 (file)
@@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat)
 
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
                                  struct v4l2_fh *fh,
-                                 const struct v4l2_event_subscription *sub)
+                                 struct v4l2_event_subscription *sub)
 {
        struct ispstat *stat = v4l2_get_subdevdata(subdev);
 
@@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
 
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
                                    struct v4l2_fh *fh,
-                                   const struct v4l2_event_subscription *sub)
+                                   struct v4l2_event_subscription *sub)
 {
        return v4l2_event_unsubscribe(fh, sub);
 }
index a6fe653eb237dc171c6aef71f31d62ddc1a30550..9b7c8654dc8a4cadea05dd1ff629ad35b8ebae85 100644 (file)
@@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name,
 void omap3isp_stat_cleanup(struct ispstat *stat);
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
                                  struct v4l2_fh *fh,
-                                 const struct v4l2_event_subscription *sub);
+                                 struct v4l2_event_subscription *sub);
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
                                    struct v4l2_fh *fh,
-                                   const struct v4l2_event_subscription *sub);
+                                   struct v4l2_event_subscription *sub);
 int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
 
 int omap3isp_stat_busy(struct ispstat *stat);
index a0b737fecf138e61413fca9ca6c36443b5b452f4..75cd309035f90f303f6bfe1d3b1ad86f078536d7 100644 (file)
@@ -792,7 +792,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
 }
 
 static int
-isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+isp_video_set_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
        struct isp_video *video = video_drvdata(file);
        struct v4l2_subdev *subdev;
index 8f090a8f270e7465b018940a2eb9fd6dba33eeaf..c16b20d86ed283d65723dda5854f5e1fb3675097 100644 (file)
@@ -24,6 +24,7 @@ config VIDEO_S5P_FIMC
 config VIDEO_S5P_MIPI_CSIS
        tristate "S5P/EXYNOS MIPI-CSI2 receiver (MIPI-CSIS) driver"
        depends on REGULATOR
+       select S5P_SETUP_MIPIPHY
        help
          This is a V4L2 driver for Samsung S5P and EXYNOS4 SoC MIPI-CSI2
          receiver (MIPI-CSIS) devices.
index 367efd164d0f1c9580111b12b51c8e2a9f225bfa..3d39d97abaa5ab3a35a4c89f20338848efc174b9 100644 (file)
@@ -1736,7 +1736,9 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
        q->mem_ops = &vb2_dma_contig_memops;
        q->buf_struct_size = sizeof(struct fimc_vid_buffer);
 
-       vb2_queue_init(q);
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto err_ent;
 
        vid_cap->vd_pad.flags = MEDIA_PAD_FL_SINK;
        ret = media_entity_init(&vfd->entity, 1, &vid_cap->vd_pad, 0);
index 70bcf39de87994f99dc38ae11c1a2c115d56433d..9db246bed841abc4622433d82f668e801e0cf3d7 100644 (file)
@@ -1253,7 +1253,9 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
        q->buf_struct_size = sizeof(struct flite_buffer);
        q->drv_priv = fimc;
 
-       vb2_queue_init(q);
+       ret = vb2_queue_init(q);
+       if (ret < 0)
+               return ret;
 
        fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
        ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
index 80ada5882f62c8156c74265a7279eca9e6fbc35c..38ea4d143a496cee415af614d0cf6f259560182a 100644 (file)
@@ -343,53 +343,50 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
 static int fimc_register_callback(struct device *dev, void *p)
 {
        struct fimc_dev *fimc = dev_get_drvdata(dev);
-       struct v4l2_subdev *sd = &fimc->vid_cap.subdev;
+       struct v4l2_subdev *sd;
        struct fimc_md *fmd = p;
-       int ret = 0;
-
-       if (!fimc || !fimc->pdev)
-               return 0;
+       int ret;
 
-       if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
+       if (fimc == NULL || fimc->id >= FIMC_MAX_DEVS)
                return 0;
 
-       fimc->pipeline_ops = &fimc_pipeline_ops;
-       fmd->fimc[fimc->pdev->id] = fimc;
+       sd = &fimc->vid_cap.subdev;
        sd->grp_id = FIMC_GROUP_ID;
 
        ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
        if (ret) {
                v4l2_err(&fmd->v4l2_dev, "Failed to register FIMC.%d (%d)\n",
                         fimc->id, ret);
+               return ret;
        }
 
-       return ret;
+       fimc->pipeline_ops = &fimc_pipeline_ops;
+       fmd->fimc[fimc->id] = fimc;
+       return 0;
 }
 
 static int fimc_lite_register_callback(struct device *dev, void *p)
 {
        struct fimc_lite *fimc = dev_get_drvdata(dev);
-       struct v4l2_subdev *sd = &fimc->subdev;
        struct fimc_md *fmd = p;
        int ret;
 
-       if (fimc == NULL)
+       if (fimc == NULL || fimc->index >= FIMC_LITE_MAX_DEVS)
                return 0;
 
-       if (fimc->index >= FIMC_LITE_MAX_DEVS)
-               return 0;
+       fimc->subdev.grp_id = FLITE_GROUP_ID;
 
-       fimc->pipeline_ops = &fimc_pipeline_ops;
-       fmd->fimc_lite[fimc->index] = fimc;
-       sd->grp_id = FLITE_GROUP_ID;
-
-       ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
+       ret = v4l2_device_register_subdev(&fmd->v4l2_dev, &fimc->subdev);
        if (ret) {
                v4l2_err(&fmd->v4l2_dev,
                         "Failed to register FIMC-LITE.%d (%d)\n",
                         fimc->index, ret);
+               return ret;
        }
-       return ret;
+
+       fimc->pipeline_ops = &fimc_pipeline_ops;
+       fmd->fimc_lite[fimc->index] = fimc;
+       return 0;
 }
 
 static int csis_register_callback(struct device *dev, void *p)
@@ -407,10 +404,12 @@ static int csis_register_callback(struct device *dev, void *p)
        v4l2_info(sd, "csis%d sd: %s\n", pdev->id, sd->name);
 
        id = pdev->id < 0 ? 0 : pdev->id;
-       fmd->csis[id].sd = sd;
        sd->grp_id = CSIS_GROUP_ID;
+
        ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd);
-       if (ret)
+       if (!ret)
+               fmd->csis[id].sd = sd;
+       else
                v4l2_err(&fmd->v4l2_dev,
                         "Failed to register CSIS subdevice: %d\n", ret);
        return ret;
index 85fd312f0a829fee9f45b1e682694cc3fc475cf3..a1c87f0ceaabe0285ddd2d6b03dd3ead5303d22d 100644 (file)
@@ -935,9 +935,10 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
 /* Assume a dull encoder, do all the work ourselves. */
 static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a)
 {
+       struct v4l2_crop a_writable = *a;
        struct video_device *vdev = video_devdata(file);
        struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_rect *rect = &a_writable.c;
        struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
        struct v4l2_pix_format *pix = &vou_dev->pix;
        struct sh_vou_geometry geo;
index bbe70991d30b6ac0b2ef598ccafba7519ab138b9..032b8c9097f99a7d35866a242b7897302b260860 100644 (file)
@@ -470,14 +470,6 @@ static void mx1_camera_remove_device(struct soc_camera_device *icd)
        pcdev->icd = NULL;
 }
 
-static int mx1_camera_set_crop(struct soc_camera_device *icd,
-                              struct v4l2_crop *a)
-{
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-
-       return v4l2_subdev_call(sd, video, s_crop, a);
-}
-
 static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
@@ -689,7 +681,6 @@ static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
        .add            = mx1_camera_add_device,
        .remove         = mx1_camera_remove_device,
        .set_bus_param  = mx1_camera_set_bus_param,
-       .set_crop       = mx1_camera_set_crop,
        .set_fmt        = mx1_camera_set_fmt,
        .try_fmt        = mx1_camera_try_fmt,
        .init_videobuf  = mx1_camera_init_videobuf,
index 9fd9d1c5b218a5b51ff0522b9969db06e795706c..9a55f4c4c7f4ec9ad9a050ca0d8220e482ee9818 100644 (file)
@@ -864,8 +864,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
 
                bytesperline = soc_mbus_bytes_per_line(icd->user_width,
                                icd->current_fmt->host_fmt);
-               if (bytesperline < 0)
+               if (bytesperline < 0) {
+                       spin_unlock_irqrestore(&pcdev->lock, flags);
                        return bytesperline;
+               }
 
                /*
                 * I didn't manage to properly enable/disable the prp
@@ -878,8 +880,10 @@ static int mx2_start_streaming(struct vb2_queue *q, unsigned int count)
                pcdev->discard_buffer = dma_alloc_coherent(ici->v4l2_dev.dev,
                                pcdev->discard_size, &pcdev->discard_buffer_dma,
                                GFP_KERNEL);
-               if (!pcdev->discard_buffer)
+               if (!pcdev->discard_buffer) {
+                       spin_unlock_irqrestore(&pcdev->lock, flags);
                        return -ENOMEM;
+               }
 
                pcdev->buf_discard[0].discard = true;
                list_add_tail(&pcdev->buf_discard[0].queue,
@@ -1099,9 +1103,10 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd)
 }
 
 static int mx2_camera_set_crop(struct soc_camera_device *icd,
-                               struct v4l2_crop *a)
+                               const struct v4l2_crop *a)
 {
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_crop a_writable = *a;
+       struct v4l2_rect *rect = &a_writable.c;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct v4l2_mbus_framefmt mf;
        int ret;
index 3557ac97e4303f4743330850a5144f43cb06cbd0..261f6e9e1b176dcbc543992204162673f06935c4 100644 (file)
@@ -799,9 +799,10 @@ static inline void stride_align(__u32 *width)
  * default g_crop and cropcap from soc_camera.c
  */
 static int mx3_camera_set_crop(struct soc_camera_device *icd,
-                              struct v4l2_crop *a)
+                              const struct v4l2_crop *a)
 {
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_crop a_writable = *a;
+       struct v4l2_rect *rect = &a_writable.c;
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
        struct mx3_camera_dev *mx3_cam = ici->priv;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
index fa08c7695ccb05aa61d680d8bcf4f002516d2894..13636a58510606635a69cda964f57054a2e607b7 100644 (file)
@@ -1215,9 +1215,9 @@ static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev,
 }
 
 static int omap1_cam_set_crop(struct soc_camera_device *icd,
-                              struct v4l2_crop *crop)
+                              const struct v4l2_crop *crop)
 {
-       struct v4l2_rect *rect = &crop->c;
+       const struct v4l2_rect *rect = &crop->c;
        const struct soc_camera_format_xlate *xlate = icd->current_fmt;
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct device *dev = icd->parent;
index 1e3776d08dacb6f6159a417ecbe5d6bf9c935f3f..3434ffe79c6ecc445a8b451dc2c55767b552c217 100644 (file)
@@ -1337,9 +1337,9 @@ static int pxa_camera_check_frame(u32 width, u32 height)
 }
 
 static int pxa_camera_set_crop(struct soc_camera_device *icd,
-                              struct v4l2_crop *a)
+                              const struct v4l2_crop *a)
 {
-       struct v4l2_rect *rect = &a->c;
+       const struct v4l2_rect *rect = &a->c;
        struct device *dev = icd->parent;
        struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct pxa_camera_dev *pcdev = ici->priv;
index 0a24253dcda2a9afd42d4a2bfb017a5c016171ac..2d8861c0e8f2c23baae9908a0fdf2955e458ead3 100644 (file)
@@ -1182,13 +1182,13 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
 }
 
 /* Check if any dimension of r1 is smaller than respective one of r2 */
-static bool is_smaller(struct v4l2_rect *r1, struct v4l2_rect *r2)
+static bool is_smaller(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
 {
        return r1->width < r2->width || r1->height < r2->height;
 }
 
 /* Check if r1 fails to cover r2 */
-static bool is_inside(struct v4l2_rect *r1, struct v4l2_rect *r2)
+static bool is_inside(const struct v4l2_rect *r1, const struct v4l2_rect *r2)
 {
        return r1->left > r2->left || r1->top > r2->top ||
                r1->left + r1->width < r2->left + r2->width ||
@@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam)
  * 3. if (2) failed, try to request the maximum image
  */
 static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop,
-                        const struct v4l2_crop *cam_crop)
+                        struct v4l2_crop *cam_crop)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c;
@@ -1519,7 +1519,8 @@ static int client_scale(struct soc_camera_device *icd,
 static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
                                  const struct v4l2_crop *a)
 {
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_crop a_writable = *a;
+       const struct v4l2_rect *rect = &a_writable.c;
        struct device *dev = icd->parent;
        struct soc_camera_host *ici = to_soc_camera_host(dev);
        struct sh_mobile_ceu_dev *pcdev = ici->priv;
@@ -1545,7 +1546,7 @@ static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
         * 1. - 2. Apply iterative camera S_CROP for new input window, read back
         * actual camera rectangle.
         */
-       ret = client_s_crop(icd, a, &cam_crop);
+       ret = client_s_crop(icd, &a_writable, &cam_crop);
        if (ret < 0)
                return ret;
 
@@ -1946,7 +1947,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
 }
 
 static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd,
-                                     struct v4l2_crop *a)
+                                     const struct v4l2_crop *a)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
index 9859d2a2449b974bf162a32f78eeb8a543f9bf5f..ba51f65204de833cb9965f5f0764f85c8ce9166e 100644 (file)
@@ -283,14 +283,13 @@ static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
 
        /* activate the pid on the device pid filter */
        if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
-                       adap->pid_filtering &&
-                       adap->props->pid_filter)
+                       adap->pid_filtering && adap->props->pid_filter) {
                ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
                                dvbdmxfeed->pid, (count == 1) ? 1 : 0);
-                       if (ret < 0)
-                               dev_err(&d->udev->dev, "%s: pid_filter() " \
-                                               "failed=%d\n", KBUILD_MODNAME,
-                                               ret);
+               if (ret < 0)
+                       dev_err(&d->udev->dev, "%s: pid_filter() failed=%d\n",
+                                       KBUILD_MODNAME, ret);
+       }
 
        /* start feeding if it is first pid */
        if (adap->feed_count == 1 && count == 1) {
index 0431beed0ef44dcfcfc7043d85fe514f602f1d10..5716662b483451f4d3a5fb6204091a6285f349e2 100644 (file)
@@ -32,9 +32,7 @@ int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
                return -EINVAL;
        }
 
-       ret = mutex_lock_interruptible(&d->usb_mutex);
-       if (ret < 0)
-               return ret;
+       mutex_lock(&d->usb_mutex);
 
        dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
 
index adabba8d28bc80fa69b76348f40b83f63a680390..093f1acce403e7fa35ddea58914dd386ee32f426 100644 (file)
@@ -1346,6 +1346,10 @@ static const struct usb_device_id rtl28xxu_id_table[] = {
                &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) },
        { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
                &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1102,
+               &rtl2832u_props, "Dexatek DK mini DVB-T Dongle", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d7,
+               &rtl2832u_props, "TerraTec Cinergy T Stick+", NULL) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
index 1b48f2094806c75fa8914657978f1b7bf814ae93..f4f9bf84bc7b6348bc804b6368f5522cc29e2ddf 100644 (file)
@@ -96,11 +96,11 @@ static irqreturn_t arizona_underclocked(int irq, void *data)
                return IRQ_NONE;
        }
 
-       if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
-               dev_err(arizona->dev, "AIF3 underclocked\n");
        if (val & ARIZONA_AIF3_UNDERCLOCKED_STS)
                dev_err(arizona->dev, "AIF3 underclocked\n");
        if (val & ARIZONA_AIF2_UNDERCLOCKED_STS)
+               dev_err(arizona->dev, "AIF2 underclocked\n");
+       if (val & ARIZONA_AIF1_UNDERCLOCKED_STS)
                dev_err(arizona->dev, "AIF1 underclocked\n");
        if (val & ARIZONA_ISRC2_UNDERCLOCKED_STS)
                dev_err(arizona->dev, "ISRC2 underclocked\n");
@@ -415,11 +415,19 @@ int __devinit arizona_dev_init(struct arizona *arizona)
 
        /* If we have a /RESET GPIO we'll already be reset */
        if (!arizona->pdata.reset) {
+               regcache_mark_dirty(arizona->regmap);
+
                ret = regmap_write(arizona->regmap, ARIZONA_SOFTWARE_RESET, 0);
                if (ret != 0) {
                        dev_err(dev, "Failed to reset device: %d\n", ret);
                        goto err_reset;
                }
+
+               ret = regcache_sync(arizona->regmap);
+               if (ret != 0) {
+                       dev_err(dev, "Failed to sync device: %d\n", ret);
+                       goto err_reset;
+               }
        }
 
        ret = arizona_wait_for_boot(arizona);
@@ -520,7 +528,7 @@ int __devinit arizona_dev_init(struct arizona *arizona)
                break;
        case WM5110:
                ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
-                                     ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
+                                     ARRAY_SIZE(wm5110_devs), NULL, 0, NULL);
                break;
        }
 
index ef0f2d001df20524695906c42993b368d9fa8a81..b1b0091774055213c6b0a573f4075b8ebb7af5d9 100644 (file)
@@ -178,6 +178,7 @@ int arizona_irq_init(struct arizona *arizona)
 
                switch (arizona->rev) {
                case 0:
+               case 1:
                        ctrlif_error = false;
                        break;
                default:
index 4ae6423202058c0e1e7d7c9c262b8c25fd38d917..a071a8643a4776e9cccd70bb3c4ea7bc786203ab 100644 (file)
@@ -671,7 +671,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
        }
 
        if (IS_ENABLED(CONFIG_PWM_TWL6030) && twl_class_is_6030()) {
-               child = add_child(TWL6030_MODULE_ID1, "twl6030-pwm", NULL, 0,
+               child = add_child(SUB_CHIP_ID1, "twl6030-pwm", NULL, 0,
                                  false, 0, 0);
                if (IS_ERR(child))
                        return PTR_ERR(child);
index ad733d76207ac11320f69603ea1a3235f81b9495..cdd1173ed4e9641b0290bffbac7a860563f6c581 100644 (file)
@@ -672,7 +672,8 @@ int twl4030_sih_setup(struct device *dev, int module, int irq_base)
        irq = sih_mod + twl4030_irq_base;
        irq_set_handler_data(irq, agent);
        agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name);
-       status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0,
+       status = request_threaded_irq(irq, NULL, handle_twl4030_sih,
+                                     IRQF_EARLY_RESUME,
                                      agent->irq_name ?: sih->name, NULL);
 
        dev_info(dev, "%s (irq %d) chaining IRQs %d..%d\n", sih->name,
index 01b9255ed6310cf9f984d4177fc59b9e21b6348e..14490cc785d29879f37a06ee52ffed57b8c32c9e 100644 (file)
@@ -43,6 +43,7 @@ static const struct reg_default wm5102_reva_patch[] = {
        { 0x479, 0x0A30 },
        { 0x47B, 0x0810 },
        { 0x47D, 0x0510 },
+       { 0x4D1, 0x017F },
        { 0x500, 0x000D },
        { 0x507, 0x1820 },
        { 0x508, 0x1820 },
@@ -52,524 +53,6 @@ static const struct reg_default wm5102_reva_patch[] = {
        { 0x580, 0x000D },
        { 0x587, 0x1820 },
        { 0x588, 0x1820 },
-       { 0x101, 0x8140 },
-       { 0x3000, 0x2225 },
-       { 0x3001, 0x3a03 },
-       { 0x3002, 0x0225 },
-       { 0x3003, 0x0801 },
-       { 0x3004, 0x6249 },
-       { 0x3005, 0x0c04 },
-       { 0x3006, 0x0225 },
-       { 0x3007, 0x5901 },
-       { 0x3008, 0xe249 },
-       { 0x3009, 0x030d },
-       { 0x300a, 0x0249 },
-       { 0x300b, 0x2c01 },
-       { 0x300c, 0xe249 },
-       { 0x300d, 0x4342 },
-       { 0x300e, 0xe249 },
-       { 0x300f, 0x73c0 },
-       { 0x3010, 0x4249 },
-       { 0x3011, 0x0c00 },
-       { 0x3012, 0x0225 },
-       { 0x3013, 0x1f01 },
-       { 0x3014, 0x0225 },
-       { 0x3015, 0x1e01 },
-       { 0x3016, 0x0225 },
-       { 0x3017, 0xfa00 },
-       { 0x3018, 0x0000 },
-       { 0x3019, 0xf000 },
-       { 0x301a, 0x0000 },
-       { 0x301b, 0xf000 },
-       { 0x301c, 0x0000 },
-       { 0x301d, 0xf000 },
-       { 0x301e, 0x0000 },
-       { 0x301f, 0xf000 },
-       { 0x3020, 0x0000 },
-       { 0x3021, 0xf000 },
-       { 0x3022, 0x0000 },
-       { 0x3023, 0xf000 },
-       { 0x3024, 0x0000 },
-       { 0x3025, 0xf000 },
-       { 0x3026, 0x0000 },
-       { 0x3027, 0xf000 },
-       { 0x3028, 0x0000 },
-       { 0x3029, 0xf000 },
-       { 0x302a, 0x0000 },
-       { 0x302b, 0xf000 },
-       { 0x302c, 0x0000 },
-       { 0x302d, 0xf000 },
-       { 0x302e, 0x0000 },
-       { 0x302f, 0xf000 },
-       { 0x3030, 0x0225 },
-       { 0x3031, 0x1a01 },
-       { 0x3032, 0x0225 },
-       { 0x3033, 0x1e00 },
-       { 0x3034, 0x0225 },
-       { 0x3035, 0x1f00 },
-       { 0x3036, 0x6225 },
-       { 0x3037, 0xf800 },
-       { 0x3038, 0x0000 },
-       { 0x3039, 0xf000 },
-       { 0x303a, 0x0000 },
-       { 0x303b, 0xf000 },
-       { 0x303c, 0x0000 },
-       { 0x303d, 0xf000 },
-       { 0x303e, 0x0000 },
-       { 0x303f, 0xf000 },
-       { 0x3040, 0x2226 },
-       { 0x3041, 0x3a03 },
-       { 0x3042, 0x0226 },
-       { 0x3043, 0x0801 },
-       { 0x3044, 0x6249 },
-       { 0x3045, 0x0c06 },
-       { 0x3046, 0x0226 },
-       { 0x3047, 0x5901 },
-       { 0x3048, 0xe249 },
-       { 0x3049, 0x030d },
-       { 0x304a, 0x0249 },
-       { 0x304b, 0x2c01 },
-       { 0x304c, 0xe249 },
-       { 0x304d, 0x4342 },
-       { 0x304e, 0xe249 },
-       { 0x304f, 0x73c0 },
-       { 0x3050, 0x4249 },
-       { 0x3051, 0x0c00 },
-       { 0x3052, 0x0226 },
-       { 0x3053, 0x1f01 },
-       { 0x3054, 0x0226 },
-       { 0x3055, 0x1e01 },
-       { 0x3056, 0x0226 },
-       { 0x3057, 0xfa00 },
-       { 0x3058, 0x0000 },
-       { 0x3059, 0xf000 },
-       { 0x305a, 0x0000 },
-       { 0x305b, 0xf000 },
-       { 0x305c, 0x0000 },
-       { 0x305d, 0xf000 },
-       { 0x305e, 0x0000 },
-       { 0x305f, 0xf000 },
-       { 0x3060, 0x0000 },
-       { 0x3061, 0xf000 },
-       { 0x3062, 0x0000 },
-       { 0x3063, 0xf000 },
-       { 0x3064, 0x0000 },
-       { 0x3065, 0xf000 },
-       { 0x3066, 0x0000 },
-       { 0x3067, 0xf000 },
-       { 0x3068, 0x0000 },
-       { 0x3069, 0xf000 },
-       { 0x306a, 0x0000 },
-       { 0x306b, 0xf000 },
-       { 0x306c, 0x0000 },
-       { 0x306d, 0xf000 },
-       { 0x306e, 0x0000 },
-       { 0x306f, 0xf000 },
-       { 0x3070, 0x0226 },
-       { 0x3071, 0x1a01 },
-       { 0x3072, 0x0226 },
-       { 0x3073, 0x1e00 },
-       { 0x3074, 0x0226 },
-       { 0x3075, 0x1f00 },
-       { 0x3076, 0x6226 },
-       { 0x3077, 0xf800 },
-       { 0x3078, 0x0000 },
-       { 0x3079, 0xf000 },
-       { 0x307a, 0x0000 },
-       { 0x307b, 0xf000 },
-       { 0x307c, 0x0000 },
-       { 0x307d, 0xf000 },
-       { 0x307e, 0x0000 },
-       { 0x307f, 0xf000 },
-       { 0x3080, 0x2227 },
-       { 0x3081, 0x3a03 },
-       { 0x3082, 0x0227 },
-       { 0x3083, 0x0801 },
-       { 0x3084, 0x6255 },
-       { 0x3085, 0x0c04 },
-       { 0x3086, 0x0227 },
-       { 0x3087, 0x5901 },
-       { 0x3088, 0xe255 },
-       { 0x3089, 0x030d },
-       { 0x308a, 0x0255 },
-       { 0x308b, 0x2c01 },
-       { 0x308c, 0xe255 },
-       { 0x308d, 0x4342 },
-       { 0x308e, 0xe255 },
-       { 0x308f, 0x73c0 },
-       { 0x3090, 0x4255 },
-       { 0x3091, 0x0c00 },
-       { 0x3092, 0x0227 },
-       { 0x3093, 0x1f01 },
-       { 0x3094, 0x0227 },
-       { 0x3095, 0x1e01 },
-       { 0x3096, 0x0227 },
-       { 0x3097, 0xfa00 },
-       { 0x3098, 0x0000 },
-       { 0x3099, 0xf000 },
-       { 0x309a, 0x0000 },
-       { 0x309b, 0xf000 },
-       { 0x309c, 0x0000 },
-       { 0x309d, 0xf000 },
-       { 0x309e, 0x0000 },
-       { 0x309f, 0xf000 },
-       { 0x30a0, 0x0000 },
-       { 0x30a1, 0xf000 },
-       { 0x30a2, 0x0000 },
-       { 0x30a3, 0xf000 },
-       { 0x30a4, 0x0000 },
-       { 0x30a5, 0xf000 },
-       { 0x30a6, 0x0000 },
-       { 0x30a7, 0xf000 },
-       { 0x30a8, 0x0000 },
-       { 0x30a9, 0xf000 },
-       { 0x30aa, 0x0000 },
-       { 0x30ab, 0xf000 },
-       { 0x30ac, 0x0000 },
-       { 0x30ad, 0xf000 },
-       { 0x30ae, 0x0000 },
-       { 0x30af, 0xf000 },
-       { 0x30b0, 0x0227 },
-       { 0x30b1, 0x1a01 },
-       { 0x30b2, 0x0227 },
-       { 0x30b3, 0x1e00 },
-       { 0x30b4, 0x0227 },
-       { 0x30b5, 0x1f00 },
-       { 0x30b6, 0x6227 },
-       { 0x30b7, 0xf800 },
-       { 0x30b8, 0x0000 },
-       { 0x30b9, 0xf000 },
-       { 0x30ba, 0x0000 },
-       { 0x30bb, 0xf000 },
-       { 0x30bc, 0x0000 },
-       { 0x30bd, 0xf000 },
-       { 0x30be, 0x0000 },
-       { 0x30bf, 0xf000 },
-       { 0x30c0, 0x2228 },
-       { 0x30c1, 0x3a03 },
-       { 0x30c2, 0x0228 },
-       { 0x30c3, 0x0801 },
-       { 0x30c4, 0x6255 },
-       { 0x30c5, 0x0c06 },
-       { 0x30c6, 0x0228 },
-       { 0x30c7, 0x5901 },
-       { 0x30c8, 0xe255 },
-       { 0x30c9, 0x030d },
-       { 0x30ca, 0x0255 },
-       { 0x30cb, 0x2c01 },
-       { 0x30cc, 0xe255 },
-       { 0x30cd, 0x4342 },
-       { 0x30ce, 0xe255 },
-       { 0x30cf, 0x73c0 },
-       { 0x30d0, 0x4255 },
-       { 0x30d1, 0x0c00 },
-       { 0x30d2, 0x0228 },
-       { 0x30d3, 0x1f01 },
-       { 0x30d4, 0x0228 },
-       { 0x30d5, 0x1e01 },
-       { 0x30d6, 0x0228 },
-       { 0x30d7, 0xfa00 },
-       { 0x30d8, 0x0000 },
-       { 0x30d9, 0xf000 },
-       { 0x30da, 0x0000 },
-       { 0x30db, 0xf000 },
-       { 0x30dc, 0x0000 },
-       { 0x30dd, 0xf000 },
-       { 0x30de, 0x0000 },
-       { 0x30df, 0xf000 },
-       { 0x30e0, 0x0000 },
-       { 0x30e1, 0xf000 },
-       { 0x30e2, 0x0000 },
-       { 0x30e3, 0xf000 },
-       { 0x30e4, 0x0000 },
-       { 0x30e5, 0xf000 },
-       { 0x30e6, 0x0000 },
-       { 0x30e7, 0xf000 },
-       { 0x30e8, 0x0000 },
-       { 0x30e9, 0xf000 },
-       { 0x30ea, 0x0000 },
-       { 0x30eb, 0xf000 },
-       { 0x30ec, 0x0000 },
-       { 0x30ed, 0xf000 },
-       { 0x30ee, 0x0000 },
-       { 0x30ef, 0xf000 },
-       { 0x30f0, 0x0228 },
-       { 0x30f1, 0x1a01 },
-       { 0x30f2, 0x0228 },
-       { 0x30f3, 0x1e00 },
-       { 0x30f4, 0x0228 },
-       { 0x30f5, 0x1f00 },
-       { 0x30f6, 0x6228 },
-       { 0x30f7, 0xf800 },
-       { 0x30f8, 0x0000 },
-       { 0x30f9, 0xf000 },
-       { 0x30fa, 0x0000 },
-       { 0x30fb, 0xf000 },
-       { 0x30fc, 0x0000 },
-       { 0x30fd, 0xf000 },
-       { 0x30fe, 0x0000 },
-       { 0x30ff, 0xf000 },
-       { 0x3100, 0x222b },
-       { 0x3101, 0x3a03 },
-       { 0x3102, 0x222b },
-       { 0x3103, 0x5803 },
-       { 0x3104, 0xe26f },
-       { 0x3105, 0x030d },
-       { 0x3106, 0x626f },
-       { 0x3107, 0x2c01 },
-       { 0x3108, 0xe26f },
-       { 0x3109, 0x4342 },
-       { 0x310a, 0xe26f },
-       { 0x310b, 0x73c0 },
-       { 0x310c, 0x026f },
-       { 0x310d, 0x0c00 },
-       { 0x310e, 0x022b },
-       { 0x310f, 0x1f01 },
-       { 0x3110, 0x022b },
-       { 0x3111, 0x1e01 },
-       { 0x3112, 0x022b },
-       { 0x3113, 0xfa00 },
-       { 0x3114, 0x0000 },
-       { 0x3115, 0xf000 },
-       { 0x3116, 0x0000 },
-       { 0x3117, 0xf000 },
-       { 0x3118, 0x0000 },
-       { 0x3119, 0xf000 },
-       { 0x311a, 0x0000 },
-       { 0x311b, 0xf000 },
-       { 0x311c, 0x0000 },
-       { 0x311d, 0xf000 },
-       { 0x311e, 0x0000 },
-       { 0x311f, 0xf000 },
-       { 0x3120, 0x022b },
-       { 0x3121, 0x0a01 },
-       { 0x3122, 0x022b },
-       { 0x3123, 0x1e00 },
-       { 0x3124, 0x022b },
-       { 0x3125, 0x1f00 },
-       { 0x3126, 0x622b },
-       { 0x3127, 0xf800 },
-       { 0x3128, 0x0000 },
-       { 0x3129, 0xf000 },
-       { 0x312a, 0x0000 },
-       { 0x312b, 0xf000 },
-       { 0x312c, 0x0000 },
-       { 0x312d, 0xf000 },
-       { 0x312e, 0x0000 },
-       { 0x312f, 0xf000 },
-       { 0x3130, 0x0000 },
-       { 0x3131, 0xf000 },
-       { 0x3132, 0x0000 },
-       { 0x3133, 0xf000 },
-       { 0x3134, 0x0000 },
-       { 0x3135, 0xf000 },
-       { 0x3136, 0x0000 },
-       { 0x3137, 0xf000 },
-       { 0x3138, 0x0000 },
-       { 0x3139, 0xf000 },
-       { 0x313a, 0x0000 },
-       { 0x313b, 0xf000 },
-       { 0x313c, 0x0000 },
-       { 0x313d, 0xf000 },
-       { 0x313e, 0x0000 },
-       { 0x313f, 0xf000 },
-       { 0x3140, 0x0000 },
-       { 0x3141, 0xf000 },
-       { 0x3142, 0x0000 },
-       { 0x3143, 0xf000 },
-       { 0x3144, 0x0000 },
-       { 0x3145, 0xf000 },
-       { 0x3146, 0x0000 },
-       { 0x3147, 0xf000 },
-       { 0x3148, 0x0000 },
-       { 0x3149, 0xf000 },
-       { 0x314a, 0x0000 },
-       { 0x314b, 0xf000 },
-       { 0x314c, 0x0000 },
-       { 0x314d, 0xf000 },
-       { 0x314e, 0x0000 },
-       { 0x314f, 0xf000 },
-       { 0x3150, 0x0000 },
-       { 0x3151, 0xf000 },
-       { 0x3152, 0x0000 },
-       { 0x3153, 0xf000 },
-       { 0x3154, 0x0000 },
-       { 0x3155, 0xf000 },
-       { 0x3156, 0x0000 },
-       { 0x3157, 0xf000 },
-       { 0x3158, 0x0000 },
-       { 0x3159, 0xf000 },
-       { 0x315a, 0x0000 },
-       { 0x315b, 0xf000 },
-       { 0x315c, 0x0000 },
-       { 0x315d, 0xf000 },
-       { 0x315e, 0x0000 },
-       { 0x315f, 0xf000 },
-       { 0x3160, 0x0000 },
-       { 0x3161, 0xf000 },
-       { 0x3162, 0x0000 },
-       { 0x3163, 0xf000 },
-       { 0x3164, 0x0000 },
-       { 0x3165, 0xf000 },
-       { 0x3166, 0x0000 },
-       { 0x3167, 0xf000 },
-       { 0x3168, 0x0000 },
-       { 0x3169, 0xf000 },
-       { 0x316a, 0x0000 },
-       { 0x316b, 0xf000 },
-       { 0x316c, 0x0000 },
-       { 0x316d, 0xf000 },
-       { 0x316e, 0x0000 },
-       { 0x316f, 0xf000 },
-       { 0x3170, 0x0000 },
-       { 0x3171, 0xf000 },
-       { 0x3172, 0x0000 },
-       { 0x3173, 0xf000 },
-       { 0x3174, 0x0000 },
-       { 0x3175, 0xf000 },
-       { 0x3176, 0x0000 },
-       { 0x3177, 0xf000 },
-       { 0x3178, 0x0000 },
-       { 0x3179, 0xf000 },
-       { 0x317a, 0x0000 },
-       { 0x317b, 0xf000 },
-       { 0x317c, 0x0000 },
-       { 0x317d, 0xf000 },
-       { 0x317e, 0x0000 },
-       { 0x317f, 0xf000 },
-       { 0x3180, 0x2001 },
-       { 0x3181, 0xf101 },
-       { 0x3182, 0x0000 },
-       { 0x3183, 0xf000 },
-       { 0x3184, 0x0000 },
-       { 0x3185, 0xf000 },
-       { 0x3186, 0x0000 },
-       { 0x3187, 0xf000 },
-       { 0x3188, 0x0000 },
-       { 0x3189, 0xf000 },
-       { 0x318a, 0x0000 },
-       { 0x318b, 0xf000 },
-       { 0x318c, 0x0000 },
-       { 0x318d, 0xf000 },
-       { 0x318e, 0x0000 },
-       { 0x318f, 0xf000 },
-       { 0x3190, 0x0000 },
-       { 0x3191, 0xf000 },
-       { 0x3192, 0x0000 },
-       { 0x3193, 0xf000 },
-       { 0x3194, 0x0000 },
-       { 0x3195, 0xf000 },
-       { 0x3196, 0x0000 },
-       { 0x3197, 0xf000 },
-       { 0x3198, 0x0000 },
-       { 0x3199, 0xf000 },
-       { 0x319a, 0x0000 },
-       { 0x319b, 0xf000 },
-       { 0x319c, 0x0000 },
-       { 0x319d, 0xf000 },
-       { 0x319e, 0x0000 },
-       { 0x319f, 0xf000 },
-       { 0x31a0, 0x0000 },
-       { 0x31a1, 0xf000 },
-       { 0x31a2, 0x0000 },
-       { 0x31a3, 0xf000 },
-       { 0x31a4, 0x0000 },
-       { 0x31a5, 0xf000 },
-       { 0x31a6, 0x0000 },
-       { 0x31a7, 0xf000 },
-       { 0x31a8, 0x0000 },
-       { 0x31a9, 0xf000 },
-       { 0x31aa, 0x0000 },
-       { 0x31ab, 0xf000 },
-       { 0x31ac, 0x0000 },
-       { 0x31ad, 0xf000 },
-       { 0x31ae, 0x0000 },
-       { 0x31af, 0xf000 },
-       { 0x31b0, 0x0000 },
-       { 0x31b1, 0xf000 },
-       { 0x31b2, 0x0000 },
-       { 0x31b3, 0xf000 },
-       { 0x31b4, 0x0000 },
-       { 0x31b5, 0xf000 },
-       { 0x31b6, 0x0000 },
-       { 0x31b7, 0xf000 },
-       { 0x31b8, 0x0000 },
-       { 0x31b9, 0xf000 },
-       { 0x31ba, 0x0000 },
-       { 0x31bb, 0xf000 },
-       { 0x31bc, 0x0000 },
-       { 0x31bd, 0xf000 },
-       { 0x31be, 0x0000 },
-       { 0x31bf, 0xf000 },
-       { 0x31c0, 0x0000 },
-       { 0x31c1, 0xf000 },
-       { 0x31c2, 0x0000 },
-       { 0x31c3, 0xf000 },
-       { 0x31c4, 0x0000 },
-       { 0x31c5, 0xf000 },
-       { 0x31c6, 0x0000 },
-       { 0x31c7, 0xf000 },
-       { 0x31c8, 0x0000 },
-       { 0x31c9, 0xf000 },
-       { 0x31ca, 0x0000 },
-       { 0x31cb, 0xf000 },
-       { 0x31cc, 0x0000 },
-       { 0x31cd, 0xf000 },
-       { 0x31ce, 0x0000 },
-       { 0x31cf, 0xf000 },
-       { 0x31d0, 0x0000 },
-       { 0x31d1, 0xf000 },
-       { 0x31d2, 0x0000 },
-       { 0x31d3, 0xf000 },
-       { 0x31d4, 0x0000 },
-       { 0x31d5, 0xf000 },
-       { 0x31d6, 0x0000 },
-       { 0x31d7, 0xf000 },
-       { 0x31d8, 0x0000 },
-       { 0x31d9, 0xf000 },
-       { 0x31da, 0x0000 },
-       { 0x31db, 0xf000 },
-       { 0x31dc, 0x0000 },
-       { 0x31dd, 0xf000 },
-       { 0x31de, 0x0000 },
-       { 0x31df, 0xf000 },
-       { 0x31e0, 0x0000 },
-       { 0x31e1, 0xf000 },
-       { 0x31e2, 0x0000 },
-       { 0x31e3, 0xf000 },
-       { 0x31e4, 0x0000 },
-       { 0x31e5, 0xf000 },
-       { 0x31e6, 0x0000 },
-       { 0x31e7, 0xf000 },
-       { 0x31e8, 0x0000 },
-       { 0x31e9, 0xf000 },
-       { 0x31ea, 0x0000 },
-       { 0x31eb, 0xf000 },
-       { 0x31ec, 0x0000 },
-       { 0x31ed, 0xf000 },
-       { 0x31ee, 0x0000 },
-       { 0x31ef, 0xf000 },
-       { 0x31f0, 0x0000 },
-       { 0x31f1, 0xf000 },
-       { 0x31f2, 0x0000 },
-       { 0x31f3, 0xf000 },
-       { 0x31f4, 0x0000 },
-       { 0x31f5, 0xf000 },
-       { 0x31f6, 0x0000 },
-       { 0x31f7, 0xf000 },
-       { 0x31f8, 0x0000 },
-       { 0x31f9, 0xf000 },
-       { 0x31fa, 0x0000 },
-       { 0x31fb, 0xf000 },
-       { 0x31fc, 0x0000 },
-       { 0x31fd, 0xf000 },
-       { 0x31fe, 0x0000 },
-       { 0x31ff, 0xf000 },
-       { 0x024d, 0xff50 },
-       { 0x0252, 0xff50 },
-       { 0x0259, 0x0112 },
-       { 0x025e, 0x0112 },
-       { 0x101, 0x0304 },
        { 0x80, 0x0000 },
 };
 
index 660bbc528862fc67915b79def806cf689d4ac755..4d50da618166e33c03856fe5845e780d785ece46 100644 (file)
@@ -208,7 +208,7 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
        MMC_CAP_CMD23,
 };
 
-static struct dw_mci_drv_data exynos5250_drv_data = {
+static const struct dw_mci_drv_data exynos5250_drv_data = {
        .caps                   = exynos5250_dwmmc_caps,
        .init                   = dw_mci_exynos_priv_init,
        .setup_clock            = dw_mci_exynos_setup_clock,
@@ -220,14 +220,14 @@ static struct dw_mci_drv_data exynos5250_drv_data = {
 
 static const struct of_device_id dw_mci_exynos_match[] = {
        { .compatible = "samsung,exynos5250-dw-mshc",
-                       .data = (void *)&exynos5250_drv_data, },
+                       .data = &exynos5250_drv_data, },
        {},
 };
-MODULE_DEVICE_TABLE(of, dw_mci_pltfm_match);
+MODULE_DEVICE_TABLE(of, dw_mci_exynos_match);
 
 int dw_mci_exynos_probe(struct platform_device *pdev)
 {
-       struct dw_mci_drv_data *drv_data;
+       const struct dw_mci_drv_data *drv_data;
        const struct of_device_id *match;
 
        match = of_match_node(dw_mci_exynos_match, pdev->dev.of_node);
index c960ca7ffbe694fa367ff7ca88c83003b3da59a6..917936bee5d50514103fbe8501a2ee40c0a4db3a 100644 (file)
@@ -24,7 +24,7 @@
 #include "dw_mmc.h"
 
 int dw_mci_pltfm_register(struct platform_device *pdev,
-                               struct dw_mci_drv_data *drv_data)
+                               const struct dw_mci_drv_data *drv_data)
 {
        struct dw_mci *host;
        struct resource *regs;
@@ -50,8 +50,8 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
        if (!host->regs)
                return -ENOMEM;
 
-       if (host->drv_data->init) {
-               ret = host->drv_data->init(host);
+       if (drv_data && drv_data->init) {
+               ret = drv_data->init(host);
                if (ret)
                        return ret;
        }
index 301f24541fc2f20f2b4c65b6cb7a8d05b1f53abe..2ac37b81de4d2774f3f468922284243090f16fd9 100644 (file)
@@ -13,7 +13,7 @@
 #define _DW_MMC_PLTFM_H_
 
 extern int dw_mci_pltfm_register(struct platform_device *pdev,
-                               struct dw_mci_drv_data *drv_data);
+                               const struct dw_mci_drv_data *drv_data);
 extern int __devexit dw_mci_pltfm_remove(struct platform_device *pdev);
 extern const struct dev_pm_ops dw_mci_pltfm_pmops;
 
index c2828f35c3b8812b4de12cb0fd4b75c28fa09bbf..c0667c8af2bd7c78502151e0f6e8a2c3f8e148bc 100644 (file)
@@ -232,6 +232,7 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
 {
        struct mmc_data *data;
        struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct dw_mci_drv_data *drv_data = slot->host->drv_data;
        u32 cmdr;
        cmd->error = -EINPROGRESS;
 
@@ -261,8 +262,8 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
                        cmdr |= SDMMC_CMD_DAT_WR;
        }
 
-       if (slot->host->drv_data->prepare_command)
-               slot->host->drv_data->prepare_command(slot->host, &cmdr);
+       if (drv_data && drv_data->prepare_command)
+               drv_data->prepare_command(slot->host, &cmdr);
 
        return cmdr;
 }
@@ -434,7 +435,7 @@ static int dw_mci_idmac_init(struct dw_mci *host)
        return 0;
 }
 
-static struct dw_mci_dma_ops dw_mci_idmac_ops = {
+static const struct dw_mci_dma_ops dw_mci_idmac_ops = {
        .init = dw_mci_idmac_init,
        .start = dw_mci_idmac_start_dma,
        .stop = dw_mci_idmac_stop_dma,
@@ -772,6 +773,7 @@ static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
+       struct dw_mci_drv_data *drv_data = slot->host->drv_data;
        u32 regs;
 
        /* set default 1 bit mode */
@@ -807,8 +809,8 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                slot->clock = ios->clock;
        }
 
-       if (slot->host->drv_data->set_ios)
-               slot->host->drv_data->set_ios(slot->host, ios);
+       if (drv_data && drv_data->set_ios)
+               drv_data->set_ios(slot->host, ios);
 
        switch (ios->power_mode) {
        case MMC_POWER_UP:
@@ -1815,6 +1817,7 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
 {
        struct mmc_host *mmc;
        struct dw_mci_slot *slot;
+       struct dw_mci_drv_data *drv_data = host->drv_data;
        int ctrl_id, ret;
        u8 bus_width;
 
@@ -1854,8 +1857,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        } else {
                ctrl_id = to_platform_device(host->dev)->id;
        }
-       if (host->drv_data && host->drv_data->caps)
-               mmc->caps |= host->drv_data->caps[ctrl_id];
+       if (drv_data && drv_data->caps)
+               mmc->caps |= drv_data->caps[ctrl_id];
 
        if (host->pdata->caps2)
                mmc->caps2 = host->pdata->caps2;
@@ -1867,10 +1870,10 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
        else
                bus_width = 1;
 
-       if (host->drv_data->setup_bus) {
+       if (drv_data && drv_data->setup_bus) {
                struct device_node *slot_np;
                slot_np = dw_mci_of_find_slot_node(host->dev, slot->id);
-               ret = host->drv_data->setup_bus(host, slot_np, bus_width);
+               ret = drv_data->setup_bus(host, slot_np, bus_width);
                if (ret)
                        goto err_setup_bus;
        }
@@ -1968,7 +1971,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
        /* Determine which DMA interface to use */
 #ifdef CONFIG_MMC_DW_IDMAC
        host->dma_ops = &dw_mci_idmac_ops;
-       dev_info(&host->dev, "Using internal DMA controller.\n");
+       dev_info(host->dev, "Using internal DMA controller.\n");
 #endif
 
        if (!host->dma_ops)
@@ -2035,6 +2038,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
        struct dw_mci_board *pdata;
        struct device *dev = host->dev;
        struct device_node *np = dev->of_node;
+       struct dw_mci_drv_data *drv_data = host->drv_data;
        int idx, ret;
 
        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
@@ -2062,8 +2066,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 
        of_property_read_u32(np, "card-detect-delay", &pdata->detect_delay_ms);
 
-       if (host->drv_data->parse_dt) {
-               ret = host->drv_data->parse_dt(host);
+       if (drv_data && drv_data->parse_dt) {
+               ret = drv_data->parse_dt(host);
                if (ret)
                        return ERR_PTR(ret);
        }
@@ -2080,6 +2084,7 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
 
 int dw_mci_probe(struct dw_mci *host)
 {
+       struct dw_mci_drv_data *drv_data = host->drv_data;
        int width, i, ret = 0;
        u32 fifo_size;
        int init_slots = 0;
@@ -2127,8 +2132,8 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->bus_hz = clk_get_rate(host->ciu_clk);
 
-       if (host->drv_data->setup_clock) {
-               ret = host->drv_data->setup_clock(host);
+       if (drv_data && drv_data->setup_clock) {
+               ret = drv_data->setup_clock(host);
                if (ret) {
                        dev_err(host->dev,
                                "implementation specific clock setup failed\n");
@@ -2228,6 +2233,21 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1;
 
+       /*
+        * Enable interrupts for command done, data over, data empty, card det,
+        * receive ready and error such as transmit, receive timeout, crc error
+        */
+       mci_writel(host, RINTSTS, 0xFFFFFFFF);
+       mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+                  SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+       mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
+
+       dev_info(host->dev, "DW MMC controller at irq %d, "
+                "%d bit host data width, "
+                "%u deep fifo\n",
+                host->irq, width, fifo_size);
+
        /* We need at least one slot to succeed */
        for (i = 0; i < host->num_slots; i++) {
                ret = dw_mci_init_slot(host, i);
@@ -2257,20 +2277,6 @@ int dw_mci_probe(struct dw_mci *host)
        else
                host->data_offset = DATA_240A_OFFSET;
 
-       /*
-        * Enable interrupts for command done, data over, data empty, card det,
-        * receive ready and error such as transmit, receive timeout, crc error
-        */
-       mci_writel(host, RINTSTS, 0xFFFFFFFF);
-       mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
-                  SDMMC_INT_TXDR | SDMMC_INT_RXDR |
-                  DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
-       mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
-
-       dev_info(host->dev, "DW MMC controller at irq %d, "
-                "%d bit host data width, "
-                "%u deep fifo\n",
-                host->irq, width, fifo_size);
        if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
                dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
 
index 565c2e4fac75cecd8890ec2d9885ffb50cc23060..6290b7f1ccfec2d56f31675663923e057a1570c8 100644 (file)
@@ -1134,4 +1134,4 @@ module_platform_driver(mxcmci_driver);
 MODULE_DESCRIPTION("i.MX Multimedia Card Interface Driver");
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:imx-mmc");
+MODULE_ALIAS("platform:mxc-mmc");
index 54bfd0cc106b92280cd75818310d81aa56c48ccb..fedd258cc4ea2effe547f1fc15729f60277d8c33 100644 (file)
@@ -178,7 +178,8 @@ struct omap_hsmmc_host {
 
 static int omap_hsmmc_card_detect(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes card detect signal is active-low */
        return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
@@ -186,7 +187,8 @@ static int omap_hsmmc_card_detect(struct device *dev, int slot)
 
 static int omap_hsmmc_get_wp(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes write protect signal is active-high */
        return gpio_get_value_cansleep(mmc->slots[0].gpio_wp);
@@ -194,7 +196,8 @@ static int omap_hsmmc_get_wp(struct device *dev, int slot)
 
 static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        /* NOTE: assumes card detect signal is active-low */
        return !gpio_get_value_cansleep(mmc->slots[0].switch_pin);
@@ -204,7 +207,8 @@ static int omap_hsmmc_get_cover_state(struct device *dev, int slot)
 
 static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        disable_irq(mmc->slots[0].card_detect_irq);
        return 0;
@@ -212,7 +216,8 @@ static int omap_hsmmc_suspend_cdirq(struct device *dev, int slot)
 
 static int omap_hsmmc_resume_cdirq(struct device *dev, int slot)
 {
-       struct omap_mmc_platform_data *mmc = dev->platform_data;
+       struct omap_hsmmc_host *host = dev_get_drvdata(dev);
+       struct omap_mmc_platform_data *mmc = host->pdata;
 
        enable_irq(mmc->slots[0].card_detect_irq);
        return 0;
@@ -2009,9 +2014,9 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
                clk_put(host->dbclk);
        }
 
-       mmc_free_host(host->mmc);
+       omap_hsmmc_gpio_free(host->pdata);
        iounmap(host->base);
-       omap_hsmmc_gpio_free(pdev->dev.platform_data);
+       mmc_free_host(host->mmc);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (res)
index 90140eb03e36a2766ffc40470271a0e63be34845..8fd50a211037126df4a4beea26dd6fc3aaa71c94 100644 (file)
@@ -19,6 +19,7 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
@@ -84,30 +85,32 @@ static int __devinit sdhci_dove_probe(struct platform_device *pdev)
        struct sdhci_dove_priv *priv;
        int ret;
 
-       ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
-       if (ret)
-               goto sdhci_dove_register_fail;
-
        priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),
                            GFP_KERNEL);
        if (!priv) {
                dev_err(&pdev->dev, "unable to allocate private data");
-               ret = -ENOMEM;
-               goto sdhci_dove_allocate_fail;
+               return -ENOMEM;
        }
 
+       priv->clk = clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(priv->clk))
+               clk_prepare_enable(priv->clk);
+
+       ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+       if (ret)
+               goto sdhci_dove_register_fail;
+
        host = platform_get_drvdata(pdev);
        pltfm_host = sdhci_priv(host);
        pltfm_host->priv = priv;
 
-       priv->clk = clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(priv->clk))
-               clk_prepare_enable(priv->clk);
        return 0;
 
-sdhci_dove_allocate_fail:
-       sdhci_pltfm_unregister(pdev);
 sdhci_dove_register_fail:
+       if (!IS_ERR(priv->clk)) {
+               clk_disable_unprepare(priv->clk);
+               clk_put(priv->clk);
+       }
        return ret;
 }
 
@@ -117,14 +120,13 @@ static int __devexit sdhci_dove_remove(struct platform_device *pdev)
        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
        struct sdhci_dove_priv *priv = pltfm_host->priv;
 
-       if (priv->clk) {
-               if (!IS_ERR(priv->clk)) {
-                       clk_disable_unprepare(priv->clk);
-                       clk_put(priv->clk);
-               }
-               devm_kfree(&pdev->dev, priv->clk);
+       sdhci_pltfm_unregister(pdev);
+
+       if (!IS_ERR(priv->clk)) {
+               clk_disable_unprepare(priv->clk);
+               clk_put(priv->clk);
        }
-       return sdhci_pltfm_unregister(pdev);
+       return 0;
 }
 
 static const struct of_device_id sdhci_dove_of_match_table[] __devinitdata = {
index ae5fcbfa1eef5986ec832616ed1ad350106e64ef..63d219f57caebcd3a4cd0216ec17aca2500cb257 100644 (file)
@@ -169,6 +169,16 @@ static void esdhc_of_resume(struct sdhci_host *host)
 }
 #endif
 
+static void esdhc_of_platform_init(struct sdhci_host *host)
+{
+       u32 vvn;
+
+       vvn = in_be32(host->ioaddr + SDHCI_SLOT_INT_STATUS);
+       vvn = (vvn & SDHCI_VENDOR_VER_MASK) >> SDHCI_VENDOR_VER_SHIFT;
+       if (vvn == VENDOR_V_22)
+               host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+}
+
 static struct sdhci_ops sdhci_esdhc_ops = {
        .read_l = esdhc_readl,
        .read_w = esdhc_readw,
@@ -180,6 +190,7 @@ static struct sdhci_ops sdhci_esdhc_ops = {
        .enable_dma = esdhc_of_enable_dma,
        .get_max_clock = esdhc_of_get_max_clock,
        .get_min_clock = esdhc_of_get_min_clock,
+       .platform_init = esdhc_of_platform_init,
 #ifdef CONFIG_PM
        .platform_suspend = esdhc_of_suspend,
        .platform_resume = esdhc_of_resume,
index 4bb74b042a06483cb3cea750dac26f56c4ab68cd..04936f353ced53461a35545b22add0460c582d3a 100644 (file)
@@ -1196,7 +1196,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
                return ERR_PTR(-ENODEV);
        }
 
-       if (pci_resource_len(pdev, bar) != 0x100) {
+       if (pci_resource_len(pdev, bar) < 0x100) {
                dev_err(&pdev->dev, "Invalid iomem size. You may "
                        "experience problems.\n");
        }
index 65551a9709ccc86e893be96dfead3fe2919677e3..27164457f861dce37da3e12b00b399bf81b00e1e 100644 (file)
@@ -150,6 +150,13 @@ struct sdhci_host *sdhci_pltfm_init(struct platform_device *pdev,
                goto err_remap;
        }
 
+       /*
+        * Some platforms need to probe the controller to be able to
+        * determine which caps should be used.
+        */
+       if (host->ops && host->ops->platform_init)
+               host->ops->platform_init(host);
+
        platform_set_drvdata(pdev, host);
 
        return host;
index 2903949594c6a1d3168d5a021c82ebec795ed138..a54dd5d7a5f94b1b3e550e799ee95999c5e54df8 100644 (file)
@@ -211,8 +211,8 @@ static void sdhci_s3c_set_clock(struct sdhci_host *host, unsigned int clock)
        if (ourhost->cur_clk != best_src) {
                struct clk *clk = ourhost->clk_bus[best_src];
 
-               clk_enable(clk);
-               clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
+               clk_prepare_enable(clk);
+               clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
 
                /* turn clock off to card before changing clock source */
                writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
@@ -607,7 +607,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
        /* enable the local io clock and keep it running for the moment. */
-       clk_enable(sc->clk_io);
+       clk_prepare_enable(sc->clk_io);
 
        for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                struct clk *clk;
@@ -638,7 +638,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
 #ifndef CONFIG_PM_RUNTIME
-       clk_enable(sc->clk_bus[sc->cur_clk]);
+       clk_prepare_enable(sc->clk_bus[sc->cur_clk]);
 #endif
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -747,13 +747,14 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
                sdhci_s3c_setup_card_detect_gpio(sc);
 
 #ifdef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_io);
+       if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
+               clk_disable_unprepare(sc->clk_io);
 #endif
        return 0;
 
  err_req_regs:
 #ifndef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_bus[sc->cur_clk]);
+       clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
 #endif
        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
@@ -762,7 +763,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
        }
 
  err_no_busclks:
-       clk_disable(sc->clk_io);
+       clk_disable_unprepare(sc->clk_io);
        clk_put(sc->clk_io);
 
  err_io_clk:
@@ -794,7 +795,8 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
                gpio_free(sc->ext_cd_gpio);
 
 #ifdef CONFIG_PM_RUNTIME
-       clk_enable(sc->clk_io);
+       if (pdata->cd_type != S3C_SDHCI_CD_INTERNAL)
+               clk_prepare_enable(sc->clk_io);
 #endif
        sdhci_remove_host(host, 1);
 
@@ -802,14 +804,14 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
        pm_runtime_disable(&pdev->dev);
 
 #ifndef CONFIG_PM_RUNTIME
-       clk_disable(sc->clk_bus[sc->cur_clk]);
+       clk_disable_unprepare(sc->clk_bus[sc->cur_clk]);
 #endif
        for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
                if (sc->clk_bus[ptr]) {
                        clk_put(sc->clk_bus[ptr]);
                }
        }
-       clk_disable(sc->clk_io);
+       clk_disable_unprepare(sc->clk_io);
        clk_put(sc->clk_io);
 
        if (pdev->dev.of_node) {
@@ -849,8 +851,8 @@ static int sdhci_s3c_runtime_suspend(struct device *dev)
 
        ret = sdhci_runtime_suspend_host(host);
 
-       clk_disable(ourhost->clk_bus[ourhost->cur_clk]);
-       clk_disable(busclk);
+       clk_disable_unprepare(ourhost->clk_bus[ourhost->cur_clk]);
+       clk_disable_unprepare(busclk);
        return ret;
 }
 
@@ -861,8 +863,8 @@ static int sdhci_s3c_runtime_resume(struct device *dev)
        struct clk *busclk = ourhost->clk_io;
        int ret;
 
-       clk_enable(busclk);
-       clk_enable(ourhost->clk_bus[ourhost->cur_clk]);
+       clk_prepare_enable(busclk);
+       clk_prepare_enable(ourhost->clk_bus[ourhost->cur_clk]);
        ret = sdhci_runtime_resume_host(host);
        return ret;
 }
index 7922adb4238625c1b4c9e1d489dea04a3d0e2353..c7851c0aabce52226d118d50bbe95fe61b4094c2 100644 (file)
@@ -1315,16 +1315,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
                 */
                if ((host->flags & SDHCI_NEEDS_RETUNING) &&
                    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
-                       /* eMMC uses cmd21 while sd and sdio use cmd19 */
-                       tuning_opcode = mmc->card->type == MMC_TYPE_MMC ?
-                               MMC_SEND_TUNING_BLOCK_HS200 :
-                               MMC_SEND_TUNING_BLOCK;
-                       spin_unlock_irqrestore(&host->lock, flags);
-                       sdhci_execute_tuning(mmc, tuning_opcode);
-                       spin_lock_irqsave(&host->lock, flags);
-
-                       /* Restore original mmc_request structure */
-                       host->mrq = mrq;
+                       if (mmc->card) {
+                               /* eMMC uses cmd21 but sd and sdio use cmd19 */
+                               tuning_opcode =
+                                       mmc->card->type == MMC_TYPE_MMC ?
+                                       MMC_SEND_TUNING_BLOCK_HS200 :
+                                       MMC_SEND_TUNING_BLOCK;
+                               spin_unlock_irqrestore(&host->lock, flags);
+                               sdhci_execute_tuning(mmc, tuning_opcode);
+                               spin_lock_irqsave(&host->lock, flags);
+
+                               /* Restore original mmc_request structure */
+                               host->mrq = mrq;
+                       }
                }
 
                if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23))
@@ -2837,6 +2840,9 @@ int sdhci_add_host(struct sdhci_host *host)
        if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
                mmc->caps |= MMC_CAP_4_BIT_DATA;
 
+       if (host->quirks2 & SDHCI_QUIRK2_HOST_NO_CMD23)
+               mmc->caps &= ~MMC_CAP_CMD23;
+
        if (caps[0] & SDHCI_CAN_DO_HISPD)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
@@ -2846,9 +2852,12 @@ int sdhci_add_host(struct sdhci_host *host)
 
        /* If vqmmc regulator and no 1.8V signalling, then there's no UHS */
        host->vqmmc = regulator_get(mmc_dev(mmc), "vqmmc");
-       if (IS_ERR(host->vqmmc)) {
-               pr_info("%s: no vqmmc regulator found\n", mmc_hostname(mmc));
-               host->vqmmc = NULL;
+       if (IS_ERR_OR_NULL(host->vqmmc)) {
+               if (PTR_ERR(host->vqmmc) < 0) {
+                       pr_info("%s: no vqmmc regulator found\n",
+                               mmc_hostname(mmc));
+                       host->vqmmc = NULL;
+               }
        }
        else if (regulator_is_supported_voltage(host->vqmmc, 1800000, 1800000))
                regulator_enable(host->vqmmc);
@@ -2904,9 +2913,12 @@ int sdhci_add_host(struct sdhci_host *host)
        ocr_avail = 0;
 
        host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
-       if (IS_ERR(host->vmmc)) {
-               pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
-               host->vmmc = NULL;
+       if (IS_ERR_OR_NULL(host->vmmc)) {
+               if (PTR_ERR(host->vmmc) < 0) {
+                       pr_info("%s: no vmmc regulator found\n",
+                               mmc_hostname(mmc));
+                       host->vmmc = NULL;
+               }
        } else
                regulator_enable(host->vmmc);
 
index 97653ea8942ba82393f47b6291942e28c2435204..71a4a7ed46c5095653ce43e90ffd6754815f98da 100644 (file)
@@ -278,6 +278,7 @@ struct sdhci_ops {
        void    (*hw_reset)(struct sdhci_host *host);
        void    (*platform_suspend)(struct sdhci_host *host);
        void    (*platform_resume)(struct sdhci_host *host);
+       void    (*platform_init)(struct sdhci_host *host);
 };
 
 #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
index 11d2bc3b51d578a357fd9b857084db1a89a91741..d25bc97dc5c60063bb609b22973e41790ced9762 100644 (file)
@@ -1466,9 +1466,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
+       clk_disable(host->hclk);
        mmc_free_host(host->mmc);
        pm_runtime_put_sync(&pdev->dev);
-       clk_disable(host->hclk);
        pm_runtime_disable(&pdev->dev);
 
        return 0;
index 8f52fc858e48bec08f900963996c0d37bd4601cb..5a5cd2ace4a6b05126e642e06d04950f52108ab8 100644 (file)
@@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
 
        if (*(szlength) != '+') {
                devlength = simple_strtoul(szlength, &buffer, 0);
-               devlength = handle_unit(devlength, buffer) - devstart;
+               devlength = handle_unit(devlength, buffer);
                if (devlength < devstart)
                        goto err_out;
 
index 374c46dff7dd65d3aea7eef69b22a332d727ad0f..ec794a72975dd886205f2460e2eaba08089a8daf 100644 (file)
@@ -1077,7 +1077,8 @@ EXPORT_SYMBOL_GPL(mtd_writev);
  * until the request succeeds or until the allocation size falls below
  * the system page size. This attempts to make sure it does not adversely
  * impact system performance, so when allocating more than one page, we
- * ask the memory allocator to avoid re-trying.
+ * ask the memory allocator to avoid re-trying, swapping, writing back
+ * or performing I/O.
  *
  * Note, this function also makes sure that the allocated buffer is aligned to
  * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value.
@@ -1091,7 +1092,8 @@ EXPORT_SYMBOL_GPL(mtd_writev);
  */
 void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
 {
-       gfp_t flags = __GFP_NOWARN | __GFP_WAIT | __GFP_NORETRY;
+       gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
+                      __GFP_NORETRY | __GFP_NO_KSWAPD;
        size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
        void *kbuf;
 
index ec6841d8e956f74f5224363392632900a39e1f8e..1a03b7f673ce0d59c8613144fd51d1ffb299e4fd 100644 (file)
@@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
        /*
         * Field definitions are in the following datasheets:
         * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-        * New style   (6 byte ID): Samsung K9GAG08U0F (p.44)
+        * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
         * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
         *
-        * Check for ID length, cell type, and Hynix/Samsung ID to decide what
-        * to do.
+        * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
+        * ID to decide what to do.
         */
-       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) {
+       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
+                       (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+                       id_data[5] != 0x00) {
                /* Calc pagesize */
                mtd->writesize = 2048 << (extid & 0x03);
                extid >>= 2;
index 64be8f0848b075cdccb647309ff88d12b3fa547d..d9127e2ed808eab6ddfe5835c68cfa88ef490cf0 100644 (file)
@@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
        nr_parts = plen / sizeof(part[0]);
 
        *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
-       if (!pparts)
+       if (!*pparts)
                return -ENOMEM;
 
        names = of_get_property(dp, "partition-names", &plen);
index 7153e0d27101e3eed06ac17addcdbd4734c7ccc3..b3f41f200622b39f5ef7d46ab6b772ed2eb9e97e 100644 (file)
@@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int
  * flexonenand_set_boundary    - Writes the SLC boundary
  * @param mtd                  - mtd info structure
  */
-int flexonenand_set_boundary(struct mtd_info *mtd, int die,
+static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
                                    int boundary, int lock)
 {
        struct onenand_chip *this = mtd->priv;
index d427493997b67ebd6e3856724eff13b4b1eb5a4b..cbc44f53755a81b24960489d6fd0de14e2ba54f3 100644 (file)
@@ -61,7 +61,7 @@ module_param(clockp, int, 0);
 module_param(clockm, int, 0);
 MODULE_LICENSE("GPL");
 
-static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct net_device *dev;
        struct arcnet_local *lp;
@@ -135,7 +135,7 @@ out_dev:
        return err;
 }
 
-static void __devexit com20020pci_remove(struct pci_dev *pdev)
+static void com20020pci_remove(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        unregister_netdev(dev);
@@ -178,7 +178,7 @@ static struct pci_driver com20020pci_driver = {
        .name           = "com20020",
        .id_table       = com20020pci_id_table,
        .probe          = com20020pci_probe,
-       .remove         = __devexit_p(com20020pci_remove),
+       .remove         = com20020pci_remove,
 };
 
 static int __init com20020pci_init(void)
index e15cc11edbbe1efc31cfe38cc73f74cd95129f88..7c9d136e74bef3f725264aeef91fae32d99da168 100644 (file)
@@ -84,6 +84,10 @@ static inline struct arp_pkt *arp_pkt(const struct sk_buff *skb)
 
 /* Forward declaration */
 static void alb_send_learning_packets(struct slave *slave, u8 mac_addr[]);
+static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp);
+static void rlb_src_unlink(struct bonding *bond, u32 index);
+static void rlb_src_link(struct bonding *bond, u32 ip_src_hash,
+                        u32 ip_dst_hash);
 
 static inline u8 _simple_hash(const u8 *hash_start, int hash_size)
 {
@@ -354,6 +358,18 @@ static int rlb_arp_recv(const struct sk_buff *skb, struct bonding *bond,
        if (!arp)
                goto out;
 
+       /* We received an ARP from arp->ip_src.
+        * We might have used this IP address previously (on the bonding host
+        * itself or on a system that is bridged together with the bond).
+        * However, if arp->mac_src is different than what is stored in
+        * rx_hashtbl, some other host is now using the IP and we must prevent
+        * sending out client updates with this IP address and the old MAC
+        * address.
+        * Clean up all hash table entries that have this address as ip_src but
+        * have a different mac_src.
+        */
+       rlb_purge_src_ip(bond, arp);
+
        if (arp->op_code == htons(ARPOP_REPLY)) {
                /* update rx hash table for this ARP */
                rlb_update_entry_from_arp(bond, arp);
@@ -432,9 +448,9 @@ static void rlb_clear_slave(struct bonding *bond, struct slave *slave)
        _lock_rx_hashtbl_bh(bond);
 
        rx_hash_table = bond_info->rx_hashtbl;
-       index = bond_info->rx_hashtbl_head;
+       index = bond_info->rx_hashtbl_used_head;
        for (; index != RLB_NULL_INDEX; index = next_index) {
-               next_index = rx_hash_table[index].next;
+               next_index = rx_hash_table[index].used_next;
                if (rx_hash_table[index].slave == slave) {
                        struct slave *assigned_slave = rlb_next_rx_slave(bond);
 
@@ -519,8 +535,9 @@ static void rlb_update_rx_clients(struct bonding *bond)
 
        _lock_rx_hashtbl_bh(bond);
 
-       hash_index = bond_info->rx_hashtbl_head;
-       for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+       hash_index = bond_info->rx_hashtbl_used_head;
+       for (; hash_index != RLB_NULL_INDEX;
+            hash_index = client_info->used_next) {
                client_info = &(bond_info->rx_hashtbl[hash_index]);
                if (client_info->ntt) {
                        rlb_update_client(client_info);
@@ -548,8 +565,9 @@ static void rlb_req_update_slave_clients(struct bonding *bond, struct slave *sla
 
        _lock_rx_hashtbl_bh(bond);
 
-       hash_index = bond_info->rx_hashtbl_head;
-       for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+       hash_index = bond_info->rx_hashtbl_used_head;
+       for (; hash_index != RLB_NULL_INDEX;
+            hash_index = client_info->used_next) {
                client_info = &(bond_info->rx_hashtbl[hash_index]);
 
                if ((client_info->slave == slave) &&
@@ -578,8 +596,9 @@ static void rlb_req_update_subnet_clients(struct bonding *bond, __be32 src_ip)
 
        _lock_rx_hashtbl(bond);
 
-       hash_index = bond_info->rx_hashtbl_head;
-       for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+       hash_index = bond_info->rx_hashtbl_used_head;
+       for (; hash_index != RLB_NULL_INDEX;
+            hash_index = client_info->used_next) {
                client_info = &(bond_info->rx_hashtbl[hash_index]);
 
                if (!client_info->slave) {
@@ -625,6 +644,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
                                /* update mac address from arp */
                                memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
                        }
+                       memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
 
                        assigned_slave = client_info->slave;
                        if (assigned_slave) {
@@ -647,6 +667,17 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
        assigned_slave = rlb_next_rx_slave(bond);
 
        if (assigned_slave) {
+               if (!(client_info->assigned &&
+                     client_info->ip_src == arp->ip_src)) {
+                       /* ip_src is going to be updated,
+                        * fix the src hash list
+                        */
+                       u32 hash_src = _simple_hash((u8 *)&arp->ip_src,
+                                                   sizeof(arp->ip_src));
+                       rlb_src_unlink(bond, hash_index);
+                       rlb_src_link(bond, hash_src, hash_index);
+               }
+
                client_info->ip_src = arp->ip_src;
                client_info->ip_dst = arp->ip_dst;
                /* arp->mac_dst is broadcast for arp reqeusts.
@@ -654,6 +685,7 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
                 * upon receiving an arp reply.
                 */
                memcpy(client_info->mac_dst, arp->mac_dst, ETH_ALEN);
+               memcpy(client_info->mac_src, arp->mac_src, ETH_ALEN);
                client_info->slave = assigned_slave;
 
                if (!ether_addr_equal_64bits(client_info->mac_dst, mac_bcast)) {
@@ -669,11 +701,11 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
                }
 
                if (!client_info->assigned) {
-                       u32 prev_tbl_head = bond_info->rx_hashtbl_head;
-                       bond_info->rx_hashtbl_head = hash_index;
-                       client_info->next = prev_tbl_head;
+                       u32 prev_tbl_head = bond_info->rx_hashtbl_used_head;
+                       bond_info->rx_hashtbl_used_head = hash_index;
+                       client_info->used_next = prev_tbl_head;
                        if (prev_tbl_head != RLB_NULL_INDEX) {
-                               bond_info->rx_hashtbl[prev_tbl_head].prev =
+                               bond_info->rx_hashtbl[prev_tbl_head].used_prev =
                                        hash_index;
                        }
                        client_info->assigned = 1;
@@ -694,6 +726,12 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
        struct arp_pkt *arp = arp_pkt(skb);
        struct slave *tx_slave = NULL;
 
+       /* Don't modify or load balance ARPs that do not originate locally
+        * (e.g.,arrive via a bridge).
+        */
+       if (!bond_slave_has_mac(bond, arp->mac_src))
+               return NULL;
+
        if (arp->op_code == htons(ARPOP_REPLY)) {
                /* the arp must be sent on the selected
                * rx channel
@@ -740,8 +778,9 @@ static void rlb_rebalance(struct bonding *bond)
        _lock_rx_hashtbl_bh(bond);
 
        ntt = 0;
-       hash_index = bond_info->rx_hashtbl_head;
-       for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+       hash_index = bond_info->rx_hashtbl_used_head;
+       for (; hash_index != RLB_NULL_INDEX;
+            hash_index = client_info->used_next) {
                client_info = &(bond_info->rx_hashtbl[hash_index]);
                assigned_slave = rlb_next_rx_slave(bond);
                if (assigned_slave && (client_info->slave != assigned_slave)) {
@@ -759,11 +798,113 @@ static void rlb_rebalance(struct bonding *bond)
 }
 
 /* Caller must hold rx_hashtbl lock */
+static void rlb_init_table_entry_dst(struct rlb_client_info *entry)
+{
+       entry->used_next = RLB_NULL_INDEX;
+       entry->used_prev = RLB_NULL_INDEX;
+       entry->assigned = 0;
+       entry->slave = NULL;
+       entry->tag = 0;
+}
+static void rlb_init_table_entry_src(struct rlb_client_info *entry)
+{
+       entry->src_first = RLB_NULL_INDEX;
+       entry->src_prev = RLB_NULL_INDEX;
+       entry->src_next = RLB_NULL_INDEX;
+}
+
 static void rlb_init_table_entry(struct rlb_client_info *entry)
 {
        memset(entry, 0, sizeof(struct rlb_client_info));
-       entry->next = RLB_NULL_INDEX;
-       entry->prev = RLB_NULL_INDEX;
+       rlb_init_table_entry_dst(entry);
+       rlb_init_table_entry_src(entry);
+}
+
+static void rlb_delete_table_entry_dst(struct bonding *bond, u32 index)
+{
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+       u32 next_index = bond_info->rx_hashtbl[index].used_next;
+       u32 prev_index = bond_info->rx_hashtbl[index].used_prev;
+
+       if (index == bond_info->rx_hashtbl_used_head)
+               bond_info->rx_hashtbl_used_head = next_index;
+       if (prev_index != RLB_NULL_INDEX)
+               bond_info->rx_hashtbl[prev_index].used_next = next_index;
+       if (next_index != RLB_NULL_INDEX)
+               bond_info->rx_hashtbl[next_index].used_prev = prev_index;
+}
+
+/* unlink a rlb hash table entry from the src list */
+static void rlb_src_unlink(struct bonding *bond, u32 index)
+{
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+       u32 next_index = bond_info->rx_hashtbl[index].src_next;
+       u32 prev_index = bond_info->rx_hashtbl[index].src_prev;
+
+       bond_info->rx_hashtbl[index].src_next = RLB_NULL_INDEX;
+       bond_info->rx_hashtbl[index].src_prev = RLB_NULL_INDEX;
+
+       if (next_index != RLB_NULL_INDEX)
+               bond_info->rx_hashtbl[next_index].src_prev = prev_index;
+
+       if (prev_index == RLB_NULL_INDEX)
+               return;
+
+       /* is prev_index pointing to the head of this list? */
+       if (bond_info->rx_hashtbl[prev_index].src_first == index)
+               bond_info->rx_hashtbl[prev_index].src_first = next_index;
+       else
+               bond_info->rx_hashtbl[prev_index].src_next = next_index;
+
+}
+
+static void rlb_delete_table_entry(struct bonding *bond, u32 index)
+{
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+       struct rlb_client_info *entry = &(bond_info->rx_hashtbl[index]);
+
+       rlb_delete_table_entry_dst(bond, index);
+       rlb_init_table_entry_dst(entry);
+
+       rlb_src_unlink(bond, index);
+}
+
+/* add the rx_hashtbl[ip_dst_hash] entry to the list
+ * of entries with identical ip_src_hash
+ */
+static void rlb_src_link(struct bonding *bond, u32 ip_src_hash, u32 ip_dst_hash)
+{
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+       u32 next;
+
+       bond_info->rx_hashtbl[ip_dst_hash].src_prev = ip_src_hash;
+       next = bond_info->rx_hashtbl[ip_src_hash].src_first;
+       bond_info->rx_hashtbl[ip_dst_hash].src_next = next;
+       if (next != RLB_NULL_INDEX)
+               bond_info->rx_hashtbl[next].src_prev = ip_dst_hash;
+       bond_info->rx_hashtbl[ip_src_hash].src_first = ip_dst_hash;
+}
+
+/* deletes all rx_hashtbl entries with  arp->ip_src if their mac_src does
+ * not match arp->mac_src */
+static void rlb_purge_src_ip(struct bonding *bond, struct arp_pkt *arp)
+{
+       struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+       u32 ip_src_hash = _simple_hash((u8*)&(arp->ip_src), sizeof(arp->ip_src));
+       u32 index;
+
+       _lock_rx_hashtbl_bh(bond);
+
+       index = bond_info->rx_hashtbl[ip_src_hash].src_first;
+       while (index != RLB_NULL_INDEX) {
+               struct rlb_client_info *entry = &(bond_info->rx_hashtbl[index]);
+               u32 next_index = entry->src_next;
+               if (entry->ip_src == arp->ip_src &&
+                   !ether_addr_equal_64bits(arp->mac_src, entry->mac_src))
+                               rlb_delete_table_entry(bond, index);
+               index = next_index;
+       }
+       _unlock_rx_hashtbl_bh(bond);
 }
 
 static int rlb_initialize(struct bonding *bond)
@@ -781,7 +922,7 @@ static int rlb_initialize(struct bonding *bond)
 
        bond_info->rx_hashtbl = new_hashtbl;
 
-       bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+       bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
 
        for (i = 0; i < RLB_HASH_TABLE_SIZE; i++) {
                rlb_init_table_entry(bond_info->rx_hashtbl + i);
@@ -803,7 +944,7 @@ static void rlb_deinitialize(struct bonding *bond)
 
        kfree(bond_info->rx_hashtbl);
        bond_info->rx_hashtbl = NULL;
-       bond_info->rx_hashtbl_head = RLB_NULL_INDEX;
+       bond_info->rx_hashtbl_used_head = RLB_NULL_INDEX;
 
        _unlock_rx_hashtbl_bh(bond);
 }
@@ -815,25 +956,13 @@ static void rlb_clear_vlan(struct bonding *bond, unsigned short vlan_id)
 
        _lock_rx_hashtbl_bh(bond);
 
-       curr_index = bond_info->rx_hashtbl_head;
+       curr_index = bond_info->rx_hashtbl_used_head;
        while (curr_index != RLB_NULL_INDEX) {
                struct rlb_client_info *curr = &(bond_info->rx_hashtbl[curr_index]);
-               u32 next_index = bond_info->rx_hashtbl[curr_index].next;
-               u32 prev_index = bond_info->rx_hashtbl[curr_index].prev;
-
-               if (curr->tag && (curr->vlan_id == vlan_id)) {
-                       if (curr_index == bond_info->rx_hashtbl_head) {
-                               bond_info->rx_hashtbl_head = next_index;
-                       }
-                       if (prev_index != RLB_NULL_INDEX) {
-                               bond_info->rx_hashtbl[prev_index].next = next_index;
-                       }
-                       if (next_index != RLB_NULL_INDEX) {
-                               bond_info->rx_hashtbl[next_index].prev = prev_index;
-                       }
+               u32 next_index = bond_info->rx_hashtbl[curr_index].used_next;
 
-                       rlb_init_table_entry(curr);
-               }
+               if (curr->tag && (curr->vlan_id == vlan_id))
+                       rlb_delete_table_entry(bond, curr_index);
 
                curr_index = next_index;
        }
index 90f140a2d197f4807a75802f18671cbb1521eaba..e7a5b8b37ea3f394a4fbf6f78b47173976da0cd4 100644 (file)
@@ -94,15 +94,35 @@ struct tlb_client_info {
 
 /* -------------------------------------------------------------------------
  * struct rlb_client_info contains all info related to a specific rx client
- * connection. This is the Clients Hash Table entry struct
+ * connection. This is the Clients Hash Table entry struct.
+ * Note that this is not a proper hash table; if a new client's IP address
+ * hash collides with an existing client entry, the old entry is replaced.
+ *
+ * There is a linked list (linked by the used_next and used_prev members)
+ * linking all the used entries of the hash table. This allows updating
+ * all the clients without walking over all the unused elements of the table.
+ *
+ * There are also linked lists of entries with identical hash(ip_src). These
+ * allow cleaning up the table from ip_src<->mac_src associations that have
+ * become outdated and would cause sending out invalid ARP updates to the
+ * network. These are linked by the (src_next and src_prev members).
  * -------------------------------------------------------------------------
  */
 struct rlb_client_info {
        __be32 ip_src;          /* the server IP address */
        __be32 ip_dst;          /* the client IP address */
+       u8  mac_src[ETH_ALEN];  /* the server MAC address */
        u8  mac_dst[ETH_ALEN];  /* the client MAC address */
-       u32 next;               /* The next Hash table entry index */
-       u32 prev;               /* The previous Hash table entry index */
+
+       /* list of used hash table entries, starting at rx_hashtbl_used_head */
+       u32 used_next;
+       u32 used_prev;
+
+       /* ip_src based hashing */
+       u32 src_next;   /* next entry with same hash(ip_src) */
+       u32 src_prev;   /* prev entry with same hash(ip_src) */
+       u32 src_first;  /* first entry with hash(ip_src) == this entry's index */
+
        u8  assigned;           /* checking whether this entry is assigned */
        u8  ntt;                /* flag - need to transmit client info */
        struct slave *slave;    /* the slave assigned to this client */
@@ -131,7 +151,7 @@ struct alb_bond_info {
        int rlb_enabled;
        struct rlb_client_info  *rx_hashtbl;    /* Receive hash table */
        spinlock_t              rx_hashtbl_lock;
-       u32                     rx_hashtbl_head;
+       u32                     rx_hashtbl_used_head;
        u8                      rx_ntt; /* flag - need to transmit
                                         * to all rx clients
                                         */
index 2cf084eb9d524d995c4e3bf72a6d327e5f1ea9cb..5fc4c2351478b21f98ba8ed2d2c329275e30ed39 100644 (file)
@@ -31,8 +31,9 @@ static int bond_debug_rlb_hash_show(struct seq_file *m, void *v)
 
        spin_lock_bh(&(BOND_ALB_INFO(bond).rx_hashtbl_lock));
 
-       hash_index = bond_info->rx_hashtbl_head;
-       for (; hash_index != RLB_NULL_INDEX; hash_index = client_info->next) {
+       hash_index = bond_info->rx_hashtbl_used_head;
+       for (; hash_index != RLB_NULL_INDEX;
+            hash_index = client_info->used_next) {
                client_info = &(bond_info->rx_hashtbl[hash_index]);
                seq_printf(m, "%-15pI4 %-15pI4 %-17pM %s\n",
                        &client_info->ip_src,
index b721902bb6b4ab785497fb345cd76f683a11f78b..800a8977d0adebe14350795a6027df470dbb1355 100644 (file)
@@ -615,15 +615,9 @@ static int bond_check_dev_link(struct bonding *bond,
                return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
 
        /* Try to get link status using Ethtool first. */
-       if (slave_dev->ethtool_ops) {
-               if (slave_dev->ethtool_ops->get_link) {
-                       u32 link;
-
-                       link = slave_dev->ethtool_ops->get_link(slave_dev);
-
-                       return link ? BMSR_LSTATUS : 0;
-               }
-       }
+       if (slave_dev->ethtool_ops->get_link)
+               return slave_dev->ethtool_ops->get_link(slave_dev) ?
+                       BMSR_LSTATUS : 0;
 
        /* Ethtool can't be used, fallback to MII ioctls. */
        ioctl = slave_ops->ndo_do_ioctl;
@@ -1379,6 +1373,8 @@ static void bond_compute_features(struct bonding *bond)
        struct net_device *bond_dev = bond->dev;
        netdev_features_t vlan_features = BOND_VLAN_FEATURES;
        unsigned short max_hard_header_len = ETH_HLEN;
+       unsigned int gso_max_size = GSO_MAX_SIZE;
+       u16 gso_max_segs = GSO_MAX_SEGS;
        int i;
        unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
 
@@ -1394,11 +1390,16 @@ static void bond_compute_features(struct bonding *bond)
                dst_release_flag &= slave->dev->priv_flags;
                if (slave->dev->hard_header_len > max_hard_header_len)
                        max_hard_header_len = slave->dev->hard_header_len;
+
+               gso_max_size = min(gso_max_size, slave->dev->gso_max_size);
+               gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs);
        }
 
 done:
        bond_dev->vlan_features = vlan_features;
        bond_dev->hard_header_len = max_hard_header_len;
+       bond_dev->gso_max_segs = gso_max_segs;
+       netif_set_gso_max_size(bond_dev, gso_max_size);
 
        flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE;
        bond_dev->priv_flags = flags | dst_release_flag;
@@ -1503,8 +1504,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
        int link_reporting;
        int res = 0;
 
-       if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
-               slave_ops->ndo_do_ioctl == NULL) {
+       if (!bond->params.use_carrier &&
+           slave_dev->ethtool_ops->get_link == NULL &&
+           slave_ops->ndo_do_ioctl == NULL) {
                pr_warning("%s: Warning: no link monitoring support for %s\n",
                           bond_dev->name, slave_dev->name);
        }
@@ -1519,7 +1521,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_vlan_used(bond)) {
+               if (vlan_uses_dev(bond_dev)) {
                        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;
@@ -1831,7 +1833,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
                 * anyway (it holds no special properties of the bond device),
                 * so we can change it without calling change_active_interface()
                 */
-               if (!bond->curr_active_slave)
+               if (!bond->curr_active_slave && new_slave->link == BOND_LINK_UP)
                        bond->curr_active_slave = new_slave;
 
                break;
index dc15d248443fd833ae17199a41f28ab6712b5d5c..ef8d2a080d17f4c61b8f28aa7e07bc54ed5c0abc 100644 (file)
@@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing primary */
        if (!strlen(ifname) || buf[0] == '\n') {
@@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,
                goto out;
        }
 
-       sscanf(buf, "%16s", ifname); /* IFNAMSIZ */
+       sscanf(buf, "%15s", ifname); /* IFNAMSIZ */
 
        /* check to see if we are clearing active */
        if (!strlen(ifname) || buf[0] == '\n') {
index f8af2fcd3d16380e29b22b927256955f67d71c5d..6dded569b111d07fee6bb49088847f633f628852 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/in6.h>
 #include <linux/netpoll.h>
 #include <linux/inetdevice.h>
+#include <linux/etherdevice.h>
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
@@ -450,6 +451,18 @@ static inline void bond_destroy_proc_dir(struct bond_net *bn)
 }
 #endif
 
+static inline struct slave *bond_slave_has_mac(struct bonding *bond,
+                                              const u8 *mac)
+{
+       int i = 0;
+       struct slave *tmp;
+
+       bond_for_each_slave(bond, tmp, i)
+               if (ether_addr_equal_64bits(mac, tmp->dev->dev_addr))
+                       return tmp;
+
+       return NULL;
+}
 
 /* exported from bond_main.c */
 extern int bond_net_id;
index bb709fd66993cd7f519186a549bd4b73e9609b3b..b56bd9e80957f0dc5f8dde896cb648e7cf939ab5 100644 (file)
@@ -110,6 +110,15 @@ config PCH_CAN
          is an IOH for x86 embedded processor (Intel Atom E6xx series).
          This driver can access CAN bus.
 
+config CAN_GRCAN
+       tristate "Aeroflex Gaisler GRCAN and GRHCAN CAN devices"
+       depends on CAN_DEV && OF
+       ---help---
+         Say Y here if you want to use Aeroflex Gaisler GRCAN or GRHCAN.
+         Note that the driver supports little endian, even though little
+         endian syntheses of the cores would need some modifications on
+         the hardware level to work.
+
 source "drivers/net/can/mscan/Kconfig"
 
 source "drivers/net/can/sja1000/Kconfig"
index 938be37b670cc7d9888b2287e5057e3b9cd0d3eb..7de59862bbe940aeddc9ac93a3c1bd16d8eac30a 100644 (file)
@@ -22,5 +22,6 @@ obj-$(CONFIG_CAN_BFIN)                += bfin_can.o
 obj-$(CONFIG_CAN_JANZ_ICAN3)   += janz-ican3.o
 obj-$(CONFIG_CAN_FLEXCAN)      += flexcan.o
 obj-$(CONFIG_PCH_CAN)          += pch_can.o
+obj-$(CONFIG_CAN_GRCAN)                += grcan.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
index fcff73a73b1d9b068565207f7d46479504fc9723..b8e81eb6df137253652cdece990e528e1d099673 100644 (file)
@@ -155,7 +155,7 @@ struct at91_priv {
        canid_t mb0_id;
 };
 
-static const struct at91_devtype_data at91_devtype_data[] __devinitconst = {
+static const struct at91_devtype_data at91_devtype_data[] = {
        [AT91_DEVTYPE_SAM9263] = {
                .rx_first = 1,
                .rx_split = 8,
@@ -1242,7 +1242,7 @@ static struct attribute_group at91_sysfs_attr_group = {
        .attrs = at91_sysfs_attrs,
 };
 
-static int __devinit at91_can_probe(struct platform_device *pdev)
+static int at91_can_probe(struct platform_device *pdev)
 {
        const struct at91_devtype_data *devtype_data;
        enum at91_devtype devtype;
@@ -1339,7 +1339,7 @@ static int __devinit at91_can_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __devexit at91_can_remove(struct platform_device *pdev)
+static int at91_can_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct at91_priv *priv = netdev_priv(dev);
@@ -1372,10 +1372,11 @@ static const struct platform_device_id at91_can_id_table[] = {
                /* sentinel */
        }
 };
+MODULE_DEVICE_TABLE(platform, at91_can_id_table);
 
 static struct platform_driver at91_can_driver = {
        .probe = at91_can_probe,
-       .remove = __devexit_p(at91_can_remove),
+       .remove = at91_can_remove,
        .driver = {
                .name = KBUILD_MODNAME,
                .owner = THIS_MODULE,
index f2d6d258a28629e3462921d37555cc85fbdb1ccb..6a0532176b69a1c47c5992c1c4e335b991892c2d 100644 (file)
@@ -531,7 +531,7 @@ static const struct net_device_ops bfin_can_netdev_ops = {
        .ndo_start_xmit         = bfin_can_start_xmit,
 };
 
-static int __devinit bfin_can_probe(struct platform_device *pdev)
+static int bfin_can_probe(struct platform_device *pdev)
 {
        int err;
        struct net_device *dev;
@@ -611,7 +611,7 @@ exit:
        return err;
 }
 
-static int __devexit bfin_can_remove(struct platform_device *pdev)
+static int bfin_can_remove(struct platform_device *pdev)
 {
        struct net_device *dev = dev_get_drvdata(&pdev->dev);
        struct bfin_can_priv *priv = netdev_priv(dev);
@@ -677,7 +677,7 @@ static int bfin_can_resume(struct platform_device *pdev)
 
 static struct platform_driver bfin_can_driver = {
        .probe = bfin_can_probe,
-       .remove = __devexit_p(bfin_can_remove),
+       .remove = bfin_can_remove,
        .suspend = bfin_can_suspend,
        .resume = bfin_can_resume,
        .driver = {
@@ -691,3 +691,4 @@ module_platform_driver(bfin_can_driver);
 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Blackfin on-chip CAN netdevice driver");
+MODULE_ALIAS("platform:" DRV_NAME);
index e5180dfddba54dc6918b8dbb3e2c8643316e130b..5233b8f58d773b6edb44f306f477674f05415084 100644 (file)
@@ -233,6 +233,12 @@ static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv)
                pm_runtime_put_sync(priv->device);
 }
 
+static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
+{
+       if (priv->raminit)
+               priv->raminit(priv, enable);
+}
+
 static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
 {
        return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
@@ -1090,6 +1096,7 @@ static int c_can_open(struct net_device *dev)
        struct c_can_priv *priv = netdev_priv(dev);
 
        c_can_pm_runtime_get_sync(priv);
+       c_can_reset_ram(priv, true);
 
        /* open the can device */
        err = open_candev(dev);
@@ -1118,6 +1125,7 @@ static int c_can_open(struct net_device *dev)
 exit_irq_fail:
        close_candev(dev);
 exit_open_fail:
+       c_can_reset_ram(priv, false);
        c_can_pm_runtime_put_sync(priv);
        return err;
 }
@@ -1131,6 +1139,8 @@ static int c_can_close(struct net_device *dev)
        c_can_stop(dev);
        free_irq(dev->irq, dev);
        close_candev(dev);
+
+       c_can_reset_ram(priv, false);
        c_can_pm_runtime_put_sync(priv);
 
        return 0;
@@ -1188,6 +1198,7 @@ int c_can_power_down(struct net_device *dev)
 
        c_can_stop(dev);
 
+       c_can_reset_ram(priv, false);
        c_can_pm_runtime_put_sync(priv);
 
        return 0;
@@ -1206,6 +1217,7 @@ int c_can_power_up(struct net_device *dev)
        WARN_ON(priv->type != BOSCH_D_CAN);
 
        c_can_pm_runtime_get_sync(priv);
+       c_can_reset_ram(priv, true);
 
        /* Clear PDR and INIT bits */
        val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
index e5ed41dafa1b94aa234749064813c587aa79c468..d2e1c21b143f4ae729edd45312de1db0a804f438 100644 (file)
@@ -169,6 +169,9 @@ struct c_can_priv {
        void *priv;             /* for board-specific data */
        u16 irqstatus;
        enum c_can_dev_id type;
+       u32 __iomem *raminit_ctrlreg;
+       unsigned int instance;
+       void (*raminit) (const struct c_can_priv *priv, bool enable);
 };
 
 struct net_device *alloc_c_can_dev(void);
index 3d7830bcd2bf83fa55346754f74c2205eae4b3f7..b374be7891a296bde66696e19d2137a47d7ffea3 100644 (file)
@@ -63,8 +63,8 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
        writew(val, priv->base + 2 * priv->regs[index]);
 }
 
-static int __devinit c_can_pci_probe(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int c_can_pci_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct c_can_pci_data *c_can_pci_data = (void *)ent->driver_data;
        struct c_can_priv *priv;
@@ -174,7 +174,7 @@ out:
        return ret;
 }
 
-static void __devexit c_can_pci_remove(struct pci_dev *pdev)
+static void c_can_pci_remove(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct c_can_priv *priv = netdev_priv(dev);
@@ -210,7 +210,7 @@ static struct pci_driver c_can_pci_driver = {
        .name = KBUILD_MODNAME,
        .id_table = c_can_pci_tbl,
        .probe = c_can_pci_probe,
-       .remove = __devexit_p(c_can_pci_remove),
+       .remove = c_can_pci_remove,
 };
 
 module_pci_driver(c_can_pci_driver);
index ee1416132aba2e1f9582b7911f67e94eb21b3084..d63b91904f829e9954596b06c0e34f48e3d1ba3b 100644 (file)
@@ -38,6 +38,8 @@
 
 #include "c_can.h"
 
+#define CAN_RAMINIT_START_MASK(i)      (1 << (i))
+
 /*
  * 16-bit c_can registers can be arranged differently in the memory
  * architecture of different implementations. For example: 16-bit
@@ -68,6 +70,18 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv,
        writew(val, priv->base + 2 * priv->regs[index]);
 }
 
+static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
+{
+       u32 val;
+
+       val = readl(priv->raminit_ctrlreg);
+       if (enable)
+               val |= CAN_RAMINIT_START_MASK(priv->instance);
+       else
+               val &= ~CAN_RAMINIT_START_MASK(priv->instance);
+       writel(val, priv->raminit_ctrlreg);
+}
+
 static struct platform_device_id c_can_id_table[] = {
        [BOSCH_C_CAN_PLATFORM] = {
                .name = KBUILD_MODNAME,
@@ -83,14 +97,16 @@ static struct platform_device_id c_can_id_table[] = {
        }, {
        }
 };
+MODULE_DEVICE_TABLE(platform, c_can_id_table);
 
 static const struct of_device_id c_can_of_table[] = {
        { .compatible = "bosch,c_can", .data = &c_can_id_table[BOSCH_C_CAN] },
        { .compatible = "bosch,d_can", .data = &c_can_id_table[BOSCH_D_CAN] },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, c_can_of_table);
 
-static int __devinit c_can_plat_probe(struct platform_device *pdev)
+static int c_can_plat_probe(struct platform_device *pdev)
 {
        int ret;
        void __iomem *addr;
@@ -99,7 +115,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
        const struct of_device_id *match;
        const struct platform_device_id *id;
        struct pinctrl *pinctrl;
-       struct resource *mem;
+       struct resource *mem, *res;
        int irq;
        struct clk *clk;
 
@@ -178,6 +194,18 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
                priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
                priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
                priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
+
+               if (pdev->dev.of_node)
+                       priv->instance = of_alias_get_id(pdev->dev.of_node, "d_can");
+               else
+                       priv->instance = pdev->id;
+
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+               priv->raminit_ctrlreg = devm_request_and_ioremap(&pdev->dev, res);
+               if (!priv->raminit_ctrlreg || priv->instance < 0)
+                       dev_info(&pdev->dev, "control memory is not used for raminit\n");
+               else
+                       priv->raminit = c_can_hw_raminit;
                break;
        default:
                ret = -EINVAL;
@@ -220,7 +248,7 @@ exit:
        return ret;
 }
 
-static int __devexit c_can_plat_remove(struct platform_device *pdev)
+static int c_can_plat_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct c_can_priv *priv = netdev_priv(dev);
@@ -306,7 +334,7 @@ static struct platform_driver c_can_plat_driver = {
                .of_match_table = of_match_ptr(c_can_of_table),
        },
        .probe = c_can_plat_probe,
-       .remove = __devexit_p(c_can_plat_remove),
+       .remove = c_can_plat_remove,
        .suspend = c_can_suspend,
        .resume = c_can_resume,
        .id_table = c_can_id_table,
index 9f3a25ccd665368b182ee9ed538cd10f3cc90922..8eaaac81f320a70040c6af68f6acabec51316134 100644 (file)
@@ -75,12 +75,12 @@ MODULE_LICENSE("GPL v2");
 
 static unsigned long port[MAXDEV];
 static unsigned long mem[MAXDEV];
-static int __devinitdata irq[MAXDEV];
-static int __devinitdata clk[MAXDEV];
-static u8 __devinitdata cir[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static u8 __devinitdata cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static u8 __devinitdata bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static int __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+static int irq[MAXDEV];
+static int clk[MAXDEV];
+static u8 cir[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static u8 cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static u8 bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
 
 module_param_array(port, ulong, NULL, S_IRUGO);
 MODULE_PARM_DESC(port, "I/O port number");
@@ -166,7 +166,7 @@ static void cc770_isa_port_write_reg_indirect(const struct cc770_priv *priv,
        spin_unlock_irqrestore(&cc770_isa_port_lock, flags);
 }
 
-static int __devinit cc770_isa_probe(struct platform_device *pdev)
+static int cc770_isa_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct cc770_priv *priv;
@@ -291,7 +291,7 @@ static int __devinit cc770_isa_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __devexit cc770_isa_remove(struct platform_device *pdev)
+static int cc770_isa_remove(struct platform_device *pdev)
 {
        struct net_device *dev = dev_get_drvdata(&pdev->dev);
        struct cc770_priv *priv = netdev_priv(dev);
@@ -316,7 +316,7 @@ static int __devexit cc770_isa_remove(struct platform_device *pdev)
 
 static struct platform_driver cc770_isa_driver = {
        .probe = cc770_isa_probe,
-       .remove = __devexit_p(cc770_isa_remove),
+       .remove = cc770_isa_remove,
        .driver = {
                .name = KBUILD_MODNAME,
                .owner = THIS_MODULE,
index 688371cda37afc51ff125efa547e819126e4ca24..d0f6bfc45aea1fae0a824f65cb431f847e2ae578 100644 (file)
@@ -60,6 +60,7 @@
 MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
 MODULE_DESCRIPTION("Socket-CAN driver for CC770 on the platform bus");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
 
 #define CC770_PLATFORM_CAN_CLOCK  16000000
 
@@ -74,8 +75,8 @@ static void cc770_platform_write_reg(const struct cc770_priv *priv, int reg,
        iowrite8(val, priv->reg_base + reg);
 }
 
-static int __devinit cc770_get_of_node_data(struct platform_device *pdev,
-                                           struct cc770_priv *priv)
+static int cc770_get_of_node_data(struct platform_device *pdev,
+                                 struct cc770_priv *priv)
 {
        struct device_node *np = pdev->dev.of_node;
        const u32 *prop;
@@ -147,8 +148,8 @@ static int __devinit cc770_get_of_node_data(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit cc770_get_platform_data(struct platform_device *pdev,
-                                            struct cc770_priv *priv)
+static int cc770_get_platform_data(struct platform_device *pdev,
+                                  struct cc770_priv *priv)
 {
 
        struct cc770_platform_data *pdata = pdev->dev.platform_data;
@@ -163,7 +164,7 @@ static int __devinit cc770_get_platform_data(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit cc770_platform_probe(struct platform_device *pdev)
+static int cc770_platform_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct cc770_priv *priv;
@@ -237,7 +238,7 @@ exit_release_mem:
        return err;
 }
 
-static int __devexit cc770_platform_remove(struct platform_device *pdev)
+static int cc770_platform_remove(struct platform_device *pdev)
 {
        struct net_device *dev = dev_get_drvdata(&pdev->dev);
        struct cc770_priv *priv = netdev_priv(dev);
@@ -253,11 +254,12 @@ static int __devexit cc770_platform_remove(struct platform_device *pdev)
        return 0;
 }
 
-static struct of_device_id __devinitdata cc770_platform_table[] = {
+static struct of_device_id cc770_platform_table[] = {
        {.compatible = "bosch,cc770"}, /* CC770 from Bosch */
        {.compatible = "intc,82527"},  /* AN82527 from Intel CP */
        {},
 };
+MODULE_DEVICE_TABLE(of, cc770_platform_table);
 
 static struct platform_driver cc770_platform_driver = {
        .driver = {
@@ -266,7 +268,7 @@ static struct platform_driver cc770_platform_driver = {
                .of_match_table = cc770_platform_table,
        },
        .probe = cc770_platform_probe,
-       .remove = __devexit_p(cc770_platform_remove),
+       .remove = cc770_platform_remove,
 };
 
 module_platform_driver(cc770_platform_driver);
index 963e2ccd10db81300748b4fac6d9dde8f084d3b5..8233e5ed2939dcfe415ee119edf8c3aaf042c47d 100644 (file)
@@ -609,8 +609,7 @@ void close_candev(struct net_device *dev)
 {
        struct can_priv *priv = netdev_priv(dev);
 
-       if (del_timer_sync(&priv->restart_timer))
-               dev_put(dev);
+       del_timer_sync(&priv->restart_timer);
        can_flush_echo_skb(dev);
 }
 EXPORT_SYMBOL_GPL(close_candev);
index c78ecfca1e4582b8e57a2a42a2e14152f3640483..0289a6d86f660d5e97f9a2f34a2d37c6d7f1d53d 100644 (file)
 
 #define FLEXCAN_MB_CODE_MASK           (0xf0ffffff)
 
-/* FLEXCAN hardware feature flags */
+/*
+ * FLEXCAN hardware feature flags
+ *
+ * Below is some version info we got:
+ *    SOC   Version   IP-Version  Glitch-  [TR]WRN_INT
+ *                                Filter?   connected?
+ *   MX25  FlexCAN2  03.00.00.00     no         no
+ *   MX28  FlexCAN2  03.00.04.00    yes        yes
+ *   MX35  FlexCAN2  03.00.00.00     no         no
+ *   MX53  FlexCAN2  03.00.00.00    yes         no
+ *   MX6s  FlexCAN3  10.00.12.00    yes        yes
+ *
+ * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
+ */
 #define FLEXCAN_HAS_V10_FEATURES       BIT(1) /* For core version >= 10 */
-#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* Broken error state handling */
+#define FLEXCAN_HAS_BROKEN_ERR_STATE   BIT(2) /* [TR]WRN_INT not connected */
 
 /* Structure of the message buffer */
 struct flexcan_mb {
@@ -205,7 +218,7 @@ static struct flexcan_devtype_data fsl_p1010_devtype_data = {
 };
 static struct flexcan_devtype_data fsl_imx28_devtype_data;
 static struct flexcan_devtype_data fsl_imx6q_devtype_data = {
-       .features = FLEXCAN_HAS_V10_FEATURES | FLEXCAN_HAS_BROKEN_ERR_STATE,
+       .features = FLEXCAN_HAS_V10_FEATURES,
 };
 
 static const struct can_bittiming_const flexcan_bittiming_const = {
@@ -909,7 +922,7 @@ static const struct net_device_ops flexcan_netdev_ops = {
        .ndo_start_xmit = flexcan_start_xmit,
 };
 
-static int __devinit register_flexcandev(struct net_device *dev)
+static int register_flexcandev(struct net_device *dev)
 {
        struct flexcan_priv *priv = netdev_priv(dev);
        struct flexcan_regs __iomem *regs = priv->base;
@@ -955,7 +968,7 @@ static int __devinit register_flexcandev(struct net_device *dev)
        return err;
 }
 
-static void __devexit unregister_flexcandev(struct net_device *dev)
+static void unregister_flexcandev(struct net_device *dev)
 {
        unregister_candev(dev);
 }
@@ -966,13 +979,15 @@ static const struct of_device_id flexcan_of_match[] = {
        { .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, flexcan_of_match);
 
 static const struct platform_device_id flexcan_id_table[] = {
        { .name = "flexcan", .driver_data = (kernel_ulong_t)&fsl_p1010_devtype_data, },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(platform, flexcan_id_table);
 
-static int __devinit flexcan_probe(struct platform_device *pdev)
+static int flexcan_probe(struct platform_device *pdev)
 {
        const struct of_device_id *of_id;
        const struct flexcan_devtype_data *devtype_data;
@@ -1094,7 +1109,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __devexit flexcan_remove(struct platform_device *pdev)
+static int flexcan_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct flexcan_priv *priv = netdev_priv(dev);
@@ -1155,7 +1170,7 @@ static struct platform_driver flexcan_driver = {
                .of_match_table = flexcan_of_match,
        },
        .probe = flexcan_probe,
-       .remove = __devexit_p(flexcan_remove),
+       .remove = flexcan_remove,
        .suspend = flexcan_suspend,
        .resume = flexcan_resume,
        .id_table = flexcan_id_table,
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
new file mode 100644 (file)
index 0000000..17fbc7a
--- /dev/null
@@ -0,0 +1,1756 @@
+/*
+ * Socket CAN driver for Aeroflex Gaisler GRCAN and GRHCAN.
+ *
+ * 2012 (c) Aeroflex Gaisler AB
+ *
+ * This driver supports GRCAN and GRHCAN CAN controllers available in the GRLIB
+ * VHDL IP core library.
+ *
+ * Full documentation of the GRCAN core can be found here:
+ * http://www.gaisler.com/products/grlib/grip.pdf
+ *
+ * See "Documentation/devicetree/bindings/net/can/grcan.txt" for information on
+ * open firmware properties.
+ *
+ * See "Documentation/ABI/testing/sysfs-class-net-grcan" for information on the
+ * sysfs interface.
+ *
+ * See "Documentation/kernel-parameters.txt" for information on the module
+ * parameters.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * Contributors: Andreas Larsson <andreas@gaisler.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/can/dev.h>
+#include <linux/spinlock.h>
+
+#include <linux/of_platform.h>
+#include <asm/prom.h>
+
+#include <linux/of_irq.h>
+
+#include <linux/dma-mapping.h>
+
+#define DRV_NAME       "grcan"
+
+#define GRCAN_NAPI_WEIGHT      32
+
+#define GRCAN_RESERVE_SIZE(slot1, slot2) (((slot2) - (slot1)) / 4 - 1)
+
+struct grcan_registers {
+       u32 conf;       /* 0x00 */
+       u32 stat;       /* 0x04 */
+       u32 ctrl;       /* 0x08 */
+       u32 __reserved1[GRCAN_RESERVE_SIZE(0x08, 0x18)];
+       u32 smask;      /* 0x18 - CanMASK */
+       u32 scode;      /* 0x1c - CanCODE */
+       u32 __reserved2[GRCAN_RESERVE_SIZE(0x1c, 0x100)];
+       u32 pimsr;      /* 0x100 */
+       u32 pimr;       /* 0x104 */
+       u32 pisr;       /* 0x108 */
+       u32 pir;        /* 0x10C */
+       u32 imr;        /* 0x110 */
+       u32 picr;       /* 0x114 */
+       u32 __reserved3[GRCAN_RESERVE_SIZE(0x114, 0x200)];
+       u32 txctrl;     /* 0x200 */
+       u32 txaddr;     /* 0x204 */
+       u32 txsize;     /* 0x208 */
+       u32 txwr;       /* 0x20C */
+       u32 txrd;       /* 0x210 */
+       u32 txirq;      /* 0x214 */
+       u32 __reserved4[GRCAN_RESERVE_SIZE(0x214, 0x300)];
+       u32 rxctrl;     /* 0x300 */
+       u32 rxaddr;     /* 0x304 */
+       u32 rxsize;     /* 0x308 */
+       u32 rxwr;       /* 0x30C */
+       u32 rxrd;       /* 0x310 */
+       u32 rxirq;      /* 0x314 */
+       u32 rxmask;     /* 0x318 */
+       u32 rxcode;     /* 0x31C */
+};
+
+#define GRCAN_CONF_ABORT       0x00000001
+#define GRCAN_CONF_ENABLE0     0x00000002
+#define GRCAN_CONF_ENABLE1     0x00000004
+#define GRCAN_CONF_SELECT      0x00000008
+#define GRCAN_CONF_SILENT      0x00000010
+#define GRCAN_CONF_SAM         0x00000020 /* Available in some hardware */
+#define GRCAN_CONF_BPR         0x00000300 /* Note: not BRP */
+#define GRCAN_CONF_RSJ         0x00007000
+#define GRCAN_CONF_PS1         0x00f00000
+#define GRCAN_CONF_PS2         0x000f0000
+#define GRCAN_CONF_SCALER      0xff000000
+#define GRCAN_CONF_OPERATION                                           \
+       (GRCAN_CONF_ABORT | GRCAN_CONF_ENABLE0 | GRCAN_CONF_ENABLE1     \
+        | GRCAN_CONF_SELECT | GRCAN_CONF_SILENT | GRCAN_CONF_SAM)
+#define GRCAN_CONF_TIMING                                              \
+       (GRCAN_CONF_BPR | GRCAN_CONF_RSJ | GRCAN_CONF_PS1               \
+        | GRCAN_CONF_PS2 | GRCAN_CONF_SCALER)
+
+#define GRCAN_CONF_RSJ_MIN     1
+#define GRCAN_CONF_RSJ_MAX     4
+#define GRCAN_CONF_PS1_MIN     1
+#define GRCAN_CONF_PS1_MAX     15
+#define GRCAN_CONF_PS2_MIN     2
+#define GRCAN_CONF_PS2_MAX     8
+#define GRCAN_CONF_SCALER_MIN  0
+#define GRCAN_CONF_SCALER_MAX  255
+#define GRCAN_CONF_SCALER_INC  1
+
+#define GRCAN_CONF_BPR_BIT     8
+#define GRCAN_CONF_RSJ_BIT     12
+#define GRCAN_CONF_PS1_BIT     20
+#define GRCAN_CONF_PS2_BIT     16
+#define GRCAN_CONF_SCALER_BIT  24
+
+#define GRCAN_STAT_PASS                0x000001
+#define GRCAN_STAT_OFF         0x000002
+#define GRCAN_STAT_OR          0x000004
+#define GRCAN_STAT_AHBERR      0x000008
+#define GRCAN_STAT_ACTIVE      0x000010
+#define GRCAN_STAT_RXERRCNT    0x00ff00
+#define GRCAN_STAT_TXERRCNT    0xff0000
+
+#define GRCAN_STAT_ERRCTR_RELATED      (GRCAN_STAT_PASS | GRCAN_STAT_OFF)
+
+#define GRCAN_STAT_RXERRCNT_BIT        8
+#define GRCAN_STAT_TXERRCNT_BIT        16
+
+#define GRCAN_STAT_ERRCNT_WARNING_LIMIT        96
+#define GRCAN_STAT_ERRCNT_PASSIVE_LIMIT        127
+
+#define GRCAN_CTRL_RESET       0x2
+#define GRCAN_CTRL_ENABLE      0x1
+
+#define GRCAN_TXCTRL_ENABLE    0x1
+#define GRCAN_TXCTRL_ONGOING   0x2
+#define GRCAN_TXCTRL_SINGLE    0x4
+
+#define GRCAN_RXCTRL_ENABLE    0x1
+#define GRCAN_RXCTRL_ONGOING   0x2
+
+/* Relative offset of IRQ sources to AMBA Plug&Play */
+#define GRCAN_IRQIX_IRQ                0
+#define GRCAN_IRQIX_TXSYNC     1
+#define GRCAN_IRQIX_RXSYNC     2
+
+#define GRCAN_IRQ_PASS         0x00001
+#define GRCAN_IRQ_OFF          0x00002
+#define GRCAN_IRQ_OR           0x00004
+#define GRCAN_IRQ_RXAHBERR     0x00008
+#define GRCAN_IRQ_TXAHBERR     0x00010
+#define GRCAN_IRQ_RXIRQ                0x00020
+#define GRCAN_IRQ_TXIRQ                0x00040
+#define GRCAN_IRQ_RXFULL       0x00080
+#define GRCAN_IRQ_TXEMPTY      0x00100
+#define GRCAN_IRQ_RX           0x00200
+#define GRCAN_IRQ_TX           0x00400
+#define GRCAN_IRQ_RXSYNC       0x00800
+#define GRCAN_IRQ_TXSYNC       0x01000
+#define GRCAN_IRQ_RXERRCTR     0x02000
+#define GRCAN_IRQ_TXERRCTR     0x04000
+#define GRCAN_IRQ_RXMISS       0x08000
+#define GRCAN_IRQ_TXLOSS       0x10000
+
+#define GRCAN_IRQ_NONE 0
+#define GRCAN_IRQ_ALL                                                  \
+       (GRCAN_IRQ_PASS | GRCAN_IRQ_OFF | GRCAN_IRQ_OR                  \
+        | GRCAN_IRQ_RXAHBERR | GRCAN_IRQ_TXAHBERR                      \
+        | GRCAN_IRQ_RXIRQ | GRCAN_IRQ_TXIRQ                            \
+        | GRCAN_IRQ_RXFULL | GRCAN_IRQ_TXEMPTY                         \
+        | GRCAN_IRQ_RX | GRCAN_IRQ_TX | GRCAN_IRQ_RXSYNC               \
+        | GRCAN_IRQ_TXSYNC | GRCAN_IRQ_RXERRCTR                        \
+        | GRCAN_IRQ_TXERRCTR | GRCAN_IRQ_RXMISS                        \
+        | GRCAN_IRQ_TXLOSS)
+
+#define GRCAN_IRQ_ERRCTR_RELATED (GRCAN_IRQ_RXERRCTR | GRCAN_IRQ_TXERRCTR \
+                                 | GRCAN_IRQ_PASS | GRCAN_IRQ_OFF)
+#define GRCAN_IRQ_ERRORS (GRCAN_IRQ_ERRCTR_RELATED | GRCAN_IRQ_OR      \
+                         | GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR     \
+                         | GRCAN_IRQ_TXLOSS)
+#define GRCAN_IRQ_DEFAULT (GRCAN_IRQ_RX | GRCAN_IRQ_TX | GRCAN_IRQ_ERRORS)
+
+#define GRCAN_MSG_SIZE         16
+
+#define GRCAN_MSG_IDE          0x80000000
+#define GRCAN_MSG_RTR          0x40000000
+#define GRCAN_MSG_BID          0x1ffc0000
+#define GRCAN_MSG_EID          0x1fffffff
+#define GRCAN_MSG_IDE_BIT      31
+#define GRCAN_MSG_RTR_BIT      30
+#define GRCAN_MSG_BID_BIT      18
+#define GRCAN_MSG_EID_BIT      0
+
+#define GRCAN_MSG_DLC          0xf0000000
+#define GRCAN_MSG_TXERRC       0x00ff0000
+#define GRCAN_MSG_RXERRC       0x0000ff00
+#define GRCAN_MSG_DLC_BIT      28
+#define GRCAN_MSG_TXERRC_BIT   16
+#define GRCAN_MSG_RXERRC_BIT   8
+#define GRCAN_MSG_AHBERR       0x00000008
+#define GRCAN_MSG_OR           0x00000004
+#define GRCAN_MSG_OFF          0x00000002
+#define GRCAN_MSG_PASS         0x00000001
+
+#define GRCAN_MSG_DATA_SLOT_INDEX(i) (2 + (i) / 4)
+#define GRCAN_MSG_DATA_SHIFT(i) ((3 - (i) % 4) * 8)
+
+#define GRCAN_BUFFER_ALIGNMENT         1024
+#define GRCAN_DEFAULT_BUFFER_SIZE      1024
+#define GRCAN_VALID_TR_SIZE_MASK       0x001fffc0
+
+#define GRCAN_INVALID_BUFFER_SIZE(s)                   \
+       ((s) == 0 || ((s) & ~GRCAN_VALID_TR_SIZE_MASK))
+
+#if GRCAN_INVALID_BUFFER_SIZE(GRCAN_DEFAULT_BUFFER_SIZE)
+#error "Invalid default buffer size"
+#endif
+
+struct grcan_dma_buffer {
+       size_t size;
+       void *buf;
+       dma_addr_t handle;
+};
+
+struct grcan_dma {
+       size_t base_size;
+       void *base_buf;
+       dma_addr_t base_handle;
+       struct grcan_dma_buffer tx;
+       struct grcan_dma_buffer rx;
+};
+
+/* GRCAN configuration parameters */
+struct grcan_device_config {
+       unsigned short enable0;
+       unsigned short enable1;
+       unsigned short select;
+       unsigned int txsize;
+       unsigned int rxsize;
+};
+
+#define GRCAN_DEFAULT_DEVICE_CONFIG {                          \
+               .enable0        = 0,                            \
+               .enable1        = 0,                            \
+               .select         = 0,                            \
+               .txsize         = GRCAN_DEFAULT_BUFFER_SIZE,    \
+               .rxsize         = GRCAN_DEFAULT_BUFFER_SIZE,    \
+               }
+
+#define GRCAN_TXBUG_SAFE_GRLIB_VERSION 0x4100
+#define GRLIB_VERSION_MASK             0xffff
+
+/* GRCAN private data structure */
+struct grcan_priv {
+       struct can_priv can;    /* must be the first member */
+       struct net_device *dev;
+       struct napi_struct napi;
+
+       struct grcan_registers __iomem *regs;   /* ioremap'ed registers */
+       struct grcan_device_config config;
+       struct grcan_dma dma;
+
+       struct sk_buff **echo_skb;      /* We allocate this on our own */
+       u8 *txdlc;                      /* Length of queued frames */
+
+       /* The echo skb pointer, pointing into echo_skb and indicating which
+        * frames can be echoed back. See the "Notes on the tx cyclic buffer
+        * handling"-comment for grcan_start_xmit for more details.
+        */
+       u32 eskbp;
+
+       /* Lock for controlling changes to the netif tx queue state, accesses to
+        * the echo_skb pointer eskbp and for making sure that a running reset
+        * and/or a close of the interface is done without interference from
+        * other parts of the code.
+        *
+        * The echo_skb pointer, eskbp, should only be accessed under this lock
+        * as it can be changed in several places and together with decisions on
+        * whether to wake up the tx queue.
+        *
+        * The tx queue must never be woken up if there is a running reset or
+        * close in progress.
+        *
+        * A running reset (see below on need_txbug_workaround) should never be
+        * done if the interface is closing down and several running resets
+        * should never be scheduled simultaneously.
+        */
+       spinlock_t lock;
+
+       /* Whether a workaround is needed due to a bug in older hardware. In
+        * this case, the driver both tries to prevent the bug from being
+        * triggered and recovers, if the bug nevertheless happens, by doing a
+        * running reset. A running reset, resets the device and continues from
+        * where it were without being noticeable from outside the driver (apart
+        * from slight delays).
+        */
+       bool need_txbug_workaround;
+
+       /* To trigger initization of running reset and to trigger running reset
+        * respectively in the case of a hanged device due to a txbug.
+        */
+       struct timer_list hang_timer;
+       struct timer_list rr_timer;
+
+       /* To avoid waking up the netif queue and restarting timers
+        * when a reset is scheduled or when closing of the device is
+        * undergoing
+        */
+       bool resetting;
+       bool closing;
+};
+
+/* Wait time for a short wait for ongoing to clear */
+#define GRCAN_SHORTWAIT_USECS  10
+
+/* Limit on the number of transmitted bits of an eff frame according to the CAN
+ * specification: 1 bit start of frame, 32 bits arbitration field, 6 bits
+ * control field, 8 bytes data field, 16 bits crc field, 2 bits ACK field and 7
+ * bits end of frame
+ */
+#define GRCAN_EFF_FRAME_MAX_BITS       (1+32+6+8*8+16+2+7)
+
+#if defined(__BIG_ENDIAN)
+static inline u32 grcan_read_reg(u32 __iomem *reg)
+{
+       return ioread32be(reg);
+}
+
+static inline void grcan_write_reg(u32 __iomem *reg, u32 val)
+{
+       iowrite32be(val, reg);
+}
+#else
+static inline u32 grcan_read_reg(u32 __iomem *reg)
+{
+       return ioread32(reg);
+}
+
+static inline void grcan_write_reg(u32 __iomem *reg, u32 val)
+{
+       iowrite32(val, reg);
+}
+#endif
+
+static inline void grcan_clear_bits(u32 __iomem *reg, u32 mask)
+{
+       grcan_write_reg(reg, grcan_read_reg(reg) & ~mask);
+}
+
+static inline void grcan_set_bits(u32 __iomem *reg, u32 mask)
+{
+       grcan_write_reg(reg, grcan_read_reg(reg) | mask);
+}
+
+static inline u32 grcan_read_bits(u32 __iomem *reg, u32 mask)
+{
+       return grcan_read_reg(reg) & mask;
+}
+
+static inline void grcan_write_bits(u32 __iomem *reg, u32 value, u32 mask)
+{
+       u32 old = grcan_read_reg(reg);
+
+       grcan_write_reg(reg, (old & ~mask) | (value & mask));
+}
+
+/* a and b should both be in [0,size] and a == b == size should not hold */
+static inline u32 grcan_ring_add(u32 a, u32 b, u32 size)
+{
+       u32 sum = a + b;
+
+       if (sum < size)
+               return sum;
+       else
+               return sum - size;
+}
+
+/* a and b should both be in [0,size) */
+static inline u32 grcan_ring_sub(u32 a, u32 b, u32 size)
+{
+       return grcan_ring_add(a, size - b, size);
+}
+
+/* Available slots for new transmissions */
+static inline u32 grcan_txspace(size_t txsize, u32 txwr, u32 eskbp)
+{
+       u32 slots = txsize / GRCAN_MSG_SIZE - 1;
+       u32 used = grcan_ring_sub(txwr, eskbp, txsize) / GRCAN_MSG_SIZE;
+
+       return slots - used;
+}
+
+/* Configuration parameters that can be set via module parameters */
+static struct grcan_device_config grcan_module_config =
+       GRCAN_DEFAULT_DEVICE_CONFIG;
+
+static const struct can_bittiming_const grcan_bittiming_const = {
+       .name           = DRV_NAME,
+       .tseg1_min      = GRCAN_CONF_PS1_MIN + 1,
+       .tseg1_max      = GRCAN_CONF_PS1_MAX + 1,
+       .tseg2_min      = GRCAN_CONF_PS2_MIN,
+       .tseg2_max      = GRCAN_CONF_PS2_MAX,
+       .sjw_max        = GRCAN_CONF_RSJ_MAX,
+       .brp_min        = GRCAN_CONF_SCALER_MIN + 1,
+       .brp_max        = GRCAN_CONF_SCALER_MAX + 1,
+       .brp_inc        = GRCAN_CONF_SCALER_INC,
+};
+
+static int grcan_set_bittiming(struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       struct can_bittiming *bt = &priv->can.bittiming;
+       u32 timing = 0;
+       int bpr, rsj, ps1, ps2, scaler;
+
+       /* Should never happen - function will not be called when
+        * device is up
+        */
+       if (grcan_read_bits(&regs->ctrl, GRCAN_CTRL_ENABLE))
+               return -EBUSY;
+
+       bpr = 0; /* Note bpr and brp are different concepts */
+       rsj = bt->sjw;
+       ps1 = (bt->prop_seg + bt->phase_seg1) - 1; /* tseg1 - 1 */
+       ps2 = bt->phase_seg2;
+       scaler = (bt->brp - 1);
+       netdev_dbg(dev, "Request for BPR=%d, RSJ=%d, PS1=%d, PS2=%d, SCALER=%d",
+                  bpr, rsj, ps1, ps2, scaler);
+       if (!(ps1 > ps2)) {
+               netdev_err(dev, "PS1 > PS2 must hold: PS1=%d, PS2=%d\n",
+                          ps1, ps2);
+               return -EINVAL;
+       }
+       if (!(ps2 >= rsj)) {
+               netdev_err(dev, "PS2 >= RSJ must hold: PS2=%d, RSJ=%d\n",
+                          ps2, rsj);
+               return -EINVAL;
+       }
+
+       timing |= (bpr << GRCAN_CONF_BPR_BIT) & GRCAN_CONF_BPR;
+       timing |= (rsj << GRCAN_CONF_RSJ_BIT) & GRCAN_CONF_RSJ;
+       timing |= (ps1 << GRCAN_CONF_PS1_BIT) & GRCAN_CONF_PS1;
+       timing |= (ps2 << GRCAN_CONF_PS2_BIT) & GRCAN_CONF_PS2;
+       timing |= (scaler << GRCAN_CONF_SCALER_BIT) & GRCAN_CONF_SCALER;
+       netdev_info(dev, "setting timing=0x%x\n", timing);
+       grcan_write_bits(&regs->conf, timing, GRCAN_CONF_TIMING);
+
+       return 0;
+}
+
+static int grcan_get_berr_counter(const struct net_device *dev,
+                                 struct can_berr_counter *bec)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       u32 status = grcan_read_reg(&regs->stat);
+
+       bec->txerr = (status & GRCAN_STAT_TXERRCNT) >> GRCAN_STAT_TXERRCNT_BIT;
+       bec->rxerr = (status & GRCAN_STAT_RXERRCNT) >> GRCAN_STAT_RXERRCNT_BIT;
+       return 0;
+}
+
+static int grcan_poll(struct napi_struct *napi, int budget);
+
+/* Reset device, but keep configuration information */
+static void grcan_reset(struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       u32 config = grcan_read_reg(&regs->conf);
+
+       grcan_set_bits(&regs->ctrl, GRCAN_CTRL_RESET);
+       grcan_write_reg(&regs->conf, config);
+
+       priv->eskbp = grcan_read_reg(&regs->txrd);
+       priv->can.state = CAN_STATE_STOPPED;
+
+       /* Turn off hardware filtering - regs->rxcode set to 0 by reset */
+       grcan_write_reg(&regs->rxmask, 0);
+}
+
+/* stop device without changing any configurations */
+static void grcan_stop_hardware(struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+
+       grcan_write_reg(&regs->imr, GRCAN_IRQ_NONE);
+       grcan_clear_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+       grcan_clear_bits(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+       grcan_clear_bits(&regs->ctrl, GRCAN_CTRL_ENABLE);
+}
+
+/* Let priv->eskbp catch up to regs->txrd and echo back the skbs if echo
+ * is true and free them otherwise.
+ *
+ * If budget is >= 0, stop after handling at most budget skbs. Otherwise,
+ * continue until priv->eskbp catches up to regs->txrd.
+ *
+ * priv->lock *must* be held when calling this function
+ */
+static int catch_up_echo_skb(struct net_device *dev, int budget, bool echo)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       struct grcan_dma *dma = &priv->dma;
+       struct net_device_stats *stats = &dev->stats;
+       int i, work_done;
+
+       /* Updates to priv->eskbp and wake-ups of the queue needs to
+        * be atomic towards the reads of priv->eskbp and shut-downs
+        * of the queue in grcan_start_xmit.
+        */
+       u32 txrd = grcan_read_reg(&regs->txrd);
+
+       for (work_done = 0; work_done < budget || budget < 0; work_done++) {
+               if (priv->eskbp == txrd)
+                       break;
+               i = priv->eskbp / GRCAN_MSG_SIZE;
+               if (echo) {
+                       /* Normal echo of messages */
+                       stats->tx_packets++;
+                       stats->tx_bytes += priv->txdlc[i];
+                       priv->txdlc[i] = 0;
+                       can_get_echo_skb(dev, i);
+               } else {
+                       /* For cleanup of untransmitted messages */
+                       can_free_echo_skb(dev, i);
+               }
+
+               priv->eskbp = grcan_ring_add(priv->eskbp, GRCAN_MSG_SIZE,
+                                            dma->tx.size);
+               txrd = grcan_read_reg(&regs->txrd);
+       }
+       return work_done;
+}
+
+static void grcan_lost_one_shot_frame(struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       struct grcan_dma *dma = &priv->dma;
+       u32 txrd;
+       unsigned long flags;
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       catch_up_echo_skb(dev, -1, true);
+
+       if (unlikely(grcan_read_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE))) {
+               /* Should never happen */
+               netdev_err(dev, "TXCTRL enabled at TXLOSS in one shot mode\n");
+       } else {
+               /* By the time an GRCAN_IRQ_TXLOSS is generated in
+                * one-shot mode there is no problem in writing
+                * to TXRD even in versions of the hardware in
+                * which GRCAN_TXCTRL_ONGOING is not cleared properly
+                * in one-shot mode.
+                */
+
+               /* Skip message and discard echo-skb */
+               txrd = grcan_read_reg(&regs->txrd);
+               txrd = grcan_ring_add(txrd, GRCAN_MSG_SIZE, dma->tx.size);
+               grcan_write_reg(&regs->txrd, txrd);
+               catch_up_echo_skb(dev, -1, false);
+
+               if (!priv->resetting && !priv->closing &&
+                   !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)) {
+                       netif_wake_queue(dev);
+                       grcan_set_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+               }
+       }
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void grcan_err(struct net_device *dev, u32 sources, u32 status)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       struct grcan_dma *dma = &priv->dma;
+       struct net_device_stats *stats = &dev->stats;
+       struct can_frame cf;
+
+       /* Zero potential error_frame */
+       memset(&cf, 0, sizeof(cf));
+
+       /* Message lost interrupt. This might be due to arbitration error, but
+        * is also triggered when there is no one else on the can bus or when
+        * there is a problem with the hardware interface or the bus itself. As
+        * arbitration errors can not be singled out, no error frames are
+        * generated reporting this event as an arbitration error.
+        */
+       if (sources & GRCAN_IRQ_TXLOSS) {
+               /* Take care of failed one-shot transmit */
+               if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+                       grcan_lost_one_shot_frame(dev);
+
+               /* Stop printing as soon as error passive or bus off is in
+                * effect to limit the amount of txloss debug printouts.
+                */
+               if (!(status & GRCAN_STAT_ERRCTR_RELATED)) {
+                       netdev_dbg(dev, "tx message lost\n");
+                       stats->tx_errors++;
+               }
+       }
+
+       /* Conditions dealing with the error counters. There is no interrupt for
+        * error warning, but there are interrupts for increases of the error
+        * counters.
+        */
+       if ((sources & GRCAN_IRQ_ERRCTR_RELATED) ||
+           (status & GRCAN_STAT_ERRCTR_RELATED)) {
+               enum can_state state = priv->can.state;
+               enum can_state oldstate = state;
+               u32 txerr = (status & GRCAN_STAT_TXERRCNT)
+                       >> GRCAN_STAT_TXERRCNT_BIT;
+               u32 rxerr = (status & GRCAN_STAT_RXERRCNT)
+                       >> GRCAN_STAT_RXERRCNT_BIT;
+
+               /* Figure out current state */
+               if (status & GRCAN_STAT_OFF) {
+                       state = CAN_STATE_BUS_OFF;
+               } else if (status & GRCAN_STAT_PASS) {
+                       state = CAN_STATE_ERROR_PASSIVE;
+               } else if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT ||
+                          rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT) {
+                       state = CAN_STATE_ERROR_WARNING;
+               } else {
+                       state = CAN_STATE_ERROR_ACTIVE;
+               }
+
+               /* Handle and report state changes */
+               if (state != oldstate) {
+                       switch (state) {
+                       case CAN_STATE_BUS_OFF:
+                               netdev_dbg(dev, "bus-off\n");
+                               netif_carrier_off(dev);
+                               priv->can.can_stats.bus_off++;
+
+                               /* Prevent the hardware from recovering from bus
+                                * off on its own if restart is disabled.
+                                */
+                               if (!priv->can.restart_ms)
+                                       grcan_stop_hardware(dev);
+
+                               cf.can_id |= CAN_ERR_BUSOFF;
+                               break;
+
+                       case CAN_STATE_ERROR_PASSIVE:
+                               netdev_dbg(dev, "Error passive condition\n");
+                               priv->can.can_stats.error_passive++;
+
+                               cf.can_id |= CAN_ERR_CRTL;
+                               if (txerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT)
+                                       cf.data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+                               if (rxerr >= GRCAN_STAT_ERRCNT_PASSIVE_LIMIT)
+                                       cf.data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+                               break;
+
+                       case CAN_STATE_ERROR_WARNING:
+                               netdev_dbg(dev, "Error warning condition\n");
+                               priv->can.can_stats.error_warning++;
+
+                               cf.can_id |= CAN_ERR_CRTL;
+                               if (txerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT)
+                                       cf.data[1] |= CAN_ERR_CRTL_TX_WARNING;
+                               if (rxerr >= GRCAN_STAT_ERRCNT_WARNING_LIMIT)
+                                       cf.data[1] |= CAN_ERR_CRTL_RX_WARNING;
+                               break;
+
+                       case CAN_STATE_ERROR_ACTIVE:
+                               netdev_dbg(dev, "Error active condition\n");
+                               cf.can_id |= CAN_ERR_CRTL;
+                               break;
+
+                       default:
+                               /* There are no others at this point */
+                               break;
+                       }
+                       cf.data[6] = txerr;
+                       cf.data[7] = rxerr;
+                       priv->can.state = state;
+               }
+
+               /* Report automatic restarts */
+               if (priv->can.restart_ms && oldstate == CAN_STATE_BUS_OFF) {
+                       unsigned long flags;
+
+                       cf.can_id |= CAN_ERR_RESTARTED;
+                       netdev_dbg(dev, "restarted\n");
+                       priv->can.can_stats.restarts++;
+                       netif_carrier_on(dev);
+
+                       spin_lock_irqsave(&priv->lock, flags);
+
+                       if (!priv->resetting && !priv->closing) {
+                               u32 txwr = grcan_read_reg(&regs->txwr);
+
+                               if (grcan_txspace(dma->tx.size, txwr,
+                                                 priv->eskbp))
+                                       netif_wake_queue(dev);
+                       }
+
+                       spin_unlock_irqrestore(&priv->lock, flags);
+               }
+       }
+
+       /* Data overrun interrupt */
+       if ((sources & GRCAN_IRQ_OR) || (status & GRCAN_STAT_OR)) {
+               netdev_dbg(dev, "got data overrun interrupt\n");
+               stats->rx_over_errors++;
+               stats->rx_errors++;
+
+               cf.can_id |= CAN_ERR_CRTL;
+               cf.data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
+       }
+
+       /* AHB bus error interrupts (not CAN bus errors) - shut down the
+        * device.
+        */
+       if (sources & (GRCAN_IRQ_TXAHBERR | GRCAN_IRQ_RXAHBERR) ||
+           (status & GRCAN_STAT_AHBERR)) {
+               char *txrx = "";
+               unsigned long flags;
+
+               if (sources & GRCAN_IRQ_TXAHBERR) {
+                       txrx = "on tx ";
+                       stats->tx_errors++;
+               } else if (sources & GRCAN_IRQ_RXAHBERR) {
+                       txrx = "on rx ";
+                       stats->rx_errors++;
+               }
+               netdev_err(dev, "Fatal AHB buss error %s- halting device\n",
+                          txrx);
+
+               spin_lock_irqsave(&priv->lock, flags);
+
+               /* Prevent anything to be enabled again and halt device */
+               priv->closing = true;
+               netif_stop_queue(dev);
+               grcan_stop_hardware(dev);
+               priv->can.state = CAN_STATE_STOPPED;
+
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+
+       /* Pass on error frame if something to report,
+        * i.e. id contains some information
+        */
+       if (cf.can_id) {
+               struct can_frame *skb_cf;
+               struct sk_buff *skb = alloc_can_err_skb(dev, &skb_cf);
+
+               if (skb == NULL) {
+                       netdev_dbg(dev, "could not allocate error frame\n");
+                       return;
+               }
+               skb_cf->can_id |= cf.can_id;
+               memcpy(skb_cf->data, cf.data, sizeof(cf.data));
+
+               netif_rx(skb);
+       }
+}
+
+static irqreturn_t grcan_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       u32 sources, status;
+
+       /* Find out the source */
+       sources = grcan_read_reg(&regs->pimsr);
+       if (!sources)
+               return IRQ_NONE;
+       grcan_write_reg(&regs->picr, sources);
+       status = grcan_read_reg(&regs->stat);
+
+       /* If we got TX progress, the device has not hanged,
+        * so disable the hang timer
+        */
+       if (priv->need_txbug_workaround &&
+           (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_TXLOSS))) {
+               del_timer(&priv->hang_timer);
+       }
+
+       /* Frame(s) received or transmitted */
+       if (sources & (GRCAN_IRQ_TX | GRCAN_IRQ_RX)) {
+               /* Disable tx/rx interrupts and schedule poll(). No need for
+                * locking as interference from a running reset at worst leads
+                * to an extra interrupt.
+                */
+               grcan_clear_bits(&regs->imr, GRCAN_IRQ_TX | GRCAN_IRQ_RX);
+               napi_schedule(&priv->napi);
+       }
+
+       /* (Potential) error conditions to take care of */
+       if (sources & GRCAN_IRQ_ERRORS)
+               grcan_err(dev, sources, status);
+
+       return IRQ_HANDLED;
+}
+
+/* Reset device and restart operations from where they were.
+ *
+ * This assumes that RXCTRL & RXCTRL is properly disabled and that RX
+ * is not ONGOING (TX might be stuck in ONGOING due to a harwrware bug
+ * for single shot)
+ */
+static void grcan_running_reset(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       unsigned long flags;
+
+       /* This temporarily messes with eskbp, so we need to lock
+        * priv->lock
+        */
+       spin_lock_irqsave(&priv->lock, flags);
+
+       priv->resetting = false;
+       del_timer(&priv->hang_timer);
+       del_timer(&priv->rr_timer);
+
+       if (!priv->closing) {
+               /* Save and reset - config register preserved by grcan_reset */
+               u32 imr = grcan_read_reg(&regs->imr);
+
+               u32 txaddr = grcan_read_reg(&regs->txaddr);
+               u32 txsize = grcan_read_reg(&regs->txsize);
+               u32 txwr = grcan_read_reg(&regs->txwr);
+               u32 txrd = grcan_read_reg(&regs->txrd);
+               u32 eskbp = priv->eskbp;
+
+               u32 rxaddr = grcan_read_reg(&regs->rxaddr);
+               u32 rxsize = grcan_read_reg(&regs->rxsize);
+               u32 rxwr = grcan_read_reg(&regs->rxwr);
+               u32 rxrd = grcan_read_reg(&regs->rxrd);
+
+               grcan_reset(dev);
+
+               /* Restore */
+               grcan_write_reg(&regs->txaddr, txaddr);
+               grcan_write_reg(&regs->txsize, txsize);
+               grcan_write_reg(&regs->txwr, txwr);
+               grcan_write_reg(&regs->txrd, txrd);
+               priv->eskbp = eskbp;
+
+               grcan_write_reg(&regs->rxaddr, rxaddr);
+               grcan_write_reg(&regs->rxsize, rxsize);
+               grcan_write_reg(&regs->rxwr, rxwr);
+               grcan_write_reg(&regs->rxrd, rxrd);
+
+               /* Turn on device again */
+               grcan_write_reg(&regs->imr, imr);
+               priv->can.state = CAN_STATE_ERROR_ACTIVE;
+               grcan_write_reg(&regs->txctrl, GRCAN_TXCTRL_ENABLE
+                               | (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT
+                                  ? GRCAN_TXCTRL_SINGLE : 0));
+               grcan_write_reg(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+               grcan_write_reg(&regs->ctrl, GRCAN_CTRL_ENABLE);
+
+               /* Start queue if there is size and listen-onle mode is not
+                * enabled
+                */
+               if (grcan_txspace(priv->dma.tx.size, txwr, priv->eskbp) &&
+                   !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+                       netif_wake_queue(dev);
+       }
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       netdev_err(dev, "Device reset and restored\n");
+}
+
+/* Waiting time in usecs corresponding to the transmission of three maximum
+ * sized can frames in the given bitrate (in bits/sec). Waiting for this amount
+ * of time makes sure that the can controller have time to finish sending or
+ * receiving a frame with a good margin.
+ *
+ * usecs/sec * number of frames * bits/frame / bits/sec
+ */
+static inline u32 grcan_ongoing_wait_usecs(__u32 bitrate)
+{
+       return 1000000 * 3 * GRCAN_EFF_FRAME_MAX_BITS / bitrate;
+}
+
+/* Set timer so that it will not fire until after a period in which the can
+ * controller have a good margin to finish transmitting a frame unless it has
+ * hanged
+ */
+static inline void grcan_reset_timer(struct timer_list *timer, __u32 bitrate)
+{
+       u32 wait_jiffies = usecs_to_jiffies(grcan_ongoing_wait_usecs(bitrate));
+
+       mod_timer(timer, jiffies + wait_jiffies);
+}
+
+/* Disable channels and schedule a running reset */
+static void grcan_initiate_running_reset(unsigned long data)
+{
+       struct net_device *dev = (struct net_device *)data;
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       unsigned long flags;
+
+       netdev_err(dev, "Device seems hanged - reset scheduled\n");
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       /* The main body of this function must never be executed again
+        * until after an execution of grcan_running_reset
+        */
+       if (!priv->resetting && !priv->closing) {
+               priv->resetting = true;
+               netif_stop_queue(dev);
+               grcan_clear_bits(&regs->txctrl, GRCAN_TXCTRL_ENABLE);
+               grcan_clear_bits(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+               grcan_reset_timer(&priv->rr_timer, priv->can.bittiming.bitrate);
+       }
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static void grcan_free_dma_buffers(struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_dma *dma = &priv->dma;
+
+       dma_free_coherent(&dev->dev, dma->base_size, dma->base_buf,
+                         dma->base_handle);
+       memset(dma, 0, sizeof(*dma));
+}
+
+static int grcan_allocate_dma_buffers(struct net_device *dev,
+                                     size_t tsize, size_t rsize)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_dma *dma = &priv->dma;
+       struct grcan_dma_buffer *large = rsize > tsize ? &dma->rx : &dma->tx;
+       struct grcan_dma_buffer *small = rsize > tsize ? &dma->tx : &dma->rx;
+       size_t shift;
+
+       /* Need a whole number of GRCAN_BUFFER_ALIGNMENT for the large,
+        * i.e. first buffer
+        */
+       size_t maxs = max(tsize, rsize);
+       size_t lsize = ALIGN(maxs, GRCAN_BUFFER_ALIGNMENT);
+
+       /* Put the small buffer after that */
+       size_t ssize = min(tsize, rsize);
+
+       /* Extra GRCAN_BUFFER_ALIGNMENT to allow for alignment */
+       dma->base_size = lsize + ssize + GRCAN_BUFFER_ALIGNMENT;
+       dma->base_buf = dma_alloc_coherent(&dev->dev,
+                                          dma->base_size,
+                                          &dma->base_handle,
+                                          GFP_KERNEL);
+
+       if (!dma->base_buf)
+               return -ENOMEM;
+
+       dma->tx.size = tsize;
+       dma->rx.size = rsize;
+
+       large->handle = ALIGN(dma->base_handle, GRCAN_BUFFER_ALIGNMENT);
+       small->handle = large->handle + lsize;
+       shift = large->handle - dma->base_handle;
+
+       large->buf = dma->base_buf + shift;
+       small->buf = large->buf + lsize;
+
+       return 0;
+}
+
+/* priv->lock *must* be held when calling this function */
+static int grcan_start(struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       u32 confop, txctrl;
+
+       grcan_reset(dev);
+
+       grcan_write_reg(&regs->txaddr, priv->dma.tx.handle);
+       grcan_write_reg(&regs->txsize, priv->dma.tx.size);
+       /* regs->txwr, regs->txrd and priv->eskbp already set to 0 by reset */
+
+       grcan_write_reg(&regs->rxaddr, priv->dma.rx.handle);
+       grcan_write_reg(&regs->rxsize, priv->dma.rx.size);
+       /* regs->rxwr and regs->rxrd already set to 0 by reset */
+
+       /* Enable interrupts */
+       grcan_read_reg(&regs->pir);
+       grcan_write_reg(&regs->imr, GRCAN_IRQ_DEFAULT);
+
+       /* Enable interfaces, channels and device */
+       confop = GRCAN_CONF_ABORT
+               | (priv->config.enable0 ? GRCAN_CONF_ENABLE0 : 0)
+               | (priv->config.enable1 ? GRCAN_CONF_ENABLE1 : 0)
+               | (priv->config.select ? GRCAN_CONF_SELECT : 0)
+               | (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY ?
+                  GRCAN_CONF_SILENT : 0)
+               | (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES ?
+                  GRCAN_CONF_SAM : 0);
+       grcan_write_bits(&regs->conf, confop, GRCAN_CONF_OPERATION);
+       txctrl = GRCAN_TXCTRL_ENABLE
+               | (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT
+                  ? GRCAN_TXCTRL_SINGLE : 0);
+       grcan_write_reg(&regs->txctrl, txctrl);
+       grcan_write_reg(&regs->rxctrl, GRCAN_RXCTRL_ENABLE);
+       grcan_write_reg(&regs->ctrl, GRCAN_CTRL_ENABLE);
+
+       priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+       return 0;
+}
+
+static int grcan_set_mode(struct net_device *dev, enum can_mode mode)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       unsigned long flags;
+       int err = 0;
+
+       if (mode == CAN_MODE_START) {
+               /* This might be called to restart the device to recover from
+                * bus off errors
+                */
+               spin_lock_irqsave(&priv->lock, flags);
+               if (priv->closing || priv->resetting) {
+                       err = -EBUSY;
+               } else {
+                       netdev_info(dev, "Restarting device\n");
+                       grcan_start(dev);
+                       if (!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+                               netif_wake_queue(dev);
+               }
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return err;
+       }
+       return -EOPNOTSUPP;
+}
+
+static int grcan_open(struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_dma *dma = &priv->dma;
+       unsigned long flags;
+       int err;
+
+       /* Allocate memory */
+       err = grcan_allocate_dma_buffers(dev, priv->config.txsize,
+                                        priv->config.rxsize);
+       if (err) {
+               netdev_err(dev, "could not allocate DMA buffers\n");
+               return err;
+       }
+
+       priv->echo_skb = kzalloc(dma->tx.size * sizeof(*priv->echo_skb),
+                                GFP_KERNEL);
+       if (!priv->echo_skb) {
+               err = -ENOMEM;
+               goto exit_free_dma_buffers;
+       }
+       priv->can.echo_skb_max = dma->tx.size;
+       priv->can.echo_skb = priv->echo_skb;
+
+       priv->txdlc = kzalloc(dma->tx.size * sizeof(*priv->txdlc), GFP_KERNEL);
+       if (!priv->txdlc) {
+               err = -ENOMEM;
+               goto exit_free_echo_skb;
+       }
+
+       /* Get can device up */
+       err = open_candev(dev);
+       if (err)
+               goto exit_free_txdlc;
+
+       err = request_irq(dev->irq, grcan_interrupt, IRQF_SHARED,
+                         dev->name, dev);
+       if (err)
+               goto exit_close_candev;
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       napi_enable(&priv->napi);
+       grcan_start(dev);
+       if (!(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+               netif_start_queue(dev);
+       priv->resetting = false;
+       priv->closing = false;
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return 0;
+
+exit_close_candev:
+       close_candev(dev);
+exit_free_txdlc:
+       kfree(priv->txdlc);
+exit_free_echo_skb:
+       kfree(priv->echo_skb);
+exit_free_dma_buffers:
+       grcan_free_dma_buffers(dev);
+       return err;
+}
+
+static int grcan_close(struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       unsigned long flags;
+
+       napi_disable(&priv->napi);
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       priv->closing = true;
+       if (priv->need_txbug_workaround) {
+               del_timer_sync(&priv->hang_timer);
+               del_timer_sync(&priv->rr_timer);
+       }
+       netif_stop_queue(dev);
+       grcan_stop_hardware(dev);
+       priv->can.state = CAN_STATE_STOPPED;
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       free_irq(dev->irq, dev);
+       close_candev(dev);
+
+       grcan_free_dma_buffers(dev);
+       priv->can.echo_skb_max = 0;
+       priv->can.echo_skb = NULL;
+       kfree(priv->echo_skb);
+       kfree(priv->txdlc);
+
+       return 0;
+}
+
+static int grcan_transmit_catch_up(struct net_device *dev, int budget)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       unsigned long flags;
+       int work_done;
+
+       spin_lock_irqsave(&priv->lock, flags);
+
+       work_done = catch_up_echo_skb(dev, budget, true);
+       if (work_done) {
+               if (!priv->resetting && !priv->closing &&
+                   !(priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY))
+                       netif_wake_queue(dev);
+
+               /* With napi we don't get TX interrupts for a while,
+                * so prevent a running reset while catching up
+                */
+               if (priv->need_txbug_workaround)
+                       del_timer(&priv->hang_timer);
+       }
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return work_done;
+}
+
+static int grcan_receive(struct net_device *dev, int budget)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       struct grcan_dma *dma = &priv->dma;
+       struct net_device_stats *stats = &dev->stats;
+       struct can_frame *cf;
+       struct sk_buff *skb;
+       u32 wr, rd, startrd;
+       u32 *slot;
+       u32 i, rtr, eff, j, shift;
+       int work_done = 0;
+
+       rd = grcan_read_reg(&regs->rxrd);
+       startrd = rd;
+       for (work_done = 0; work_done < budget; work_done++) {
+               /* Check for packet to receive */
+               wr = grcan_read_reg(&regs->rxwr);
+               if (rd == wr)
+                       break;
+
+               /* Take care of packet */
+               skb = alloc_can_skb(dev, &cf);
+               if (skb == NULL) {
+                       netdev_err(dev,
+                                  "dropping frame: skb allocation failed\n");
+                       stats->rx_dropped++;
+                       continue;
+               }
+
+               slot = dma->rx.buf + rd;
+               eff = slot[0] & GRCAN_MSG_IDE;
+               rtr = slot[0] & GRCAN_MSG_RTR;
+               if (eff) {
+                       cf->can_id = ((slot[0] & GRCAN_MSG_EID)
+                                     >> GRCAN_MSG_EID_BIT);
+                       cf->can_id |= CAN_EFF_FLAG;
+               } else {
+                       cf->can_id = ((slot[0] & GRCAN_MSG_BID)
+                                     >> GRCAN_MSG_BID_BIT);
+               }
+               cf->can_dlc = get_can_dlc((slot[1] & GRCAN_MSG_DLC)
+                                         >> GRCAN_MSG_DLC_BIT);
+               if (rtr) {
+                       cf->can_id |= CAN_RTR_FLAG;
+               } else {
+                       for (i = 0; i < cf->can_dlc; i++) {
+                               j = GRCAN_MSG_DATA_SLOT_INDEX(i);
+                               shift = GRCAN_MSG_DATA_SHIFT(i);
+                               cf->data[i] = (u8)(slot[j] >> shift);
+                       }
+               }
+               netif_receive_skb(skb);
+
+               /* Update statistics and read pointer */
+               stats->rx_packets++;
+               stats->rx_bytes += cf->can_dlc;
+               rd = grcan_ring_add(rd, GRCAN_MSG_SIZE, dma->rx.size);
+       }
+
+       /* Make sure everything is read before allowing hardware to
+        * use the memory
+        */
+       mb();
+
+       /* Update read pointer - no need to check for ongoing */
+       if (likely(rd != startrd))
+               grcan_write_reg(&regs->rxrd, rd);
+
+       return work_done;
+}
+
+static int grcan_poll(struct napi_struct *napi, int budget)
+{
+       struct grcan_priv *priv = container_of(napi, struct grcan_priv, napi);
+       struct net_device *dev = priv->dev;
+       struct grcan_registers __iomem *regs = priv->regs;
+       unsigned long flags;
+       int tx_work_done, rx_work_done;
+       int rx_budget = budget / 2;
+       int tx_budget = budget - rx_budget;
+
+       /* Half of the budget for receiveing messages */
+       rx_work_done = grcan_receive(dev, rx_budget);
+
+       /* Half of the budget for transmitting messages as that can trigger echo
+        * frames being received
+        */
+       tx_work_done = grcan_transmit_catch_up(dev, tx_budget);
+
+       if (rx_work_done < rx_budget && tx_work_done < tx_budget) {
+               napi_complete(napi);
+
+               /* Guarantee no interference with a running reset that otherwise
+                * could turn off interrupts.
+                */
+               spin_lock_irqsave(&priv->lock, flags);
+
+               /* Enable tx and rx interrupts again. No need to check
+                * priv->closing as napi_disable in grcan_close is waiting for
+                * scheduled napi calls to finish.
+                */
+               grcan_set_bits(&regs->imr, GRCAN_IRQ_TX | GRCAN_IRQ_RX);
+
+               spin_unlock_irqrestore(&priv->lock, flags);
+       }
+
+       return rx_work_done + tx_work_done;
+}
+
+/* Work tx bug by waiting while for the risky situation to clear. If that fails,
+ * drop a frame in one-shot mode or indicate a busy device otherwise.
+ *
+ * Returns 0 on successful wait. Otherwise it sets *netdev_tx_status to the
+ * value that should be returned by grcan_start_xmit when aborting the xmit.
+ */
+static int grcan_txbug_workaround(struct net_device *dev, struct sk_buff *skb,
+                                 u32 txwr, u32 oneshotmode,
+                                 netdev_tx_t *netdev_tx_status)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       struct grcan_dma *dma = &priv->dma;
+       int i;
+       unsigned long flags;
+
+       /* Wait a while for ongoing to be cleared or read pointer to catch up to
+        * write pointer. The latter is needed due to a bug in older versions of
+        * GRCAN in which ONGOING is not cleared properly one-shot mode when a
+        * transmission fails.
+        */
+       for (i = 0; i < GRCAN_SHORTWAIT_USECS; i++) {
+               udelay(1);
+               if (!grcan_read_bits(&regs->txctrl, GRCAN_TXCTRL_ONGOING) ||
+                   grcan_read_reg(&regs->txrd) == txwr) {
+                       return 0;
+               }
+       }
+
+       /* Clean up, in case the situation was not resolved */
+       spin_lock_irqsave(&priv->lock, flags);
+       if (!priv->resetting && !priv->closing) {
+               /* Queue might have been stopped earlier in grcan_start_xmit */
+               if (grcan_txspace(dma->tx.size, txwr, priv->eskbp))
+                       netif_wake_queue(dev);
+               /* Set a timer to resolve a hanged tx controller */
+               if (!timer_pending(&priv->hang_timer))
+                       grcan_reset_timer(&priv->hang_timer,
+                                         priv->can.bittiming.bitrate);
+       }
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       if (oneshotmode) {
+               /* In one-shot mode we should never end up here because
+                * then the interrupt handler increases txrd on TXLOSS,
+                * but it is consistent with one-shot mode to drop the
+                * frame in this case.
+                */
+               kfree_skb(skb);
+               *netdev_tx_status = NETDEV_TX_OK;
+       } else {
+               /* In normal mode the socket-can transmission queue get
+                * to keep the frame so that it can be retransmitted
+                * later
+                */
+               *netdev_tx_status = NETDEV_TX_BUSY;
+       }
+       return -EBUSY;
+}
+
+/* Notes on the tx cyclic buffer handling:
+ *
+ * regs->txwr  - the next slot for the driver to put data to be sent
+ * regs->txrd  - the next slot for the device to read data
+ * priv->eskbp - the next slot for the driver to call can_put_echo_skb for
+ *
+ * grcan_start_xmit can enter more messages as long as regs->txwr does
+ * not reach priv->eskbp (within 1 message gap)
+ *
+ * The device sends messages until regs->txrd reaches regs->txwr
+ *
+ * The interrupt calls handler calls can_put_echo_skb until
+ * priv->eskbp reaches regs->txrd
+ */
+static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
+                                   struct net_device *dev)
+{
+       struct grcan_priv *priv = netdev_priv(dev);
+       struct grcan_registers __iomem *regs = priv->regs;
+       struct grcan_dma *dma = &priv->dma;
+       struct can_frame *cf = (struct can_frame *)skb->data;
+       u32 id, txwr, txrd, space, txctrl;
+       int slotindex;
+       u32 *slot;
+       u32 i, rtr, eff, dlc, tmp, err;
+       int j, shift;
+       unsigned long flags;
+       u32 oneshotmode = priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT;
+
+       if (can_dropped_invalid_skb(dev, skb))
+               return NETDEV_TX_OK;
+
+       /* Trying to transmit in silent mode will generate error interrupts, but
+        * this should never happen - the queue should not have been started.
+        */
+       if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+               return NETDEV_TX_BUSY;
+
+       /* Reads of priv->eskbp and shut-downs of the queue needs to
+        * be atomic towards the updates to priv->eskbp and wake-ups
+        * of the queue in the interrupt handler.
+        */
+       spin_lock_irqsave(&priv->lock, flags);
+
+       txwr = grcan_read_reg(&regs->txwr);
+       space = grcan_txspace(dma->tx.size, txwr, priv->eskbp);
+
+       slotindex = txwr / GRCAN_MSG_SIZE;
+       slot = dma->tx.buf + txwr;
+
+       if (unlikely(space == 1))
+               netif_stop_queue(dev);
+
+       spin_unlock_irqrestore(&priv->lock, flags);
+       /* End of critical section*/
+
+       /* This should never happen. If circular buffer is full, the
+        * netif_stop_queue should have been stopped already.
+        */
+       if (unlikely(!space)) {
+               netdev_err(dev, "No buffer space, but queue is non-stopped.\n");
+               return NETDEV_TX_BUSY;
+       }
+
+       /* Convert and write CAN message to DMA buffer */
+       eff = cf->can_id & CAN_EFF_FLAG;
+       rtr = cf->can_id & CAN_RTR_FLAG;
+       id = cf->can_id & (eff ? CAN_EFF_MASK : CAN_SFF_MASK);
+       dlc = cf->can_dlc;
+       if (eff)
+               tmp = (id << GRCAN_MSG_EID_BIT) & GRCAN_MSG_EID;
+       else
+               tmp = (id << GRCAN_MSG_BID_BIT) & GRCAN_MSG_BID;
+       slot[0] = (eff ? GRCAN_MSG_IDE : 0) | (rtr ? GRCAN_MSG_RTR : 0) | tmp;
+
+       slot[1] = ((dlc << GRCAN_MSG_DLC_BIT) & GRCAN_MSG_DLC);
+       slot[2] = 0;
+       slot[3] = 0;
+       for (i = 0; i < dlc; i++) {
+               j = GRCAN_MSG_DATA_SLOT_INDEX(i);
+               shift = GRCAN_MSG_DATA_SHIFT(i);
+               slot[j] |= cf->data[i] << shift;
+       }
+
+       /* Checking that channel has not been disabled. These cases
+        * should never happen
+        */
+       txctrl = grcan_read_reg(&regs->txctrl);
+       if (!(txctrl & GRCAN_TXCTRL_ENABLE))
+               netdev_err(dev, "tx channel spuriously disabled\n");
+
+       if (oneshotmode && !(txctrl & GRCAN_TXCTRL_SINGLE))
+               netdev_err(dev, "one-shot mode spuriously disabled\n");
+
+       /* Bug workaround for old version of grcan where updating txwr
+        * in the same clock cycle as the controller updates txrd to
+        * the current txwr could hang the can controller
+        */
+       if (priv->need_txbug_workaround) {
+               txrd = grcan_read_reg(&regs->txrd);
+               if (unlikely(grcan_ring_sub(txwr, txrd, dma->tx.size) == 1)) {
+                       netdev_tx_t txstatus;
+
+                       err = grcan_txbug_workaround(dev, skb, txwr,
+                                                    oneshotmode, &txstatus);
+                       if (err)
+                               return txstatus;
+               }
+       }
+
+       /* Prepare skb for echoing. This must be after the bug workaround above
+        * as ownership of the skb is passed on by calling can_put_echo_skb.
+        * Returning NETDEV_TX_BUSY or accessing skb or cf after a call to
+        * can_put_echo_skb would be an error unless other measures are
+        * taken.
+        */
+       priv->txdlc[slotindex] = cf->can_dlc; /* Store dlc for statistics */
+       can_put_echo_skb(skb, dev, slotindex);
+
+       /* Make sure everything is written before allowing hardware to
+        * read from the memory
+        */
+       wmb();
+
+       /* Update write pointer to start transmission */
+       grcan_write_reg(&regs->txwr,
+                       grcan_ring_add(txwr, GRCAN_MSG_SIZE, dma->tx.size));
+
+       return NETDEV_TX_OK;
+}
+
+/* ========== Setting up sysfs interface and module parameters ========== */
+
+#define GRCAN_NOT_BOOL(unsigned_val) ((unsigned_val) > 1)
+
+#define GRCAN_MODULE_PARAM(name, mtype, valcheckf, desc)               \
+       static void grcan_sanitize_##name(struct platform_device *pd)   \
+       {                                                               \
+               struct grcan_device_config grcan_default_config         \
+                       = GRCAN_DEFAULT_DEVICE_CONFIG;                  \
+               if (valcheckf(grcan_module_config.name)) {              \
+                       dev_err(&pd->dev,                               \
+                               "Invalid module parameter value for "   \
+                               #name " - setting default\n");          \
+                       grcan_module_config.name =                      \
+                               grcan_default_config.name;              \
+               }                                                       \
+       }                                                               \
+       module_param_named(name, grcan_module_config.name,              \
+                          mtype, S_IRUGO);                             \
+       MODULE_PARM_DESC(name, desc)
+
+#define GRCAN_CONFIG_ATTR(name, desc)                                  \
+       static ssize_t grcan_store_##name(struct device *sdev,          \
+                                         struct device_attribute *att, \
+                                         const char *buf,              \
+                                         size_t count)                 \
+       {                                                               \
+               struct net_device *dev = to_net_dev(sdev);              \
+               struct grcan_priv *priv = netdev_priv(dev);             \
+               u8 val;                                                 \
+               int ret;                                                \
+               if (dev->flags & IFF_UP)                                \
+                       return -EBUSY;                                  \
+               ret = kstrtou8(buf, 0, &val);                           \
+               if (ret < 0 || val > 1)                                 \
+                       return -EINVAL;                                 \
+               priv->config.name = val;                                \
+               return count;                                           \
+       }                                                               \
+       static ssize_t grcan_show_##name(struct device *sdev,           \
+                                        struct device_attribute *att,  \
+                                        char *buf)                     \
+       {                                                               \
+               struct net_device *dev = to_net_dev(sdev);              \
+               struct grcan_priv *priv = netdev_priv(dev);             \
+               return sprintf(buf, "%d\n", priv->config.name);         \
+       }                                                               \
+       static DEVICE_ATTR(name, S_IRUGO | S_IWUSR,                     \
+                          grcan_show_##name,                           \
+                          grcan_store_##name);                         \
+       GRCAN_MODULE_PARAM(name, ushort, GRCAN_NOT_BOOL, desc)
+
+/* The following configuration options are made available both via module
+ * parameters and writable sysfs files. See the chapter about GRCAN in the
+ * documentation for the GRLIB VHDL library for further details.
+ */
+GRCAN_CONFIG_ATTR(enable0,
+                 "Configuration of physical interface 0. Determines\n" \
+                 "the \"Enable 0\" bit of the configuration register.\n" \
+                 "Format: 0 | 1\nDefault: 0\n");
+
+GRCAN_CONFIG_ATTR(enable1,
+                 "Configuration of physical interface 1. Determines\n" \
+                 "the \"Enable 1\" bit of the configuration register.\n" \
+                 "Format: 0 | 1\nDefault: 0\n");
+
+GRCAN_CONFIG_ATTR(select,
+                 "Select which physical interface to use.\n"   \
+                 "Format: 0 | 1\nDefault: 0\n");
+
+/* The tx and rx buffer size configuration options are only available via module
+ * parameters.
+ */
+GRCAN_MODULE_PARAM(txsize, uint, GRCAN_INVALID_BUFFER_SIZE,
+                  "Sets the size of the tx buffer.\n"                  \
+                  "Format: <unsigned int> where (txsize & ~0x1fffc0) == 0\n" \
+                  "Default: 1024\n");
+GRCAN_MODULE_PARAM(rxsize, uint, GRCAN_INVALID_BUFFER_SIZE,
+                  "Sets the size of the rx buffer.\n"                  \
+                  "Format: <unsigned int> where (size & ~0x1fffc0) == 0\n" \
+                  "Default: 1024\n");
+
+/* Function that makes sure that configuration done using
+ * module parameters are set to valid values
+ */
+static void grcan_sanitize_module_config(struct platform_device *ofdev)
+{
+       grcan_sanitize_enable0(ofdev);
+       grcan_sanitize_enable1(ofdev);
+       grcan_sanitize_select(ofdev);
+       grcan_sanitize_txsize(ofdev);
+       grcan_sanitize_rxsize(ofdev);
+}
+
+static const struct attribute *const sysfs_grcan_attrs[] = {
+       /* Config attrs */
+       &dev_attr_enable0.attr,
+       &dev_attr_enable1.attr,
+       &dev_attr_select.attr,
+       NULL,
+};
+
+static const struct attribute_group sysfs_grcan_group = {
+       .name   = "grcan",
+       .attrs  = (struct attribute **)sysfs_grcan_attrs,
+};
+
+/* ========== Setting up the driver ========== */
+
+static const struct net_device_ops grcan_netdev_ops = {
+       .ndo_open       = grcan_open,
+       .ndo_stop       = grcan_close,
+       .ndo_start_xmit = grcan_start_xmit,
+};
+
+static int grcan_setup_netdev(struct platform_device *ofdev,
+                             void __iomem *base,
+                             int irq, u32 ambafreq, bool txbug)
+{
+       struct net_device *dev;
+       struct grcan_priv *priv;
+       struct grcan_registers __iomem *regs;
+       int err;
+
+       dev = alloc_candev(sizeof(struct grcan_priv), 0);
+       if (!dev)
+               return -ENOMEM;
+
+       dev->irq = irq;
+       dev->flags |= IFF_ECHO;
+       dev->netdev_ops = &grcan_netdev_ops;
+       dev->sysfs_groups[0] = &sysfs_grcan_group;
+
+       priv = netdev_priv(dev);
+       memcpy(&priv->config, &grcan_module_config,
+              sizeof(struct grcan_device_config));
+       priv->dev = dev;
+       priv->regs = base;
+       priv->can.bittiming_const = &grcan_bittiming_const;
+       priv->can.do_set_bittiming = grcan_set_bittiming;
+       priv->can.do_set_mode = grcan_set_mode;
+       priv->can.do_get_berr_counter = grcan_get_berr_counter;
+       priv->can.clock.freq = ambafreq;
+       priv->can.ctrlmode_supported =
+               CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_ONE_SHOT;
+       priv->need_txbug_workaround = txbug;
+
+       /* Discover if triple sampling is supported by hardware */
+       regs = priv->regs;
+       grcan_set_bits(&regs->ctrl, GRCAN_CTRL_RESET);
+       grcan_set_bits(&regs->conf, GRCAN_CONF_SAM);
+       if (grcan_read_bits(&regs->conf, GRCAN_CONF_SAM)) {
+               priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
+               dev_dbg(&ofdev->dev, "Hardware supports triple-sampling\n");
+       }
+
+       spin_lock_init(&priv->lock);
+
+       if (priv->need_txbug_workaround) {
+               init_timer(&priv->rr_timer);
+               priv->rr_timer.function = grcan_running_reset;
+               priv->rr_timer.data = (unsigned long)dev;
+
+               init_timer(&priv->hang_timer);
+               priv->hang_timer.function = grcan_initiate_running_reset;
+               priv->hang_timer.data = (unsigned long)dev;
+       }
+
+       netif_napi_add(dev, &priv->napi, grcan_poll, GRCAN_NAPI_WEIGHT);
+
+       SET_NETDEV_DEV(dev, &ofdev->dev);
+       dev_info(&ofdev->dev, "regs=0x%p, irq=%d, clock=%d\n",
+                priv->regs, dev->irq, priv->can.clock.freq);
+
+       err = register_candev(dev);
+       if (err)
+               goto exit_free_candev;
+
+       dev_set_drvdata(&ofdev->dev, dev);
+
+       /* Reset device to allow bit-timing to be set. No need to call
+        * grcan_reset at this stage. That is done in grcan_open.
+        */
+       grcan_write_reg(&regs->ctrl, GRCAN_CTRL_RESET);
+
+       return 0;
+exit_free_candev:
+       free_candev(dev);
+       return err;
+}
+
+static int grcan_probe(struct platform_device *ofdev)
+{
+       struct device_node *np = ofdev->dev.of_node;
+       struct resource *res;
+       u32 sysid, ambafreq;
+       int irq, err;
+       void __iomem *base;
+       bool txbug = true;
+
+       /* Compare GRLIB version number with the first that does not
+        * have the tx bug (see start_xmit)
+        */
+       err = of_property_read_u32(np, "systemid", &sysid);
+       if (!err && ((sysid & GRLIB_VERSION_MASK)
+                    >= GRCAN_TXBUG_SAFE_GRLIB_VERSION))
+               txbug = false;
+
+       err = of_property_read_u32(np, "freq", &ambafreq);
+       if (err) {
+               dev_err(&ofdev->dev, "unable to fetch \"freq\" property\n");
+               goto exit_error;
+       }
+
+       res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+       base = devm_request_and_ioremap(&ofdev->dev, res);
+       if (!base) {
+               dev_err(&ofdev->dev, "couldn't map IO resource\n");
+               err = -EADDRNOTAVAIL;
+               goto exit_error;
+       }
+
+       irq = irq_of_parse_and_map(np, GRCAN_IRQIX_IRQ);
+       if (!irq) {
+               dev_err(&ofdev->dev, "no irq found\n");
+               err = -ENODEV;
+               goto exit_error;
+       }
+
+       grcan_sanitize_module_config(ofdev);
+
+       err = grcan_setup_netdev(ofdev, base, irq, ambafreq, txbug);
+       if (err)
+               goto exit_dispose_irq;
+
+       return 0;
+
+exit_dispose_irq:
+       irq_dispose_mapping(irq);
+exit_error:
+       dev_err(&ofdev->dev,
+               "%s socket CAN driver initialization failed with error %d\n",
+               DRV_NAME, err);
+       return err;
+}
+
+static int grcan_remove(struct platform_device *ofdev)
+{
+       struct net_device *dev = dev_get_drvdata(&ofdev->dev);
+       struct grcan_priv *priv = netdev_priv(dev);
+
+       unregister_candev(dev); /* Will in turn call grcan_close */
+
+       irq_dispose_mapping(dev->irq);
+       dev_set_drvdata(&ofdev->dev, NULL);
+       netif_napi_del(&priv->napi);
+       free_candev(dev);
+
+       return 0;
+}
+
+static struct of_device_id grcan_match[] = {
+       {.name = "GAISLER_GRCAN"},
+       {.name = "01_03d"},
+       {.name = "GAISLER_GRHCAN"},
+       {.name = "01_034"},
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, grcan_match);
+
+static struct platform_driver grcan_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+               .of_match_table = grcan_match,
+       },
+       .probe = grcan_probe,
+       .remove = grcan_remove,
+};
+
+module_platform_driver(grcan_driver);
+
+MODULE_AUTHOR("Aeroflex Gaisler AB.");
+MODULE_DESCRIPTION("Socket CAN driver for Aeroflex Gaisler GRCAN");
+MODULE_LICENSE("GPL");
index 7edadee487bab16c0cbcf514ab59540f35cc2a41..c4bc1d2e2033214db1a20ff584d184f35d8635ec 100644 (file)
@@ -365,7 +365,7 @@ static int ican3_old_send_msg(struct ican3_dev *mod, struct ican3_msg *msg)
  * ICAN3 "new-style" Host Interface Setup
  */
 
-static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod)
+static void ican3_init_new_host_interface(struct ican3_dev *mod)
 {
        struct ican3_new_desc desc;
        unsigned long flags;
@@ -444,7 +444,7 @@ static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod)
  * ICAN3 Fast Host Interface Setup
  */
 
-static void __devinit ican3_init_fast_host_interface(struct ican3_dev *mod)
+static void ican3_init_fast_host_interface(struct ican3_dev *mod)
 {
        struct ican3_fast_desc desc;
        unsigned long flags;
@@ -631,7 +631,7 @@ static int ican3_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg)
  * Quick Pre-constructed Messages
  */
 
-static int __devinit ican3_msg_connect(struct ican3_dev *mod)
+static int ican3_msg_connect(struct ican3_dev *mod)
 {
        struct ican3_msg msg;
 
@@ -642,7 +642,7 @@ static int __devinit ican3_msg_connect(struct ican3_dev *mod)
        return ican3_send_msg(mod, &msg);
 }
 
-static int __devexit ican3_msg_disconnect(struct ican3_dev *mod)
+static int ican3_msg_disconnect(struct ican3_dev *mod)
 {
        struct ican3_msg msg;
 
@@ -653,7 +653,7 @@ static int __devexit ican3_msg_disconnect(struct ican3_dev *mod)
        return ican3_send_msg(mod, &msg);
 }
 
-static int __devinit ican3_msg_newhostif(struct ican3_dev *mod)
+static int ican3_msg_newhostif(struct ican3_dev *mod)
 {
        struct ican3_msg msg;
        int ret;
@@ -674,7 +674,7 @@ static int __devinit ican3_msg_newhostif(struct ican3_dev *mod)
        return 0;
 }
 
-static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod)
+static int ican3_msg_fasthostif(struct ican3_dev *mod)
 {
        struct ican3_msg msg;
        unsigned int addr;
@@ -707,7 +707,7 @@ static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod)
  * Setup the CAN filter to either accept or reject all
  * messages from the CAN bus.
  */
-static int __devinit ican3_set_id_filter(struct ican3_dev *mod, bool accept)
+static int ican3_set_id_filter(struct ican3_dev *mod, bool accept)
 {
        struct ican3_msg msg;
        int ret;
@@ -1421,7 +1421,7 @@ static int ican3_reset_module(struct ican3_dev *mod)
        return -ETIMEDOUT;
 }
 
-static void __devexit ican3_shutdown_module(struct ican3_dev *mod)
+static void ican3_shutdown_module(struct ican3_dev *mod)
 {
        ican3_msg_disconnect(mod);
        ican3_reset_module(mod);
@@ -1430,7 +1430,7 @@ static void __devexit ican3_shutdown_module(struct ican3_dev *mod)
 /*
  * Startup an ICAN module, bringing it into fast mode
  */
-static int __devinit ican3_startup_module(struct ican3_dev *mod)
+static int ican3_startup_module(struct ican3_dev *mod)
 {
        int ret;
 
@@ -1692,7 +1692,7 @@ static int ican3_get_berr_counter(const struct net_device *ndev,
                return ret;
 
        ret = wait_for_completion_timeout(&mod->buserror_comp, HZ);
-       if (ret <= 0) {
+       if (ret == 0) {
                dev_info(mod->dev, "%s timed out\n", __func__);
                return -ETIMEDOUT;
        }
@@ -1718,7 +1718,7 @@ static ssize_t ican3_sysfs_show_term(struct device *dev,
                return ret;
 
        ret = wait_for_completion_timeout(&mod->termination_comp, HZ);
-       if (ret <= 0) {
+       if (ret == 0) {
                dev_info(mod->dev, "%s timed out\n", __func__);
                return -ETIMEDOUT;
        }
@@ -1760,7 +1760,7 @@ static struct attribute_group ican3_sysfs_attr_group = {
  * PCI Subsystem
  */
 
-static int __devinit ican3_probe(struct platform_device *pdev)
+static int ican3_probe(struct platform_device *pdev)
 {
        struct janz_platform_data *pdata;
        struct net_device *ndev;
@@ -1898,7 +1898,7 @@ out_return:
        return ret;
 }
 
-static int __devexit ican3_remove(struct platform_device *pdev)
+static int ican3_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct ican3_dev *mod = netdev_priv(ndev);
@@ -1927,7 +1927,7 @@ static struct platform_driver ican3_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ican3_probe,
-       .remove         = __devexit_p(ican3_remove),
+       .remove         = ican3_remove,
 };
 
 module_platform_driver(ican3_driver);
index 26e7129332abc7e18bd7b27cd3f49d67976c3a16..5eaf47b8e37bc4427a7004b1199da5dee8d7bccc 100644 (file)
@@ -981,7 +981,7 @@ static const struct net_device_ops mcp251x_netdev_ops = {
        .ndo_start_xmit = mcp251x_hard_start_xmit,
 };
 
-static int __devinit mcp251x_can_probe(struct spi_device *spi)
+static int mcp251x_can_probe(struct spi_device *spi)
 {
        struct net_device *net;
        struct mcp251x_priv *priv;
@@ -1100,7 +1100,7 @@ error_out:
        return ret;
 }
 
-static int __devexit mcp251x_can_remove(struct spi_device *spi)
+static int mcp251x_can_remove(struct spi_device *spi)
 {
        struct mcp251x_platform_data *pdata = spi->dev.platform_data;
        struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
@@ -1198,7 +1198,7 @@ static struct spi_driver mcp251x_can_driver = {
 
        .id_table = mcp251x_id_table,
        .probe = mcp251x_can_probe,
-       .remove = __devexit_p(mcp251x_can_remove),
+       .remove = mcp251x_can_remove,
        .suspend = mcp251x_can_suspend,
        .resume = mcp251x_can_resume,
 };
index 799c354083c4800cf738837587a202725322cbac..668850e441dcd7e3c13e901efc2cc1e0f3473f53 100644 (file)
@@ -43,14 +43,13 @@ struct mpc5xxx_can_data {
 };
 
 #ifdef CONFIG_PPC_MPC52xx
-static struct of_device_id __devinitdata mpc52xx_cdm_ids[] = {
+static struct of_device_id mpc52xx_cdm_ids[] = {
        { .compatible = "fsl,mpc5200-cdm", },
        {}
 };
 
-static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
-                                          const char *clock_name,
-                                          int *mscan_clksrc)
+static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
+                                const char *clock_name, int *mscan_clksrc)
 {
        unsigned int pvr;
        struct mpc52xx_cdm  __iomem *cdm;
@@ -101,9 +100,8 @@ static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
        return freq;
 }
 #else /* !CONFIG_PPC_MPC52xx */
-static u32 __devinit mpc52xx_can_get_clock(struct platform_device *ofdev,
-                                          const char *clock_name,
-                                          int *mscan_clksrc)
+static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
+                                const char *clock_name, int *mscan_clksrc)
 {
        return 0;
 }
@@ -124,14 +122,13 @@ struct mpc512x_clockctl {
        u32 mccr[4];            /* MSCAN Clk Ctrl Reg 1-3 */
 };
 
-static struct of_device_id __devinitdata mpc512x_clock_ids[] = {
+static struct of_device_id mpc512x_clock_ids[] = {
        { .compatible = "fsl,mpc5121-clock", },
        {}
 };
 
-static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
-                                          const char *clock_name,
-                                          int *mscan_clksrc)
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+                                const char *clock_name, int *mscan_clksrc)
 {
        struct mpc512x_clockctl __iomem *clockctl;
        struct device_node *np_clock;
@@ -239,16 +236,15 @@ exit_put:
        return freq;
 }
 #else /* !CONFIG_PPC_MPC512x */
-static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev,
-                                          const char *clock_name,
-                                          int *mscan_clksrc)
+static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
+                                const char *clock_name, int *mscan_clksrc)
 {
        return 0;
 }
 #endif /* CONFIG_PPC_MPC512x */
 
 static const struct of_device_id mpc5xxx_can_table[];
-static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
+static int mpc5xxx_can_probe(struct platform_device *ofdev)
 {
        const struct of_device_id *match;
        const struct mpc5xxx_can_data *data;
@@ -323,7 +319,7 @@ exit_unmap_mem:
        return err;
 }
 
-static int __devexit mpc5xxx_can_remove(struct platform_device *ofdev)
+static int mpc5xxx_can_remove(struct platform_device *ofdev)
 {
        struct net_device *dev = dev_get_drvdata(&ofdev->dev);
        struct mscan_priv *priv = netdev_priv(dev);
@@ -380,22 +376,23 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
 }
 #endif
 
-static const struct mpc5xxx_can_data __devinitconst mpc5200_can_data = {
+static const struct mpc5xxx_can_data mpc5200_can_data = {
        .type = MSCAN_TYPE_MPC5200,
        .get_clock = mpc52xx_can_get_clock,
 };
 
-static const struct mpc5xxx_can_data __devinitconst mpc5121_can_data = {
+static const struct mpc5xxx_can_data mpc5121_can_data = {
        .type = MSCAN_TYPE_MPC5121,
        .get_clock = mpc512x_can_get_clock,
 };
 
-static const struct of_device_id __devinitconst mpc5xxx_can_table[] = {
+static const struct of_device_id mpc5xxx_can_table[] = {
        { .compatible = "fsl,mpc5200-mscan", .data = &mpc5200_can_data, },
        /* Note that only MPC5121 Rev. 2 (and later) is supported */
        { .compatible = "fsl,mpc5121-mscan", .data = &mpc5121_can_data, },
        {},
 };
+MODULE_DEVICE_TABLE(of, mpc5xxx_can_table);
 
 static struct platform_driver mpc5xxx_can_driver = {
        .driver = {
@@ -404,7 +401,7 @@ static struct platform_driver mpc5xxx_can_driver = {
                .of_match_table = mpc5xxx_can_table,
        },
        .probe = mpc5xxx_can_probe,
-       .remove = __devexit_p(mpc5xxx_can_remove),
+       .remove = mpc5xxx_can_remove,
 #ifdef CONFIG_PM
        .suspend = mpc5xxx_can_suspend,
        .resume = mpc5xxx_can_resume,
index 2b104d5f422c07b497e3fd8966bc9675b7bfe4ce..e6b40954e204d77bfb6a465a8ecc607db7231f98 100644 (file)
@@ -517,12 +517,8 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
 
 static int mscan_do_set_mode(struct net_device *dev, enum can_mode mode)
 {
-       struct mscan_priv *priv = netdev_priv(dev);
        int ret = 0;
 
-       if (!priv->open_time)
-               return -EINVAL;
-
        switch (mode) {
        case CAN_MODE_START:
                ret = mscan_restart(dev);
@@ -590,8 +586,6 @@ static int mscan_open(struct net_device *dev)
                goto exit_napi_disable;
        }
 
-       priv->open_time = jiffies;
-
        if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
                setbits8(&regs->canctl1, MSCAN_LISTEN);
        else
@@ -606,7 +600,6 @@ static int mscan_open(struct net_device *dev)
        return 0;
 
 exit_free_irq:
-       priv->open_time = 0;
        free_irq(dev->irq, dev);
 exit_napi_disable:
        napi_disable(&priv->napi);
@@ -627,7 +620,6 @@ static int mscan_close(struct net_device *dev)
        mscan_set_mode(dev, MSCAN_INIT_MODE);
        close_candev(dev);
        free_irq(dev->irq, dev);
-       priv->open_time = 0;
 
        return 0;
 }
index b43e9f5d32683794508d88ea03098376abbb4d44..af2ed8baf0a3b30b9361c0376f65ec0672d7b1b7 100644 (file)
@@ -281,7 +281,6 @@ struct tx_queue_entry {
 struct mscan_priv {
        struct can_priv can;    /* must be the first member */
        unsigned int type;      /* MSCAN type variants */
-       long open_time;
        unsigned long flags;
        void __iomem *reg_base; /* ioremap'ed address to registers */
        u8 shadow_statflg;
index 48b3d62b34cba9021373091aea34049bdc608bde..7d1748575b1fffc45f38351ea3f071269545548a 100644 (file)
@@ -954,7 +954,7 @@ static const struct net_device_ops pch_can_netdev_ops = {
        .ndo_start_xmit         = pch_xmit,
 };
 
-static void __devexit pch_can_remove(struct pci_dev *pdev)
+static void pch_can_remove(struct pci_dev *pdev)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
        struct pch_can_priv *priv = netdev_priv(ndev);
@@ -1178,7 +1178,7 @@ static int pch_can_get_berr_counter(const struct net_device *dev,
        return 0;
 }
 
-static int __devinit pch_can_probe(struct pci_dev *pdev,
+static int pch_can_probe(struct pci_dev *pdev,
                                   const struct pci_device_id *id)
 {
        struct net_device *ndev;
@@ -1269,7 +1269,7 @@ static struct pci_driver pch_can_pci_driver = {
        .name = "pch_can",
        .id_table = pch_pci_tbl,
        .probe = pch_can_probe,
-       .remove = __devexit_p(pch_can_remove),
+       .remove = pch_can_remove,
        .suspend = pch_can_suspend,
        .resume = pch_can_resume,
 };
index 03df9a8f2bbf0c9a444c045a979937c501e38c4a..92f73c708a3d7c3ec80133fb4b2f05872fd11849 100644 (file)
@@ -21,7 +21,7 @@ config CAN_SJA1000_PLATFORM
 
 config CAN_SJA1000_OF_PLATFORM
        tristate "Generic OF Platform Bus based SJA1000 driver"
-       depends on PPC_OF
+       depends on OF
        ---help---
          This driver adds support for the SJA1000 chips connected to
          the OpenFirmware "platform bus" found on embedded systems with
@@ -93,6 +93,7 @@ config CAN_PLX_PCI
           - Marathon CAN-bus-PCI card (http://www.marathon.ru/)
           - TEWS TECHNOLOGIES TPMC810 card (http://www.tews.com/)
           - IXXAT Automation PC-I 04/PCI card (http://www.ixxat.com/)
+          - Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card (http://www.connecttech.com)
 
 config CAN_TSCAN1
        tristate "TS-CAN1 PC104 boards"
index 5c6d412bafb505f0379ca0ae7f3f2eb5691ad8c8..036a326836b29871d8710f23f5e2d57a6c02ac52 100644 (file)
@@ -220,8 +220,8 @@ static void ems_pci_card_reset(struct ems_pci_card *card)
  * Probe PCI device for EMS CAN signature and register each available
  * CAN channel to SJA1000 Socket-CAN subsystem.
  */
-static int __devinit ems_pci_add_card(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent)
+static int ems_pci_add_card(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        struct sja1000_priv *priv;
        struct net_device *dev;
index 075a5457a19067c217e6c9fabee75b0d425a90b4..5c2f3fbbf5ae8fc4028ecf0fdc50ac03e92fd21b 100644 (file)
@@ -166,8 +166,7 @@ static void ems_pcmcia_del_card(struct pcmcia_device *pdev)
  * Probe PCI device for EMS CAN signature and register each available
  * CAN channel to SJA1000 Socket-CAN subsystem.
  */
-static int __devinit ems_pcmcia_add_card(struct pcmcia_device *pdev,
-                                        unsigned long base)
+static int ems_pcmcia_add_card(struct pcmcia_device *pdev, unsigned long base)
 {
        struct sja1000_priv *priv;
        struct net_device *dev;
@@ -256,7 +255,7 @@ failure_cleanup:
 /*
  * Setup PCMCIA socket and probe for EMS CPC-CARD
  */
-static int __devinit ems_pcmcia_probe(struct pcmcia_device *dev)
+static int ems_pcmcia_probe(struct pcmcia_device *dev)
 {
        int csval;
 
index 23ed6ea4c7c350cb9a232d15e8a9d792a9e04cfa..37b0381f532e6458e13b7a424330047aec368e0c 100644 (file)
@@ -290,8 +290,8 @@ failure:
        return err;
 }
 
-static int __devinit kvaser_pci_init_one(struct pci_dev *pdev,
-                                        const struct pci_device_id *ent)
+static int kvaser_pci_init_one(struct pci_dev *pdev,
+                              const struct pci_device_id *ent)
 {
        int err;
        struct net_device *master_dev = NULL;
@@ -379,7 +379,7 @@ failure:
 
 }
 
-static void __devexit kvaser_pci_remove_one(struct pci_dev *pdev)
+static void kvaser_pci_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -394,7 +394,7 @@ static struct pci_driver kvaser_pci_driver = {
        .name = DRV_NAME,
        .id_table = kvaser_pci_tbl,
        .probe = kvaser_pci_init_one,
-       .remove = __devexit_p(kvaser_pci_remove_one),
+       .remove = kvaser_pci_remove_one,
 };
 
 module_pci_driver(kvaser_pci_driver);
index f5b82aeb2540af2646f38dce966096ac221e3eaf..d84888f03d92e28995cd4087b511db1ca3c3a4f1 100644 (file)
 
 #include "sja1000.h"
 
-MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_AUTHOR("Stephane Grosjean <s.grosjean@peak-system.com>");
 MODULE_DESCRIPTION("Socket-CAN driver for PEAK PCAN PCI family cards");
 MODULE_SUPPORTED_DEVICE("PEAK PCAN PCI/PCIe/PCIeC miniPCI CAN cards");
+MODULE_SUPPORTED_DEVICE("PEAK PCAN miniPCIe/cPCI PC/104+ PCI/104e CAN Cards");
 MODULE_LICENSE("GPL v2");
 
 #define DRV_NAME  "peak_pci"
@@ -64,7 +65,11 @@ struct peak_pci_chan {
 #define PEAK_PCI_DEVICE_ID     0x0001  /* for PCI/PCIe slot cards */
 #define PEAK_PCIEC_DEVICE_ID   0x0002  /* for ExpressCard slot cards */
 #define PEAK_PCIE_DEVICE_ID    0x0003  /* for nextgen PCIe slot cards */
-#define PEAK_MPCI_DEVICE_ID    0x0008  /* The miniPCI slot cards */
+#define PEAK_CPCI_DEVICE_ID    0x0004  /* for nextgen cPCI slot cards */
+#define PEAK_MPCI_DEVICE_ID    0x0005  /* for nextgen miniPCI slot cards */
+#define PEAK_PC_104P_DEVICE_ID 0x0006  /* PCAN-PC/104+ cards */
+#define PEAK_PCI_104E_DEVICE_ID        0x0007  /* PCAN-PCI/104 Express cards */
+#define PEAK_MPCIE_DEVICE_ID   0x0008  /* The miniPCIe slot cards */
 
 #define PEAK_PCI_CHAN_MAX      4
 
@@ -76,6 +81,10 @@ static DEFINE_PCI_DEVICE_TABLE(peak_pci_tbl) = {
        {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
        {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
+       {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #ifdef CONFIG_CAN_PEAK_PCIEC
        {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
 #endif
@@ -542,8 +551,7 @@ static void peak_pci_post_irq(const struct sja1000_priv *priv)
                writew(chan->icr_mask, chan->cfg_base + PITA_ICR);
 }
 
-static int __devinit peak_pci_probe(struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct sja1000_priv *priv;
        struct peak_pci_chan *chan;
@@ -708,7 +716,7 @@ failure_disable_pci:
        return err;
 }
 
-static void __devexit peak_pci_remove(struct pci_dev *pdev)
+static void peak_pci_remove(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev); /* Last device */
        struct sja1000_priv *priv = netdev_priv(dev);
@@ -748,7 +756,7 @@ static struct pci_driver peak_pci_driver = {
        .name = DRV_NAME,
        .id_table = peak_pci_tbl,
        .probe = peak_pci_probe,
-       .remove = __devexit_p(peak_pci_remove),
+       .remove = peak_pci_remove,
 };
 
 module_pci_driver(peak_pci_driver);
index 272a85f32b14c86b040bf854b0df541e463a4af7..f1175142b0a079ef61018e8bff78098ba2829a8f 100644 (file)
@@ -632,7 +632,7 @@ static void pcan_free(struct pcmcia_device *pdev)
 /*
  * setup PCMCIA socket and probe for PEAK-System PC-CARD
  */
-static int __devinit pcan_probe(struct pcmcia_device *pdev)
+static int pcan_probe(struct pcmcia_device *pdev)
 {
        struct pcan_pccard *card;
        int err;
index 8bc95982840fadfcd88952255e75220bea7fd9b1..11d1062a9449f612bf3d6a62c81b26a459427c03 100644 (file)
@@ -44,6 +44,7 @@ MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, "
                        "esd CAN-PCI/CPCI/PCI104/200, "
                        "esd CAN-PCI/PMC/266, "
                        "esd CAN-PCIe/2000, "
+                       "Connect Tech Inc. CANpro/104-Plus Opto (CRG001), "
                        "IXXAT PC-I 04/PCI")
 MODULE_LICENSE("GPL v2");
 
@@ -131,6 +132,9 @@ struct plx_pci_card {
 #define TEWS_PCI_VENDOR_ID             0x1498
 #define TEWS_PCI_DEVICE_ID_TMPC810     0x032A
 
+#define CTI_PCI_VENDOR_ID              0x12c4
+#define CTI_PCI_DEVICE_ID_CRG001       0x0900
+
 static void plx_pci_reset_common(struct pci_dev *pdev);
 static void plx_pci_reset_marathon(struct pci_dev *pdev);
 static void plx9056_pci_reset_common(struct pci_dev *pdev);
@@ -158,7 +162,7 @@ struct plx_pci_card_info {
        void (*reset_func)(struct pci_dev *pdev);
 };
 
-static struct plx_pci_card_info plx_pci_card_info_adlink __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_adlink = {
        "Adlink PCI-7841/cPCI-7841", 2,
        PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
        {1, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x80, 0x80} },
@@ -166,7 +170,7 @@ static struct plx_pci_card_info plx_pci_card_info_adlink __devinitdata = {
        /* based on PLX9052 */
 };
 
-static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_adlink_se = {
        "Adlink PCI-7841/cPCI-7841 SE", 2,
        PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
        {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x80, 0x80} },
@@ -174,7 +178,7 @@ static struct plx_pci_card_info plx_pci_card_info_adlink_se __devinitdata = {
        /* based on PLX9052 */
 };
 
-static struct plx_pci_card_info plx_pci_card_info_esd200 __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_esd200 = {
        "esd CAN-PCI/CPCI/PCI104/200", 2,
        PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
        {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
@@ -182,7 +186,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd200 __devinitdata = {
        /* based on PLX9030/9050 */
 };
 
-static struct plx_pci_card_info plx_pci_card_info_esd266 __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_esd266 = {
        "esd CAN-PCI/PMC/266", 2,
        PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
        {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
@@ -190,7 +194,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd266 __devinitdata = {
        /* based on PLX9056 */
 };
 
-static struct plx_pci_card_info plx_pci_card_info_esd2000 __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_esd2000 = {
        "esd CAN-PCIe/2000", 2,
        PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
        {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x100, 0x80} },
@@ -198,7 +202,7 @@ static struct plx_pci_card_info plx_pci_card_info_esd2000 __devinitdata = {
        /* based on PEX8311 */
 };
 
-static struct plx_pci_card_info plx_pci_card_info_ixxat __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_ixxat = {
        "IXXAT PC-I 04/PCI", 2,
        PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
        {0, 0x00, 0x00}, { {2, 0x00, 0x80}, {2, 0x200, 0x80} },
@@ -206,7 +210,7 @@ static struct plx_pci_card_info plx_pci_card_info_ixxat __devinitdata = {
        /* based on PLX9050 */
 };
 
-static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_marathon = {
        "Marathon CAN-bus-PCI", 2,
        PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
        {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} },
@@ -214,7 +218,7 @@ static struct plx_pci_card_info plx_pci_card_info_marathon __devinitdata = {
        /* based on PLX9052 */
 };
 
-static struct plx_pci_card_info plx_pci_card_info_tews __devinitdata = {
+static struct plx_pci_card_info plx_pci_card_info_tews = {
        "TEWS TECHNOLOGIES TPMC810", 2,
        PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
        {0, 0x00, 0x00}, { {2, 0x000, 0x80}, {2, 0x100, 0x80} },
@@ -222,6 +226,14 @@ static struct plx_pci_card_info plx_pci_card_info_tews __devinitdata = {
        /* based on PLX9030 */
 };
 
+static struct plx_pci_card_info plx_pci_card_info_cti = {
+       "Connect Tech Inc. CANpro/104-Plus Opto (CRG001)", 2,
+       PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR,
+       {0, 0x00, 0x00}, { {2, 0x000, 0x80}, {2, 0x100, 0x80} },
+       &plx_pci_reset_common
+       /* based on PLX9030 */
+};
+
 static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
        {
                /* Adlink PCI-7841/cPCI-7841 */
@@ -300,6 +312,13 @@ static DEFINE_PCI_DEVICE_TABLE(plx_pci_tbl) = {
                0, 0,
                (kernel_ulong_t)&plx_pci_card_info_tews
        },
+       {
+               /* Connect Tech Inc. CANpro/104-Plus Opto (CRG001) card */
+               PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030,
+               CTI_PCI_VENDOR_ID, CTI_PCI_DEVICE_ID_CRG001,
+               0, 0,
+               (kernel_ulong_t)&plx_pci_card_info_cti
+       },
        { 0,}
 };
 MODULE_DEVICE_TABLE(pci, plx_pci_tbl);
@@ -465,8 +484,8 @@ static void plx_pci_del_card(struct pci_dev *pdev)
  * Probe PLX90xx based device for the SJA1000 chips and register each
  * available CAN channel to SJA1000 Socket-CAN subsystem.
  */
-static int __devinit plx_pci_add_card(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int plx_pci_add_card(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        struct sja1000_priv *priv;
        struct net_device *dev;
index 25011dbe1b96f15b951ba555477f4ba14be94b0f..83ee11eca0e2de4a54220bbc9e2b0d55c6edf057 100644 (file)
@@ -188,11 +188,6 @@ static void sja1000_start(struct net_device *dev)
 
 static int sja1000_set_mode(struct net_device *dev, enum can_mode mode)
 {
-       struct sja1000_priv *priv = netdev_priv(dev);
-
-       if (!priv->open_time)
-               return -EINVAL;
-
        switch (mode) {
        case CAN_MODE_START:
                sja1000_start(dev);
@@ -579,7 +574,6 @@ static int sja1000_open(struct net_device *dev)
 
        /* init and start chi */
        sja1000_start(dev);
-       priv->open_time = jiffies;
 
        netif_start_queue(dev);
 
@@ -598,8 +592,6 @@ static int sja1000_close(struct net_device *dev)
 
        close_candev(dev);
 
-       priv->open_time = 0;
-
        return 0;
 }
 
index 23fff06875f5703601b1a608937c67f3944422fb..afa99847a5101ffa6399726b57d4189f6c3057f5 100644 (file)
  */
 struct sja1000_priv {
        struct can_priv can;    /* must be the first member */
-       int open_time;
        struct sk_buff *echo_skb;
 
        /* the lower-layer is responsible for appropriate locking */
index 90c5c2dfd2fd17a515232520daf4dadd1a33d53f..5c8da46614892504c1a30972f3199ffd7309b68a 100644 (file)
@@ -42,11 +42,11 @@ MODULE_LICENSE("GPL v2");
 
 static unsigned long port[MAXDEV];
 static unsigned long mem[MAXDEV];
-static int __devinitdata irq[MAXDEV];
-static int __devinitdata clk[MAXDEV];
-static unsigned char __devinitdata cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static unsigned char __devinitdata ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
-static int __devinitdata indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
+static int irq[MAXDEV];
+static int clk[MAXDEV];
+static unsigned char cdr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
+static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
 
 module_param_array(port, ulong, NULL, S_IRUGO);
 MODULE_PARM_DESC(port, "I/O port number");
@@ -117,7 +117,7 @@ static void sja1000_isa_port_write_reg_indirect(const struct sja1000_priv *priv,
        outb(val, base + 1);
 }
 
-static int __devinit sja1000_isa_probe(struct platform_device *pdev)
+static int sja1000_isa_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct sja1000_priv *priv;
@@ -223,7 +223,7 @@ static int __devinit sja1000_isa_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __devexit sja1000_isa_remove(struct platform_device *pdev)
+static int sja1000_isa_remove(struct platform_device *pdev)
 {
        struct net_device *dev = dev_get_drvdata(&pdev->dev);
        struct sja1000_priv *priv = netdev_priv(dev);
@@ -248,7 +248,7 @@ static int __devexit sja1000_isa_remove(struct platform_device *pdev)
 
 static struct platform_driver sja1000_isa_driver = {
        .probe = sja1000_isa_probe,
-       .remove = __devexit_p(sja1000_isa_remove),
+       .remove = sja1000_isa_remove,
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index f2683eb6a3d588a7dff7af9f8830a79dc18206c7..0f5917000aa20687aa1669e5c1e8ed7c1e2edbbd 100644 (file)
@@ -42,6 +42,8 @@
 #include <linux/can/dev.h>
 
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 #include <asm/prom.h>
 
 #include "sja1000.h"
@@ -59,16 +61,16 @@ MODULE_LICENSE("GPL v2");
 
 static u8 sja1000_ofp_read_reg(const struct sja1000_priv *priv, int reg)
 {
-       return in_8(priv->reg_base + reg);
+       return ioread8(priv->reg_base + reg);
 }
 
 static void sja1000_ofp_write_reg(const struct sja1000_priv *priv,
                                  int reg, u8 val)
 {
-       out_8(priv->reg_base + reg, val);
+       iowrite8(val, priv->reg_base + reg);
 }
 
-static int __devexit sja1000_ofp_remove(struct platform_device *ofdev)
+static int sja1000_ofp_remove(struct platform_device *ofdev)
 {
        struct net_device *dev = dev_get_drvdata(&ofdev->dev);
        struct sja1000_priv *priv = netdev_priv(dev);
@@ -88,7 +90,7 @@ static int __devexit sja1000_ofp_remove(struct platform_device *ofdev)
        return 0;
 }
 
-static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
+static int sja1000_ofp_probe(struct platform_device *ofdev)
 {
        struct device_node *np = ofdev->dev.of_node;
        struct net_device *dev;
@@ -204,7 +206,7 @@ exit_release_mem:
        return err;
 }
 
-static struct of_device_id __devinitdata sja1000_ofp_table[] = {
+static struct of_device_id sja1000_ofp_table[] = {
        {.compatible = "nxp,sja1000"},
        {},
 };
@@ -217,7 +219,7 @@ static struct platform_driver sja1000_ofp_driver = {
                .of_match_table = sja1000_ofp_table,
        },
        .probe = sja1000_ofp_probe,
-       .remove = __devexit_p(sja1000_ofp_remove),
+       .remove = sja1000_ofp_remove,
 };
 
 module_platform_driver(sja1000_ofp_driver);
index 662c5f7eb0c54af4cb3c788959109a7693798629..21619bb5b869282a2d0a2f20090d93ea35908282 100644 (file)
@@ -34,6 +34,7 @@
 
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("Socket-CAN driver for SJA1000 on the platform bus");
+MODULE_ALIAS("platform:" DRV_NAME);
 MODULE_LICENSE("GPL v2");
 
 static u8 sp_read_reg8(const struct sja1000_priv *priv, int reg)
index 9756099a883aa56416bb709d607131ad934a2999..76513dd780c7c0ad01a5f3b53311a2322af4ec05 100644 (file)
@@ -71,7 +71,7 @@ MODULE_LICENSE("GPL");
 #define TSCAN1_SJA1000_XTAL 16000000
 
 /* SJA1000 IO base addresses */
-static const unsigned short tscan1_sja1000_addresses[] __devinitconst = {
+static const unsigned short tscan1_sja1000_addresses[] = {
        0x100, 0x120, 0x180, 0x1a0, 0x200, 0x240, 0x280, 0x320
 };
 
@@ -88,7 +88,7 @@ static void tscan1_write(const struct sja1000_priv *priv, int reg, u8 val)
 }
 
 /* Probe for a TS-CAN1 board with JP2:JP1 jumper setting ID */
-static int __devinit tscan1_probe(struct device *dev, unsigned id)
+static int tscan1_probe(struct device *dev, unsigned id)
 {
        struct net_device *netdev;
        struct sja1000_priv *priv;
@@ -171,7 +171,7 @@ static int __devinit tscan1_probe(struct device *dev, unsigned id)
        return -ENXIO;
 }
 
-static int __devexit tscan1_remove(struct device *dev, unsigned id /*unused*/)
+static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
 {
        struct net_device *netdev;
        struct sja1000_priv *priv;
@@ -197,7 +197,7 @@ static int __devexit tscan1_remove(struct device *dev, unsigned id /*unused*/)
 
 static struct isa_driver tscan1_isa_driver = {
        .probe = tscan1_probe,
-       .remove = __devexit_p(tscan1_remove),
+       .remove = tscan1_remove,
        .driver = {
                .name = "tscan1",
        },
index c0e1b1eb87a9d5ffa4b37bea76359472e2122075..c2c0a5bb0b214c92d90f423c27bb394f66d5da9e 100644 (file)
@@ -159,7 +159,7 @@ MODULE_FIRMWARE(fw_dir "bcard2.bin");
 MODULE_FIRMWARE(fw_dir "ldcard2.bin");
 MODULE_FIRMWARE(fw_dir "cancrd2.bin");
 
-static __devinit const struct softing_platform_data
+static const struct softing_platform_data
 *softingcs_find_platform_data(unsigned int manf, unsigned int prod)
 {
        const struct softing_platform_data *lp;
@@ -193,8 +193,7 @@ static int softingcs_enable_irq(struct platform_device *pdev, int v)
 /*
  * pcmcia check
  */
-static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
-               void *priv_data)
+static int softingcs_probe_config(struct pcmcia_device *pcmcia, void *priv_data)
 {
        struct softing_platform_data *pdat = priv_data;
        struct resource *pres;
@@ -215,7 +214,7 @@ static __devinit int softingcs_probe_config(struct pcmcia_device *pcmcia,
        return pcmcia_request_window(pcmcia, pres, memspeed);
 }
 
-static __devexit void softingcs_remove(struct pcmcia_device *pcmcia)
+static void softingcs_remove(struct pcmcia_device *pcmcia)
 {
        struct platform_device *pdev = pcmcia->priv;
 
@@ -235,7 +234,7 @@ static void softingcs_pdev_release(struct device *dev)
        kfree(pdev);
 }
 
-static __devinit int softingcs_probe(struct pcmcia_device *pcmcia)
+static int softingcs_probe(struct pcmcia_device *pcmcia)
 {
        int ret;
        struct platform_device *pdev;
@@ -338,7 +337,7 @@ static struct pcmcia_driver softingcs_driver = {
        .name           = "softingcs",
        .id_table       = softingcs_ids,
        .probe          = softingcs_probe,
-       .remove         = __devexit_p(softingcs_remove),
+       .remove         = softingcs_remove,
 };
 
 static int __init softingcs_start(void)
index f2a221e7b968263014a85f897872be6eeaaa19c6..3a2b45601ec29d69f07ec4dab98425ebb09add15 100644 (file)
@@ -478,7 +478,7 @@ static void softing_card_shutdown(struct softing *card)
        mutex_unlock(&card->fw.lock);
 }
 
-static __devinit int softing_card_boot(struct softing *card)
+static int softing_card_boot(struct softing *card)
 {
        int ret, j;
        static const uint8_t stream[] = {
@@ -645,8 +645,8 @@ static const struct can_bittiming_const softing_btr_const = {
 };
 
 
-static __devinit struct net_device *softing_netdev_create(struct softing *card,
-               uint16_t chip_id)
+static struct net_device *softing_netdev_create(struct softing *card,
+                                               uint16_t chip_id)
 {
        struct net_device *netdev;
        struct softing_priv *priv;
@@ -676,7 +676,7 @@ static __devinit struct net_device *softing_netdev_create(struct softing *card,
        return netdev;
 }
 
-static __devinit int softing_netdev_register(struct net_device *netdev)
+static int softing_netdev_register(struct net_device *netdev)
 {
        int ret;
 
@@ -745,7 +745,7 @@ static const struct attribute_group softing_pdev_group = {
 /*
  * platform driver
  */
-static __devexit int softing_pdev_remove(struct platform_device *pdev)
+static int softing_pdev_remove(struct platform_device *pdev)
 {
        struct softing *card = platform_get_drvdata(pdev);
        int j;
@@ -766,7 +766,7 @@ static __devexit int softing_pdev_remove(struct platform_device *pdev)
        return 0;
 }
 
-static __devinit int softing_pdev_probe(struct platform_device *pdev)
+static int softing_pdev_probe(struct platform_device *pdev)
 {
        const struct softing_platform_data *pdat = pdev->dev.platform_data;
        struct softing *card;
@@ -871,7 +871,7 @@ static struct platform_driver softing_driver = {
                .owner = THIS_MODULE,
        },
        .probe = softing_pdev_probe,
-       .remove = __devexit_p(softing_pdev_remove),
+       .remove = softing_pdev_remove,
 };
 
 module_platform_driver(softing_driver);
index 9ded21e79db5866602706ca568dea6613bc0a727..f898c6363729b2a41be58c824f3f3bb145a95897 100644 (file)
@@ -978,7 +978,7 @@ probe_exit:
        return err;
 }
 
-static int __devexit ti_hecc_remove(struct platform_device *pdev)
+static int ti_hecc_remove(struct platform_device *pdev)
 {
        struct resource *res;
        struct net_device *ndev = platform_get_drvdata(pdev);
@@ -1045,7 +1045,7 @@ static struct platform_driver ti_hecc_driver = {
                .owner   = THIS_MODULE,
        },
        .probe = ti_hecc_probe,
-       .remove = __devexit_p(ti_hecc_remove),
+       .remove = ti_hecc_remove,
        .suspend = ti_hecc_suspend,
        .resume = ti_hecc_resume,
 };
@@ -1055,3 +1055,4 @@ module_platform_driver(ti_hecc_driver);
 MODULE_AUTHOR("Anant Gole <anantgole@ti.com>");
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION(DRV_DESC);
+MODULE_ALIAS("platform:" DRV_NAME);
index 0a6876841c20b62ab75f49e41b33ca6c45afbf12..a4e4bee35710fa3f71b1b597c98782765603c45f 100644 (file)
@@ -13,6 +13,35 @@ config CAN_ESD_USB2
           This driver supports the CAN-USB/2 interface
           from esd electronic system design gmbh (http://www.esd.eu).
 
+config CAN_KVASER_USB
+       tristate "Kvaser CAN/USB interface"
+       ---help---
+         This driver adds support for Kvaser CAN/USB devices like Kvaser
+         Leaf Light.
+
+         The driver gives support for the following devices:
+           - Kvaser Leaf Light
+           - Kvaser Leaf Professional HS
+           - Kvaser Leaf SemiPro HS
+           - Kvaser Leaf Professional LS
+           - Kvaser Leaf Professional SWC
+           - Kvaser Leaf Professional LIN
+           - Kvaser Leaf SemiPro LS
+           - Kvaser Leaf SemiPro SWC
+           - Kvaser Memorator II HS/HS
+           - Kvaser USBcan Professional HS/HS
+           - Kvaser Leaf Light GI
+           - Kvaser Leaf Professional HS (OBD-II connector)
+           - Kvaser Memorator Professional HS/LS
+           - Kvaser Leaf Light "China"
+           - Kvaser BlackBird SemiPro
+           - Kvaser USBcan R
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called kvaser_usb.
+
 config CAN_PEAK_USB
        tristate "PEAK PCAN-USB/USB Pro interfaces"
        ---help---
index da6d1d3b2969939758b6165c67ce3278a1e3e831..80a2ee41fd61726dc43b70724d20e6c63c9b8cac 100644 (file)
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_CAN_EMS_USB) += ems_usb.o
 obj-$(CONFIG_CAN_ESD_USB2) += esd_usb2.o
+obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
 obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
index 086fa321677a0b45c3e3a7471fa631c47768327a..c69f0b72b352dc97bfc047a54a5e0d344ec7476b 100644 (file)
@@ -245,7 +245,6 @@ struct ems_tx_urb_context {
 
 struct ems_usb {
        struct can_priv can; /* must be the first member */
-       int open_time;
 
        struct sk_buff *echo_skb[MAX_TX_URBS];
 
@@ -728,7 +727,6 @@ static int ems_usb_open(struct net_device *netdev)
                return err;
        }
 
-       dev->open_time = jiffies;
 
        netif_start_queue(netdev);
 
@@ -878,8 +876,6 @@ static int ems_usb_close(struct net_device *netdev)
 
        close_candev(netdev);
 
-       dev->open_time = 0;
-
        return 0;
 }
 
@@ -905,9 +901,6 @@ static int ems_usb_set_mode(struct net_device *netdev, enum can_mode mode)
 {
        struct ems_usb *dev = netdev_priv(netdev);
 
-       if (!dev->open_time)
-               return -EINVAL;
-
        switch (mode) {
        case CAN_MODE_START:
                if (ems_usb_write_mode(dev, SJA1000_MOD_NORMAL))
index bd36e55171737734d23e75309e00b3e6142dd8b2..9b74d1e3ad44a51c950257b6588bf082247a75d4 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * CAN driver for esd CAN-USB/2
+ * CAN driver for esd CAN-USB/2 and CAN-USB/Micro
  *
- * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
+ * Copyright (C) 2010-2012 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published
 #include <linux/can/error.h>
 
 MODULE_AUTHOR("Matthias Fuchs <matthias.fuchs@esd.eu>");
-MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 interfaces");
+MODULE_DESCRIPTION("CAN driver for esd CAN-USB/2 and CAN-USB/Micro interfaces");
 MODULE_LICENSE("GPL v2");
 
 /* Define these values to match your devices */
 #define USB_ESDGMBH_VENDOR_ID  0x0ab4
 #define USB_CANUSB2_PRODUCT_ID 0x0010
+#define USB_CANUSBM_PRODUCT_ID 0x0011
 
 #define ESD_USB2_CAN_CLOCK     60000000
+#define ESD_USBM_CAN_CLOCK     36000000
 #define ESD_USB2_MAX_NETS      2
 
 /* USB2 commands */
@@ -69,6 +71,7 @@ MODULE_LICENSE("GPL v2");
 #define ESD_USB2_TSEG2_SHIFT   20
 #define ESD_USB2_SJW_MAX       4
 #define ESD_USB2_SJW_SHIFT     14
+#define ESD_USBM_SJW_SHIFT     24
 #define ESD_USB2_BRP_MIN       1
 #define ESD_USB2_BRP_MAX       1024
 #define ESD_USB2_BRP_INC       1
@@ -183,6 +186,7 @@ struct __attribute__ ((packed)) esd_usb2_msg {
 
 static struct usb_device_id esd_usb2_table[] = {
        {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSB2_PRODUCT_ID)},
+       {USB_DEVICE(USB_ESDGMBH_VENDOR_ID, USB_CANUSBM_PRODUCT_ID)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, esd_usb2_table);
@@ -213,7 +217,6 @@ struct esd_usb2_net_priv {
        struct usb_anchor tx_submitted;
        struct esd_tx_urb_context tx_contexts[MAX_TX_URBS];
 
-       int open_time;
        struct esd_usb2 *usb2;
        struct net_device *netdev;
        int index;
@@ -691,8 +694,6 @@ static int esd_usb2_open(struct net_device *netdev)
                return err;
        }
 
-       priv->open_time = jiffies;
-
        netif_start_queue(netdev);
 
        return 0;
@@ -860,8 +861,6 @@ static int esd_usb2_close(struct net_device *netdev)
 
        close_candev(netdev);
 
-       priv->open_time = 0;
-
        return 0;
 }
 
@@ -889,11 +888,22 @@ static int esd_usb2_set_bittiming(struct net_device *netdev)
        struct can_bittiming *bt = &priv->can.bittiming;
        struct esd_usb2_msg msg;
        u32 canbtr;
+       int sjw_shift;
 
        canbtr = ESD_USB2_UBR;
+       if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+               canbtr |= ESD_USB2_LOM;
+
        canbtr |= (bt->brp - 1) & (ESD_USB2_BRP_MAX - 1);
+
+       if (le16_to_cpu(priv->usb2->udev->descriptor.idProduct) ==
+           USB_CANUSBM_PRODUCT_ID)
+               sjw_shift = ESD_USBM_SJW_SHIFT;
+       else
+               sjw_shift = ESD_USB2_SJW_SHIFT;
+
        canbtr |= ((bt->sjw - 1) & (ESD_USB2_SJW_MAX - 1))
-               << ESD_USB2_SJW_SHIFT;
+               << sjw_shift;
        canbtr |= ((bt->prop_seg + bt->phase_seg1 - 1)
                   & (ESD_USB2_TSEG1_MAX - 1))
                << ESD_USB2_TSEG1_SHIFT;
@@ -926,11 +936,6 @@ static int esd_usb2_get_berr_counter(const struct net_device *netdev,
 
 static int esd_usb2_set_mode(struct net_device *netdev, enum can_mode mode)
 {
-       struct esd_usb2_net_priv *priv = netdev_priv(netdev);
-
-       if (!priv->open_time)
-               return -EINVAL;
-
        switch (mode) {
        case CAN_MODE_START:
                netif_wake_queue(netdev);
@@ -971,12 +976,20 @@ static int esd_usb2_probe_one_net(struct usb_interface *intf, int index)
        priv->index = index;
 
        priv->can.state = CAN_STATE_STOPPED;
-       priv->can.clock.freq = ESD_USB2_CAN_CLOCK;
+       priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY;
+
+       if (le16_to_cpu(dev->udev->descriptor.idProduct) ==
+           USB_CANUSBM_PRODUCT_ID)
+               priv->can.clock.freq = ESD_USBM_CAN_CLOCK;
+       else {
+               priv->can.clock.freq = ESD_USB2_CAN_CLOCK;
+               priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
+       }
+
        priv->can.bittiming_const = &esd_usb2_bittiming_const;
        priv->can.do_set_bittiming = esd_usb2_set_bittiming;
        priv->can.do_set_mode = esd_usb2_set_mode;
        priv->can.do_get_berr_counter = esd_usb2_get_berr_counter;
-       priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
 
        netdev->flags |= IFF_ECHO; /* we support local echo */
 
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
new file mode 100644 (file)
index 0000000..5b58a4d
--- /dev/null
@@ -0,0 +1,1627 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * Parts of this driver are based on the following:
+ *  - Kvaser linux leaf driver (version 4.78)
+ *  - CAN driver for esd CAN-USB/2
+ *
+ * Copyright (C) 2002-2006 KVASER AB, Sweden. All rights reserved.
+ * Copyright (C) 2010 Matthias Fuchs <matthias.fuchs@esd.eu>, esd gmbh
+ * Copyright (C) 2012 Olivier Sobrie <olivier@sobrie.be>
+ */
+
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#define MAX_TX_URBS                    16
+#define MAX_RX_URBS                    4
+#define START_TIMEOUT                  1000 /* msecs */
+#define STOP_TIMEOUT                   1000 /* msecs */
+#define USB_SEND_TIMEOUT               1000 /* msecs */
+#define USB_RECV_TIMEOUT               1000 /* msecs */
+#define RX_BUFFER_SIZE                 3072
+#define CAN_USB_CLOCK                  8000000
+#define MAX_NET_DEVICES                        3
+
+/* Kvaser USB devices */
+#define KVASER_VENDOR_ID               0x0bfd
+#define USB_LEAF_DEVEL_PRODUCT_ID      10
+#define USB_LEAF_LITE_PRODUCT_ID       11
+#define USB_LEAF_PRO_PRODUCT_ID                12
+#define USB_LEAF_SPRO_PRODUCT_ID       14
+#define USB_LEAF_PRO_LS_PRODUCT_ID     15
+#define USB_LEAF_PRO_SWC_PRODUCT_ID    16
+#define USB_LEAF_PRO_LIN_PRODUCT_ID    17
+#define USB_LEAF_SPRO_LS_PRODUCT_ID    18
+#define USB_LEAF_SPRO_SWC_PRODUCT_ID   19
+#define USB_MEMO2_DEVEL_PRODUCT_ID     22
+#define USB_MEMO2_HSHS_PRODUCT_ID      23
+#define USB_UPRO_HSHS_PRODUCT_ID       24
+#define USB_LEAF_LITE_GI_PRODUCT_ID    25
+#define USB_LEAF_PRO_OBDII_PRODUCT_ID  26
+#define USB_MEMO2_HSLS_PRODUCT_ID      27
+#define USB_LEAF_LITE_CH_PRODUCT_ID    28
+#define USB_BLACKBIRD_SPRO_PRODUCT_ID  29
+#define USB_OEM_MERCURY_PRODUCT_ID     34
+#define USB_OEM_LEAF_PRODUCT_ID                35
+#define USB_CAN_R_PRODUCT_ID           39
+
+/* USB devices features */
+#define KVASER_HAS_SILENT_MODE         BIT(0)
+#define KVASER_HAS_TXRX_ERRORS         BIT(1)
+
+/* Message header size */
+#define MSG_HEADER_LEN                 2
+
+/* Can message flags */
+#define MSG_FLAG_ERROR_FRAME           BIT(0)
+#define MSG_FLAG_OVERRUN               BIT(1)
+#define MSG_FLAG_NERR                  BIT(2)
+#define MSG_FLAG_WAKEUP                        BIT(3)
+#define MSG_FLAG_REMOTE_FRAME          BIT(4)
+#define MSG_FLAG_RESERVED              BIT(5)
+#define MSG_FLAG_TX_ACK                        BIT(6)
+#define MSG_FLAG_TX_REQUEST            BIT(7)
+
+/* Can states */
+#define M16C_STATE_BUS_RESET           BIT(0)
+#define M16C_STATE_BUS_ERROR           BIT(4)
+#define M16C_STATE_BUS_PASSIVE         BIT(5)
+#define M16C_STATE_BUS_OFF             BIT(6)
+
+/* Can msg ids */
+#define CMD_RX_STD_MESSAGE             12
+#define CMD_TX_STD_MESSAGE             13
+#define CMD_RX_EXT_MESSAGE             14
+#define CMD_TX_EXT_MESSAGE             15
+#define CMD_SET_BUS_PARAMS             16
+#define CMD_GET_BUS_PARAMS             17
+#define CMD_GET_BUS_PARAMS_REPLY       18
+#define CMD_GET_CHIP_STATE             19
+#define CMD_CHIP_STATE_EVENT           20
+#define CMD_SET_CTRL_MODE              21
+#define CMD_GET_CTRL_MODE              22
+#define CMD_GET_CTRL_MODE_REPLY                23
+#define CMD_RESET_CHIP                 24
+#define CMD_RESET_CARD                 25
+#define CMD_START_CHIP                 26
+#define CMD_START_CHIP_REPLY           27
+#define CMD_STOP_CHIP                  28
+#define CMD_STOP_CHIP_REPLY            29
+#define CMD_GET_CARD_INFO2             32
+#define CMD_GET_CARD_INFO              34
+#define CMD_GET_CARD_INFO_REPLY                35
+#define CMD_GET_SOFTWARE_INFO          38
+#define CMD_GET_SOFTWARE_INFO_REPLY    39
+#define CMD_ERROR_EVENT                        45
+#define CMD_FLUSH_QUEUE                        48
+#define CMD_RESET_ERROR_COUNTER                49
+#define CMD_TX_ACKNOWLEDGE             50
+#define CMD_CAN_ERROR_EVENT            51
+#define CMD_USB_THROTTLE               77
+#define CMD_LOG_MESSAGE                        106
+
+/* error factors */
+#define M16C_EF_ACKE                   BIT(0)
+#define M16C_EF_CRCE                   BIT(1)
+#define M16C_EF_FORME                  BIT(2)
+#define M16C_EF_STFE                   BIT(3)
+#define M16C_EF_BITE0                  BIT(4)
+#define M16C_EF_BITE1                  BIT(5)
+#define M16C_EF_RCVE                   BIT(6)
+#define M16C_EF_TRE                    BIT(7)
+
+/* bittiming parameters */
+#define KVASER_USB_TSEG1_MIN           1
+#define KVASER_USB_TSEG1_MAX           16
+#define KVASER_USB_TSEG2_MIN           1
+#define KVASER_USB_TSEG2_MAX           8
+#define KVASER_USB_SJW_MAX             4
+#define KVASER_USB_BRP_MIN             1
+#define KVASER_USB_BRP_MAX             64
+#define KVASER_USB_BRP_INC             1
+
+/* ctrl modes */
+#define KVASER_CTRL_MODE_NORMAL                1
+#define KVASER_CTRL_MODE_SILENT                2
+#define KVASER_CTRL_MODE_SELFRECEPTION 3
+#define KVASER_CTRL_MODE_OFF           4
+
+struct kvaser_msg_simple {
+       u8 tid;
+       u8 channel;
+} __packed;
+
+struct kvaser_msg_cardinfo {
+       u8 tid;
+       u8 nchannels;
+       __le32 serial_number;
+       __le32 padding;
+       __le32 clock_resolution;
+       __le32 mfgdate;
+       u8 ean[8];
+       u8 hw_revision;
+       u8 usb_hs_mode;
+       __le16 padding2;
+} __packed;
+
+struct kvaser_msg_cardinfo2 {
+       u8 tid;
+       u8 channel;
+       u8 pcb_id[24];
+       __le32 oem_unlock_code;
+} __packed;
+
+struct kvaser_msg_softinfo {
+       u8 tid;
+       u8 channel;
+       __le32 sw_options;
+       __le32 fw_version;
+       __le16 max_outstanding_tx;
+       __le16 padding[9];
+} __packed;
+
+struct kvaser_msg_busparams {
+       u8 tid;
+       u8 channel;
+       __le32 bitrate;
+       u8 tseg1;
+       u8 tseg2;
+       u8 sjw;
+       u8 no_samp;
+} __packed;
+
+struct kvaser_msg_tx_can {
+       u8 channel;
+       u8 tid;
+       u8 msg[14];
+       u8 padding;
+       u8 flags;
+} __packed;
+
+struct kvaser_msg_rx_can {
+       u8 channel;
+       u8 flag;
+       __le16 time[3];
+       u8 msg[14];
+} __packed;
+
+struct kvaser_msg_chip_state_event {
+       u8 tid;
+       u8 channel;
+       __le16 time[3];
+       u8 tx_errors_count;
+       u8 rx_errors_count;
+       u8 status;
+       u8 padding[3];
+} __packed;
+
+struct kvaser_msg_tx_acknowledge {
+       u8 channel;
+       u8 tid;
+       __le16 time[3];
+       u8 flags;
+       u8 time_offset;
+} __packed;
+
+struct kvaser_msg_error_event {
+       u8 tid;
+       u8 flags;
+       __le16 time[3];
+       u8 channel;
+       u8 padding;
+       u8 tx_errors_count;
+       u8 rx_errors_count;
+       u8 status;
+       u8 error_factor;
+} __packed;
+
+struct kvaser_msg_ctrl_mode {
+       u8 tid;
+       u8 channel;
+       u8 ctrl_mode;
+       u8 padding[3];
+} __packed;
+
+struct kvaser_msg_flush_queue {
+       u8 tid;
+       u8 channel;
+       u8 flags;
+       u8 padding[3];
+} __packed;
+
+struct kvaser_msg_log_message {
+       u8 channel;
+       u8 flags;
+       __le16 time[3];
+       u8 dlc;
+       u8 time_offset;
+       __le32 id;
+       u8 data[8];
+} __packed;
+
+struct kvaser_msg {
+       u8 len;
+       u8 id;
+       union   {
+               struct kvaser_msg_simple simple;
+               struct kvaser_msg_cardinfo cardinfo;
+               struct kvaser_msg_cardinfo2 cardinfo2;
+               struct kvaser_msg_softinfo softinfo;
+               struct kvaser_msg_busparams busparams;
+               struct kvaser_msg_tx_can tx_can;
+               struct kvaser_msg_rx_can rx_can;
+               struct kvaser_msg_chip_state_event chip_state_event;
+               struct kvaser_msg_tx_acknowledge tx_acknowledge;
+               struct kvaser_msg_error_event error_event;
+               struct kvaser_msg_ctrl_mode ctrl_mode;
+               struct kvaser_msg_flush_queue flush_queue;
+               struct kvaser_msg_log_message log_message;
+       } u;
+} __packed;
+
+struct kvaser_usb_tx_urb_context {
+       struct kvaser_usb_net_priv *priv;
+       u32 echo_index;
+       int dlc;
+};
+
+struct kvaser_usb {
+       struct usb_device *udev;
+       struct kvaser_usb_net_priv *nets[MAX_NET_DEVICES];
+
+       struct usb_endpoint_descriptor *bulk_in, *bulk_out;
+       struct usb_anchor rx_submitted;
+
+       u32 fw_version;
+       unsigned int nchannels;
+
+       bool rxinitdone;
+       void *rxbuf[MAX_RX_URBS];
+       dma_addr_t rxbuf_dma[MAX_RX_URBS];
+};
+
+struct kvaser_usb_net_priv {
+       struct can_priv can;
+
+       atomic_t active_tx_urbs;
+       struct usb_anchor tx_submitted;
+       struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS];
+
+       struct completion start_comp, stop_comp;
+
+       struct kvaser_usb *dev;
+       struct net_device *netdev;
+       int channel;
+
+       struct can_berr_counter bec;
+};
+
+static const struct usb_device_id kvaser_usb_table[] = {
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_DEVEL_PRODUCT_ID) },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_PRODUCT_ID) },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LS_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_SWC_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_LIN_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_LS_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_SPRO_SWC_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_DEVEL_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSHS_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_UPRO_HSHS_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_GI_PRODUCT_ID) },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_PRO_OBDII_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS |
+                              KVASER_HAS_SILENT_MODE },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_MEMO2_HSLS_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_LEAF_LITE_CH_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_BLACKBIRD_SPRO_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_MERCURY_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_OEM_LEAF_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS },
+       { USB_DEVICE(KVASER_VENDOR_ID, USB_CAN_R_PRODUCT_ID),
+               .driver_info = KVASER_HAS_TXRX_ERRORS },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, kvaser_usb_table);
+
+static inline int kvaser_usb_send_msg(const struct kvaser_usb *dev,
+                                     struct kvaser_msg *msg)
+{
+       int actual_len;
+
+       return usb_bulk_msg(dev->udev,
+                           usb_sndbulkpipe(dev->udev,
+                                       dev->bulk_out->bEndpointAddress),
+                           msg, msg->len, &actual_len,
+                           USB_SEND_TIMEOUT);
+}
+
+static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
+                              struct kvaser_msg *msg)
+{
+       struct kvaser_msg *tmp;
+       void *buf;
+       int actual_len;
+       int err;
+       int pos = 0;
+
+       buf = kzalloc(RX_BUFFER_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       err = usb_bulk_msg(dev->udev,
+                          usb_rcvbulkpipe(dev->udev,
+                                          dev->bulk_in->bEndpointAddress),
+                          buf, RX_BUFFER_SIZE, &actual_len,
+                          USB_RECV_TIMEOUT);
+       if (err < 0)
+               goto end;
+
+       while (pos <= actual_len - MSG_HEADER_LEN) {
+               tmp = buf + pos;
+
+               if (!tmp->len)
+                       break;
+
+               if (pos + tmp->len > actual_len) {
+                       dev_err(dev->udev->dev.parent, "Format error\n");
+                       break;
+               }
+
+               if (tmp->id == id) {
+                       memcpy(msg, tmp, tmp->len);
+                       goto end;
+               }
+
+               pos += tmp->len;
+       }
+
+       err = -EINVAL;
+
+end:
+       kfree(buf);
+
+       return err;
+}
+
+static int kvaser_usb_send_simple_msg(const struct kvaser_usb *dev,
+                                     u8 msg_id, int channel)
+{
+       struct kvaser_msg *msg;
+       int rc;
+
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       msg->id = msg_id;
+       msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple);
+       msg->u.simple.channel = channel;
+       msg->u.simple.tid = 0xff;
+
+       rc = kvaser_usb_send_msg(dev, msg);
+
+       kfree(msg);
+       return rc;
+}
+
+static int kvaser_usb_get_software_info(struct kvaser_usb *dev)
+{
+       struct kvaser_msg msg;
+       int err;
+
+       err = kvaser_usb_send_simple_msg(dev, CMD_GET_SOFTWARE_INFO, 0);
+       if (err)
+               return err;
+
+       err = kvaser_usb_wait_msg(dev, CMD_GET_SOFTWARE_INFO_REPLY, &msg);
+       if (err)
+               return err;
+
+       dev->fw_version = le32_to_cpu(msg.u.softinfo.fw_version);
+
+       return 0;
+}
+
+static int kvaser_usb_get_card_info(struct kvaser_usb *dev)
+{
+       struct kvaser_msg msg;
+       int err;
+
+       err = kvaser_usb_send_simple_msg(dev, CMD_GET_CARD_INFO, 0);
+       if (err)
+               return err;
+
+       err = kvaser_usb_wait_msg(dev, CMD_GET_CARD_INFO_REPLY, &msg);
+       if (err)
+               return err;
+
+       dev->nchannels = msg.u.cardinfo.nchannels;
+
+       return 0;
+}
+
+static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
+                                     const struct kvaser_msg *msg)
+{
+       struct net_device_stats *stats;
+       struct kvaser_usb_tx_urb_context *context;
+       struct kvaser_usb_net_priv *priv;
+       struct sk_buff *skb;
+       struct can_frame *cf;
+       u8 channel = msg->u.tx_acknowledge.channel;
+       u8 tid = msg->u.tx_acknowledge.tid;
+
+       if (channel >= dev->nchannels) {
+               dev_err(dev->udev->dev.parent,
+                       "Invalid channel number (%d)\n", channel);
+               return;
+       }
+
+       priv = dev->nets[channel];
+
+       if (!netif_device_present(priv->netdev))
+               return;
+
+       stats = &priv->netdev->stats;
+
+       context = &priv->tx_contexts[tid % MAX_TX_URBS];
+
+       /* Sometimes the state change doesn't come after a bus-off event */
+       if (priv->can.restart_ms &&
+           (priv->can.state >= CAN_STATE_BUS_OFF)) {
+               skb = alloc_can_err_skb(priv->netdev, &cf);
+               if (skb) {
+                       cf->can_id |= CAN_ERR_RESTARTED;
+                       netif_rx(skb);
+
+                       stats->rx_packets++;
+                       stats->rx_bytes += cf->can_dlc;
+               } else {
+                       netdev_err(priv->netdev,
+                                  "No memory left for err_skb\n");
+               }
+
+               priv->can.can_stats.restarts++;
+               netif_carrier_on(priv->netdev);
+
+               priv->can.state = CAN_STATE_ERROR_ACTIVE;
+       }
+
+       stats->tx_packets++;
+       stats->tx_bytes += context->dlc;
+       can_get_echo_skb(priv->netdev, context->echo_index);
+
+       context->echo_index = MAX_TX_URBS;
+       atomic_dec(&priv->active_tx_urbs);
+
+       netif_wake_queue(priv->netdev);
+}
+
+static void kvaser_usb_simple_msg_callback(struct urb *urb)
+{
+       struct net_device *netdev = urb->context;
+
+       kfree(urb->transfer_buffer);
+
+       if (urb->status)
+               netdev_warn(netdev, "urb status received: %d\n",
+                           urb->status);
+}
+
+static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
+                                      u8 msg_id)
+{
+       struct kvaser_usb *dev = priv->dev;
+       struct net_device *netdev = priv->netdev;
+       struct kvaser_msg *msg;
+       struct urb *urb;
+       void *buf;
+       int err;
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               netdev_err(netdev, "No memory left for URBs\n");
+               return -ENOMEM;
+       }
+
+       buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
+       if (!buf) {
+               netdev_err(netdev, "No memory left for USB buffer\n");
+               usb_free_urb(urb);
+               return -ENOMEM;
+       }
+
+       msg = (struct kvaser_msg *)buf;
+       msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_simple);
+       msg->id = msg_id;
+       msg->u.simple.channel = priv->channel;
+
+       usb_fill_bulk_urb(urb, dev->udev,
+                         usb_sndbulkpipe(dev->udev,
+                                         dev->bulk_out->bEndpointAddress),
+                         buf, msg->len,
+                         kvaser_usb_simple_msg_callback, priv);
+       usb_anchor_urb(urb, &priv->tx_submitted);
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err) {
+               netdev_err(netdev, "Error transmitting URB\n");
+               usb_unanchor_urb(urb);
+               usb_free_urb(urb);
+               kfree(buf);
+               return err;
+       }
+
+       usb_free_urb(urb);
+
+       return 0;
+}
+
+static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
+{
+       int i;
+
+       usb_kill_anchored_urbs(&priv->tx_submitted);
+       atomic_set(&priv->active_tx_urbs, 0);
+
+       for (i = 0; i < MAX_TX_URBS; i++)
+               priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+}
+
+static void kvaser_usb_rx_error(const struct kvaser_usb *dev,
+                               const struct kvaser_msg *msg)
+{
+       struct can_frame *cf;
+       struct sk_buff *skb;
+       struct net_device_stats *stats;
+       struct kvaser_usb_net_priv *priv;
+       unsigned int new_state;
+       u8 channel, status, txerr, rxerr, error_factor;
+
+       switch (msg->id) {
+       case CMD_CAN_ERROR_EVENT:
+               channel = msg->u.error_event.channel;
+               status =  msg->u.error_event.status;
+               txerr = msg->u.error_event.tx_errors_count;
+               rxerr = msg->u.error_event.rx_errors_count;
+               error_factor = msg->u.error_event.error_factor;
+               break;
+       case CMD_LOG_MESSAGE:
+               channel = msg->u.log_message.channel;
+               status = msg->u.log_message.data[0];
+               txerr = msg->u.log_message.data[2];
+               rxerr = msg->u.log_message.data[3];
+               error_factor = msg->u.log_message.data[1];
+               break;
+       case CMD_CHIP_STATE_EVENT:
+               channel = msg->u.chip_state_event.channel;
+               status =  msg->u.chip_state_event.status;
+               txerr = msg->u.chip_state_event.tx_errors_count;
+               rxerr = msg->u.chip_state_event.rx_errors_count;
+               error_factor = 0;
+               break;
+       default:
+               dev_err(dev->udev->dev.parent, "Invalid msg id (%d)\n",
+                       msg->id);
+               return;
+       }
+
+       if (channel >= dev->nchannels) {
+               dev_err(dev->udev->dev.parent,
+                       "Invalid channel number (%d)\n", channel);
+               return;
+       }
+
+       priv = dev->nets[channel];
+       stats = &priv->netdev->stats;
+
+       if (status & M16C_STATE_BUS_RESET) {
+               kvaser_usb_unlink_tx_urbs(priv);
+               return;
+       }
+
+       skb = alloc_can_err_skb(priv->netdev, &cf);
+       if (!skb) {
+               stats->rx_dropped++;
+               return;
+       }
+
+       new_state = priv->can.state;
+
+       netdev_dbg(priv->netdev, "Error status: 0x%02x\n", status);
+
+       if (status & M16C_STATE_BUS_OFF) {
+               cf->can_id |= CAN_ERR_BUSOFF;
+
+               priv->can.can_stats.bus_off++;
+               if (!priv->can.restart_ms)
+                       kvaser_usb_simple_msg_async(priv, CMD_STOP_CHIP);
+
+               netif_carrier_off(priv->netdev);
+
+               new_state = CAN_STATE_BUS_OFF;
+       } else if (status & M16C_STATE_BUS_PASSIVE) {
+               if (priv->can.state != CAN_STATE_ERROR_PASSIVE) {
+                       cf->can_id |= CAN_ERR_CRTL;
+
+                       if (txerr || rxerr)
+                               cf->data[1] = (txerr > rxerr)
+                                               ? CAN_ERR_CRTL_TX_PASSIVE
+                                               : CAN_ERR_CRTL_RX_PASSIVE;
+                       else
+                               cf->data[1] = CAN_ERR_CRTL_TX_PASSIVE |
+                                             CAN_ERR_CRTL_RX_PASSIVE;
+
+                       priv->can.can_stats.error_passive++;
+               }
+
+               new_state = CAN_STATE_ERROR_PASSIVE;
+       }
+
+       if (status == M16C_STATE_BUS_ERROR) {
+               if ((priv->can.state < CAN_STATE_ERROR_WARNING) &&
+                   ((txerr >= 96) || (rxerr >= 96))) {
+                       cf->can_id |= CAN_ERR_CRTL;
+                       cf->data[1] = (txerr > rxerr)
+                                       ? CAN_ERR_CRTL_TX_WARNING
+                                       : CAN_ERR_CRTL_RX_WARNING;
+
+                       priv->can.can_stats.error_warning++;
+                       new_state = CAN_STATE_ERROR_WARNING;
+               } else if (priv->can.state > CAN_STATE_ERROR_ACTIVE) {
+                       cf->can_id |= CAN_ERR_PROT;
+                       cf->data[2] = CAN_ERR_PROT_ACTIVE;
+
+                       new_state = CAN_STATE_ERROR_ACTIVE;
+               }
+       }
+
+       if (!status) {
+               cf->can_id |= CAN_ERR_PROT;
+               cf->data[2] = CAN_ERR_PROT_ACTIVE;
+
+               new_state = CAN_STATE_ERROR_ACTIVE;
+       }
+
+       if (priv->can.restart_ms &&
+           (priv->can.state >= CAN_STATE_BUS_OFF) &&
+           (new_state < CAN_STATE_BUS_OFF)) {
+               cf->can_id |= CAN_ERR_RESTARTED;
+               netif_carrier_on(priv->netdev);
+
+               priv->can.can_stats.restarts++;
+       }
+
+       if (error_factor) {
+               priv->can.can_stats.bus_error++;
+               stats->rx_errors++;
+
+               cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
+
+               if (error_factor & M16C_EF_ACKE)
+                       cf->data[3] |= (CAN_ERR_PROT_LOC_ACK);
+               if (error_factor & M16C_EF_CRCE)
+                       cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+                                       CAN_ERR_PROT_LOC_CRC_DEL);
+               if (error_factor & M16C_EF_FORME)
+                       cf->data[2] |= CAN_ERR_PROT_FORM;
+               if (error_factor & M16C_EF_STFE)
+                       cf->data[2] |= CAN_ERR_PROT_STUFF;
+               if (error_factor & M16C_EF_BITE0)
+                       cf->data[2] |= CAN_ERR_PROT_BIT0;
+               if (error_factor & M16C_EF_BITE1)
+                       cf->data[2] |= CAN_ERR_PROT_BIT1;
+               if (error_factor & M16C_EF_TRE)
+                       cf->data[2] |= CAN_ERR_PROT_TX;
+       }
+
+       cf->data[6] = txerr;
+       cf->data[7] = rxerr;
+
+       priv->bec.txerr = txerr;
+       priv->bec.rxerr = rxerr;
+
+       priv->can.state = new_state;
+
+       netif_rx(skb);
+
+       stats->rx_packets++;
+       stats->rx_bytes += cf->can_dlc;
+}
+
+static void kvaser_usb_rx_can_err(const struct kvaser_usb_net_priv *priv,
+                                 const struct kvaser_msg *msg)
+{
+       struct can_frame *cf;
+       struct sk_buff *skb;
+       struct net_device_stats *stats = &priv->netdev->stats;
+
+       if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME |
+                                        MSG_FLAG_NERR)) {
+               netdev_err(priv->netdev, "Unknow error (flags: 0x%02x)\n",
+                          msg->u.rx_can.flag);
+
+               stats->rx_errors++;
+               return;
+       }
+
+       if (msg->u.rx_can.flag & MSG_FLAG_OVERRUN) {
+               skb = alloc_can_err_skb(priv->netdev, &cf);
+               if (!skb) {
+                       stats->rx_dropped++;
+                       return;
+               }
+
+               cf->can_id |= CAN_ERR_CRTL;
+               cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+
+               stats->rx_over_errors++;
+               stats->rx_errors++;
+
+               netif_rx(skb);
+
+               stats->rx_packets++;
+               stats->rx_bytes += cf->can_dlc;
+       }
+}
+
+static void kvaser_usb_rx_can_msg(const struct kvaser_usb *dev,
+                                 const struct kvaser_msg *msg)
+{
+       struct kvaser_usb_net_priv *priv;
+       struct can_frame *cf;
+       struct sk_buff *skb;
+       struct net_device_stats *stats;
+       u8 channel = msg->u.rx_can.channel;
+
+       if (channel >= dev->nchannels) {
+               dev_err(dev->udev->dev.parent,
+                       "Invalid channel number (%d)\n", channel);
+               return;
+       }
+
+       priv = dev->nets[channel];
+       stats = &priv->netdev->stats;
+
+       if (msg->u.rx_can.flag & (MSG_FLAG_ERROR_FRAME | MSG_FLAG_NERR |
+                                 MSG_FLAG_OVERRUN)) {
+               kvaser_usb_rx_can_err(priv, msg);
+               return;
+       } else if (msg->u.rx_can.flag & ~MSG_FLAG_REMOTE_FRAME) {
+               netdev_warn(priv->netdev,
+                           "Unhandled frame (flags: 0x%02x)",
+                           msg->u.rx_can.flag);
+               return;
+       }
+
+       skb = alloc_can_skb(priv->netdev, &cf);
+       if (!skb) {
+               stats->tx_dropped++;
+               return;
+       }
+
+       cf->can_id = ((msg->u.rx_can.msg[0] & 0x1f) << 6) |
+                    (msg->u.rx_can.msg[1] & 0x3f);
+       cf->can_dlc = get_can_dlc(msg->u.rx_can.msg[5]);
+
+       if (msg->id == CMD_RX_EXT_MESSAGE) {
+               cf->can_id <<= 18;
+               cf->can_id |= ((msg->u.rx_can.msg[2] & 0x0f) << 14) |
+                             ((msg->u.rx_can.msg[3] & 0xff) << 6) |
+                             (msg->u.rx_can.msg[4] & 0x3f);
+               cf->can_id |= CAN_EFF_FLAG;
+       }
+
+       if (msg->u.rx_can.flag & MSG_FLAG_REMOTE_FRAME)
+               cf->can_id |= CAN_RTR_FLAG;
+       else
+               memcpy(cf->data, &msg->u.rx_can.msg[6], cf->can_dlc);
+
+       netif_rx(skb);
+
+       stats->rx_packets++;
+       stats->rx_bytes += cf->can_dlc;
+}
+
+static void kvaser_usb_start_chip_reply(const struct kvaser_usb *dev,
+                                       const struct kvaser_msg *msg)
+{
+       struct kvaser_usb_net_priv *priv;
+       u8 channel = msg->u.simple.channel;
+
+       if (channel >= dev->nchannels) {
+               dev_err(dev->udev->dev.parent,
+                       "Invalid channel number (%d)\n", channel);
+               return;
+       }
+
+       priv = dev->nets[channel];
+
+       if (completion_done(&priv->start_comp) &&
+           netif_queue_stopped(priv->netdev)) {
+               netif_wake_queue(priv->netdev);
+       } else {
+               netif_start_queue(priv->netdev);
+               complete(&priv->start_comp);
+       }
+}
+
+static void kvaser_usb_stop_chip_reply(const struct kvaser_usb *dev,
+                                      const struct kvaser_msg *msg)
+{
+       struct kvaser_usb_net_priv *priv;
+       u8 channel = msg->u.simple.channel;
+
+       if (channel >= dev->nchannels) {
+               dev_err(dev->udev->dev.parent,
+                       "Invalid channel number (%d)\n", channel);
+               return;
+       }
+
+       priv = dev->nets[channel];
+
+       complete(&priv->stop_comp);
+}
+
+static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
+                                     const struct kvaser_msg *msg)
+{
+       switch (msg->id) {
+       case CMD_START_CHIP_REPLY:
+               kvaser_usb_start_chip_reply(dev, msg);
+               break;
+
+       case CMD_STOP_CHIP_REPLY:
+               kvaser_usb_stop_chip_reply(dev, msg);
+               break;
+
+       case CMD_RX_STD_MESSAGE:
+       case CMD_RX_EXT_MESSAGE:
+               kvaser_usb_rx_can_msg(dev, msg);
+               break;
+
+       case CMD_CHIP_STATE_EVENT:
+       case CMD_CAN_ERROR_EVENT:
+               kvaser_usb_rx_error(dev, msg);
+               break;
+
+       case CMD_LOG_MESSAGE:
+               if (msg->u.log_message.flags & MSG_FLAG_ERROR_FRAME)
+                       kvaser_usb_rx_error(dev, msg);
+               break;
+
+       case CMD_TX_ACKNOWLEDGE:
+               kvaser_usb_tx_acknowledge(dev, msg);
+               break;
+
+       default:
+               dev_warn(dev->udev->dev.parent,
+                        "Unhandled message (%d)\n", msg->id);
+               break;
+       }
+}
+
+static void kvaser_usb_read_bulk_callback(struct urb *urb)
+{
+       struct kvaser_usb *dev = urb->context;
+       struct kvaser_msg *msg;
+       int pos = 0;
+       int err, i;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:
+               dev_info(dev->udev->dev.parent, "Rx URB aborted (%d)\n",
+                        urb->status);
+               goto resubmit_urb;
+       }
+
+       while (pos <= urb->actual_length - MSG_HEADER_LEN) {
+               msg = urb->transfer_buffer + pos;
+
+               if (!msg->len)
+                       break;
+
+               if (pos + msg->len > urb->actual_length) {
+                       dev_err(dev->udev->dev.parent, "Format error\n");
+                       break;
+               }
+
+               kvaser_usb_handle_message(dev, msg);
+
+               pos += msg->len;
+       }
+
+resubmit_urb:
+       usb_fill_bulk_urb(urb, dev->udev,
+                         usb_rcvbulkpipe(dev->udev,
+                                         dev->bulk_in->bEndpointAddress),
+                         urb->transfer_buffer, RX_BUFFER_SIZE,
+                         kvaser_usb_read_bulk_callback, dev);
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err == -ENODEV) {
+               for (i = 0; i < dev->nchannels; i++) {
+                       if (!dev->nets[i])
+                               continue;
+
+                       netif_device_detach(dev->nets[i]->netdev);
+               }
+       } else if (err) {
+               dev_err(dev->udev->dev.parent,
+                       "Failed resubmitting read bulk urb: %d\n", err);
+       }
+
+       return;
+}
+
+static int kvaser_usb_setup_rx_urbs(struct kvaser_usb *dev)
+{
+       int i, err = 0;
+
+       if (dev->rxinitdone)
+               return 0;
+
+       for (i = 0; i < MAX_RX_URBS; i++) {
+               struct urb *urb = NULL;
+               u8 *buf = NULL;
+               dma_addr_t buf_dma;
+
+               urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!urb) {
+                       dev_warn(dev->udev->dev.parent,
+                                "No memory left for URBs\n");
+                       err = -ENOMEM;
+                       break;
+               }
+
+               buf = usb_alloc_coherent(dev->udev, RX_BUFFER_SIZE,
+                                        GFP_KERNEL, &buf_dma);
+               if (!buf) {
+                       dev_warn(dev->udev->dev.parent,
+                                "No memory left for USB buffer\n");
+                       usb_free_urb(urb);
+                       err = -ENOMEM;
+                       break;
+               }
+
+               usb_fill_bulk_urb(urb, dev->udev,
+                                 usb_rcvbulkpipe(dev->udev,
+                                         dev->bulk_in->bEndpointAddress),
+                                 buf, RX_BUFFER_SIZE,
+                                 kvaser_usb_read_bulk_callback,
+                                 dev);
+               urb->transfer_dma = buf_dma;
+               urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+               usb_anchor_urb(urb, &dev->rx_submitted);
+
+               err = usb_submit_urb(urb, GFP_KERNEL);
+               if (err) {
+                       usb_unanchor_urb(urb);
+                       usb_free_coherent(dev->udev, RX_BUFFER_SIZE, buf,
+                                         buf_dma);
+                       usb_free_urb(urb);
+                       break;
+               }
+
+               dev->rxbuf[i] = buf;
+               dev->rxbuf_dma[i] = buf_dma;
+
+               usb_free_urb(urb);
+       }
+
+       if (i == 0) {
+               dev_warn(dev->udev->dev.parent,
+                        "Cannot setup read URBs, error %d\n", err);
+               return err;
+       } else if (i < MAX_RX_URBS) {
+               dev_warn(dev->udev->dev.parent,
+                        "RX performances may be slow\n");
+       }
+
+       dev->rxinitdone = true;
+
+       return 0;
+}
+
+static int kvaser_usb_set_opt_mode(const struct kvaser_usb_net_priv *priv)
+{
+       struct kvaser_msg *msg;
+       int rc;
+
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       msg->id = CMD_SET_CTRL_MODE;
+       msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_ctrl_mode);
+       msg->u.ctrl_mode.tid = 0xff;
+       msg->u.ctrl_mode.channel = priv->channel;
+
+       if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+               msg->u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_SILENT;
+       else
+               msg->u.ctrl_mode.ctrl_mode = KVASER_CTRL_MODE_NORMAL;
+
+       rc = kvaser_usb_send_msg(priv->dev, msg);
+
+       kfree(msg);
+       return rc;
+}
+
+static int kvaser_usb_start_chip(struct kvaser_usb_net_priv *priv)
+{
+       int err;
+
+       init_completion(&priv->start_comp);
+
+       err = kvaser_usb_send_simple_msg(priv->dev, CMD_START_CHIP,
+                                        priv->channel);
+       if (err)
+               return err;
+
+       if (!wait_for_completion_timeout(&priv->start_comp,
+                                        msecs_to_jiffies(START_TIMEOUT)))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int kvaser_usb_open(struct net_device *netdev)
+{
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+       struct kvaser_usb *dev = priv->dev;
+       int err;
+
+       err = open_candev(netdev);
+       if (err)
+               return err;
+
+       err = kvaser_usb_setup_rx_urbs(dev);
+       if (err)
+               goto error;
+
+       err = kvaser_usb_set_opt_mode(priv);
+       if (err)
+               goto error;
+
+       err = kvaser_usb_start_chip(priv);
+       if (err) {
+               netdev_warn(netdev, "Cannot start device, error %d\n", err);
+               goto error;
+       }
+
+       priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+       return 0;
+
+error:
+       close_candev(netdev);
+       return err;
+}
+
+static void kvaser_usb_unlink_all_urbs(struct kvaser_usb *dev)
+{
+       int i;
+
+       usb_kill_anchored_urbs(&dev->rx_submitted);
+
+       for (i = 0; i < MAX_RX_URBS; i++)
+               usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
+                                 dev->rxbuf[i],
+                                 dev->rxbuf_dma[i]);
+
+       for (i = 0; i < MAX_NET_DEVICES; i++) {
+               struct kvaser_usb_net_priv *priv = dev->nets[i];
+
+               if (priv)
+                       kvaser_usb_unlink_tx_urbs(priv);
+       }
+}
+
+static int kvaser_usb_stop_chip(struct kvaser_usb_net_priv *priv)
+{
+       int err;
+
+       init_completion(&priv->stop_comp);
+
+       err = kvaser_usb_send_simple_msg(priv->dev, CMD_STOP_CHIP,
+                                        priv->channel);
+       if (err)
+               return err;
+
+       if (!wait_for_completion_timeout(&priv->stop_comp,
+                                        msecs_to_jiffies(STOP_TIMEOUT)))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int kvaser_usb_flush_queue(struct kvaser_usb_net_priv *priv)
+{
+       struct kvaser_msg *msg;
+       int rc;
+
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       msg->id = CMD_FLUSH_QUEUE;
+       msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_flush_queue);
+       msg->u.flush_queue.channel = priv->channel;
+       msg->u.flush_queue.flags = 0x00;
+
+       rc = kvaser_usb_send_msg(priv->dev, msg);
+
+       kfree(msg);
+       return rc;
+}
+
+static int kvaser_usb_close(struct net_device *netdev)
+{
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+       struct kvaser_usb *dev = priv->dev;
+       int err;
+
+       netif_stop_queue(netdev);
+
+       err = kvaser_usb_flush_queue(priv);
+       if (err)
+               netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
+
+       if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel))
+               netdev_warn(netdev, "Cannot reset card, error %d\n", err);
+
+       err = kvaser_usb_stop_chip(priv);
+       if (err)
+               netdev_warn(netdev, "Cannot stop device, error %d\n", err);
+
+       priv->can.state = CAN_STATE_STOPPED;
+       close_candev(priv->netdev);
+
+       return 0;
+}
+
+static void kvaser_usb_write_bulk_callback(struct urb *urb)
+{
+       struct kvaser_usb_tx_urb_context *context = urb->context;
+       struct kvaser_usb_net_priv *priv;
+       struct net_device *netdev;
+
+       if (WARN_ON(!context))
+               return;
+
+       priv = context->priv;
+       netdev = priv->netdev;
+
+       kfree(urb->transfer_buffer);
+
+       if (!netif_device_present(netdev))
+               return;
+
+       if (urb->status)
+               netdev_info(netdev, "Tx URB aborted (%d)\n", urb->status);
+}
+
+static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
+                                        struct net_device *netdev)
+{
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+       struct kvaser_usb *dev = priv->dev;
+       struct net_device_stats *stats = &netdev->stats;
+       struct can_frame *cf = (struct can_frame *)skb->data;
+       struct kvaser_usb_tx_urb_context *context = NULL;
+       struct urb *urb;
+       void *buf;
+       struct kvaser_msg *msg;
+       int i, err;
+       int ret = NETDEV_TX_OK;
+
+       if (can_dropped_invalid_skb(netdev, skb))
+               return NETDEV_TX_OK;
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               netdev_err(netdev, "No memory left for URBs\n");
+               stats->tx_dropped++;
+               goto nourbmem;
+       }
+
+       buf = kmalloc(sizeof(struct kvaser_msg), GFP_ATOMIC);
+       if (!buf) {
+               netdev_err(netdev, "No memory left for USB buffer\n");
+               stats->tx_dropped++;
+               goto nobufmem;
+       }
+
+       msg = buf;
+       msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_tx_can);
+       msg->u.tx_can.flags = 0;
+       msg->u.tx_can.channel = priv->channel;
+
+       if (cf->can_id & CAN_EFF_FLAG) {
+               msg->id = CMD_TX_EXT_MESSAGE;
+               msg->u.tx_can.msg[0] = (cf->can_id >> 24) & 0x1f;
+               msg->u.tx_can.msg[1] = (cf->can_id >> 18) & 0x3f;
+               msg->u.tx_can.msg[2] = (cf->can_id >> 14) & 0x0f;
+               msg->u.tx_can.msg[3] = (cf->can_id >> 6) & 0xff;
+               msg->u.tx_can.msg[4] = cf->can_id & 0x3f;
+       } else {
+               msg->id = CMD_TX_STD_MESSAGE;
+               msg->u.tx_can.msg[0] = (cf->can_id >> 6) & 0x1f;
+               msg->u.tx_can.msg[1] = cf->can_id & 0x3f;
+       }
+
+       msg->u.tx_can.msg[5] = cf->can_dlc;
+       memcpy(&msg->u.tx_can.msg[6], cf->data, cf->can_dlc);
+
+       if (cf->can_id & CAN_RTR_FLAG)
+               msg->u.tx_can.flags |= MSG_FLAG_REMOTE_FRAME;
+
+       for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
+               if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
+                       context = &priv->tx_contexts[i];
+                       break;
+               }
+       }
+
+       if (!context) {
+               netdev_warn(netdev, "cannot find free context\n");
+               ret =  NETDEV_TX_BUSY;
+               goto releasebuf;
+       }
+
+       context->priv = priv;
+       context->echo_index = i;
+       context->dlc = cf->can_dlc;
+
+       msg->u.tx_can.tid = context->echo_index;
+
+       usb_fill_bulk_urb(urb, dev->udev,
+                         usb_sndbulkpipe(dev->udev,
+                                         dev->bulk_out->bEndpointAddress),
+                         buf, msg->len,
+                         kvaser_usb_write_bulk_callback, context);
+       usb_anchor_urb(urb, &priv->tx_submitted);
+
+       can_put_echo_skb(skb, netdev, context->echo_index);
+
+       atomic_inc(&priv->active_tx_urbs);
+
+       if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
+               netif_stop_queue(netdev);
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (unlikely(err)) {
+               can_free_echo_skb(netdev, context->echo_index);
+
+               skb = NULL; /* set to NULL to avoid double free in
+                            * dev_kfree_skb(skb) */
+
+               atomic_dec(&priv->active_tx_urbs);
+               usb_unanchor_urb(urb);
+
+               stats->tx_dropped++;
+
+               if (err == -ENODEV)
+                       netif_device_detach(netdev);
+               else
+                       netdev_warn(netdev, "Failed tx_urb %d\n", err);
+
+               goto releasebuf;
+       }
+
+       usb_free_urb(urb);
+
+       return NETDEV_TX_OK;
+
+releasebuf:
+       kfree(buf);
+nobufmem:
+       usb_free_urb(urb);
+nourbmem:
+       dev_kfree_skb(skb);
+       return ret;
+}
+
+static const struct net_device_ops kvaser_usb_netdev_ops = {
+       .ndo_open = kvaser_usb_open,
+       .ndo_stop = kvaser_usb_close,
+       .ndo_start_xmit = kvaser_usb_start_xmit,
+};
+
+static const struct can_bittiming_const kvaser_usb_bittiming_const = {
+       .name = "kvaser_usb",
+       .tseg1_min = KVASER_USB_TSEG1_MIN,
+       .tseg1_max = KVASER_USB_TSEG1_MAX,
+       .tseg2_min = KVASER_USB_TSEG2_MIN,
+       .tseg2_max = KVASER_USB_TSEG2_MAX,
+       .sjw_max = KVASER_USB_SJW_MAX,
+       .brp_min = KVASER_USB_BRP_MIN,
+       .brp_max = KVASER_USB_BRP_MAX,
+       .brp_inc = KVASER_USB_BRP_INC,
+};
+
+static int kvaser_usb_set_bittiming(struct net_device *netdev)
+{
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+       struct can_bittiming *bt = &priv->can.bittiming;
+       struct kvaser_usb *dev = priv->dev;
+       struct kvaser_msg *msg;
+       int rc;
+
+       msg = kmalloc(sizeof(*msg), GFP_KERNEL);
+       if (!msg)
+               return -ENOMEM;
+
+       msg->id = CMD_SET_BUS_PARAMS;
+       msg->len = MSG_HEADER_LEN + sizeof(struct kvaser_msg_busparams);
+       msg->u.busparams.channel = priv->channel;
+       msg->u.busparams.tid = 0xff;
+       msg->u.busparams.bitrate = cpu_to_le32(bt->bitrate);
+       msg->u.busparams.sjw = bt->sjw;
+       msg->u.busparams.tseg1 = bt->prop_seg + bt->phase_seg1;
+       msg->u.busparams.tseg2 = bt->phase_seg2;
+
+       if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
+               msg->u.busparams.no_samp = 3;
+       else
+               msg->u.busparams.no_samp = 1;
+
+       rc = kvaser_usb_send_msg(dev, msg);
+
+       kfree(msg);
+       return rc;
+}
+
+static int kvaser_usb_set_mode(struct net_device *netdev,
+                              enum can_mode mode)
+{
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+       int err;
+
+       switch (mode) {
+       case CAN_MODE_START:
+               err = kvaser_usb_simple_msg_async(priv, CMD_START_CHIP);
+               if (err)
+                       return err;
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int kvaser_usb_get_berr_counter(const struct net_device *netdev,
+                                      struct can_berr_counter *bec)
+{
+       struct kvaser_usb_net_priv *priv = netdev_priv(netdev);
+
+       *bec = priv->bec;
+
+       return 0;
+}
+
+static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
+{
+       int i;
+
+       for (i = 0; i < dev->nchannels; i++) {
+               if (!dev->nets[i])
+                       continue;
+
+               unregister_netdev(dev->nets[i]->netdev);
+       }
+
+       kvaser_usb_unlink_all_urbs(dev);
+
+       for (i = 0; i < dev->nchannels; i++) {
+               if (!dev->nets[i])
+                       continue;
+
+               free_candev(dev->nets[i]->netdev);
+       }
+}
+
+static int kvaser_usb_init_one(struct usb_interface *intf,
+                              const struct usb_device_id *id, int channel)
+{
+       struct kvaser_usb *dev = usb_get_intfdata(intf);
+       struct net_device *netdev;
+       struct kvaser_usb_net_priv *priv;
+       int i, err;
+
+       netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
+       if (!netdev) {
+               dev_err(&intf->dev, "Cannot alloc candev\n");
+               return -ENOMEM;
+       }
+
+       priv = netdev_priv(netdev);
+
+       init_completion(&priv->start_comp);
+       init_completion(&priv->stop_comp);
+
+       init_usb_anchor(&priv->tx_submitted);
+       atomic_set(&priv->active_tx_urbs, 0);
+
+       for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++)
+               priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+
+       priv->dev = dev;
+       priv->netdev = netdev;
+       priv->channel = channel;
+
+       priv->can.state = CAN_STATE_STOPPED;
+       priv->can.clock.freq = CAN_USB_CLOCK;
+       priv->can.bittiming_const = &kvaser_usb_bittiming_const;
+       priv->can.do_set_bittiming = kvaser_usb_set_bittiming;
+       priv->can.do_set_mode = kvaser_usb_set_mode;
+       if (id->driver_info & KVASER_HAS_TXRX_ERRORS)
+               priv->can.do_get_berr_counter = kvaser_usb_get_berr_counter;
+       priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
+       if (id->driver_info & KVASER_HAS_SILENT_MODE)
+               priv->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;
+
+       netdev->flags |= IFF_ECHO;
+
+       netdev->netdev_ops = &kvaser_usb_netdev_ops;
+
+       SET_NETDEV_DEV(netdev, &intf->dev);
+
+       dev->nets[channel] = priv;
+
+       err = register_candev(netdev);
+       if (err) {
+               dev_err(&intf->dev, "Failed to register can device\n");
+               free_candev(netdev);
+               dev->nets[channel] = NULL;
+               return err;
+       }
+
+       netdev_dbg(netdev, "device registered\n");
+
+       return 0;
+}
+
+static void kvaser_usb_get_endpoints(const struct usb_interface *intf,
+                                    struct usb_endpoint_descriptor **in,
+                                    struct usb_endpoint_descriptor **out)
+{
+       const struct usb_host_interface *iface_desc;
+       struct usb_endpoint_descriptor *endpoint;
+       int i;
+
+       iface_desc = &intf->altsetting[0];
+
+       for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+               endpoint = &iface_desc->endpoint[i].desc;
+
+               if (usb_endpoint_is_bulk_in(endpoint))
+                       *in = endpoint;
+
+               if (usb_endpoint_is_bulk_out(endpoint))
+                       *out = endpoint;
+       }
+}
+
+static int kvaser_usb_probe(struct usb_interface *intf,
+                           const struct usb_device_id *id)
+{
+       struct kvaser_usb *dev;
+       int err = -ENOMEM;
+       int i;
+
+       dev = devm_kzalloc(&intf->dev, sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       kvaser_usb_get_endpoints(intf, &dev->bulk_in, &dev->bulk_out);
+       if (!dev->bulk_in || !dev->bulk_out) {
+               dev_err(&intf->dev, "Cannot get usb endpoint(s)");
+               return err;
+       }
+
+       dev->udev = interface_to_usbdev(intf);
+
+       init_usb_anchor(&dev->rx_submitted);
+
+       usb_set_intfdata(intf, dev);
+
+       for (i = 0; i < MAX_NET_DEVICES; i++)
+               kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, i);
+
+       err = kvaser_usb_get_software_info(dev);
+       if (err) {
+               dev_err(&intf->dev,
+                       "Cannot get software infos, error %d\n", err);
+               return err;
+       }
+
+       err = kvaser_usb_get_card_info(dev);
+       if (err) {
+               dev_err(&intf->dev,
+                       "Cannot get card infos, error %d\n", err);
+               return err;
+       }
+
+       dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
+               ((dev->fw_version >> 24) & 0xff),
+               ((dev->fw_version >> 16) & 0xff),
+               (dev->fw_version & 0xffff));
+
+       for (i = 0; i < dev->nchannels; i++) {
+               err = kvaser_usb_init_one(intf, id, i);
+               if (err) {
+                       kvaser_usb_remove_interfaces(dev);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static void kvaser_usb_disconnect(struct usb_interface *intf)
+{
+       struct kvaser_usb *dev = usb_get_intfdata(intf);
+
+       usb_set_intfdata(intf, NULL);
+
+       if (!dev)
+               return;
+
+       kvaser_usb_remove_interfaces(dev);
+}
+
+static struct usb_driver kvaser_usb_driver = {
+       .name = "kvaser_usb",
+       .probe = kvaser_usb_probe,
+       .disconnect = kvaser_usb_disconnect,
+       .id_table = kvaser_usb_table,
+};
+
+module_usb_driver(kvaser_usb_driver);
+
+MODULE_AUTHOR("Olivier Sobrie <olivier@sobrie.be>");
+MODULE_DESCRIPTION("CAN driver for Kvaser CAN/USB devices");
+MODULE_LICENSE("GPL v2");
index 86f26a1ede4c18a233a85310b0bfb5f9a92da856..25723d8ee20130b19ad95b885a99e5c1ba019517 100644 (file)
@@ -519,8 +519,10 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
        mc->pdev->dev.can.state = new_state;
 
        if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
+               struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
+
                peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv);
-               skb->tstamp = timeval_to_ktime(tv);
+               hwts->hwtstamp = timeval_to_ktime(tv);
        }
 
        netif_rx(skb);
@@ -605,6 +607,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
        struct sk_buff *skb;
        struct can_frame *cf;
        struct timeval tv;
+       struct skb_shared_hwtstamps *hwts;
 
        skb = alloc_can_skb(mc->netdev, &cf);
        if (!skb)
@@ -652,7 +655,8 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
 
        /* convert timestamp into kernel time */
        peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv);
-       skb->tstamp = timeval_to_ktime(tv);
+       hwts = skb_hwtstamps(skb);
+       hwts->hwtstamp = timeval_to_ktime(tv);
 
        /* push the skb */
        netif_rx(skb);
index c4643c400d462bfc63ce7b4df6c76558e4e92e50..d9290ea788e02665d169e34b4fd7704a116622b4 100644 (file)
@@ -520,7 +520,6 @@ static int peak_usb_ndo_open(struct net_device *netdev)
                return err;
        }
 
-       dev->open_time = jiffies;
        netif_start_queue(netdev);
 
        return 0;
@@ -576,7 +575,6 @@ static int peak_usb_ndo_stop(struct net_device *netdev)
 
        close_candev(netdev);
 
-       dev->open_time = 0;
        dev->can.state = CAN_STATE_STOPPED;
 
        /* can set bus off now */
@@ -661,9 +659,6 @@ static int peak_usb_set_mode(struct net_device *netdev, enum can_mode mode)
        struct peak_usb_device *dev = netdev_priv(netdev);
        int err = 0;
 
-       if (!dev->open_time)
-               return -EINVAL;
-
        switch (mode) {
        case CAN_MODE_START:
                err = peak_usb_restart(dev);
index c8e5e91d7cb571f350eef5ff2b0e26cf317d6460..073b47ff8eee3065b2bf9f1319fc7207c93c2aa8 100644 (file)
@@ -104,7 +104,6 @@ struct peak_usb_device {
        struct can_priv can;
        struct peak_usb_adapter *adapter;
        unsigned int ctrl_idx;
-       int open_time;
        u32 state;
 
        struct sk_buff *echo_skb[PCAN_USB_MAX_TX_URBS];
index e1626d92511adc88d084345f7fdbf098a4aafb09..30d79bfa5b109e5d6d212df46658a4cf1216d6e1 100644 (file)
@@ -532,6 +532,7 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
        struct can_frame *can_frame;
        struct sk_buff *skb;
        struct timeval tv;
+       struct skb_shared_hwtstamps *hwts;
 
        skb = alloc_can_skb(netdev, &can_frame);
        if (!skb)
@@ -549,7 +550,8 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if,
                memcpy(can_frame->data, rx->data, can_frame->can_dlc);
 
        peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv);
-       skb->tstamp = timeval_to_ktime(tv);
+       hwts = skb_hwtstamps(skb);
+       hwts->hwtstamp = timeval_to_ktime(tv);
 
        netif_rx(skb);
        netdev->stats.rx_packets++;
@@ -570,6 +572,7 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
        u8 err_mask = 0;
        struct sk_buff *skb;
        struct timeval tv;
+       struct skb_shared_hwtstamps *hwts;
 
        /* nothing should be sent while in BUS_OFF state */
        if (dev->can.state == CAN_STATE_BUS_OFF)
@@ -664,7 +667,8 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if,
        dev->can.state = new_state;
 
        peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv);
-       skb->tstamp = timeval_to_ktime(tv);
+       hwts = skb_hwtstamps(skb);
+       hwts->hwtstamp = timeval_to_ktime(tv);
        netif_rx(skb);
        netdev->stats.rx_packets++;
        netdev->stats.rx_bytes += can_frame->can_dlc;
index dd151d53d506dc1e68c3f65b6a9973a51d6e083f..b8fe808b7957c735e0f4c8248ad3bcff14b46716 100644 (file)
@@ -1,5 +1,5 @@
 menu "Distributed Switch Architecture drivers"
-       depends on NET_DSA
+       depends on HAVE_NET_DSA
 
 config NET_DSA_MV88E6XXX
        tristate
@@ -7,6 +7,7 @@ config NET_DSA_MV88E6XXX
 
 config NET_DSA_MV88E6060
        tristate "Marvell 88E6060 ethernet switch chip support"
+       select NET_DSA
        select NET_DSA_TAG_TRAILER
        ---help---
          This enables support for the Marvell 88E6060 ethernet switch
@@ -18,6 +19,7 @@ config NET_DSA_MV88E6XXX_NEED_PPU
 
 config NET_DSA_MV88E6131
        tristate "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
+       select NET_DSA
        select NET_DSA_MV88E6XXX
        select NET_DSA_MV88E6XXX_NEED_PPU
        select NET_DSA_TAG_DSA
@@ -27,6 +29,7 @@ config NET_DSA_MV88E6131
 
 config NET_DSA_MV88E6123_61_65
        tristate "Marvell 88E6123/6161/6165 ethernet switch chip support"
+       select NET_DSA
        select NET_DSA_MV88E6XXX
        select NET_DSA_TAG_EDSA
        ---help---
index 1a8eef2c3d58aa9cee7d06cd96a3850dd3ace2f4..633c709b9d996943c415cd0ad49e628a200eec34 100644 (file)
@@ -92,7 +92,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-static char version[] __devinitdata = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
+static char version[] = DRV_NAME ".c:" DRV_VERSION " " DRV_RELDATE " becker@scyld.com\n";
 
 #ifdef EL3_DEBUG
 static int el3_debug = EL3_DEBUG;
@@ -184,7 +184,7 @@ static int max_interrupt_work = 10;
 static int nopnp;
 #endif
 
-static int __devinit el3_common_init(struct net_device *dev);
+static int el3_common_init(struct net_device *dev);
 static void el3_common_remove(struct net_device *dev);
 static ushort id_read_eeprom(int index);
 static ushort read_eeprom(int ioaddr, int index);
@@ -270,9 +270,8 @@ static int el3_isa_id_sequence(__be16 *phys_addr)
 
 }
 
-static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
-                                  int ioaddr, int irq, int if_port,
-                                  enum el3_cardtype type)
+static void el3_dev_fill(struct net_device *dev, __be16 *phys_addr, int ioaddr,
+                        int irq, int if_port, enum el3_cardtype type)
 {
        struct el3_private *lp = netdev_priv(dev);
 
@@ -283,8 +282,7 @@ static void __devinit el3_dev_fill(struct net_device *dev, __be16 *phys_addr,
        lp->type = type;
 }
 
-static int __devinit el3_isa_match(struct device *pdev,
-                                  unsigned int ndev)
+static int el3_isa_match(struct device *pdev, unsigned int ndev)
 {
        struct net_device *dev;
        int ioaddr, isa_irq, if_port, err;
@@ -341,7 +339,7 @@ static int __devinit el3_isa_match(struct device *pdev,
        return 1;
 }
 
-static int __devexit el3_isa_remove(struct device *pdev,
+static int el3_isa_remove(struct device *pdev,
                                    unsigned int ndev)
 {
        el3_device_remove(pdev);
@@ -382,7 +380,7 @@ static int el3_isa_resume(struct device *dev, unsigned int n)
 
 static struct isa_driver el3_isa_driver = {
        .match          = el3_isa_match,
-       .remove         = __devexit_p(el3_isa_remove),
+       .remove         = el3_isa_remove,
 #ifdef CONFIG_PM
        .suspend        = el3_isa_suspend,
        .resume         = el3_isa_resume,
@@ -406,8 +404,7 @@ static struct pnp_device_id el3_pnp_ids[] = {
 };
 MODULE_DEVICE_TABLE(pnp, el3_pnp_ids);
 
-static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
-                                   const struct pnp_device_id *id)
+static int el3_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id)
 {
        short i;
        int ioaddr, irq, if_port;
@@ -445,7 +442,7 @@ static int __devinit el3_pnp_probe(struct pnp_dev *pdev,
        return 0;
 }
 
-static void __devexit el3_pnp_remove(struct pnp_dev *pdev)
+static void el3_pnp_remove(struct pnp_dev *pdev)
 {
        el3_common_remove(pnp_get_drvdata(pdev));
        pnp_set_drvdata(pdev, NULL);
@@ -467,7 +464,7 @@ static struct pnp_driver el3_pnp_driver = {
        .name           = "3c509",
        .id_table       = el3_pnp_ids,
        .probe          = el3_pnp_probe,
-       .remove         = __devexit_p(el3_pnp_remove),
+       .remove         = el3_pnp_remove,
 #ifdef CONFIG_PM
        .suspend        = el3_pnp_suspend,
        .resume         = el3_pnp_resume,
@@ -496,7 +493,7 @@ static struct eisa_driver el3_eisa_driver = {
                .driver   = {
                                .name    = "3c579",
                                .probe   = el3_eisa_probe,
-                               .remove  = __devexit_p (el3_device_remove),
+                               .remove  = el3_device_remove,
                                .suspend = el3_suspend,
                                .resume  = el3_resume,
                }
@@ -519,7 +516,7 @@ static const struct net_device_ops netdev_ops = {
 #endif
 };
 
-static int __devinit el3_common_init(struct net_device *dev)
+static int el3_common_init(struct net_device *dev)
 {
        struct el3_private *lp = netdev_priv(dev);
        int err;
@@ -618,7 +615,7 @@ static int __init el3_eisa_probe (struct device *device)
 /* This remove works for all device types.
  *
  * The net dev must be stored in the driver data field */
-static int __devexit el3_device_remove (struct device *device)
+static int el3_device_remove(struct device *device)
 {
        struct net_device *dev;
 
index e463d10368294a57ceaeb17aa3ba27f21dad0bca..ed0feb3cc6fac83436a862b11e49d1fdbc07648c 100644 (file)
@@ -102,7 +102,7 @@ static int vortex_debug = 1;
 #include <linux/delay.h>
 
 
-static const char version[] __devinitconst =
+static const char version[] =
        DRV_NAME ": Donald Becker and others.\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
@@ -277,7 +277,7 @@ static struct vortex_chip_info {
        int flags;
        int drv_flags;
        int io_size;
-} vortex_info_tbl[] __devinitdata = {
+} vortex_info_tbl[] = {
        {"3c590 Vortex 10Mbps",
         PCI_USES_MASTER, IS_VORTEX, 32, },
        {"3c592 EISA 10Mbps Demon/Vortex",                                      /* AKPM: from Don's 3c59x_cb.c 0.49H */
@@ -931,7 +931,7 @@ static int __init vortex_eisa_probe(struct device *device)
        return 0;
 }
 
-static int __devexit vortex_eisa_remove(struct device *device)
+static int vortex_eisa_remove(struct device *device)
 {
        struct eisa_device *edev;
        struct net_device *dev;
@@ -962,7 +962,7 @@ static struct eisa_driver vortex_eisa_driver = {
        .driver   = {
                .name    = "3c59x",
                .probe   = vortex_eisa_probe,
-               .remove  = __devexit_p(vortex_eisa_remove)
+               .remove  = vortex_eisa_remove
        }
 };
 
@@ -1000,8 +1000,8 @@ static int __init vortex_eisa_init(void)
 }
 
 /* returns count (>= 0), or negative on error */
-static int __devinit vortex_init_one(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int vortex_init_one(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        int rc, unit, pci_bar;
        struct vortex_chip_info *vci;
@@ -1088,9 +1088,8 @@ static const struct net_device_ops vortex_netdev_ops = {
  *
  * NOTE: pdev can be NULL, for the case of a Compaq device
  */
-static int __devinit vortex_probe1(struct device *gendev,
-                                  void __iomem *ioaddr, int irq,
-                                  int chip_idx, int card_idx)
+static int vortex_probe1(struct device *gendev, void __iomem *ioaddr, int irq,
+                        int chip_idx, int card_idx)
 {
        struct vortex_private *vp;
        int option;
@@ -3222,7 +3221,7 @@ static void acpi_set_WOL(struct net_device *dev)
 }
 
 
-static void __devexit vortex_remove_one(struct pci_dev *pdev)
+static void vortex_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct vortex_private *vp;
@@ -3265,7 +3264,7 @@ static void __devexit vortex_remove_one(struct pci_dev *pdev)
 static struct pci_driver vortex_driver = {
        .name           = "3c59x",
        .probe          = vortex_init_one,
-       .remove         = __devexit_p(vortex_remove_one),
+       .remove         = vortex_remove_one,
        .id_table       = vortex_pci_tbl,
        .driver.pm      = VORTEX_PM_OPS,
 };
index bad4fa6815c597133d7971f2555f9f141b83a712..eb56174469a7f9d90f96f8f8dc2858b0b0c4addb 100644 (file)
@@ -80,7 +80,7 @@ config PCMCIA_3C589
 
 config VORTEX
        tristate "3c590/3c900 series (592/595/597) \"Vortex/Boomerang\" support"
-       depends on (PCI || EISA)
+       depends on (PCI || EISA) && HAS_IOPORT
        select NET_CORE
        select MII
        ---help---
index bb9670f29b59795a2972effb1884fc20027b1059..27aaaf99e73e62ed9949e6b76838b78b682ac5d2 100644 (file)
@@ -168,7 +168,7 @@ enum typhoon_cards {
 };
 
 /* directly indexed by enum typhoon_cards, above */
-static struct typhoon_card_info typhoon_card_info[] __devinitdata = {
+static struct typhoon_card_info typhoon_card_info[] = {
        { "3Com Typhoon (3C990-TX)",
                TYPHOON_CRYPTO_NONE},
        { "3Com Typhoon (3CR990-TX-95)",
@@ -2200,7 +2200,7 @@ need_resume:
 }
 #endif
 
-static int __devinit
+static int
 typhoon_test_mmio(struct pci_dev *pdev)
 {
        void __iomem *ioaddr = pci_iomap(pdev, 1, 128);
@@ -2258,7 +2258,7 @@ static const struct net_device_ops typhoon_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
 };
 
-static int __devinit
+static int
 typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
@@ -2509,7 +2509,7 @@ error_out:
        return err;
 }
 
-static void __devexit
+static void
 typhoon_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
@@ -2533,7 +2533,7 @@ static struct pci_driver typhoon_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = typhoon_pci_tbl,
        .probe          = typhoon_init_one,
-       .remove         = __devexit_p(typhoon_remove_one),
+       .remove         = typhoon_remove_one,
 #ifdef CONFIG_PM
        .suspend        = typhoon_suspend,
        .resume         = typhoon_resume,
index 203ff9dccadb03206a20f96ea1e71437a98be3be..0338352bc0369cc4d7f1836ec2395b6bf2383e28 100644 (file)
@@ -191,11 +191,11 @@ static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
        ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
        if (ei_local->word16)
-               readsw(nic_base + NE_DATAPORT, hdr,
-                      sizeof(struct e8390_pkt_hdr) >> 1);
+               ioread16_rep(nic_base + NE_DATAPORT, hdr,
+                            sizeof(struct e8390_pkt_hdr) >> 1);
        else
-               readsb(nic_base + NE_DATAPORT, hdr,
-                      sizeof(struct e8390_pkt_hdr));
+               ioread8_rep(nic_base + NE_DATAPORT, hdr,
+                           sizeof(struct e8390_pkt_hdr));
 
        ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
        ei_local->dmaing &= ~0x01;
@@ -237,12 +237,12 @@ static void ax_block_input(struct net_device *dev, int count,
        ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
        if (ei_local->word16) {
-               readsw(nic_base + NE_DATAPORT, buf, count >> 1);
+               ioread16_rep(nic_base + NE_DATAPORT, buf, count >> 1);
                if (count & 0x01)
                        buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
 
        } else {
-               readsb(nic_base + NE_DATAPORT, buf, count);
+               ioread8_rep(nic_base + NE_DATAPORT, buf, count);
        }
 
        ei_local->dmaing &= ~1;
@@ -286,9 +286,9 @@ static void ax_block_output(struct net_device *dev, int count,
 
        ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
        if (ei_local->word16)
-               writesw(nic_base + NE_DATAPORT, buf, count >> 1);
+               iowrite16_rep(nic_base + NE_DATAPORT, buf, count >> 1);
        else
-               writesb(nic_base + NE_DATAPORT, buf, count);
+               iowrite8_rep(nic_base + NE_DATAPORT, buf, count);
 
        dma_start = jiffies;
 
index 8322c54972f3668710c8418c8cf02fb0526cabfe..78c6fb4b11437e2b187cb9e93a9e44ba71806692 100644 (file)
@@ -463,12 +463,6 @@ etherh_open(struct net_device *dev)
 {
        struct ei_device *ei_local = netdev_priv(dev);
 
-       if (!is_valid_ether_addr(dev->dev_addr)) {
-               printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-                       dev->name);
-               return -EINVAL;
-       }
-
        if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev))
                return -EAGAIN;
 
@@ -527,7 +521,7 @@ static void __init etherh_banner(void)
  * Read the ethernet address string from the on board rom.
  * This is an ascii string...
  */
-static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
+static int etherh_addr(char *addr, struct expansion_card *ec)
 {
        struct in_chunk_dir cd;
        char *s;
@@ -657,7 +651,7 @@ static const struct net_device_ops etherh_netdev_ops = {
 static u32 etherh_regoffsets[16];
 static u32 etherm_regoffsets[16];
 
-static int __devinit
+static int
 etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        const struct etherh_data *data = id->data;
@@ -775,7 +769,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit etherh_remove(struct expansion_card *ec)
+static void etherh_remove(struct expansion_card *ec)
 {
        struct net_device *dev = ecard_get_drvdata(ec);
 
@@ -839,7 +833,7 @@ static const struct ecard_id etherh_ids[] = {
 
 static struct ecard_driver etherh_driver = {
        .probe          = etherh_probe,
-       .remove         = __devexit_p(etherh_remove),
+       .remove         = etherh_remove,
        .id_table       = etherh_ids,
        .drv = {
                .name   = DRV_NAME,
index 5370c884620b1503a6526bb305ee6c7f495b031f..fb3dd4399cf36e24cd4a1fe809333d140c8419f2 100644 (file)
@@ -53,9 +53,9 @@ static const char version[] =
 #define WORDSWAP(a)     ((((a)>>8)&0xff) | ((a)<<8))
 
 
-static int __devinit hydra_init_one(struct zorro_dev *z,
+static int hydra_init_one(struct zorro_dev *z,
                                    const struct zorro_device_id *ent);
-static int __devinit hydra_init(struct zorro_dev *z);
+static int hydra_init(struct zorro_dev *z);
 static int hydra_open(struct net_device *dev);
 static int hydra_close(struct net_device *dev);
 static void hydra_reset_8390(struct net_device *dev);
@@ -65,9 +65,9 @@ static void hydra_block_input(struct net_device *dev, int count,
                              struct sk_buff *skb, int ring_offset);
 static void hydra_block_output(struct net_device *dev, int count,
                               const unsigned char *buf, int start_page);
-static void __devexit hydra_remove_one(struct zorro_dev *z);
+static void hydra_remove_one(struct zorro_dev *z);
 
-static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id hydra_zorro_tbl[] = {
     { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET },
     { 0 }
 };
@@ -77,11 +77,11 @@ static struct zorro_driver hydra_driver = {
     .name      = "hydra",
     .id_table  = hydra_zorro_tbl,
     .probe     = hydra_init_one,
-    .remove    = __devexit_p(hydra_remove_one),
+    .remove    = hydra_remove_one,
 };
 
-static int __devinit hydra_init_one(struct zorro_dev *z,
-                                   const struct zorro_device_id *ent)
+static int hydra_init_one(struct zorro_dev *z,
+                         const struct zorro_device_id *ent)
 {
     int err;
 
@@ -110,7 +110,7 @@ static const struct net_device_ops hydra_netdev_ops = {
 #endif
 };
 
-static int __devinit hydra_init(struct zorro_dev *z)
+static int hydra_init(struct zorro_dev *z)
 {
     struct net_device *dev;
     unsigned long board = ZTWO_VADDR(z->resource.start);
@@ -247,7 +247,7 @@ static void hydra_block_output(struct net_device *dev, int count,
     z_memcpy_toio(mem_base+((start_page - NESM_START_PG)<<8), buf, count);
 }
 
-static void __devexit hydra_remove_one(struct zorro_dev *z)
+static void hydra_remove_one(struct zorro_dev *z)
 {
     struct net_device *dev = zorro_get_drvdata(z);
 
index d04911d33b647080278f81678869c032e1a3c853..47618e505355ae91fc0ade4e50231ec780bcc56f 100644 (file)
@@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev)
                dev->irq = irq[this_dev];
                dev->mem_end = bad[this_dev];
        }
+       SET_NETDEV_DEV(dev, &pdev->dev);
        err = do_ne_probe(dev);
        if (err) {
                free_netdev(dev);
index 5e8845febfb8f40be7cdacaa2b398434a37e8dfe..c0c127913dec6d471d75ae42be7d9e139329b867 100644 (file)
@@ -61,7 +61,7 @@ static int options[MAX_UNITS];
 #include "8390.h"
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
        KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
        " D. Becker/P. Gortmaker\n";
 
@@ -119,7 +119,7 @@ enum ne2k_pci_chipsets {
 static struct {
        char *name;
        int flags;
-} pci_clone_list[] __devinitdata = {
+} pci_clone_list[] = {
        {"RealTek RTL-8029", REALTEK_FDX},
        {"Winbond 89C940", 0},
        {"Compex RL2000", 0},
@@ -215,8 +215,8 @@ static const struct net_device_ops ne2k_netdev_ops = {
 #endif
 };
 
-static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int ne2k_pci_init_one(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        struct net_device *dev;
        int i;
@@ -647,7 +647,7 @@ static const struct ethtool_ops ne2k_pci_ethtool_ops = {
        .get_drvinfo            = ne2k_pci_get_drvinfo,
 };
 
-static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev)
+static void ne2k_pci_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -696,7 +696,7 @@ static int ne2k_pci_resume (struct pci_dev *pdev)
 static struct pci_driver ne2k_driver = {
        .name           = DRV_NAME,
        .probe          = ne2k_pci_init_one,
-       .remove         = __devexit_p(ne2k_pci_remove_one),
+       .remove         = ne2k_pci_remove_one,
        .id_table       = ne2k_pci_tbl,
 #ifdef CONFIG_PM
        .suspend        = ne2k_pci_suspend,
index e3f57427d5c51cce6b89687aafdd016308483646..ebcdb52ec739a612216195306a5537c0ca209997 100644 (file)
@@ -222,7 +222,7 @@ static int __init ne3210_eisa_probe (struct device *device)
        return retval;
 }
 
-static int __devexit ne3210_eisa_remove (struct device *device)
+static int ne3210_eisa_remove(struct device *device)
 {
        struct net_device  *dev    = dev_get_drvdata(device);
        unsigned long       ioaddr = to_eisa_device (device)->base_addr;
@@ -324,7 +324,7 @@ static struct eisa_driver ne3210_eisa_driver = {
        .driver   = {
                .name   = "ne3210",
                .probe  = ne3210_eisa_probe,
-               .remove = __devexit_p (ne3210_eisa_remove),
+               .remove = ne3210_eisa_remove,
        },
 };
 
index 7818e6397e913870dcbfab18b5d171af127f99f4..85ec4c2d2645582339eb7ecfa796e9b37fee91ad 100644 (file)
@@ -75,7 +75,7 @@ static struct card_info {
        zorro_id id;
        const char *name;
        unsigned int offset;
-} cards[] __devinitdata = {
+} cards[] = {
        { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, "Ariadne II", 0x0600 },
        { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, "X-Surf", 0x8600 },
 };
@@ -254,7 +254,7 @@ static int zorro8390_close(struct net_device *dev)
        return 0;
 }
 
-static void __devexit zorro8390_remove_one(struct zorro_dev *z)
+static void zorro8390_remove_one(struct zorro_dev *z)
 {
        struct net_device *dev = zorro_get_drvdata(z);
 
@@ -264,7 +264,7 @@ static void __devexit zorro8390_remove_one(struct zorro_dev *z)
        free_netdev(dev);
 }
 
-static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id zorro8390_zorro_tbl[] = {
        { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, },
        { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, },
        { 0 }
@@ -286,9 +286,8 @@ static const struct net_device_ops zorro8390_netdev_ops = {
 #endif
 };
 
-static int __devinit zorro8390_init(struct net_device *dev,
-                                   unsigned long board, const char *name,
-                                   unsigned long ioaddr)
+static int zorro8390_init(struct net_device *dev, unsigned long board,
+                         const char *name, unsigned long ioaddr)
 {
        int i;
        int err;
@@ -396,8 +395,8 @@ static int __devinit zorro8390_init(struct net_device *dev,
        return 0;
 }
 
-static int __devinit zorro8390_init_one(struct zorro_dev *z,
-                                       const struct zorro_device_id *ent)
+static int zorro8390_init_one(struct zorro_dev *z,
+                             const struct zorro_device_id *ent)
 {
        struct net_device *dev;
        unsigned long board, ioaddr;
@@ -432,7 +431,7 @@ static struct zorro_driver zorro8390_driver = {
        .name           = "zorro8390",
        .id_table       = zorro8390_zorro_tbl,
        .probe          = zorro8390_init_one,
-       .remove         = __devexit_p(zorro8390_remove_one),
+       .remove         = zorro8390_remove_one,
 };
 
 static int __init zorro8390_init_module(void)
index 5b65992c2a0ae4882a3196ce73e0c5ed32cfa6f2..549b77500579e823b60d34633555d482dff1c7b6 100644 (file)
@@ -166,7 +166,7 @@ static int rx_copybreak /* = 0 */;
 #define FIRMWARE_TX    "adaptec/starfire_tx.bin"
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
 " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
@@ -295,7 +295,7 @@ MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
 static const struct chip_info {
        const char *name;
        int drv_flags;
-} netdrv_tbl[] __devinitconst = {
+} netdrv_tbl[] = {
        { "Adaptec Starfire 6915", CanHaveMII },
 };
 
@@ -641,8 +641,8 @@ static const struct net_device_ops netdev_ops = {
 #endif
 };
 
-static int __devinit starfire_init_one(struct pci_dev *pdev,
-                                      const struct pci_device_id *ent)
+static int starfire_init_one(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        struct device *d = &pdev->dev;
        struct netdev_private *np;
@@ -1990,7 +1990,7 @@ static int starfire_resume(struct pci_dev *pdev)
 #endif /* CONFIG_PM */
 
 
-static void __devexit starfire_remove_one (struct pci_dev *pdev)
+static void starfire_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct netdev_private *np = netdev_priv(dev);
@@ -2018,7 +2018,7 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
 static struct pci_driver starfire_driver = {
        .name           = DRV_NAME,
        .probe          = starfire_init_one,
-       .remove         = __devexit_p(starfire_remove_one),
+       .remove         = starfire_remove_one,
 #ifdef CONFIG_PM
        .suspend        = starfire_suspend,
        .resume         = starfire_resume,
index 49a30d37ae4a93cf2c84f1e733093722f0799405..e49c0eff040b50a95bdacc050f8ff3a83f172a8e 100644 (file)
@@ -61,7 +61,7 @@ config BFIN_RX_DESC_NUM
 
 config BFIN_MAC_USE_HWSTAMP
        bool "Use IEEE 1588 hwstamp"
-       depends on BFIN_MAC && BF518
+       select PTP_1588_CLOCK
        default y
        ---help---
          To support the IEEE 1588 Precision Time Protocol (PTP), select y here
index f816426e1085812b6524c037992594e4a539c746..c1fdb8be8beeb193a565384470117e048a0db1dc 100644 (file)
@@ -548,14 +548,17 @@ static int bfin_mac_ethtool_setwol(struct net_device *dev,
        return 0;
 }
 
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
 static int bfin_mac_ethtool_get_ts_info(struct net_device *dev,
        struct ethtool_ts_info *info)
 {
+       struct bfin_mac_local *lp = netdev_priv(dev);
+
        info->so_timestamping =
                SOF_TIMESTAMPING_TX_HARDWARE |
                SOF_TIMESTAMPING_RX_HARDWARE |
-               SOF_TIMESTAMPING_SYS_HARDWARE;
-       info->phc_index = -1;
+               SOF_TIMESTAMPING_RAW_HARDWARE;
+       info->phc_index = lp->phc_index;
        info->tx_types =
                (1 << HWTSTAMP_TX_OFF) |
                (1 << HWTSTAMP_TX_ON);
@@ -566,6 +569,7 @@ static int bfin_mac_ethtool_get_ts_info(struct net_device *dev,
                (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
        return 0;
 }
+#endif
 
 static const struct ethtool_ops bfin_mac_ethtool_ops = {
        .get_settings = bfin_mac_ethtool_getsettings,
@@ -574,7 +578,9 @@ static const struct ethtool_ops bfin_mac_ethtool_ops = {
        .get_drvinfo = bfin_mac_ethtool_getdrvinfo,
        .get_wol = bfin_mac_ethtool_getwol,
        .set_wol = bfin_mac_ethtool_setwol,
+#ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
        .get_ts_info = bfin_mac_ethtool_get_ts_info,
+#endif
 };
 
 /**************************************************************************/
@@ -649,6 +655,20 @@ static int bfin_mac_set_mac_address(struct net_device *dev, void *p)
 #ifdef CONFIG_BFIN_MAC_USE_HWSTAMP
 #define bfin_mac_hwtstamp_is_none(cfg) ((cfg) == HWTSTAMP_FILTER_NONE)
 
+static u32 bfin_select_phc_clock(u32 input_clk, unsigned int *shift_result)
+{
+       u32 ipn = 1000000000UL / input_clk;
+       u32 ppn = 1;
+       unsigned int shift = 0;
+
+       while (ppn <= ipn) {
+               ppn <<= 1;
+               shift++;
+       }
+       *shift_result = shift;
+       return 1000000000UL / ppn;
+}
+
 static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
                struct ifreq *ifr, int cmd)
 {
@@ -798,19 +818,7 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
                bfin_read_EMAC_PTP_TXSNAPLO();
                bfin_read_EMAC_PTP_TXSNAPHI();
 
-               /*
-                * Set registers so that rollover occurs soon to test this.
-                */
-               bfin_write_EMAC_PTP_TIMELO(0x00000000);
-               bfin_write_EMAC_PTP_TIMEHI(0xFF800000);
-
                SSYNC();
-
-               lp->compare.last_update = 0;
-               timecounter_init(&lp->clock,
-                               &lp->cycles,
-                               ktime_to_ns(ktime_get_real()));
-               timecompare_update(&lp->compare, 0);
        }
 
        lp->stamp_cfg = config;
@@ -818,15 +826,6 @@ static int bfin_mac_hwtstamp_ioctl(struct net_device *netdev,
                -EFAULT : 0;
 }
 
-static void bfin_dump_hwtamp(char *s, ktime_t *hw, ktime_t *ts, struct timecompare *cmp)
-{
-       ktime_t sys = ktime_get_real();
-
-       pr_debug("%s %s hardware:%d,%d transform system:%d,%d system:%d,%d, cmp:%lld, %lld\n",
-                       __func__, s, hw->tv.sec, hw->tv.nsec, ts->tv.sec, ts->tv.nsec, sys.tv.sec,
-                       sys.tv.nsec, cmp->offset, cmp->skew);
-}
-
 static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
 {
        struct bfin_mac_local *lp = netdev_priv(netdev);
@@ -857,15 +856,9 @@ static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
                        regval = bfin_read_EMAC_PTP_TXSNAPLO();
                        regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32;
                        memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-                       ns = timecounter_cyc2time(&lp->clock,
-                                       regval);
-                       timecompare_update(&lp->compare, ns);
+                       ns = regval << lp->shift;
                        shhwtstamps.hwtstamp = ns_to_ktime(ns);
-                       shhwtstamps.syststamp =
-                               timecompare_transform(&lp->compare, ns);
                        skb_tstamp_tx(skb, &shhwtstamps);
-
-                       bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare);
                }
        }
 }
@@ -888,55 +881,184 @@ static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb)
 
        regval = bfin_read_EMAC_PTP_RXSNAPLO();
        regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32;
-       ns = timecounter_cyc2time(&lp->clock, regval);
-       timecompare_update(&lp->compare, ns);
+       ns = regval << lp->shift;
        memset(shhwtstamps, 0, sizeof(*shhwtstamps));
        shhwtstamps->hwtstamp = ns_to_ktime(ns);
-       shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns);
+}
+
+static void bfin_mac_hwtstamp_init(struct net_device *netdev)
+{
+       struct bfin_mac_local *lp = netdev_priv(netdev);
+       u64 addend, ppb;
+       u32 input_clk, phc_clk;
+
+       /* Initialize hardware timer */
+       input_clk = get_sclk();
+       phc_clk = bfin_select_phc_clock(input_clk, &lp->shift);
+       addend = phc_clk * (1ULL << 32);
+       do_div(addend, input_clk);
+       bfin_write_EMAC_PTP_ADDEND((u32)addend);
+
+       lp->addend = addend;
+       ppb = 1000000000ULL * input_clk;
+       do_div(ppb, phc_clk);
+       lp->max_ppb = ppb - 1000000000ULL - 1ULL;
 
-       bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare);
+       /* Initialize hwstamp config */
+       lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
+       lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
 }
 
-/*
- * bfin_read_clock - read raw cycle counter (to be used by time counter)
- */
-static cycle_t bfin_read_clock(const struct cyclecounter *tc)
+static u64 bfin_ptp_time_read(struct bfin_mac_local *lp)
 {
-       u64 stamp;
+       u64 ns;
+       u32 lo, hi;
+
+       lo = bfin_read_EMAC_PTP_TIMELO();
+       hi = bfin_read_EMAC_PTP_TIMEHI();
 
-       stamp =  bfin_read_EMAC_PTP_TIMELO();
-       stamp |= (u64)bfin_read_EMAC_PTP_TIMEHI() << 32ULL;
+       ns = ((u64) hi) << 32;
+       ns |= lo;
+       ns <<= lp->shift;
 
-       return stamp;
+       return ns;
 }
 
-#define PTP_CLK 25000000
+static void bfin_ptp_time_write(struct bfin_mac_local *lp, u64 ns)
+{
+       u32 hi, lo;
 
-static void bfin_mac_hwtstamp_init(struct net_device *netdev)
+       ns >>= lp->shift;
+       hi = ns >> 32;
+       lo = ns & 0xffffffff;
+
+       bfin_write_EMAC_PTP_TIMELO(lo);
+       bfin_write_EMAC_PTP_TIMEHI(hi);
+}
+
+/* PTP Hardware Clock operations */
+
+static int bfin_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+       u64 adj;
+       u32 diff, addend;
+       int neg_adj = 0;
+       struct bfin_mac_local *lp =
+               container_of(ptp, struct bfin_mac_local, caps);
+
+       if (ppb < 0) {
+               neg_adj = 1;
+               ppb = -ppb;
+       }
+       addend = lp->addend;
+       adj = addend;
+       adj *= ppb;
+       diff = div_u64(adj, 1000000000ULL);
+
+       addend = neg_adj ? addend - diff : addend + diff;
+
+       bfin_write_EMAC_PTP_ADDEND(addend);
+
+       return 0;
+}
+
+static int bfin_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+       s64 now;
+       unsigned long flags;
+       struct bfin_mac_local *lp =
+               container_of(ptp, struct bfin_mac_local, caps);
+
+       spin_lock_irqsave(&lp->phc_lock, flags);
+
+       now = bfin_ptp_time_read(lp);
+       now += delta;
+       bfin_ptp_time_write(lp, now);
+
+       spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+       return 0;
+}
+
+static int bfin_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+       u64 ns;
+       u32 remainder;
+       unsigned long flags;
+       struct bfin_mac_local *lp =
+               container_of(ptp, struct bfin_mac_local, caps);
+
+       spin_lock_irqsave(&lp->phc_lock, flags);
+
+       ns = bfin_ptp_time_read(lp);
+
+       spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+       ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+       ts->tv_nsec = remainder;
+       return 0;
+}
+
+static int bfin_ptp_settime(struct ptp_clock_info *ptp,
+                          const struct timespec *ts)
+{
+       u64 ns;
+       unsigned long flags;
+       struct bfin_mac_local *lp =
+               container_of(ptp, struct bfin_mac_local, caps);
+
+       ns = ts->tv_sec * 1000000000ULL;
+       ns += ts->tv_nsec;
+
+       spin_lock_irqsave(&lp->phc_lock, flags);
+
+       bfin_ptp_time_write(lp, ns);
+
+       spin_unlock_irqrestore(&lp->phc_lock, flags);
+
+       return 0;
+}
+
+static int bfin_ptp_enable(struct ptp_clock_info *ptp,
+                         struct ptp_clock_request *rq, int on)
+{
+       return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info bfin_ptp_caps = {
+       .owner          = THIS_MODULE,
+       .name           = "BF518 clock",
+       .max_adj        = 0,
+       .n_alarm        = 0,
+       .n_ext_ts       = 0,
+       .n_per_out      = 0,
+       .pps            = 0,
+       .adjfreq        = bfin_ptp_adjfreq,
+       .adjtime        = bfin_ptp_adjtime,
+       .gettime        = bfin_ptp_gettime,
+       .settime        = bfin_ptp_settime,
+       .enable         = bfin_ptp_enable,
+};
+
+static int bfin_phc_init(struct net_device *netdev, struct device *dev)
 {
        struct bfin_mac_local *lp = netdev_priv(netdev);
-       u64 append;
 
-       /* Initialize hardware timer */
-       append = PTP_CLK * (1ULL << 32);
-       do_div(append, get_sclk());
-       bfin_write_EMAC_PTP_ADDEND((u32)append);
-
-       memset(&lp->cycles, 0, sizeof(lp->cycles));
-       lp->cycles.read = bfin_read_clock;
-       lp->cycles.mask = CLOCKSOURCE_MASK(64);
-       lp->cycles.mult = 1000000000 / PTP_CLK;
-       lp->cycles.shift = 0;
-
-       /* Synchronize our NIC clock against system wall clock */
-       memset(&lp->compare, 0, sizeof(lp->compare));
-       lp->compare.source = &lp->clock;
-       lp->compare.target = ktime_get_real;
-       lp->compare.num_samples = 10;
+       lp->caps = bfin_ptp_caps;
+       lp->caps.max_adj = lp->max_ppb;
+       lp->clock = ptp_clock_register(&lp->caps, dev);
+       if (IS_ERR(lp->clock))
+               return PTR_ERR(lp->clock);
 
-       /* Initialize hwstamp config */
-       lp->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
-       lp->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
+       lp->phc_index = ptp_clock_index(lp->clock);
+       spin_lock_init(&lp->phc_lock);
+
+       return 0;
+}
+
+static void bfin_phc_release(struct bfin_mac_local *lp)
+{
+       ptp_clock_unregister(lp->clock);
 }
 
 #else
@@ -945,6 +1067,8 @@ static void bfin_mac_hwtstamp_init(struct net_device *netdev)
 # define bfin_mac_hwtstamp_ioctl(dev, ifr, cmd) (-EOPNOTSUPP)
 # define bfin_rx_hwtstamp(dev, skb)
 # define bfin_tx_hwtstamp(dev, skb)
+# define bfin_phc_init(netdev, dev) 0
+# define bfin_phc_release(lp)
 #endif
 
 static inline void _tx_reclaim_skb(void)
@@ -1479,7 +1603,7 @@ static const struct net_device_ops bfin_mac_netdev_ops = {
 #endif
 };
 
-static int __devinit bfin_mac_probe(struct platform_device *pdev)
+static int bfin_mac_probe(struct platform_device *pdev)
 {
        struct net_device *ndev;
        struct bfin_mac_local *lp;
@@ -1579,12 +1703,17 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
        }
 
        bfin_mac_hwtstamp_init(ndev);
+       if (bfin_phc_init(ndev, &pdev->dev)) {
+               dev_err(&pdev->dev, "Cannot register PHC device!\n");
+               goto out_err_phc;
+       }
 
        /* now, print out the card info, in a short format.. */
        netdev_info(ndev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);
 
        return 0;
 
+out_err_phc:
 out_err_reg_ndev:
        free_irq(IRQ_MAC_RX, ndev);
 out_err_request_irq:
@@ -1598,11 +1727,13 @@ out_err_probe_mac:
        return rc;
 }
 
-static int __devexit bfin_mac_remove(struct platform_device *pdev)
+static int bfin_mac_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct bfin_mac_local *lp = netdev_priv(ndev);
 
+       bfin_phc_release(lp);
+
        platform_set_drvdata(pdev, NULL);
 
        lp->mii_bus->priv = NULL;
@@ -1655,7 +1786,7 @@ static int bfin_mac_resume(struct platform_device *pdev)
 #define bfin_mac_resume NULL
 #endif /* CONFIG_PM */
 
-static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
+static int bfin_mii_bus_probe(struct platform_device *pdev)
 {
        struct mii_bus *miibus;
        struct bfin_mii_bus_platform_data *mii_bus_pd;
@@ -1733,7 +1864,7 @@ out_err_alloc:
        return rc;
 }
 
-static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
+static int bfin_mii_bus_remove(struct platform_device *pdev)
 {
        struct mii_bus *miibus = platform_get_drvdata(pdev);
        struct bfin_mii_bus_platform_data *mii_bus_pd =
@@ -1750,7 +1881,7 @@ static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_mii_bus_driver = {
        .probe = bfin_mii_bus_probe,
-       .remove = __devexit_p(bfin_mii_bus_remove),
+       .remove = bfin_mii_bus_remove,
        .driver = {
                .name = "bfin_mii_bus",
                .owner  = THIS_MODULE,
@@ -1759,7 +1890,7 @@ static struct platform_driver bfin_mii_bus_driver = {
 
 static struct platform_driver bfin_mac_driver = {
        .probe = bfin_mac_probe,
-       .remove = __devexit_p(bfin_mac_remove),
+       .remove = bfin_mac_remove,
        .resume = bfin_mac_resume,
        .suspend = bfin_mac_suspend,
        .driver = {
index 960905c0822389cee89101671fea646ce5d140a2..7a07ee07906b280f2d849ae0959c604ee58d411b 100644 (file)
@@ -11,8 +11,7 @@
 #define _BFIN_MAC_H_
 
 #include <linux/net_tstamp.h>
-#include <linux/clocksource.h>
-#include <linux/timecompare.h>
+#include <linux/ptp_clock_kernel.h>
 #include <linux/timer.h>
 #include <linux/etherdevice.h>
 #include <linux/bfin_mac.h>
@@ -94,10 +93,14 @@ struct bfin_mac_local {
        struct mii_bus *mii_bus;
 
 #if defined(CONFIG_BFIN_MAC_USE_HWSTAMP)
-       struct cyclecounter cycles;
-       struct timecounter clock;
-       struct timecompare compare;
+       u32 addend;
+       unsigned int shift;
+       s32 max_ppb;
        struct hwtstamp_config stamp_cfg;
+       struct ptp_clock_info caps;
+       struct ptp_clock *clock;
+       int phc_index;
+       spinlock_t phc_lock; /* protects time lo/hi registers */
 #endif
 };
 
index 9c77c736f171a8af6773d7d4a3ca4e562115cc04..aa53115bb38b91d45329be5914241591da6776c7 100644 (file)
@@ -1376,7 +1376,7 @@ error:
 }
 
 /* Initialize the GRETH MAC */
-static int __devinit greth_of_probe(struct platform_device *ofdev)
+static int greth_of_probe(struct platform_device *ofdev)
 {
        struct net_device *dev;
        struct greth_private *greth;
@@ -1576,7 +1576,7 @@ error1:
        return err;
 }
 
-static int __devexit greth_of_remove(struct platform_device *of_dev)
+static int greth_of_remove(struct platform_device *of_dev)
 {
        struct net_device *ndev = dev_get_drvdata(&of_dev->dev);
        struct greth_private *greth = netdev_priv(ndev);
@@ -1619,7 +1619,7 @@ static struct platform_driver greth_of_driver = {
                .of_match_table = greth_of_match,
        },
        .probe = greth_of_probe,
-       .remove = __devexit_p(greth_of_remove),
+       .remove = greth_of_remove,
 };
 
 module_platform_driver(greth_of_driver);
index 7219123fa0a433985bd24a6d775d70aea6365529..c0bc41a784ca253b012f327807e9d42a1ff0197b 100644 (file)
@@ -426,7 +426,7 @@ MODULE_PARM_DESC(max_rx_desc, "AceNIC/3C985/GA620 max number of receive descript
 MODULE_PARM_DESC(tx_ratio, "AceNIC/3C985/GA620 ratio of NIC memory used for TX/RX descriptors (range 0-63)");
 
 
-static const char version[] __devinitconst =
+static const char version[] =
   "acenic.c: v0.92 08/05/2002  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
@@ -454,8 +454,8 @@ static const struct net_device_ops ace_netdev_ops = {
        .ndo_change_mtu         = ace_change_mtu,
 };
 
-static int __devinit acenic_probe_one(struct pci_dev *pdev,
-               const struct pci_device_id *id)
+static int acenic_probe_one(struct pci_dev *pdev,
+                           const struct pci_device_id *id)
 {
        struct net_device *dev;
        struct ace_private *ap;
@@ -603,7 +603,7 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
        return -ENODEV;
 }
 
-static void __devexit acenic_remove_one(struct pci_dev *pdev)
+static void acenic_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct ace_private *ap = netdev_priv(dev);
@@ -699,7 +699,7 @@ static struct pci_driver acenic_pci_driver = {
        .name           = "acenic",
        .id_table       = acenic_pci_tbl,
        .probe          = acenic_probe_one,
-       .remove         = __devexit_p(acenic_remove_one),
+       .remove         = acenic_remove_one,
 };
 
 static int __init acenic_init(void)
@@ -871,7 +871,7 @@ static inline void ace_issue_cmd(struct ace_regs __iomem *regs, struct cmd *cmd)
 }
 
 
-static int __devinit ace_init(struct net_device *dev)
+static int ace_init(struct net_device *dev)
 {
        struct ace_private *ap;
        struct ace_regs __iomem *regs;
@@ -2824,8 +2824,8 @@ static struct net_device_stats *ace_get_stats(struct net_device *dev)
 }
 
 
-static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
-                              u32 dest, int size)
+static void ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
+                    u32 dest, int size)
 {
        void __iomem *tdest;
        short tsize, i;
@@ -2851,7 +2851,7 @@ static void __devinit ace_copy(struct ace_regs __iomem *regs, const __be32 *src,
 }
 
 
-static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
+static void ace_clear(struct ace_regs __iomem *regs, u32 dest, int size)
 {
        void __iomem *tdest;
        short tsize = 0, i;
@@ -2882,7 +2882,7 @@ static void __devinit ace_clear(struct ace_regs __iomem *regs, u32 dest, int siz
  * This operation requires the NIC to be halted and is performed with
  * interrupts disabled and with the spinlock hold.
  */
-static int __devinit ace_load_firmware(struct net_device *dev)
+static int ace_load_firmware(struct net_device *dev)
 {
        const struct firmware *fw;
        const char *fw_name = "acenic/tg2.bin";
@@ -2962,7 +2962,7 @@ static int __devinit ace_load_firmware(struct net_device *dev)
  * Thanks to Stevarino Webinski for helping tracking down the bugs in the
  * code i2c readout code by beta testing all my hacks.
  */
-static void __devinit eeprom_start(struct ace_regs __iomem *regs)
+static void eeprom_start(struct ace_regs __iomem *regs)
 {
        u32 local;
 
@@ -2991,7 +2991,7 @@ static void __devinit eeprom_start(struct ace_regs __iomem *regs)
 }
 
 
-static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
+static void eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
 {
        short i;
        u32 local;
@@ -3028,7 +3028,7 @@ static void __devinit eeprom_prep(struct ace_regs __iomem *regs, u8 magic)
 }
 
 
-static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
+static int eeprom_check_ack(struct ace_regs __iomem *regs)
 {
        int state;
        u32 local;
@@ -3056,7 +3056,7 @@ static int __devinit eeprom_check_ack(struct ace_regs __iomem *regs)
 }
 
 
-static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
+static void eeprom_stop(struct ace_regs __iomem *regs)
 {
        u32 local;
 
@@ -3091,8 +3091,7 @@ static void __devinit eeprom_stop(struct ace_regs __iomem *regs)
 /*
  * Read a whole byte from the EEPROM.
  */
-static int __devinit read_eeprom_byte(struct net_device *dev,
-                                  unsigned long offset)
+static int read_eeprom_byte(struct net_device *dev, unsigned long offset)
 {
        struct ace_private *ap = netdev_priv(dev);
        struct ace_regs __iomem *regs = ap->regs;
index 689dfcafc6d47ed843f35ffd1a9ab09517f36d43..3789affbc0e5cbff032f5cf225725fd4a80a013d 100644 (file)
@@ -639,12 +639,12 @@ static void lance_set_multicast(struct net_device *dev)
        netif_wake_queue(dev);
 }
 
-static int __devinit a2065_init_one(struct zorro_dev *z,
-                                   const struct zorro_device_id *ent);
-static void __devexit a2065_remove_one(struct zorro_dev *z);
+static int a2065_init_one(struct zorro_dev *z,
+                         const struct zorro_device_id *ent);
+static void a2065_remove_one(struct zorro_dev *z);
 
 
-static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id a2065_zorro_tbl[] = {
        { ZORRO_PROD_CBM_A2065_1 },
        { ZORRO_PROD_CBM_A2065_2 },
        { ZORRO_PROD_AMERISTAR_A2065 },
@@ -656,7 +656,7 @@ static struct zorro_driver a2065_driver = {
        .name           = "a2065",
        .id_table       = a2065_zorro_tbl,
        .probe          = a2065_init_one,
-       .remove         = __devexit_p(a2065_remove_one),
+       .remove         = a2065_remove_one,
 };
 
 static const struct net_device_ops lance_netdev_ops = {
@@ -670,8 +670,8 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __devinit a2065_init_one(struct zorro_dev *z,
-                                   const struct zorro_device_id *ent)
+static int a2065_init_one(struct zorro_dev *z,
+                         const struct zorro_device_id *ent)
 {
        struct net_device *dev;
        struct lance_private *priv;
@@ -754,7 +754,7 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
 }
 
 
-static void __devexit a2065_remove_one(struct zorro_dev *z)
+static void a2065_remove_one(struct zorro_dev *z)
 {
        struct net_device *dev = zorro_get_drvdata(z);
 
index e10ffad525a788e06bae64c8581f47280be9c4fc..60e2b701afe726f05b041f0694ed6b454ddd05bd 100644 (file)
@@ -671,7 +671,7 @@ static const struct net_device_ops am79c961_netdev_ops = {
 #endif
 };
 
-static int __devinit am79c961_probe(struct platform_device *pdev)
+static int am79c961_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct net_device *dev;
index 3491d4312fc9252639a082f7897643a2ee6f3c0a..42d4e6ad58a5f81098d7d7829528ecb057434e3d 100644 (file)
@@ -1702,7 +1702,7 @@ static int amd8111e_resume(struct pci_dev *pci_dev)
 }
 
 
-static void __devexit amd8111e_remove_one(struct pci_dev *pdev)
+static void amd8111e_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        if (dev) {
@@ -1774,7 +1774,7 @@ static void amd8111e_config_ipg(struct net_device* dev)
 
 }
 
-static void __devinit amd8111e_probe_ext_phy(struct net_device* dev)
+static void amd8111e_probe_ext_phy(struct net_device *dev)
 {
        struct amd8111e_priv *lp = netdev_priv(dev);
        int i;
@@ -1810,7 +1810,7 @@ static const struct net_device_ops amd8111e_netdev_ops = {
 #endif
 };
 
-static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
+static int amd8111e_probe_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
        int err,i,pm_cap;
@@ -1976,7 +1976,7 @@ static struct pci_driver amd8111e_driver = {
        .name           = MODULE_NAME,
        .id_table       = amd8111e_pci_tbl,
        .probe          = amd8111e_probe_one,
-       .remove         = __devexit_p(amd8111e_remove_one),
+       .remove         = amd8111e_remove_one,
        .suspend        = amd8111e_suspend,
        .resume         = amd8111e_resume
 };
index f2958df9a1e41f6e460a6bb51f786897bf01c7a9..98f4522fd17b7e69d3c524568d4b8c991ca80533 100644 (file)
@@ -682,7 +682,7 @@ static void set_multicast_list(struct net_device *dev)
 }
 
 
-static void __devexit ariadne_remove_one(struct zorro_dev *z)
+static void ariadne_remove_one(struct zorro_dev *z)
 {
        struct net_device *dev = zorro_get_drvdata(z);
 
@@ -692,7 +692,7 @@ static void __devexit ariadne_remove_one(struct zorro_dev *z)
        free_netdev(dev);
 }
 
-static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = {
+static struct zorro_device_id ariadne_zorro_tbl[] = {
        { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE },
        { 0 }
 };
@@ -710,8 +710,8 @@ static const struct net_device_ops ariadne_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __devinit ariadne_init_one(struct zorro_dev *z,
-                                     const struct zorro_device_id *ent)
+static int ariadne_init_one(struct zorro_dev *z,
+                           const struct zorro_device_id *ent)
 {
        unsigned long board = z->resource.start;
        unsigned long base_addr = board + ARIADNE_LANCE;
@@ -774,7 +774,7 @@ static struct zorro_driver ariadne_driver = {
        .name           = "ariadne",
        .id_table       = ariadne_zorro_tbl,
        .probe          = ariadne_init_one,
-       .remove         = __devexit_p(ariadne_remove_one),
+       .remove         = ariadne_remove_one,
 };
 
 static int __init ariadne_init_module(void)
index f195acfa2df7dc4efcc5368173be475e6cd5b72f..2ea221ed4777f01527a81d08d299dcf44a3b6b8f 100644 (file)
@@ -1016,7 +1016,7 @@ static const struct net_device_ops au1000_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
 };
 
-static int __devinit au1000_probe(struct platform_device *pdev)
+static int au1000_probe(struct platform_device *pdev)
 {
        static unsigned version_printed;
        struct au1000_private *aup = NULL;
@@ -1295,7 +1295,7 @@ out:
        return err;
 }
 
-static int __devexit au1000_remove(struct platform_device *pdev)
+static int au1000_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct au1000_private *aup = netdev_priv(dev);
@@ -1340,7 +1340,7 @@ static int __devexit au1000_remove(struct platform_device *pdev)
 
 static struct platform_driver au1000_eth_driver = {
        .probe  = au1000_probe,
-       .remove = __devexit_p(au1000_remove),
+       .remove = au1000_remove,
        .driver = {
                .name   = "au1000-eth",
                .owner  = THIS_MODULE,
index 7203b522f234591f6db66e0cd447ac852adb058b..baca0bd1b39361b7d5ce7ff90a82cc43064fce7f 100644 (file)
@@ -72,7 +72,7 @@
 #include <asm/dec/machtype.h>
 #include <asm/dec/system.h>
 
-static char version[] __devinitdata =
+static char version[] =
 "declance.c: v0.011 by Linux MIPS DECstation task force\n";
 
 MODULE_AUTHOR("Linux MIPS DECstation task force");
@@ -1020,7 +1020,7 @@ static const struct net_device_ops lance_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __devinit dec_lance_probe(struct device *bdev, const int type)
+static int dec_lance_probe(struct device *bdev, const int type)
 {
        static unsigned version_printed;
        static const char fmt[] = "declance%d";
@@ -1322,7 +1322,7 @@ static void __exit dec_lance_platform_remove(void)
 }
 
 #ifdef CONFIG_TC
-static int __devinit dec_lance_tc_probe(struct device *dev);
+static int dec_lance_tc_probe(struct device *dev);
 static int __exit dec_lance_tc_remove(struct device *dev);
 
 static const struct tc_device_id dec_lance_tc_table[] = {
@@ -1341,7 +1341,7 @@ static struct tc_driver dec_lance_tc_driver = {
        },
 };
 
-static int __devinit dec_lance_tc_probe(struct device *dev)
+static int dec_lance_tc_probe(struct device *dev)
 {
         int status = dec_lance_probe(dev, PMAD_LANCE);
         if (!status)
index c771de71612a8f75d82dc11e2ca629015c7c78da..34a485363d5b7dcc77b715577bd0cc63af19b5a6 100644 (file)
@@ -338,21 +338,21 @@ static struct eisa_driver depca_eisa_driver = {
        .driver   = {
                .name    = depca_string,
                .probe   = depca_eisa_probe,
-               .remove  = __devexit_p (depca_device_remove)
+               .remove  = depca_device_remove
        }
 };
 #endif
 
 static int depca_isa_probe (struct platform_device *);
 
-static int __devexit depca_isa_remove(struct platform_device *pdev)
+static int depca_isa_remove(struct platform_device *pdev)
 {
        return depca_device_remove(&pdev->dev);
 }
 
 static struct platform_driver depca_isa_driver = {
        .probe  = depca_isa_probe,
-       .remove = __devexit_p(depca_isa_remove),
+       .remove = depca_isa_remove,
        .driver = {
                .name   = depca_string,
        },
@@ -1320,7 +1320,7 @@ static enum depca_type __init depca_shmem_probe (ulong *mem_start)
        return adapter;
 }
 
-static int __devinit depca_isa_probe (struct platform_device *device)
+static int depca_isa_probe(struct platform_device *device)
 {
        struct net_device *dev;
        struct depca_private *lp;
@@ -1412,7 +1412,7 @@ static int __init depca_eisa_probe (struct device *device)
 }
 #endif
 
-static int __devexit depca_device_remove (struct device *device)
+static int depca_device_remove(struct device *device)
 {
        struct net_device *dev;
        struct depca_private *lp;
index 8baff4e5d964ed6f172f0cd1f44a3ac2c3a5ce0e..0c61fd50d8829f13789b7c3583000929de25084d 100644 (file)
@@ -46,11 +46,9 @@ struct hplance_private {
  * plus board-specific init, open and close actions.
  * Oh, and we need to tell the generic code how to read and write LANCE registers...
  */
-static int __devinit hplance_init_one(struct dio_dev *d,
-                               const struct dio_device_id *ent);
-static void __devinit hplance_init(struct net_device *dev,
-                               struct dio_dev *d);
-static void __devexit hplance_remove_one(struct dio_dev *d);
+static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent);
+static void hplance_init(struct net_device *dev, struct dio_dev *d);
+static void hplance_remove_one(struct dio_dev *d);
 static void hplance_writerap(void *priv, unsigned short value);
 static void hplance_writerdp(void *priv, unsigned short value);
 static unsigned short hplance_readrdp(void *priv);
@@ -66,7 +64,7 @@ static struct dio_driver hplance_driver = {
        .name      = "hplance",
        .id_table  = hplance_dio_tbl,
        .probe     = hplance_init_one,
-       .remove    = __devexit_p(hplance_remove_one),
+       .remove    = hplance_remove_one,
 };
 
 static const struct net_device_ops hplance_netdev_ops = {
@@ -83,8 +81,7 @@ static const struct net_device_ops hplance_netdev_ops = {
 };
 
 /* Find all the HP Lance boards and initialise them... */
-static int __devinit hplance_init_one(struct dio_dev *d,
-                               const struct dio_device_id *ent)
+static int hplance_init_one(struct dio_dev *d, const struct dio_device_id *ent)
 {
        struct net_device *dev;
        int err = -ENOMEM;
@@ -118,7 +115,7 @@ static int __devinit hplance_init_one(struct dio_dev *d,
        return err;
 }
 
-static void __devexit hplance_remove_one(struct dio_dev *d)
+static void hplance_remove_one(struct dio_dev *d)
 {
        struct net_device *dev = dio_get_drvdata(d);
 
@@ -128,7 +125,7 @@ static void __devexit hplance_remove_one(struct dio_dev *d)
 }
 
 /* Initialise a single lance board at the given DIO device */
-static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d)
+static void hplance_init(struct net_device *dev, struct dio_dev *d)
 {
         unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
         struct hplance_private *lp;
index 86b6d8e4e6cd594ec39bdb5ca41fe130008fac64..a227ccdcb9b5e94447a5cd3c23c9ebef94b08932 100644 (file)
@@ -1443,7 +1443,7 @@ static const struct ethtool_ops pcnet32_ethtool_ops = {
 /* only probes for non-PCI devices, the rest are handled by
  * pci_register_driver via pcnet32_probe_pci */
 
-static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
+static void pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
 {
        unsigned int *port, ioaddr;
 
@@ -1462,7 +1462,7 @@ static void __devinit pcnet32_probe_vlbus(unsigned int *pcnet32_portlist)
        }
 }
 
-static int __devinit
+static int
 pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned long ioaddr;
@@ -1521,7 +1521,7 @@ static const struct net_device_ops pcnet32_netdev_ops = {
  *  Called from both pcnet32_probe_vlbus and pcnet_probe_pci.
  *  pdev will be NULL when called from pcnet32_probe_vlbus.
  */
-static int __devinit
+static int
 pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
 {
        struct pcnet32_private *lp;
@@ -2823,7 +2823,7 @@ static int pcnet32_pm_resume(struct pci_dev *pdev)
        return 0;
 }
 
-static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
+static void pcnet32_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -2844,7 +2844,7 @@ static void __devexit pcnet32_remove_one(struct pci_dev *pdev)
 static struct pci_driver pcnet32_driver = {
        .name = DRV_NAME,
        .probe = pcnet32_probe_pci,
-       .remove = __devexit_p(pcnet32_remove_one),
+       .remove = pcnet32_remove_one,
        .id_table = pcnet32_pci_tbl,
        .suspend = pcnet32_pm_suspend,
        .resume = pcnet32_pm_resume,
index d7a3533d990b165774a585343a440217b90ec517..c2d696c88e4687c46233b017429f2fc86c9aca8f 100644 (file)
@@ -1304,9 +1304,9 @@ static const struct net_device_ops sparc_lance_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit sparc_lance_probe_one(struct platform_device *op,
-                                          struct platform_device *ledma,
-                                          struct platform_device *lebuffer)
+static int sparc_lance_probe_one(struct platform_device *op,
+                                struct platform_device *ledma,
+                                struct platform_device *lebuffer)
 {
        struct device_node *dp = op->dev.of_node;
        static unsigned version_printed;
@@ -1488,7 +1488,7 @@ fail:
        return -ENODEV;
 }
 
-static int __devinit sunlance_sbus_probe(struct platform_device *op)
+static int sunlance_sbus_probe(struct platform_device *op)
 {
        struct platform_device *parent = to_platform_device(op->dev.parent);
        struct device_node *parent_dp = parent->dev.of_node;
@@ -1504,7 +1504,7 @@ static int __devinit sunlance_sbus_probe(struct platform_device *op)
        return err;
 }
 
-static int __devexit sunlance_sbus_remove(struct platform_device *op)
+static int sunlance_sbus_remove(struct platform_device *op)
 {
        struct lance_private *lp = dev_get_drvdata(&op->dev);
        struct net_device *net_dev = lp->dev;
@@ -1536,7 +1536,7 @@ static struct platform_driver sunlance_sbus_driver = {
                .of_match_table = sunlance_sbus_match,
        },
        .probe          = sunlance_sbus_probe,
-       .remove         = __devexit_p(sunlance_sbus_remove),
+       .remove         = sunlance_sbus_remove,
 };
 
 module_platform_driver(sunlance_sbus_driver);
index 855bdafb1a8759dec969cd5c84a212df0ed7daaf..f36bbd6d5085da5f5d2ba830b88c7e517e3f5f9e 100644 (file)
@@ -1244,7 +1244,7 @@ static const struct net_device_ops bmac_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
+static int bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
 {
        int j, rev, ret;
        struct bmac_data *bp;
@@ -1602,7 +1602,7 @@ bmac_proc_info(char *buffer, char **start, off_t offset, int length)
 }
 #endif
 
-static int __devexit bmac_remove(struct macio_dev *mdev)
+static int bmac_remove(struct macio_dev *mdev)
 {
        struct net_device *dev = macio_get_drvdata(mdev);
        struct bmac_data *bp = netdev_priv(dev);
index e1df4b76c8850bab2d3a4af5f8e08b1a7def77eb..842fe7684904351652f669d7838966597e467bcc 100644 (file)
@@ -106,7 +106,7 @@ static const struct net_device_ops mace_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
+static int mace_probe(struct macio_dev *mdev, const struct of_device_id *match)
 {
        struct device_node *mace = macio_get_of_node(mdev);
        struct net_device *dev;
@@ -271,7 +271,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
        return rc;
 }
 
-static int __devexit mace_remove(struct macio_dev *mdev)
+static int mace_remove(struct macio_dev *mdev)
 {
        struct net_device *dev = macio_get_drvdata(mdev);
        struct mace_data *mp;
index a92ddee7f665c63a33156ac864f8d1e5e804f817..a206779c68cf2d48f5a6bcc6f98b99dd2c98426f 100644 (file)
@@ -195,7 +195,7 @@ static const struct net_device_ops mace_netdev_ops = {
  * model of Macintrash has a MACE (AV macintoshes)
  */
 
-static int __devinit mace_probe(struct platform_device *pdev)
+static int mace_probe(struct platform_device *pdev)
 {
        int j;
        struct mace_data *mp;
@@ -746,7 +746,7 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
 MODULE_ALIAS("platform:macmace");
 
-static int __devexit mac_mace_device_remove (struct platform_device *pdev)
+static int mac_mace_device_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct mace_data *mp = netdev_priv(dev);
@@ -768,7 +768,7 @@ static int __devexit mac_mace_device_remove (struct platform_device *pdev)
 
 static struct platform_driver mac_mace_driver = {
        .probe  = mace_probe,
-       .remove = __devexit_p(mac_mace_device_remove),
+       .remove = mac_mace_device_remove,
        .driver = {
                .name   = mac_mace_string,
                .owner  = THIS_MODULE,
index d19f82f7597a6c3e079a71dffc727cd5fbd9cd21..56d3f697e0c7f0a05d8044a37f954c8d536f1c0a 100644 (file)
@@ -643,7 +643,7 @@ static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
  * @adapter: board private structure to initialize
  *
  */
-static int __devinit atl1c_alloc_queues(struct atl1c_adapter *adapter)
+static int atl1c_alloc_queues(struct atl1c_adapter *adapter)
 {
        return 0;
 }
@@ -702,7 +702,7 @@ struct atl1c_platform_patch {
        u32 patch_flag;
 #define ATL1C_LINK_PATCH       0x1
 };
-static const struct atl1c_platform_patch plats[] __devinitconst = {
+static const struct atl1c_platform_patch plats[] = {
 {0x2060, 0xC1, 0x1019, 0x8152, 0x1},
 {0x2060, 0xC1, 0x1019, 0x2060, 0x1},
 {0x2060, 0xC1, 0x1019, 0xE000, 0x1},
@@ -725,7 +725,7 @@ static const struct atl1c_platform_patch plats[] __devinitconst = {
 {0},
 };
 
-static void __devinit atl1c_patch_assign(struct atl1c_hw *hw)
+static void atl1c_patch_assign(struct atl1c_hw *hw)
 {
        struct pci_dev  *pdev = hw->adapter->pdev;
        u32 misc_ctrl;
@@ -764,7 +764,7 @@ static void __devinit atl1c_patch_assign(struct atl1c_hw *hw)
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  */
-static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
+static int atl1c_sw_init(struct atl1c_adapter *adapter)
 {
        struct atl1c_hw *hw   = &adapter->hw;
        struct pci_dev  *pdev = adapter->pdev;
@@ -2442,8 +2442,7 @@ static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  */
-static int __devinit atl1c_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct atl1c_adapter *adapter;
@@ -2587,7 +2586,7 @@ err_dma:
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  */
-static void __devexit atl1c_remove(struct pci_dev *pdev)
+static void atl1c_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct atl1c_adapter *adapter = netdev_priv(netdev);
@@ -2697,7 +2696,7 @@ static struct pci_driver atl1c_driver = {
        .name     = atl1c_driver_name,
        .id_table = atl1c_pci_tbl,
        .probe    = atl1c_probe,
-       .remove   = __devexit_p(atl1c_remove),
+       .remove   = atl1c_remove,
        .shutdown = atl1c_shutdown,
        .err_handler = &atl1c_err_handler,
        .driver.pm = &atl1c_pm_ops,
index e213da29e73d4debb9666810c2482cd1f8f51b50..e4466a36d1063b38c71b3937ba5cc055482ab82a 100644 (file)
@@ -534,7 +534,7 @@ static void atl1e_setup_pcicmd(struct pci_dev *pdev)
  * @adapter: board private structure to initialize
  *
  */
-static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
+static int atl1e_alloc_queues(struct atl1e_adapter *adapter)
 {
        return 0;
 }
@@ -547,7 +547,7 @@ static int __devinit atl1e_alloc_queues(struct atl1e_adapter *adapter)
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  */
-static int __devinit atl1e_sw_init(struct atl1e_adapter *adapter)
+static int atl1e_sw_init(struct atl1e_adapter *adapter)
 {
        struct atl1e_hw *hw   = &adapter->hw;
        struct pci_dev  *pdev = adapter->pdev;
@@ -2235,8 +2235,7 @@ static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev)
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  */
-static int __devinit atl1e_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct atl1e_adapter *adapter = NULL;
@@ -2387,7 +2386,7 @@ err_dma:
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  */
-static void __devexit atl1e_remove(struct pci_dev *pdev)
+static void atl1e_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct atl1e_adapter *adapter = netdev_priv(netdev);
@@ -2499,7 +2498,7 @@ static struct pci_driver atl1e_driver = {
        .name     = atl1e_driver_name,
        .id_table = atl1e_pci_tbl,
        .probe    = atl1e_probe,
-       .remove   = __devexit_p(atl1e_remove),
+       .remove   = atl1e_remove,
        /* Power Management Hooks */
 #ifdef CONFIG_PM
        .suspend  = atl1e_suspend,
index b5086f1e637f8179311e29c150fc9f1301b93bdb..fa314282c9ad332673e007c199981b04edef0ca0 100644 (file)
@@ -40,7 +40,7 @@
 #define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET }
 
 #define ATL1E_PARAM(x, desc) \
-       static int __devinitdata x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
+       static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \
        static unsigned int num_##x; \
        module_param_array_named(x, x, int, &num_##x, 0); \
        MODULE_PARM_DESC(x, desc);
@@ -116,7 +116,8 @@ struct atl1e_option {
        } arg;
 };
 
-static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt, struct atl1e_adapter *adapter)
+static int atl1e_validate_option(int *value, struct atl1e_option *opt,
+                                struct atl1e_adapter *adapter)
 {
        if (*value == OPTION_UNSET) {
                *value = opt->def;
@@ -177,7 +178,7 @@ static int __devinit atl1e_validate_option(int *value, struct atl1e_option *opt,
  * value exists, a default value is used.  The final value is stored
  * in a variable in the adapter structure.
  */
-void __devinit atl1e_check_options(struct atl1e_adapter *adapter)
+void atl1e_check_options(struct atl1e_adapter *adapter)
 {
        int bd = adapter->bd_number;
 
index 7bae2ad7a7c0ed66b360c844960bb3b4ed50c683..71b3d7daa21d06c70e4b62732c91b04137342c64 100644 (file)
@@ -113,7 +113,7 @@ static const struct ethtool_ops atl1_ethtool_ops;
  *
  * Default Value: 100 (200us)
  */
-static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
+static int int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT;
 static unsigned int num_int_mod_timer;
 module_param_array_named(int_mod_timer, int_mod_timer, int,
        &num_int_mod_timer, 0);
@@ -143,8 +143,8 @@ struct atl1_option {
        } arg;
 };
 
-static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
-       struct pci_dev *pdev)
+static int atl1_validate_option(int *value, struct atl1_option *opt,
+                               struct pci_dev *pdev)
 {
        if (*value == OPTION_UNSET) {
                *value = opt->def;
@@ -204,7 +204,7 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
  * value exists, a default value is used.  The final value is stored
  * in a variable in the adapter structure.
  */
-static void __devinit atl1_check_options(struct atl1_adapter *adapter)
+static void atl1_check_options(struct atl1_adapter *adapter)
 {
        struct pci_dev *pdev = adapter->pdev;
        int bd = adapter->bd_number;
@@ -945,7 +945,7 @@ static void atl1_set_mac_addr(struct atl1_hw *hw)
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  */
-static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
+static int atl1_sw_init(struct atl1_adapter *adapter)
 {
        struct atl1_hw *hw = &adapter->hw;
        struct net_device *netdev = adapter->netdev;
@@ -2934,8 +2934,7 @@ static const struct net_device_ops atl1_netdev_ops = {
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  */
-static int __devinit atl1_probe(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int atl1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct atl1_adapter *adapter;
@@ -3113,7 +3112,7 @@ err_request_regions:
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  */
-static void __devexit atl1_remove(struct pci_dev *pdev)
+static void atl1_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct atl1_adapter *adapter;
@@ -3146,7 +3145,7 @@ static struct pci_driver atl1_driver = {
        .name = ATLX_DRIVER_NAME,
        .id_table = atl1_pci_tbl,
        .probe = atl1_probe,
-       .remove = __devexit_p(atl1_remove),
+       .remove = atl1_remove,
        .shutdown = atl1_shutdown,
        .driver.pm = ATL1_PM_OPS,
 };
index 623dd8635c46eb0fd9e209025ff60464627dbcd6..aab83a2d4e0770a2cb781c5e6062bdb42360e413 100644 (file)
@@ -83,7 +83,7 @@ static void atl2_check_options(struct atl2_adapter *adapter);
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  */
-static int __devinit atl2_sw_init(struct atl2_adapter *adapter)
+static int atl2_sw_init(struct atl2_adapter *adapter)
 {
        struct atl2_hw *hw = &adapter->hw;
        struct pci_dev *pdev = adapter->pdev;
@@ -1338,8 +1338,7 @@ static const struct net_device_ops atl2_netdev_ops = {
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  */
-static int __devinit atl2_probe(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct atl2_adapter *adapter;
@@ -1498,7 +1497,7 @@ err_dma:
  */
 /* FIXME: write the original MAC address back in case it was changed from a
  * BIOS-set value, as in atl1 -- CHS */
-static void __devexit atl2_remove(struct pci_dev *pdev)
+static void atl2_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct atl2_adapter *adapter = netdev_priv(netdev);
@@ -1705,7 +1704,7 @@ static struct pci_driver atl2_driver = {
        .name     = atl2_driver_name,
        .id_table = atl2_pci_tbl,
        .probe    = atl2_probe,
-       .remove   = __devexit_p(atl2_remove),
+       .remove   = atl2_remove,
        /* Power Management Hooks */
        .suspend  = atl2_suspend,
 #ifdef CONFIG_PM
@@ -2845,12 +2844,12 @@ static void atl2_force_ps(struct atl2_hw *hw)
  */
 
 #define ATL2_PARAM(X, desc) \
-    static const int __devinitconst X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
+    static const int X[ATL2_MAX_NIC + 1] = ATL2_PARAM_INIT; \
     MODULE_PARM(X, "1-" __MODULE_STRING(ATL2_MAX_NIC) "i"); \
     MODULE_PARM_DESC(X, desc);
 #else
 #define ATL2_PARAM(X, desc) \
-    static int __devinitdata X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \
+    static int X[ATL2_MAX_NIC+1] = ATL2_PARAM_INIT; \
     static unsigned int num_##X; \
     module_param_array_named(X, X, int, &num_##X, 0); \
     MODULE_PARM_DESC(X, desc);
@@ -2934,7 +2933,7 @@ struct atl2_option {
        } arg;
 };
 
-static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)
+static int atl2_validate_option(int *value, struct atl2_option *opt)
 {
        int i;
        struct atl2_opt_list *ent;
@@ -2992,7 +2991,7 @@ static int __devinit atl2_validate_option(int *value, struct atl2_option *opt)
  * value exists, a default value is used.  The final value is stored
  * in a variable in the adapter structure.
  */
-static void __devinit atl2_check_options(struct atl2_adapter *adapter)
+static void atl2_check_options(struct atl2_adapter *adapter)
 {
        int val;
        struct atl2_option opt;
index 4bd416b72e65a9a5423930e9a52340bb087f2174..f55267363f355d1238dfecf9eb8df1367f53aad1 100644 (file)
@@ -102,6 +102,7 @@ config TIGON3
        depends on PCI
        select PHYLIB
        select HWMON
+       select PTP_1588_CLOCK
        ---help---
          This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
 
index 9786c0e9890edc5548410741c07a82bcd34c1ded..219f6226fcb139a50795da6af0f4daa5a8ceb12a 100644 (file)
@@ -2083,7 +2083,7 @@ out:
        return err;
 }
 
-static int __devinit b44_get_invariants(struct b44 *bp)
+static int b44_get_invariants(struct b44 *bp)
 {
        struct ssb_device *sdev = bp->sdev;
        int err = 0;
@@ -2141,8 +2141,8 @@ static const struct net_device_ops b44_netdev_ops = {
 #endif
 };
 
-static int __devinit b44_init_one(struct ssb_device *sdev,
-                                 const struct ssb_device_id *ent)
+static int b44_init_one(struct ssb_device *sdev,
+                       const struct ssb_device_id *ent)
 {
        struct net_device *dev;
        struct b44 *bp;
@@ -2249,7 +2249,7 @@ out:
        return err;
 }
 
-static void __devexit b44_remove_one(struct ssb_device *sdev)
+static void b44_remove_one(struct ssb_device *sdev)
 {
        struct net_device *dev = ssb_get_drvdata(sdev);
 
@@ -2340,7 +2340,7 @@ static struct ssb_driver b44_ssb_driver = {
        .name           = DRV_MODULE_NAME,
        .id_table       = b44_ssb_tbl,
        .probe          = b44_init_one,
-       .remove         = __devexit_p(b44_remove_one),
+       .remove         = b44_remove_one,
        .suspend        = b44_suspend,
        .resume         = b44_resume,
 };
index c7ca7ec065eeea7dfe164f96384ec3aaf464809d..39387d67b7222beee3a5fd122218c645851f90c6 100644 (file)
@@ -1612,7 +1612,7 @@ static const struct net_device_ops bcm_enet_ops = {
 /*
  * allocate netdevice, request register memory and register device.
  */
-static int __devinit bcm_enet_probe(struct platform_device *pdev)
+static int bcm_enet_probe(struct platform_device *pdev)
 {
        struct bcm_enet_priv *priv;
        struct net_device *dev;
@@ -1830,7 +1830,7 @@ out:
 /*
  * exit func, stops hardware and unregisters netdevice
  */
-static int __devexit bcm_enet_remove(struct platform_device *pdev)
+static int bcm_enet_remove(struct platform_device *pdev)
 {
        struct bcm_enet_priv *priv;
        struct net_device *dev;
@@ -1877,7 +1877,7 @@ static int __devexit bcm_enet_remove(struct platform_device *pdev)
 
 struct platform_driver bcm63xx_enet_driver = {
        .probe  = bcm_enet_probe,
-       .remove = __devexit_p(bcm_enet_remove),
+       .remove = bcm_enet_remove,
        .driver = {
                .name   = "bcm63xx_enet",
                .owner  = THIS_MODULE,
@@ -1887,7 +1887,7 @@ struct platform_driver bcm63xx_enet_driver = {
 /*
  * reserve & remap memory space shared between all macs
  */
-static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
+static int bcm_enet_shared_probe(struct platform_device *pdev)
 {
        struct resource *res;
        unsigned int iomem_size;
@@ -1908,7 +1908,7 @@ static int __devinit bcm_enet_shared_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
+static int bcm_enet_shared_remove(struct platform_device *pdev)
 {
        struct resource *res;
 
@@ -1924,7 +1924,7 @@ static int __devexit bcm_enet_shared_remove(struct platform_device *pdev)
  */
 struct platform_driver bcm63xx_enet_shared_driver = {
        .probe  = bcm_enet_shared_probe,
-       .remove = __devexit_p(bcm_enet_shared_remove),
+       .remove = bcm_enet_shared_remove,
        .driver = {
                .name   = "bcm63xx_enet_shared",
                .owner  = THIS_MODULE,
index d4310700c7a71409ae399bae819bac5fdebe32fa..c16526d3046fc7b3574073c89564afa012620241 100644 (file)
@@ -71,7 +71,7 @@
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (5*HZ)
 
-static char version[] __devinitdata =
+static char version[] =
        "Broadcom NetXtreme II Gigabit Ethernet Driver " DRV_MODULE_NAME " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Michael Chan <mchan@broadcom.com>");
@@ -106,7 +106,7 @@ typedef enum {
 /* indexed by board_t, above */
 static struct {
        char *name;
-} board_info[] __devinitdata = {
+} board_info[] = {
        { "Broadcom NetXtreme II BCM5706 1000Base-T" },
        { "HP NC370T Multifunction Gigabit Server Adapter" },
        { "HP NC370i Multifunction Gigabit Server Adapter" },
@@ -260,10 +260,10 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp, struct bnx2_tx_ring_info *txr)
         * needs to be skipped.
         */
        diff = txr->tx_prod - txr->tx_cons;
-       if (unlikely(diff >= TX_DESC_CNT)) {
+       if (unlikely(diff >= BNX2_TX_DESC_CNT)) {
                diff &= 0xffff;
-               if (diff == TX_DESC_CNT)
-                       diff = MAX_TX_DESC_CNT;
+               if (diff == BNX2_TX_DESC_CNT)
+                       diff = BNX2_MAX_TX_DESC_CNT;
        }
        return bp->tx_ring_size - diff;
 }
@@ -274,8 +274,8 @@ bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
        u32 val;
 
        spin_lock_bh(&bp->indirect_lock);
-       REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
-       val = REG_RD(bp, BNX2_PCICFG_REG_WINDOW);
+       BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+       val = BNX2_RD(bp, BNX2_PCICFG_REG_WINDOW);
        spin_unlock_bh(&bp->indirect_lock);
        return val;
 }
@@ -284,8 +284,8 @@ static void
 bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
 {
        spin_lock_bh(&bp->indirect_lock);
-       REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
-       REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
+       BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
+       BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
        spin_unlock_bh(&bp->indirect_lock);
 }
 
@@ -306,21 +306,21 @@ bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
 {
        offset += cid_addr;
        spin_lock_bh(&bp->indirect_lock);
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                int i;
 
-               REG_WR(bp, BNX2_CTX_CTX_DATA, val);
-               REG_WR(bp, BNX2_CTX_CTX_CTRL,
-                      offset | BNX2_CTX_CTX_CTRL_WRITE_REQ);
+               BNX2_WR(bp, BNX2_CTX_CTX_DATA, val);
+               BNX2_WR(bp, BNX2_CTX_CTX_CTRL,
+                       offset | BNX2_CTX_CTX_CTRL_WRITE_REQ);
                for (i = 0; i < 5; i++) {
-                       val = REG_RD(bp, BNX2_CTX_CTX_CTRL);
+                       val = BNX2_RD(bp, BNX2_CTX_CTX_CTRL);
                        if ((val & BNX2_CTX_CTX_CTRL_WRITE_REQ) == 0)
                                break;
                        udelay(5);
                }
        } else {
-               REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
-               REG_WR(bp, BNX2_CTX_DATA, val);
+               BNX2_WR(bp, BNX2_CTX_DATA_ADR, offset);
+               BNX2_WR(bp, BNX2_CTX_DATA, val);
        }
        spin_unlock_bh(&bp->indirect_lock);
 }
@@ -434,7 +434,6 @@ struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev)
 
        return cp;
 }
-EXPORT_SYMBOL(bnx2_cnic_probe);
 
 static void
 bnx2_cnic_stop(struct bnx2 *bp)
@@ -494,11 +493,11 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
        int i, ret;
 
        if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
-               val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+               val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
                val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
 
-               REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
-               REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+               BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+               BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
 
                udelay(40);
        }
@@ -506,16 +505,16 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
        val1 = (bp->phy_addr << 21) | (reg << 16) |
                BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT |
                BNX2_EMAC_MDIO_COMM_START_BUSY;
-       REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+       BNX2_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
 
        for (i = 0; i < 50; i++) {
                udelay(10);
 
-               val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+               val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM);
                if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
                        udelay(5);
 
-                       val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+                       val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM);
                        val1 &= BNX2_EMAC_MDIO_COMM_DATA;
 
                        break;
@@ -532,11 +531,11 @@ bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
        }
 
        if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
-               val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+               val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
                val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
 
-               REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
-               REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+               BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+               BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
 
                udelay(40);
        }
@@ -551,11 +550,11 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
        int i, ret;
 
        if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
-               val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+               val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
                val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
 
-               REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
-               REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+               BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+               BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
 
                udelay(40);
        }
@@ -563,12 +562,12 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
        val1 = (bp->phy_addr << 21) | (reg << 16) | val |
                BNX2_EMAC_MDIO_COMM_COMMAND_WRITE |
                BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT;
-       REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
+       BNX2_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
 
        for (i = 0; i < 50; i++) {
                udelay(10);
 
-               val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
+               val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_COMM);
                if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
                        udelay(5);
                        break;
@@ -581,11 +580,11 @@ bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
                ret = 0;
 
        if (bp->phy_flags & BNX2_PHY_FLAG_INT_MODE_AUTO_POLLING) {
-               val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+               val1 = BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
                val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
 
-               REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
-               REG_RD(bp, BNX2_EMAC_MDIO_MODE);
+               BNX2_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
+               BNX2_RD(bp, BNX2_EMAC_MDIO_MODE);
 
                udelay(40);
        }
@@ -601,10 +600,10 @@ bnx2_disable_int(struct bnx2 *bp)
 
        for (i = 0; i < bp->irq_nvecs; i++) {
                bnapi = &bp->bnx2_napi[i];
-               REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
+               BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
                       BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
        }
-       REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+       BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
 }
 
 static void
@@ -616,16 +615,16 @@ bnx2_enable_int(struct bnx2 *bp)
        for (i = 0; i < bp->irq_nvecs; i++) {
                bnapi = &bp->bnx2_napi[i];
 
-               REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
-                      BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-                      BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
-                      bnapi->last_status_idx);
+               BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
+                       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                       BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+                       bnapi->last_status_idx);
 
-               REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
-                      BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-                      bnapi->last_status_idx);
+               BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
+                       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                       bnapi->last_status_idx);
        }
-       REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
+       BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
 }
 
 static void
@@ -824,7 +823,7 @@ bnx2_free_mem(struct bnx2 *bp)
 
        for (i = 0; i < bp->ctx_pages; i++) {
                if (bp->ctx_blk[i]) {
-                       dma_free_coherent(&bp->pdev->dev, BCM_PAGE_SIZE,
+                       dma_free_coherent(&bp->pdev->dev, BNX2_PAGE_SIZE,
                                          bp->ctx_blk[i],
                                          bp->ctx_blk_mapping[i]);
                        bp->ctx_blk[i] = NULL;
@@ -887,13 +886,13 @@ bnx2_alloc_mem(struct bnx2 *bp)
 
        bp->stats_blk_mapping = bp->status_blk_mapping + status_blk_size;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-               bp->ctx_pages = 0x2000 / BCM_PAGE_SIZE;
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+               bp->ctx_pages = 0x2000 / BNX2_PAGE_SIZE;
                if (bp->ctx_pages == 0)
                        bp->ctx_pages = 1;
                for (i = 0; i < bp->ctx_pages; i++) {
                        bp->ctx_blk[i] = dma_alloc_coherent(&bp->pdev->dev,
-                                               BCM_PAGE_SIZE,
+                                               BNX2_PAGE_SIZE,
                                                &bp->ctx_blk_mapping[i],
                                                GFP_KERNEL);
                        if (bp->ctx_blk[i] == NULL)
@@ -1034,7 +1033,7 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp)
        }
 
        if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-           (CHIP_NUM(bp) == CHIP_NUM_5708)) {
+           (BNX2_CHIP(bp) == BNX2_CHIP_5708)) {
                u32 val;
 
                bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
@@ -1294,14 +1293,14 @@ bnx2_set_mac_link(struct bnx2 *bp)
 {
        u32 val;
 
-       REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
+       BNX2_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
        if (bp->link_up && (bp->line_speed == SPEED_1000) &&
                (bp->duplex == DUPLEX_HALF)) {
-               REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
+               BNX2_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
        }
 
        /* Configure the EMAC mode register. */
-       val = REG_RD(bp, BNX2_EMAC_MODE);
+       val = BNX2_RD(bp, BNX2_EMAC_MODE);
 
        val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
                BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
@@ -1310,7 +1309,7 @@ bnx2_set_mac_link(struct bnx2 *bp)
        if (bp->link_up) {
                switch (bp->line_speed) {
                        case SPEED_10:
-                               if (CHIP_NUM(bp) != CHIP_NUM_5706) {
+                               if (BNX2_CHIP(bp) != BNX2_CHIP_5706) {
                                        val |= BNX2_EMAC_MODE_PORT_MII_10M;
                                        break;
                                }
@@ -1333,25 +1332,25 @@ bnx2_set_mac_link(struct bnx2 *bp)
        /* Set the MAC to operate in the appropriate duplex mode. */
        if (bp->duplex == DUPLEX_HALF)
                val |= BNX2_EMAC_MODE_HALF_DUPLEX;
-       REG_WR(bp, BNX2_EMAC_MODE, val);
+       BNX2_WR(bp, BNX2_EMAC_MODE, val);
 
        /* Enable/disable rx PAUSE. */
        bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN;
 
        if (bp->flow_ctrl & FLOW_CTRL_RX)
                bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN;
-       REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
+       BNX2_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
 
        /* Enable/disable tx PAUSE. */
-       val = REG_RD(bp, BNX2_EMAC_TX_MODE);
+       val = BNX2_RD(bp, BNX2_EMAC_TX_MODE);
        val &= ~BNX2_EMAC_TX_MODE_FLOW_EN;
 
        if (bp->flow_ctrl & FLOW_CTRL_TX)
                val |= BNX2_EMAC_TX_MODE_FLOW_EN;
-       REG_WR(bp, BNX2_EMAC_TX_MODE, val);
+       BNX2_WR(bp, BNX2_EMAC_TX_MODE, val);
 
        /* Acknowledge the interrupt. */
-       REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
+       BNX2_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
 
        bnx2_init_all_rx_contexts(bp);
 }
@@ -1360,7 +1359,7 @@ static void
 bnx2_enable_bmsr1(struct bnx2 *bp)
 {
        if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-           (CHIP_NUM(bp) == CHIP_NUM_5709))
+           (BNX2_CHIP(bp) == BNX2_CHIP_5709))
                bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
                               MII_BNX2_BLK_ADDR_GP_STATUS);
 }
@@ -1369,7 +1368,7 @@ static void
 bnx2_disable_bmsr1(struct bnx2 *bp)
 {
        if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-           (CHIP_NUM(bp) == CHIP_NUM_5709))
+           (BNX2_CHIP(bp) == BNX2_CHIP_5709))
                bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
                               MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
 }
@@ -1386,7 +1385,7 @@ bnx2_test_and_enable_2g5(struct bnx2 *bp)
        if (bp->autoneg & AUTONEG_SPEED)
                bp->advertising |= ADVERTISED_2500baseX_Full;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
 
        bnx2_read_phy(bp, bp->mii_up1, &up1);
@@ -1396,7 +1395,7 @@ bnx2_test_and_enable_2g5(struct bnx2 *bp)
                ret = 0;
        }
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
                               MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
 
@@ -1412,7 +1411,7 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp)
        if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
                return 0;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                bnx2_write_phy(bp, MII_BNX2_BLK_ADDR, MII_BNX2_BLK_ADDR_OVER1G);
 
        bnx2_read_phy(bp, bp->mii_up1, &up1);
@@ -1422,7 +1421,7 @@ bnx2_test_and_disable_2g5(struct bnx2 *bp)
                ret = 1;
        }
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
                               MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
 
@@ -1438,7 +1437,7 @@ bnx2_enable_forced_2g5(struct bnx2 *bp)
        if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
                return;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                u32 val;
 
                bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
@@ -1454,7 +1453,7 @@ bnx2_enable_forced_2g5(struct bnx2 *bp)
                               MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
                err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
-       } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+       } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) {
                err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
                if (!err)
                        bmcr |= BCM5708S_BMCR_FORCE_2500;
@@ -1482,7 +1481,7 @@ bnx2_disable_forced_2g5(struct bnx2 *bp)
        if (!(bp->phy_flags & BNX2_PHY_FLAG_2_5G_CAPABLE))
                return;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                u32 val;
 
                bnx2_write_phy(bp, MII_BNX2_BLK_ADDR,
@@ -1496,7 +1495,7 @@ bnx2_disable_forced_2g5(struct bnx2 *bp)
                               MII_BNX2_BLK_ADDR_COMBO_IEEEB0);
                err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
 
-       } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+       } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) {
                err = bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
                if (!err)
                        bmcr &= ~BCM5708S_BMCR_FORCE_2500;
@@ -1547,14 +1546,14 @@ bnx2_set_link(struct bnx2 *bp)
        bnx2_disable_bmsr1(bp);
 
        if ((bp->phy_flags & BNX2_PHY_FLAG_SERDES) &&
-           (CHIP_NUM(bp) == CHIP_NUM_5706)) {
+           (BNX2_CHIP(bp) == BNX2_CHIP_5706)) {
                u32 val, an_dbg;
 
                if (bp->phy_flags & BNX2_PHY_FLAG_FORCED_DOWN) {
                        bnx2_5706s_force_link_dn(bp, 0);
                        bp->phy_flags &= ~BNX2_PHY_FLAG_FORCED_DOWN;
                }
-               val = REG_RD(bp, BNX2_EMAC_STATUS);
+               val = BNX2_RD(bp, BNX2_EMAC_STATUS);
 
                bnx2_write_phy(bp, MII_BNX2_MISC_SHADOW, MISC_SHDW_AN_DBG);
                bnx2_read_phy(bp, MII_BNX2_MISC_SHADOW, &an_dbg);
@@ -1571,11 +1570,11 @@ bnx2_set_link(struct bnx2 *bp)
                bp->link_up = 1;
 
                if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-                       if (CHIP_NUM(bp) == CHIP_NUM_5706)
+                       if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
                                bnx2_5706s_linkup(bp);
-                       else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+                       else if (BNX2_CHIP(bp) == BNX2_CHIP_5708)
                                bnx2_5708s_linkup(bp);
-                       else if (CHIP_NUM(bp) == CHIP_NUM_5709)
+                       else if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                                bnx2_5709s_linkup(bp);
                }
                else {
@@ -1757,7 +1756,7 @@ __acquires(&bp->phy_lock)
                new_bmcr = bmcr & ~BMCR_ANENABLE;
                new_bmcr |= BMCR_SPEED1000;
 
-               if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+               if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                        if (bp->req_line_speed == SPEED_2500)
                                bnx2_enable_forced_2g5(bp);
                        else if (bp->req_line_speed == SPEED_1000) {
@@ -1765,7 +1764,7 @@ __acquires(&bp->phy_lock)
                                new_bmcr &= ~0x2000;
                        }
 
-               } else if (CHIP_NUM(bp) == CHIP_NUM_5708) {
+               } else if (BNX2_CHIP(bp) == BNX2_CHIP_5708) {
                        if (bp->req_line_speed == SPEED_2500)
                                new_bmcr |= BCM5708S_BMCR_FORCE_2500;
                        else
@@ -1942,8 +1941,8 @@ bnx2_send_heart_beat(struct bnx2 *bp)
        spin_lock(&bp->indirect_lock);
        msg = (u32) (++bp->fw_drv_pulse_wr_seq & BNX2_DRV_PULSE_SEQ_MASK);
        addr = bp->shmem_base + BNX2_DRV_PULSE_MB;
-       REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr);
-       REG_WR(bp, BNX2_PCICFG_REG_WINDOW, msg);
+       BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, addr);
+       BNX2_WR(bp, BNX2_PCICFG_REG_WINDOW, msg);
        spin_unlock(&bp->indirect_lock);
 }
 
@@ -2230,9 +2229,9 @@ bnx2_init_5708s_phy(struct bnx2 *bp, int reset_phy)
                bnx2_write_phy(bp, BCM5708S_UP1, val);
        }
 
-       if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
-           (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
-           (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
+       if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0) ||
+           (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B0) ||
+           (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B1)) {
                /* increase tx signal amplitude */
                bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
                               BCM5708S_BLK_ADDR_TX_MISC);
@@ -2268,8 +2267,8 @@ bnx2_init_5706s_phy(struct bnx2 *bp, int reset_phy)
 
        bp->phy_flags &= ~BNX2_PHY_FLAG_PARALLEL_DETECT;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5706)
-               REG_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
+               BNX2_WR(bp, BNX2_MISC_GP_HW_CTL0, 0x300);
 
        if (bp->dev->mtu > 1500) {
                u32 val;
@@ -2368,7 +2367,7 @@ __acquires(&bp->phy_lock)
        bp->mii_adv = MII_ADVERTISE;
        bp->mii_lpa = MII_LPA;
 
-        REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+       BNX2_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
 
        if (bp->phy_flags & BNX2_PHY_FLAG_REMOTE_PHY_CAP)
                goto setup_phy;
@@ -2379,11 +2378,11 @@ __acquires(&bp->phy_lock)
        bp->phy_id |= val & 0xffff;
 
        if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-               if (CHIP_NUM(bp) == CHIP_NUM_5706)
+               if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
                        rc = bnx2_init_5706s_phy(bp, reset_phy);
-               else if (CHIP_NUM(bp) == CHIP_NUM_5708)
+               else if (BNX2_CHIP(bp) == BNX2_CHIP_5708)
                        rc = bnx2_init_5708s_phy(bp, reset_phy);
-               else if (CHIP_NUM(bp) == CHIP_NUM_5709)
+               else if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                        rc = bnx2_init_5709s_phy(bp, reset_phy);
        }
        else {
@@ -2402,10 +2401,10 @@ bnx2_set_mac_loopback(struct bnx2 *bp)
 {
        u32 mac_mode;
 
-       mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
+       mac_mode = BNX2_RD(bp, BNX2_EMAC_MODE);
        mac_mode &= ~BNX2_EMAC_MODE_PORT;
        mac_mode |= BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK;
-       REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
+       BNX2_WR(bp, BNX2_EMAC_MODE, mac_mode);
        bp->link_up = 1;
        return 0;
 }
@@ -2431,13 +2430,13 @@ bnx2_set_phy_loopback(struct bnx2 *bp)
                msleep(100);
        }
 
-       mac_mode = REG_RD(bp, BNX2_EMAC_MODE);
+       mac_mode = BNX2_RD(bp, BNX2_EMAC_MODE);
        mac_mode &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
                      BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
                      BNX2_EMAC_MODE_25G_MODE);
 
        mac_mode |= BNX2_EMAC_MODE_PORT_GMII;
-       REG_WR(bp, BNX2_EMAC_MODE, mac_mode);
+       BNX2_WR(bp, BNX2_EMAC_MODE, mac_mode);
        bp->link_up = 1;
        return 0;
 }
@@ -2449,7 +2448,7 @@ bnx2_dump_mcp_state(struct bnx2 *bp)
        u32 mcp_p0, mcp_p1;
 
        netdev_err(dev, "<--- start MCP states dump --->\n");
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                mcp_p0 = BNX2_MCP_STATE_P0;
                mcp_p1 = BNX2_MCP_STATE_P1;
        } else {
@@ -2538,10 +2537,10 @@ bnx2_init_5709_context(struct bnx2 *bp)
        u32 val;
 
        val = BNX2_CTX_COMMAND_ENABLED | BNX2_CTX_COMMAND_MEM_INIT | (1 << 12);
-       val |= (BCM_PAGE_BITS - 8) << 16;
-       REG_WR(bp, BNX2_CTX_COMMAND, val);
+       val |= (BNX2_PAGE_BITS - 8) << 16;
+       BNX2_WR(bp, BNX2_CTX_COMMAND, val);
        for (i = 0; i < 10; i++) {
-               val = REG_RD(bp, BNX2_CTX_COMMAND);
+               val = BNX2_RD(bp, BNX2_CTX_COMMAND);
                if (!(val & BNX2_CTX_COMMAND_MEM_INIT))
                        break;
                udelay(2);
@@ -2553,20 +2552,20 @@ bnx2_init_5709_context(struct bnx2 *bp)
                int j;
 
                if (bp->ctx_blk[i])
-                       memset(bp->ctx_blk[i], 0, BCM_PAGE_SIZE);
+                       memset(bp->ctx_blk[i], 0, BNX2_PAGE_SIZE);
                else
                        return -ENOMEM;
 
-               REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0,
-                      (bp->ctx_blk_mapping[i] & 0xffffffff) |
-                      BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID);
-               REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1,
-                      (u64) bp->ctx_blk_mapping[i] >> 32);
-               REG_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i |
-                      BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
+               BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA0,
+                       (bp->ctx_blk_mapping[i] & 0xffffffff) |
+                       BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID);
+               BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_DATA1,
+                       (u64) bp->ctx_blk_mapping[i] >> 32);
+               BNX2_WR(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL, i |
+                       BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ);
                for (j = 0; j < 10; j++) {
 
-                       val = REG_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL);
+                       val = BNX2_RD(bp, BNX2_CTX_HOST_PAGE_TBL_CTRL);
                        if (!(val & BNX2_CTX_HOST_PAGE_TBL_CTRL_WRITE_REQ))
                                break;
                        udelay(5);
@@ -2591,7 +2590,7 @@ bnx2_init_context(struct bnx2 *bp)
 
                vcid--;
 
-               if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+               if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
                        u32 new_vcid;
 
                        vcid_addr = GET_PCID_ADDR(vcid);
@@ -2612,8 +2611,8 @@ bnx2_init_context(struct bnx2 *bp)
                        vcid_addr += (i << PHY_CTX_SHIFT);
                        pcid_addr += (i << PHY_CTX_SHIFT);
 
-                       REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
-                       REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
+                       BNX2_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
+                       BNX2_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
 
                        /* Zero out the context. */
                        for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
@@ -2633,7 +2632,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
        if (good_mbuf == NULL)
                return -ENOMEM;
 
-       REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+       BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
                BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
 
        good_mbuf_cnt = 0;
@@ -2678,21 +2677,21 @@ bnx2_set_mac_addr(struct bnx2 *bp, u8 *mac_addr, u32 pos)
 
        val = (mac_addr[0] << 8) | mac_addr[1];
 
-       REG_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val);
+       BNX2_WR(bp, BNX2_EMAC_MAC_MATCH0 + (pos * 8), val);
 
        val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
                (mac_addr[4] << 8) | mac_addr[5];
 
-       REG_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val);
+       BNX2_WR(bp, BNX2_EMAC_MAC_MATCH1 + (pos * 8), val);
 }
 
 static inline int
 bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp)
 {
        dma_addr_t mapping;
-       struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
-       struct rx_bd *rxbd =
-               &rxr->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
+       struct bnx2_sw_pg *rx_pg = &rxr->rx_pg_ring[index];
+       struct bnx2_rx_bd *rxbd =
+               &rxr->rx_pg_desc_ring[BNX2_RX_RING(index)][BNX2_RX_IDX(index)];
        struct page *page = alloc_page(gfp);
 
        if (!page)
@@ -2714,7 +2713,7 @@ bnx2_alloc_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gf
 static void
 bnx2_free_rx_page(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index)
 {
-       struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
+       struct bnx2_sw_pg *rx_pg = &rxr->rx_pg_ring[index];
        struct page *page = rx_pg->page;
 
        if (!page)
@@ -2731,9 +2730,10 @@ static inline int
 bnx2_alloc_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr, u16 index, gfp_t gfp)
 {
        u8 *data;
-       struct sw_bd *rx_buf = &rxr->rx_buf_ring[index];
+       struct bnx2_sw_bd *rx_buf = &rxr->rx_buf_ring[index];
        dma_addr_t mapping;
-       struct rx_bd *rxbd = &rxr->rx_desc_ring[RX_RING(index)][RX_IDX(index)];
+       struct bnx2_rx_bd *rxbd =
+               &rxr->rx_desc_ring[BNX2_RX_RING(index)][BNX2_RX_IDX(index)];
 
        data = kmalloc(bp->rx_buf_size, gfp);
        if (!data)
@@ -2770,9 +2770,9 @@ bnx2_phy_event_is_set(struct bnx2 *bp, struct bnx2_napi *bnapi, u32 event)
        old_link_state = sblk->status_attn_bits_ack & event;
        if (new_link_state != old_link_state) {
                if (new_link_state)
-                       REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event);
+                       BNX2_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD, event);
                else
-                       REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event);
+                       BNX2_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD, event);
        } else
                is_set = 0;
 
@@ -2802,7 +2802,7 @@ bnx2_get_hw_tx_cons(struct bnx2_napi *bnapi)
        barrier();
        cons = *bnapi->hw_tx_cons_ptr;
        barrier();
-       if (unlikely((cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT))
+       if (unlikely((cons & BNX2_MAX_TX_DESC_CNT) == BNX2_MAX_TX_DESC_CNT))
                cons++;
        return cons;
 }
@@ -2823,11 +2823,11 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
        sw_cons = txr->tx_cons;
 
        while (sw_cons != hw_cons) {
-               struct sw_tx_bd *tx_buf;
+               struct bnx2_sw_tx_bd *tx_buf;
                struct sk_buff *skb;
                int i, last;
 
-               sw_ring_cons = TX_RING_IDX(sw_cons);
+               sw_ring_cons = BNX2_TX_RING_IDX(sw_cons);
 
                tx_buf = &txr->tx_buf_ring[sw_ring_cons];
                skb = tx_buf->skb;
@@ -2841,7 +2841,7 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
 
                        last_idx = sw_cons + tx_buf->nr_frags + 1;
                        last_ring_idx = sw_ring_cons + tx_buf->nr_frags + 1;
-                       if (unlikely(last_ring_idx >= MAX_TX_DESC_CNT)) {
+                       if (unlikely(last_ring_idx >= BNX2_MAX_TX_DESC_CNT)) {
                                last_idx++;
                        }
                        if (((s16) ((s16) last_idx - (s16) hw_cons)) > 0) {
@@ -2856,17 +2856,18 @@ bnx2_tx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                last = tx_buf->nr_frags;
 
                for (i = 0; i < last; i++) {
-                       sw_cons = NEXT_TX_BD(sw_cons);
+                       struct bnx2_sw_tx_bd *tx_buf;
 
+                       sw_cons = BNX2_NEXT_TX_BD(sw_cons);
+
+                       tx_buf = &txr->tx_buf_ring[BNX2_TX_RING_IDX(sw_cons)];
                        dma_unmap_page(&bp->pdev->dev,
-                               dma_unmap_addr(
-                                       &txr->tx_buf_ring[TX_RING_IDX(sw_cons)],
-                                       mapping),
+                               dma_unmap_addr(tx_buf, mapping),
                                skb_frag_size(&skb_shinfo(skb)->frags[i]),
                                PCI_DMA_TODEVICE);
                }
 
-               sw_cons = NEXT_TX_BD(sw_cons);
+               sw_cons = BNX2_NEXT_TX_BD(sw_cons);
 
                tx_bytes += skb->len;
                dev_kfree_skb(skb);
@@ -2905,8 +2906,8 @@ static void
 bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
                        struct sk_buff *skb, int count)
 {
-       struct sw_pg *cons_rx_pg, *prod_rx_pg;
-       struct rx_bd *cons_bd, *prod_bd;
+       struct bnx2_sw_pg *cons_rx_pg, *prod_rx_pg;
+       struct bnx2_rx_bd *cons_bd, *prod_bd;
        int i;
        u16 hw_prod, prod;
        u16 cons = rxr->rx_pg_cons;
@@ -2933,12 +2934,14 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
        hw_prod = rxr->rx_pg_prod;
 
        for (i = 0; i < count; i++) {
-               prod = RX_PG_RING_IDX(hw_prod);
+               prod = BNX2_RX_PG_RING_IDX(hw_prod);
 
                prod_rx_pg = &rxr->rx_pg_ring[prod];
                cons_rx_pg = &rxr->rx_pg_ring[cons];
-               cons_bd = &rxr->rx_pg_desc_ring[RX_RING(cons)][RX_IDX(cons)];
-               prod_bd = &rxr->rx_pg_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+               cons_bd = &rxr->rx_pg_desc_ring[BNX2_RX_RING(cons)]
+                                               [BNX2_RX_IDX(cons)];
+               prod_bd = &rxr->rx_pg_desc_ring[BNX2_RX_RING(prod)]
+                                               [BNX2_RX_IDX(prod)];
 
                if (prod != cons) {
                        prod_rx_pg->page = cons_rx_pg->page;
@@ -2950,8 +2953,8 @@ bnx2_reuse_rx_skb_pages(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
                        prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
 
                }
-               cons = RX_PG_RING_IDX(NEXT_RX_BD(cons));
-               hw_prod = NEXT_RX_BD(hw_prod);
+               cons = BNX2_RX_PG_RING_IDX(BNX2_NEXT_RX_BD(cons));
+               hw_prod = BNX2_NEXT_RX_BD(hw_prod);
        }
        rxr->rx_pg_prod = hw_prod;
        rxr->rx_pg_cons = cons;
@@ -2961,8 +2964,8 @@ static inline void
 bnx2_reuse_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
                   u8 *data, u16 cons, u16 prod)
 {
-       struct sw_bd *cons_rx_buf, *prod_rx_buf;
-       struct rx_bd *cons_bd, *prod_bd;
+       struct bnx2_sw_bd *cons_rx_buf, *prod_rx_buf;
+       struct bnx2_rx_bd *cons_bd, *prod_bd;
 
        cons_rx_buf = &rxr->rx_buf_ring[cons];
        prod_rx_buf = &rxr->rx_buf_ring[prod];
@@ -2981,8 +2984,8 @@ bnx2_reuse_rx_data(struct bnx2 *bp, struct bnx2_rx_ring_info *rxr,
        dma_unmap_addr_set(prod_rx_buf, mapping,
                        dma_unmap_addr(cons_rx_buf, mapping));
 
-       cons_bd = &rxr->rx_desc_ring[RX_RING(cons)][RX_IDX(cons)];
-       prod_bd = &rxr->rx_desc_ring[RX_RING(prod)][RX_IDX(prod)];
+       cons_bd = &rxr->rx_desc_ring[BNX2_RX_RING(cons)][BNX2_RX_IDX(cons)];
+       prod_bd = &rxr->rx_desc_ring[BNX2_RX_RING(prod)][BNX2_RX_IDX(prod)];
        prod_bd->rx_bd_haddr_hi = cons_bd->rx_bd_haddr_hi;
        prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
 }
@@ -3022,7 +3025,7 @@ error:
                return skb;
        } else {
                unsigned int i, frag_len, frag_size, pages;
-               struct sw_pg *rx_pg;
+               struct bnx2_sw_pg *rx_pg;
                u16 pg_cons = rxr->rx_pg_cons;
                u16 pg_prod = rxr->rx_pg_prod;
 
@@ -3065,7 +3068,7 @@ error:
                        rx_pg->page = NULL;
 
                        err = bnx2_alloc_rx_page(bp, rxr,
-                                                RX_PG_RING_IDX(pg_prod),
+                                                BNX2_RX_PG_RING_IDX(pg_prod),
                                                 GFP_ATOMIC);
                        if (unlikely(err)) {
                                rxr->rx_pg_cons = pg_cons;
@@ -3083,8 +3086,8 @@ error:
                        skb->truesize += PAGE_SIZE;
                        skb->len += frag_len;
 
-                       pg_prod = NEXT_RX_BD(pg_prod);
-                       pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons));
+                       pg_prod = BNX2_NEXT_RX_BD(pg_prod);
+                       pg_cons = BNX2_RX_PG_RING_IDX(BNX2_NEXT_RX_BD(pg_cons));
                }
                rxr->rx_pg_prod = pg_prod;
                rxr->rx_pg_cons = pg_cons;
@@ -3101,7 +3104,7 @@ bnx2_get_hw_rx_cons(struct bnx2_napi *bnapi)
        barrier();
        cons = *bnapi->hw_rx_cons_ptr;
        barrier();
-       if (unlikely((cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT))
+       if (unlikely((cons & BNX2_MAX_RX_DESC_CNT) == BNX2_MAX_RX_DESC_CNT))
                cons++;
        return cons;
 }
@@ -3125,13 +3128,14 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
        while (sw_cons != hw_cons) {
                unsigned int len, hdr_len;
                u32 status;
-               struct sw_bd *rx_buf, *next_rx_buf;
+               struct bnx2_sw_bd *rx_buf, *next_rx_buf;
                struct sk_buff *skb;
                dma_addr_t dma_addr;
                u8 *data;
+               u16 next_ring_idx;
 
-               sw_ring_cons = RX_RING_IDX(sw_cons);
-               sw_ring_prod = RX_RING_IDX(sw_prod);
+               sw_ring_cons = BNX2_RX_RING_IDX(sw_cons);
+               sw_ring_prod = BNX2_RX_RING_IDX(sw_prod);
 
                rx_buf = &rxr->rx_buf_ring[sw_ring_cons];
                data = rx_buf->data;
@@ -3146,8 +3150,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                        BNX2_RX_OFFSET + BNX2_RX_COPY_THRESH,
                        PCI_DMA_FROMDEVICE);
 
-               next_rx_buf =
-                       &rxr->rx_buf_ring[RX_RING_IDX(NEXT_RX_BD(sw_cons))];
+               next_ring_idx = BNX2_RX_RING_IDX(BNX2_NEXT_RX_BD(sw_cons));
+               next_rx_buf = &rxr->rx_buf_ring[next_ring_idx];
                prefetch(get_l2_fhdr(next_rx_buf->data));
 
                len = rx_hdr->l2_fhdr_pkt_len;
@@ -3239,8 +3243,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
                rx_pkt++;
 
 next_rx:
-               sw_cons = NEXT_RX_BD(sw_cons);
-               sw_prod = NEXT_RX_BD(sw_prod);
+               sw_cons = BNX2_NEXT_RX_BD(sw_cons);
+               sw_prod = BNX2_NEXT_RX_BD(sw_prod);
 
                if ((rx_pkt == budget))
                        break;
@@ -3255,11 +3259,11 @@ next_rx:
        rxr->rx_prod = sw_prod;
 
        if (pg_ring_used)
-               REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
+               BNX2_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
 
-       REG_WR16(bp, rxr->rx_bidx_addr, sw_prod);
+       BNX2_WR16(bp, rxr->rx_bidx_addr, sw_prod);
 
-       REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
+       BNX2_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
 
        mmiowb();
 
@@ -3277,7 +3281,7 @@ bnx2_msi(int irq, void *dev_instance)
        struct bnx2 *bp = bnapi->bp;
 
        prefetch(bnapi->status_blk.msi);
-       REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+       BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
                BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
 
@@ -3321,18 +3325,18 @@ bnx2_interrupt(int irq, void *dev_instance)
         * the status block write.
         */
        if ((sblk->status_idx == bnapi->last_status_idx) &&
-           (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
+           (BNX2_RD(bp, BNX2_PCICFG_MISC_STATUS) &
             BNX2_PCICFG_MISC_STATUS_INTA_VALUE))
                return IRQ_NONE;
 
-       REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+       BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
                BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
                BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
 
        /* Read back to deassert IRQ immediately to avoid too many
         * spurious interrupts.
         */
-       REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
+       BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
 
        /* Return here if interrupt is shared and is disabled. */
        if (unlikely(atomic_read(&bp->intr_sem) != 0))
@@ -3388,14 +3392,14 @@ bnx2_chk_missed_msi(struct bnx2 *bp)
        u32 msi_ctrl;
 
        if (bnx2_has_work(bnapi)) {
-               msi_ctrl = REG_RD(bp, BNX2_PCICFG_MSI_CONTROL);
+               msi_ctrl = BNX2_RD(bp, BNX2_PCICFG_MSI_CONTROL);
                if (!(msi_ctrl & BNX2_PCICFG_MSI_CONTROL_ENABLE))
                        return;
 
                if (bnapi->last_status_idx == bp->idle_chk_status_idx) {
-                       REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl &
-                              ~BNX2_PCICFG_MSI_CONTROL_ENABLE);
-                       REG_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl);
+                       BNX2_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl &
+                               ~BNX2_PCICFG_MSI_CONTROL_ENABLE);
+                       BNX2_WR(bp, BNX2_PCICFG_MSI_CONTROL, msi_ctrl);
                        bnx2_msi(bp->irq_tbl[0].vector, bnapi);
                }
        }
@@ -3434,9 +3438,9 @@ static void bnx2_poll_link(struct bnx2 *bp, struct bnx2_napi *bnapi)
                /* This is needed to take care of transient status
                 * during link changes.
                 */
-               REG_WR(bp, BNX2_HC_COMMAND,
-                      bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
-               REG_RD(bp, BNX2_HC_COMMAND);
+               BNX2_WR(bp, BNX2_HC_COMMAND,
+                       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+               BNX2_RD(bp, BNX2_HC_COMMAND);
        }
 }
 
@@ -3473,9 +3477,9 @@ static int bnx2_poll_msix(struct napi_struct *napi, int budget)
                if (likely(!bnx2_has_fast_work(bnapi))) {
 
                        napi_complete(napi);
-                       REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
-                              BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-                              bnapi->last_status_idx);
+                       BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
+                               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                               bnapi->last_status_idx);
                        break;
                }
        }
@@ -3511,19 +3515,19 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
                if (likely(!bnx2_has_work(bnapi))) {
                        napi_complete(napi);
                        if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) {
-                               REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-                                      BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-                                      bnapi->last_status_idx);
+                               BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+                                       BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                                       bnapi->last_status_idx);
                                break;
                        }
-                       REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-                              BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-                              BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
-                              bnapi->last_status_idx);
-
-                       REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
-                              BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
-                              bnapi->last_status_idx);
+                       BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+                               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                               BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
+                               bnapi->last_status_idx);
+
+                       BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
+                               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
+                               bnapi->last_status_idx);
                        break;
                }
        }
@@ -3561,8 +3565,8 @@ bnx2_set_rx_mode(struct net_device *dev)
        }
        else if (dev->flags & IFF_ALLMULTI) {
                for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
-                       REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
-                              0xffffffff);
+                       BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+                               0xffffffff);
                }
                sort_mode |= BNX2_RPM_SORT_USER0_MC_EN;
        }
@@ -3584,8 +3588,8 @@ bnx2_set_rx_mode(struct net_device *dev)
                }
 
                for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
-                       REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
-                              mc_filter[i]);
+                       BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+                               mc_filter[i]);
                }
 
                sort_mode |= BNX2_RPM_SORT_USER0_MC_HSH_EN;
@@ -3610,12 +3614,12 @@ bnx2_set_rx_mode(struct net_device *dev)
 
        if (rx_mode != bp->rx_mode) {
                bp->rx_mode = rx_mode;
-               REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
+               BNX2_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
        }
 
-       REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
-       REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
-       REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
+       BNX2_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+       BNX2_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
+       BNX2_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
 
        spin_unlock_bh(&bp->phy_lock);
 }
@@ -3663,10 +3667,10 @@ static int bnx2_request_uncached_firmware(struct bnx2 *bp)
        const struct bnx2_rv2p_fw_file *rv2p_fw;
        int rc;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                mips_fw_file = FW_MIPS_FILE_09;
-               if ((CHIP_ID(bp) == CHIP_ID_5709_A0) ||
-                   (CHIP_ID(bp) == CHIP_ID_5709_A1))
+               if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5709_A0) ||
+                   (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5709_A1))
                        rv2p_fw_file = FW_RV2P_FILE_09_Ax;
                else
                        rv2p_fw_file = FW_RV2P_FILE_09;
@@ -3756,13 +3760,13 @@ load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
        }
 
        for (i = 0; i < rv2p_code_len; i += 8) {
-               REG_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code));
+               BNX2_WR(bp, BNX2_RV2P_INSTR_HIGH, be32_to_cpu(*rv2p_code));
                rv2p_code++;
-               REG_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code));
+               BNX2_WR(bp, BNX2_RV2P_INSTR_LOW, be32_to_cpu(*rv2p_code));
                rv2p_code++;
 
                val = (i / 8) | cmd;
-               REG_WR(bp, addr, val);
+               BNX2_WR(bp, addr, val);
        }
 
        rv2p_code = (__be32 *)(bp->rv2p_firmware->data + file_offset);
@@ -3772,22 +3776,22 @@ load_rv2p_fw(struct bnx2 *bp, u32 rv2p_proc,
                loc = be32_to_cpu(fw_entry->fixup[i]);
                if (loc && ((loc * 4) < rv2p_code_len)) {
                        code = be32_to_cpu(*(rv2p_code + loc - 1));
-                       REG_WR(bp, BNX2_RV2P_INSTR_HIGH, code);
+                       BNX2_WR(bp, BNX2_RV2P_INSTR_HIGH, code);
                        code = be32_to_cpu(*(rv2p_code + loc));
                        code = rv2p_fw_fixup(rv2p_proc, i, loc, code);
-                       REG_WR(bp, BNX2_RV2P_INSTR_LOW, code);
+                       BNX2_WR(bp, BNX2_RV2P_INSTR_LOW, code);
 
                        val = (loc / 2) | cmd;
-                       REG_WR(bp, addr, val);
+                       BNX2_WR(bp, addr, val);
                }
        }
 
        /* Reset the processor, un-stall is done later. */
        if (rv2p_proc == RV2P_PROC1) {
-               REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
+               BNX2_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
        }
        else {
-               REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
+               BNX2_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
        }
 
        return 0;
@@ -3924,14 +3928,14 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
                        /* delay required during transition out of D3hot */
                        msleep(20);
 
-               val = REG_RD(bp, BNX2_EMAC_MODE);
+               val = BNX2_RD(bp, BNX2_EMAC_MODE);
                val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
                val &= ~BNX2_EMAC_MODE_MPKT;
-               REG_WR(bp, BNX2_EMAC_MODE, val);
+               BNX2_WR(bp, BNX2_EMAC_MODE, val);
 
-               val = REG_RD(bp, BNX2_RPM_CONFIG);
+               val = BNX2_RD(bp, BNX2_RPM_CONFIG);
                val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
-               REG_WR(bp, BNX2_RPM_CONFIG, val);
+               BNX2_WR(bp, BNX2_RPM_CONFIG, val);
                break;
        }
        case PCI_D3hot: {
@@ -3963,7 +3967,7 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
 
                        bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
 
-                       val = REG_RD(bp, BNX2_EMAC_MODE);
+                       val = BNX2_RD(bp, BNX2_EMAC_MODE);
 
                        /* Enable port mode. */
                        val &= ~BNX2_EMAC_MODE_PORT;
@@ -3978,32 +3982,32 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
                                        val |= BNX2_EMAC_MODE_25G_MODE;
                        }
 
-                       REG_WR(bp, BNX2_EMAC_MODE, val);
+                       BNX2_WR(bp, BNX2_EMAC_MODE, val);
 
                        /* receive all multicast */
                        for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
-                               REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
-                                      0xffffffff);
+                               BNX2_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
+                                       0xffffffff);
                        }
-                       REG_WR(bp, BNX2_EMAC_RX_MODE,
-                              BNX2_EMAC_RX_MODE_SORT_MODE);
+                       BNX2_WR(bp, BNX2_EMAC_RX_MODE,
+                               BNX2_EMAC_RX_MODE_SORT_MODE);
 
                        val = 1 | BNX2_RPM_SORT_USER0_BC_EN |
                              BNX2_RPM_SORT_USER0_MC_EN;
-                       REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
-                       REG_WR(bp, BNX2_RPM_SORT_USER0, val);
-                       REG_WR(bp, BNX2_RPM_SORT_USER0, val |
-                              BNX2_RPM_SORT_USER0_ENA);
+                       BNX2_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
+                       BNX2_WR(bp, BNX2_RPM_SORT_USER0, val);
+                       BNX2_WR(bp, BNX2_RPM_SORT_USER0, val |
+                               BNX2_RPM_SORT_USER0_ENA);
 
                        /* Need to enable EMAC and RPM for WOL. */
-                       REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
-                              BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
-                              BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
-                              BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
+                       BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+                               BNX2_MISC_ENABLE_SET_BITS_RX_PARSER_MAC_ENABLE |
+                               BNX2_MISC_ENABLE_SET_BITS_TX_HEADER_Q_ENABLE |
+                               BNX2_MISC_ENABLE_SET_BITS_EMAC_ENABLE);
 
-                       val = REG_RD(bp, BNX2_RPM_CONFIG);
+                       val = BNX2_RD(bp, BNX2_RPM_CONFIG);
                        val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
-                       REG_WR(bp, BNX2_RPM_CONFIG, val);
+                       BNX2_WR(bp, BNX2_RPM_CONFIG, val);
 
                        wol_msg = BNX2_DRV_MSG_CODE_SUSPEND_WOL;
                }
@@ -4016,8 +4020,8 @@ bnx2_set_power_state(struct bnx2 *bp, pci_power_t state)
                                     1, 0);
 
                pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
-               if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
-                   (CHIP_ID(bp) == CHIP_ID_5706_A1)) {
+               if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) ||
+                   (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1)) {
 
                        if (bp->wol)
                                pmcsr |= 3;
@@ -4050,9 +4054,9 @@ bnx2_acquire_nvram_lock(struct bnx2 *bp)
        int j;
 
        /* Request access to the flash interface. */
-       REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2);
+       BNX2_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_SET2);
        for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
-               val = REG_RD(bp, BNX2_NVM_SW_ARB);
+               val = BNX2_RD(bp, BNX2_NVM_SW_ARB);
                if (val & BNX2_NVM_SW_ARB_ARB_ARB2)
                        break;
 
@@ -4072,10 +4076,10 @@ bnx2_release_nvram_lock(struct bnx2 *bp)
        u32 val;
 
        /* Relinquish nvram interface. */
-       REG_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2);
+       BNX2_WR(bp, BNX2_NVM_SW_ARB, BNX2_NVM_SW_ARB_ARB_REQ_CLR2);
 
        for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
-               val = REG_RD(bp, BNX2_NVM_SW_ARB);
+               val = BNX2_RD(bp, BNX2_NVM_SW_ARB);
                if (!(val & BNX2_NVM_SW_ARB_ARB_ARB2))
                        break;
 
@@ -4094,20 +4098,20 @@ bnx2_enable_nvram_write(struct bnx2 *bp)
 {
        u32 val;
 
-       val = REG_RD(bp, BNX2_MISC_CFG);
-       REG_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI);
+       val = BNX2_RD(bp, BNX2_MISC_CFG);
+       BNX2_WR(bp, BNX2_MISC_CFG, val | BNX2_MISC_CFG_NVM_WR_EN_PCI);
 
        if (bp->flash_info->flags & BNX2_NV_WREN) {
                int j;
 
-               REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
-               REG_WR(bp, BNX2_NVM_COMMAND,
-                      BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT);
+               BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+               BNX2_WR(bp, BNX2_NVM_COMMAND,
+                       BNX2_NVM_COMMAND_WREN | BNX2_NVM_COMMAND_DOIT);
 
                for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
                        udelay(5);
 
-                       val = REG_RD(bp, BNX2_NVM_COMMAND);
+                       val = BNX2_RD(bp, BNX2_NVM_COMMAND);
                        if (val & BNX2_NVM_COMMAND_DONE)
                                break;
                }
@@ -4123,8 +4127,8 @@ bnx2_disable_nvram_write(struct bnx2 *bp)
 {
        u32 val;
 
-       val = REG_RD(bp, BNX2_MISC_CFG);
-       REG_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN);
+       val = BNX2_RD(bp, BNX2_MISC_CFG);
+       BNX2_WR(bp, BNX2_MISC_CFG, val & ~BNX2_MISC_CFG_NVM_WR_EN);
 }
 
 
@@ -4133,10 +4137,10 @@ bnx2_enable_nvram_access(struct bnx2 *bp)
 {
        u32 val;
 
-       val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+       val = BNX2_RD(bp, BNX2_NVM_ACCESS_ENABLE);
        /* Enable both bits, even on read. */
-       REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
-              val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
+       BNX2_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+               val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
 }
 
 static void
@@ -4144,9 +4148,9 @@ bnx2_disable_nvram_access(struct bnx2 *bp)
 {
        u32 val;
 
-       val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
+       val = BNX2_RD(bp, BNX2_NVM_ACCESS_ENABLE);
        /* Disable both bits, even after read. */
-       REG_WR(bp, BNX2_NVM_ACCESS_ENABLE,
+       BNX2_WR(bp, BNX2_NVM_ACCESS_ENABLE,
                val & ~(BNX2_NVM_ACCESS_ENABLE_EN |
                        BNX2_NVM_ACCESS_ENABLE_WR_EN));
 }
@@ -4166,13 +4170,13 @@ bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset)
              BNX2_NVM_COMMAND_DOIT;
 
        /* Need to clear DONE bit separately. */
-       REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+       BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
 
        /* Address of the NVRAM to read from. */
-       REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+       BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
 
        /* Issue an erase command. */
-       REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+       BNX2_WR(bp, BNX2_NVM_COMMAND, cmd);
 
        /* Wait for completion. */
        for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
@@ -4180,7 +4184,7 @@ bnx2_nvram_erase_page(struct bnx2 *bp, u32 offset)
 
                udelay(5);
 
-               val = REG_RD(bp, BNX2_NVM_COMMAND);
+               val = BNX2_RD(bp, BNX2_NVM_COMMAND);
                if (val & BNX2_NVM_COMMAND_DONE)
                        break;
        }
@@ -4208,13 +4212,13 @@ bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags)
        }
 
        /* Need to clear DONE bit separately. */
-       REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+       BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
 
        /* Address of the NVRAM to read from. */
-       REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+       BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
 
        /* Issue a read command. */
-       REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+       BNX2_WR(bp, BNX2_NVM_COMMAND, cmd);
 
        /* Wait for completion. */
        for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
@@ -4222,9 +4226,9 @@ bnx2_nvram_read_dword(struct bnx2 *bp, u32 offset, u8 *ret_val, u32 cmd_flags)
 
                udelay(5);
 
-               val = REG_RD(bp, BNX2_NVM_COMMAND);
+               val = BNX2_RD(bp, BNX2_NVM_COMMAND);
                if (val & BNX2_NVM_COMMAND_DONE) {
-                       __be32 v = cpu_to_be32(REG_RD(bp, BNX2_NVM_READ));
+                       __be32 v = cpu_to_be32(BNX2_RD(bp, BNX2_NVM_READ));
                        memcpy(ret_val, &v, 4);
                        break;
                }
@@ -4254,24 +4258,24 @@ bnx2_nvram_write_dword(struct bnx2 *bp, u32 offset, u8 *val, u32 cmd_flags)
        }
 
        /* Need to clear DONE bit separately. */
-       REG_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
+       BNX2_WR(bp, BNX2_NVM_COMMAND, BNX2_NVM_COMMAND_DONE);
 
        memcpy(&val32, val, 4);
 
        /* Write the data. */
-       REG_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32));
+       BNX2_WR(bp, BNX2_NVM_WRITE, be32_to_cpu(val32));
 
        /* Address of the NVRAM to write to. */
-       REG_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
+       BNX2_WR(bp, BNX2_NVM_ADDR, offset & BNX2_NVM_ADDR_NVM_ADDR_VALUE);
 
        /* Issue the write command. */
-       REG_WR(bp, BNX2_NVM_COMMAND, cmd);
+       BNX2_WR(bp, BNX2_NVM_COMMAND, cmd);
 
        /* Wait for completion. */
        for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
                udelay(5);
 
-               if (REG_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE)
+               if (BNX2_RD(bp, BNX2_NVM_COMMAND) & BNX2_NVM_COMMAND_DONE)
                        break;
        }
        if (j >= NVRAM_TIMEOUT_COUNT)
@@ -4287,13 +4291,13 @@ bnx2_init_nvram(struct bnx2 *bp)
        int j, entry_count, rc = 0;
        const struct flash_spec *flash;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                bp->flash_info = &flash_5709;
                goto get_flash_size;
        }
 
        /* Determine the selected interface. */
-       val = REG_RD(bp, BNX2_NVM_CFG1);
+       val = BNX2_RD(bp, BNX2_NVM_CFG1);
 
        entry_count = ARRAY_SIZE(flash_table);
 
@@ -4332,10 +4336,10 @@ bnx2_init_nvram(struct bnx2 *bp)
                                bnx2_enable_nvram_access(bp);
 
                                /* Reconfigure the flash interface */
-                               REG_WR(bp, BNX2_NVM_CFG1, flash->config1);
-                               REG_WR(bp, BNX2_NVM_CFG2, flash->config2);
-                               REG_WR(bp, BNX2_NVM_CFG3, flash->config3);
-                               REG_WR(bp, BNX2_NVM_WRITE1, flash->write1);
+                               BNX2_WR(bp, BNX2_NVM_CFG1, flash->config1);
+                               BNX2_WR(bp, BNX2_NVM_CFG2, flash->config2);
+                               BNX2_WR(bp, BNX2_NVM_CFG3, flash->config3);
+                               BNX2_WR(bp, BNX2_NVM_WRITE1, flash->write1);
 
                                /* Disable access to flash interface */
                                bnx2_disable_nvram_access(bp);
@@ -4696,10 +4700,10 @@ bnx2_init_fw_cap(struct bnx2 *bp)
 static void
 bnx2_setup_msix_tbl(struct bnx2 *bp)
 {
-       REG_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN);
+       BNX2_WR(bp, BNX2_PCI_GRC_WINDOW_ADDR, BNX2_PCI_GRC_WINDOW_ADDR_SEP_WIN);
 
-       REG_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR);
-       REG_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR);
+       BNX2_WR(bp, BNX2_PCI_GRC_WINDOW2_ADDR, BNX2_MSIX_TABLE_ADDR);
+       BNX2_WR(bp, BNX2_PCI_GRC_WINDOW3_ADDR, BNX2_MSIX_PBA_ADDR);
 }
 
 static int
@@ -4711,24 +4715,24 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
 
        /* Wait for the current PCI transaction to complete before
         * issuing a reset. */
-       if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
-           (CHIP_NUM(bp) == CHIP_NUM_5708)) {
-               REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
-                      BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
-                      BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
-                      BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
-                      BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
-               val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
+       if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) ||
+           (BNX2_CHIP(bp) == BNX2_CHIP_5708)) {
+               BNX2_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
+                       BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
+                       BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
+                       BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
+                       BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
+               val = BNX2_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
                udelay(5);
        } else {  /* 5709 */
-               val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+               val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL);
                val &= ~BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
-               REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
-               val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+               BNX2_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+               val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL);
 
                for (i = 0; i < 100; i++) {
                        msleep(1);
-                       val = REG_RD(bp, BNX2_PCICFG_DEVICE_CONTROL);
+                       val = BNX2_RD(bp, BNX2_PCICFG_DEVICE_CONTROL);
                        if (!(val & BNX2_PCICFG_DEVICE_STATUS_NO_PEND))
                                break;
                }
@@ -4744,17 +4748,17 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
 
        /* Do a dummy read to force the chip to complete all current transaction
         * before we issue a reset. */
-       val = REG_RD(bp, BNX2_MISC_ID);
+       val = BNX2_RD(bp, BNX2_MISC_ID);
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-               REG_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET);
-               REG_RD(bp, BNX2_MISC_COMMAND);
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+               BNX2_WR(bp, BNX2_MISC_COMMAND, BNX2_MISC_COMMAND_SW_RESET);
+               BNX2_RD(bp, BNX2_MISC_COMMAND);
                udelay(5);
 
                val = BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
                      BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
 
-               REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+               BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
 
        } else {
                val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
@@ -4762,19 +4766,19 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
                      BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
 
                /* Chip reset. */
-               REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
+               BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
 
                /* Reading back any register after chip reset will hang the
                 * bus on 5706 A0 and A1.  The msleep below provides plenty
                 * of margin for write posting.
                 */
-               if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
-                   (CHIP_ID(bp) == CHIP_ID_5706_A1))
+               if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) ||
+                   (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1))
                        msleep(20);
 
                /* Reset takes approximate 30 usec */
                for (i = 0; i < 10; i++) {
-                       val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
+                       val = BNX2_RD(bp, BNX2_PCICFG_MISC_CONFIG);
                        if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
                                    BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0)
                                break;
@@ -4789,7 +4793,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
        }
 
        /* Make sure byte swapping is properly configured. */
-       val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
+       val = BNX2_RD(bp, BNX2_PCI_SWAP_DIAG0);
        if (val != 0x01020304) {
                pr_err("Chip not in correct endian mode\n");
                return -ENODEV;
@@ -4808,10 +4812,10 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
                bnx2_set_default_remote_link(bp);
        spin_unlock_bh(&bp->phy_lock);
 
-       if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+       if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
                /* Adjust the voltage regular to two steps lower.  The default
                 * of this register is 0x0000000e. */
-               REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
+               BNX2_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
 
                /* Remove bad rbuf memory from the free pool. */
                rc = bnx2_alloc_bad_rbuf(bp);
@@ -4820,7 +4824,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
        if (bp->flags & BNX2_FLAG_USING_MSIX) {
                bnx2_setup_msix_tbl(bp);
                /* Prevent MSIX table reads and write from timing out */
-               REG_WR(bp, BNX2_MISC_ECO_HW_CTL,
+               BNX2_WR(bp, BNX2_MISC_ECO_HW_CTL,
                        BNX2_MISC_ECO_HW_CTL_LARGE_GRC_TMOUT_EN);
        }
 
@@ -4834,7 +4838,7 @@ bnx2_init_chip(struct bnx2 *bp)
        int rc, i;
 
        /* Make sure the interrupt is not active. */
-       REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
+       BNX2_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
 
        val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP |
              BNX2_DMA_CONFIG_DATA_WORD_SWAP |
@@ -4850,16 +4854,17 @@ bnx2_init_chip(struct bnx2 *bp)
        if ((bp->flags & BNX2_FLAG_PCIX) && (bp->bus_speed_mhz == 133))
                val |= (1 << 23);
 
-       if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
-           (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & BNX2_FLAG_PCIX))
+       if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) &&
+           (BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A0) &&
+           !(bp->flags & BNX2_FLAG_PCIX))
                val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA;
 
-       REG_WR(bp, BNX2_DMA_CONFIG, val);
+       BNX2_WR(bp, BNX2_DMA_CONFIG, val);
 
-       if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
-               val = REG_RD(bp, BNX2_TDMA_CONFIG);
+       if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
+               val = BNX2_RD(bp, BNX2_TDMA_CONFIG);
                val |= BNX2_TDMA_CONFIG_ONE_DMA;
-               REG_WR(bp, BNX2_TDMA_CONFIG, val);
+               BNX2_WR(bp, BNX2_TDMA_CONFIG, val);
        }
 
        if (bp->flags & BNX2_FLAG_PCIX) {
@@ -4871,14 +4876,14 @@ bnx2_init_chip(struct bnx2 *bp)
                                      val16 & ~PCI_X_CMD_ERO);
        }
 
-       REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
-              BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
-              BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
-              BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
+       BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
+               BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
+               BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
+               BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
 
        /* Initialize context mapping and zero out the quick contexts.  The
         * context block must have already been enabled. */
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                rc = bnx2_init_5709_context(bp);
                if (rc)
                        return rc;
@@ -4892,29 +4897,29 @@ bnx2_init_chip(struct bnx2 *bp)
 
        bnx2_set_mac_addr(bp, bp->dev->dev_addr, 0);
 
-       val = REG_RD(bp, BNX2_MQ_CONFIG);
+       val = BNX2_RD(bp, BNX2_MQ_CONFIG);
        val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
        val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                val |= BNX2_MQ_CONFIG_BIN_MQ_MODE;
-               if (CHIP_REV(bp) == CHIP_REV_Ax)
+               if (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax)
                        val |= BNX2_MQ_CONFIG_HALT_DIS;
        }
 
-       REG_WR(bp, BNX2_MQ_CONFIG, val);
+       BNX2_WR(bp, BNX2_MQ_CONFIG, val);
 
        val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
-       REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
-       REG_WR(bp, BNX2_MQ_KNL_WIND_END, val);
+       BNX2_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
+       BNX2_WR(bp, BNX2_MQ_KNL_WIND_END, val);
 
-       val = (BCM_PAGE_BITS - 8) << 24;
-       REG_WR(bp, BNX2_RV2P_CONFIG, val);
+       val = (BNX2_PAGE_BITS - 8) << 24;
+       BNX2_WR(bp, BNX2_RV2P_CONFIG, val);
 
        /* Configure page size. */
-       val = REG_RD(bp, BNX2_TBDR_CONFIG);
+       val = BNX2_RD(bp, BNX2_TBDR_CONFIG);
        val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE;
-       val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
-       REG_WR(bp, BNX2_TBDR_CONFIG, val);
+       val |= (BNX2_PAGE_BITS - 8) << 24 | 0x40;
+       BNX2_WR(bp, BNX2_TBDR_CONFIG, val);
 
        val = bp->mac_addr[0] +
              (bp->mac_addr[1] << 8) +
@@ -4922,14 +4927,14 @@ bnx2_init_chip(struct bnx2 *bp)
              bp->mac_addr[3] +
              (bp->mac_addr[4] << 8) +
              (bp->mac_addr[5] << 16);
-       REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
+       BNX2_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
 
        /* Program the MTU.  Also include 4 bytes for CRC32. */
        mtu = bp->dev->mtu;
        val = mtu + ETH_HLEN + ETH_FCS_LEN;
        if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
                val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
-       REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
+       BNX2_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
 
        if (mtu < 1500)
                mtu = 1500;
@@ -4947,43 +4952,43 @@ bnx2_init_chip(struct bnx2 *bp)
        bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
 
        /* Set up how to generate a link change interrupt. */
-       REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
+       BNX2_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
 
-       REG_WR(bp, BNX2_HC_STATUS_ADDR_L,
-              (u64) bp->status_blk_mapping & 0xffffffff);
-       REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
+       BNX2_WR(bp, BNX2_HC_STATUS_ADDR_L,
+               (u64) bp->status_blk_mapping & 0xffffffff);
+       BNX2_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
 
-       REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
-              (u64) bp->stats_blk_mapping & 0xffffffff);
-       REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
-              (u64) bp->stats_blk_mapping >> 32);
+       BNX2_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
+               (u64) bp->stats_blk_mapping & 0xffffffff);
+       BNX2_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
+               (u64) bp->stats_blk_mapping >> 32);
 
-       REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
-              (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
+       BNX2_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP,
+               (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
 
-       REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
-              (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
+       BNX2_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
+               (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
 
-       REG_WR(bp, BNX2_HC_COMP_PROD_TRIP,
-              (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
+       BNX2_WR(bp, BNX2_HC_COMP_PROD_TRIP,
+               (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
 
-       REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
+       BNX2_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
 
-       REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
+       BNX2_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
 
-       REG_WR(bp, BNX2_HC_COM_TICKS,
-              (bp->com_ticks_int << 16) | bp->com_ticks);
+       BNX2_WR(bp, BNX2_HC_COM_TICKS,
+               (bp->com_ticks_int << 16) | bp->com_ticks);
 
-       REG_WR(bp, BNX2_HC_CMD_TICKS,
-              (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
+       BNX2_WR(bp, BNX2_HC_CMD_TICKS,
+               (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
 
        if (bp->flags & BNX2_FLAG_BROKEN_STATS)
-               REG_WR(bp, BNX2_HC_STATS_TICKS, 0);
+               BNX2_WR(bp, BNX2_HC_STATS_TICKS, 0);
        else
-               REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks);
-       REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */
+               BNX2_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks);
+       BNX2_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */
 
-       if (CHIP_ID(bp) == CHIP_ID_5706_A1)
+       if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1)
                val = BNX2_HC_CONFIG_COLLECT_STATS;
        else {
                val = BNX2_HC_CONFIG_RX_TMR_MODE | BNX2_HC_CONFIG_TX_TMR_MODE |
@@ -4991,8 +4996,8 @@ bnx2_init_chip(struct bnx2 *bp)
        }
 
        if (bp->flags & BNX2_FLAG_USING_MSIX) {
-               REG_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
-                      BNX2_HC_MSIX_BIT_VECTOR_VAL);
+               BNX2_WR(bp, BNX2_HC_MSIX_BIT_VECTOR,
+                       BNX2_HC_MSIX_BIT_VECTOR_VAL);
 
                val |= BNX2_HC_CONFIG_SB_ADDR_INC_128B;
        }
@@ -5000,7 +5005,7 @@ bnx2_init_chip(struct bnx2 *bp)
        if (bp->flags & BNX2_FLAG_ONE_SHOT_MSI)
                val |= BNX2_HC_CONFIG_ONE_SHOT | BNX2_HC_CONFIG_USE_INT_PARAM;
 
-       REG_WR(bp, BNX2_HC_CONFIG, val);
+       BNX2_WR(bp, BNX2_HC_CONFIG, val);
 
        if (bp->rx_ticks < 25)
                bnx2_reg_wr_ind(bp, BNX2_FW_RX_LOW_LATENCY, 1);
@@ -5011,48 +5016,48 @@ bnx2_init_chip(struct bnx2 *bp)
                u32 base = ((i - 1) * BNX2_HC_SB_CONFIG_SIZE) +
                           BNX2_HC_SB_CONFIG_1;
 
-               REG_WR(bp, base,
+               BNX2_WR(bp, base,
                        BNX2_HC_SB_CONFIG_1_TX_TMR_MODE |
                        BNX2_HC_SB_CONFIG_1_RX_TMR_MODE |
                        BNX2_HC_SB_CONFIG_1_ONE_SHOT);
 
-               REG_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF,
+               BNX2_WR(bp, base + BNX2_HC_TX_QUICK_CONS_TRIP_OFF,
                        (bp->tx_quick_cons_trip_int << 16) |
                         bp->tx_quick_cons_trip);
 
-               REG_WR(bp, base + BNX2_HC_TX_TICKS_OFF,
+               BNX2_WR(bp, base + BNX2_HC_TX_TICKS_OFF,
                        (bp->tx_ticks_int << 16) | bp->tx_ticks);
 
-               REG_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF,
-                      (bp->rx_quick_cons_trip_int << 16) |
+               BNX2_WR(bp, base + BNX2_HC_RX_QUICK_CONS_TRIP_OFF,
+                       (bp->rx_quick_cons_trip_int << 16) |
                        bp->rx_quick_cons_trip);
 
-               REG_WR(bp, base + BNX2_HC_RX_TICKS_OFF,
+               BNX2_WR(bp, base + BNX2_HC_RX_TICKS_OFF,
                        (bp->rx_ticks_int << 16) | bp->rx_ticks);
        }
 
        /* Clear internal stats counters. */
-       REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
+       BNX2_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
 
-       REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS);
+       BNX2_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_EVENTS);
 
        /* Initialize the receive filter. */
        bnx2_set_rx_mode(bp->dev);
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-               val = REG_RD(bp, BNX2_MISC_NEW_CORE_CTL);
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+               val = BNX2_RD(bp, BNX2_MISC_NEW_CORE_CTL);
                val |= BNX2_MISC_NEW_CORE_CTL_DMA_ENABLE;
-               REG_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
+               BNX2_WR(bp, BNX2_MISC_NEW_CORE_CTL, val);
        }
        rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
                          1, 0);
 
-       REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
-       REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
+       BNX2_WR(bp, BNX2_MISC_ENABLE_SET_BITS, BNX2_MISC_ENABLE_DEFAULT);
+       BNX2_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
 
        udelay(20);
 
-       bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
+       bp->hc_cmd = BNX2_RD(bp, BNX2_HC_COMMAND);
 
        return rc;
 }
@@ -5086,7 +5091,7 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr)
        u32 val, offset0, offset1, offset2, offset3;
        u32 cid_addr = GET_CID_ADDR(cid);
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                offset0 = BNX2_L2CTX_TYPE_XI;
                offset1 = BNX2_L2CTX_CMD_TYPE_XI;
                offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI;
@@ -5113,7 +5118,7 @@ bnx2_init_tx_context(struct bnx2 *bp, u32 cid, struct bnx2_tx_ring_info *txr)
 static void
 bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
 {
-       struct tx_bd *txbd;
+       struct bnx2_tx_bd *txbd;
        u32 cid = TX_CID;
        struct bnx2_napi *bnapi;
        struct bnx2_tx_ring_info *txr;
@@ -5128,7 +5133,7 @@ bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
 
        bp->tx_wake_thresh = bp->tx_ring_size / 2;
 
-       txbd = &txr->tx_desc_ring[MAX_TX_DESC_CNT];
+       txbd = &txr->tx_desc_ring[BNX2_MAX_TX_DESC_CNT];
 
        txbd->tx_bd_haddr_hi = (u64) txr->tx_desc_mapping >> 32;
        txbd->tx_bd_haddr_lo = (u64) txr->tx_desc_mapping & 0xffffffff;
@@ -5143,17 +5148,17 @@ bnx2_init_tx_ring(struct bnx2 *bp, int ring_num)
 }
 
 static void
-bnx2_init_rxbd_rings(struct rx_bd *rx_ring[], dma_addr_t dma[], u32 buf_size,
-                    int num_rings)
+bnx2_init_rxbd_rings(struct bnx2_rx_bd *rx_ring[], dma_addr_t dma[],
+                    u32 buf_size, int num_rings)
 {
        int i;
-       struct rx_bd *rxbd;
+       struct bnx2_rx_bd *rxbd;
 
        for (i = 0; i < num_rings; i++) {
                int j;
 
                rxbd = &rx_ring[i][0];
-               for (j = 0; j < MAX_RX_DESC_CNT; j++, rxbd++) {
+               for (j = 0; j < BNX2_MAX_RX_DESC_CNT; j++, rxbd++) {
                        rxbd->rx_bd_len = buf_size;
                        rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
                }
@@ -5187,9 +5192,9 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
 
        bnx2_init_rx_context(bp, cid);
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
-               val = REG_RD(bp, BNX2_MQ_MAP_L2_5);
-               REG_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM);
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
+               val = BNX2_RD(bp, BNX2_MQ_MAP_L2_5);
+               BNX2_WR(bp, BNX2_MQ_MAP_L2_5, val | BNX2_MQ_MAP_L2_5_ARM);
        }
 
        bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_PG_BUF_SIZE, 0);
@@ -5208,8 +5213,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
                val = (u64) rxr->rx_pg_desc_mapping[0] & 0xffffffff;
                bnx2_ctx_wr(bp, rx_cid_addr, BNX2_L2CTX_NX_PG_BDHADDR_LO, val);
 
-               if (CHIP_NUM(bp) == CHIP_NUM_5709)
-                       REG_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
+               if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
+                       BNX2_WR(bp, BNX2_MQ_MAP_L2_3, BNX2_MQ_MAP_L2_3_DEFAULT);
        }
 
        val = (u64) rxr->rx_desc_mapping[0] >> 32;
@@ -5225,8 +5230,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
                                    ring_num, i, bp->rx_pg_ring_size);
                        break;
                }
-               prod = NEXT_RX_BD(prod);
-               ring_prod = RX_PG_RING_IDX(prod);
+               prod = BNX2_NEXT_RX_BD(prod);
+               ring_prod = BNX2_RX_PG_RING_IDX(prod);
        }
        rxr->rx_pg_prod = prod;
 
@@ -5237,8 +5242,8 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
                                    ring_num, i, bp->rx_ring_size);
                        break;
                }
-               prod = NEXT_RX_BD(prod);
-               ring_prod = RX_RING_IDX(prod);
+               prod = BNX2_NEXT_RX_BD(prod);
+               ring_prod = BNX2_RX_RING_IDX(prod);
        }
        rxr->rx_prod = prod;
 
@@ -5246,10 +5251,10 @@ bnx2_init_rx_ring(struct bnx2 *bp, int ring_num)
        rxr->rx_bseq_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_BSEQ;
        rxr->rx_pg_bidx_addr = MB_GET_CID_ADDR(cid) + BNX2_L2CTX_HOST_PG_BDIDX;
 
-       REG_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
-       REG_WR16(bp, rxr->rx_bidx_addr, prod);
+       BNX2_WR16(bp, rxr->rx_pg_bidx_addr, rxr->rx_pg_prod);
+       BNX2_WR16(bp, rxr->rx_bidx_addr, prod);
 
-       REG_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
+       BNX2_WR(bp, rxr->rx_bseq_addr, rxr->rx_prod_bseq);
 }
 
 static void
@@ -5260,15 +5265,15 @@ bnx2_init_all_rings(struct bnx2 *bp)
 
        bnx2_clear_ring_states(bp);
 
-       REG_WR(bp, BNX2_TSCH_TSS_CFG, 0);
+       BNX2_WR(bp, BNX2_TSCH_TSS_CFG, 0);
        for (i = 0; i < bp->num_tx_rings; i++)
                bnx2_init_tx_ring(bp, i);
 
        if (bp->num_tx_rings > 1)
-               REG_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
-                      (TX_TSS_CID << 7));
+               BNX2_WR(bp, BNX2_TSCH_TSS_CFG, ((bp->num_tx_rings - 1) << 24) |
+                       (TX_TSS_CID << 7));
 
-       REG_WR(bp, BNX2_RLUP_RSS_CONFIG, 0);
+       BNX2_WR(bp, BNX2_RLUP_RSS_CONFIG, 0);
        bnx2_reg_wr_ind(bp, BNX2_RXP_SCRATCH_RSS_TBL_SZ, 0);
 
        for (i = 0; i < bp->num_rx_rings; i++)
@@ -5282,8 +5287,8 @@ bnx2_init_all_rings(struct bnx2 *bp)
 
                        tbl_32 |= (i % (bp->num_rx_rings - 1)) << shift;
                        if ((i % 8) == 7) {
-                               REG_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32);
-                               REG_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) |
+                               BNX2_WR(bp, BNX2_RLUP_RSS_DATA, tbl_32);
+                               BNX2_WR(bp, BNX2_RLUP_RSS_COMMAND, (i >> 3) |
                                        BNX2_RLUP_RSS_COMMAND_RSS_WRITE_MASK |
                                        BNX2_RLUP_RSS_COMMAND_WRITE |
                                        BNX2_RLUP_RSS_COMMAND_HASH_MASK);
@@ -5294,7 +5299,7 @@ bnx2_init_all_rings(struct bnx2 *bp)
                val = BNX2_RLUP_RSS_CONFIG_IPV4_RSS_TYPE_ALL_XI |
                      BNX2_RLUP_RSS_CONFIG_IPV6_RSS_TYPE_ALL_XI;
 
-               REG_WR(bp, BNX2_RLUP_RSS_CONFIG, val);
+               BNX2_WR(bp, BNX2_RLUP_RSS_CONFIG, val);
 
        }
 }
@@ -5303,8 +5308,8 @@ static u32 bnx2_find_max_ring(u32 ring_size, u32 max_size)
 {
        u32 max, num_rings = 1;
 
-       while (ring_size > MAX_RX_DESC_CNT) {
-               ring_size -= MAX_RX_DESC_CNT;
+       while (ring_size > BNX2_MAX_RX_DESC_CNT) {
+               ring_size -= BNX2_MAX_RX_DESC_CNT;
                num_rings++;
        }
        /* round to next power of 2 */
@@ -5337,13 +5342,14 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
                int pages = PAGE_ALIGN(bp->dev->mtu - 40) >> PAGE_SHIFT;
 
                jumbo_size = size * pages;
-               if (jumbo_size > MAX_TOTAL_RX_PG_DESC_CNT)
-                       jumbo_size = MAX_TOTAL_RX_PG_DESC_CNT;
+               if (jumbo_size > BNX2_MAX_TOTAL_RX_PG_DESC_CNT)
+                       jumbo_size = BNX2_MAX_TOTAL_RX_PG_DESC_CNT;
 
                bp->rx_pg_ring_size = jumbo_size;
                bp->rx_max_pg_ring = bnx2_find_max_ring(jumbo_size,
-                                                       MAX_RX_PG_RINGS);
-               bp->rx_max_pg_ring_idx = (bp->rx_max_pg_ring * RX_DESC_CNT) - 1;
+                                                       BNX2_MAX_RX_PG_RINGS);
+               bp->rx_max_pg_ring_idx =
+                       (bp->rx_max_pg_ring * BNX2_RX_DESC_CNT) - 1;
                rx_size = BNX2_RX_COPY_THRESH + BNX2_RX_OFFSET;
                bp->rx_copy_thresh = 0;
        }
@@ -5354,8 +5360,8 @@ bnx2_set_rx_ring_size(struct bnx2 *bp, u32 size)
                NET_SKB_PAD + SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
        bp->rx_jumbo_thresh = rx_size - BNX2_RX_OFFSET;
        bp->rx_ring_size = size;
-       bp->rx_max_ring = bnx2_find_max_ring(size, MAX_RX_RINGS);
-       bp->rx_max_ring_idx = (bp->rx_max_ring * RX_DESC_CNT) - 1;
+       bp->rx_max_ring = bnx2_find_max_ring(size, BNX2_MAX_RX_RINGS);
+       bp->rx_max_ring_idx = (bp->rx_max_ring * BNX2_RX_DESC_CNT) - 1;
 }
 
 static void
@@ -5371,13 +5377,13 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
                if (txr->tx_buf_ring == NULL)
                        continue;
 
-               for (j = 0; j < TX_DESC_CNT; ) {
-                       struct sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
+               for (j = 0; j < BNX2_TX_DESC_CNT; ) {
+                       struct bnx2_sw_tx_bd *tx_buf = &txr->tx_buf_ring[j];
                        struct sk_buff *skb = tx_buf->skb;
                        int k, last;
 
                        if (skb == NULL) {
-                               j = NEXT_TX_BD(j);
+                               j = BNX2_NEXT_TX_BD(j);
                                continue;
                        }
 
@@ -5389,9 +5395,9 @@ bnx2_free_tx_skbs(struct bnx2 *bp)
                        tx_buf->skb = NULL;
 
                        last = tx_buf->nr_frags;
-                       j = NEXT_TX_BD(j);
-                       for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) {
-                               tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)];
+                       j = BNX2_NEXT_TX_BD(j);
+                       for (k = 0; k < last; k++, j = BNX2_NEXT_TX_BD(j)) {
+                               tx_buf = &txr->tx_buf_ring[BNX2_TX_RING_IDX(j)];
                                dma_unmap_page(&bp->pdev->dev,
                                        dma_unmap_addr(tx_buf, mapping),
                                        skb_frag_size(&skb_shinfo(skb)->frags[k]),
@@ -5417,7 +5423,7 @@ bnx2_free_rx_skbs(struct bnx2 *bp)
                        return;
 
                for (j = 0; j < bp->rx_max_ring_idx; j++) {
-                       struct sw_bd *rx_buf = &rxr->rx_buf_ring[j];
+                       struct bnx2_sw_bd *rx_buf = &rxr->rx_buf_ring[j];
                        u8 *data = rx_buf->data;
 
                        if (data == NULL)
@@ -5615,7 +5621,7 @@ bnx2_test_registers(struct bnx2 *bp)
 
        ret = 0;
        is_5709 = 0;
-       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                is_5709 = 1;
 
        for (i = 0; reg_tbl[i].offset != 0xffff; i++) {
@@ -5714,7 +5720,7 @@ bnx2_test_memory(struct bnx2 *bp)
        };
        struct mem_entry *mem_tbl;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                mem_tbl = mem_tbl_5709;
        else
                mem_tbl = mem_tbl_5706;
@@ -5741,8 +5747,8 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
        unsigned char *packet;
        u16 rx_start_idx, rx_idx;
        dma_addr_t map;
-       struct tx_bd *txbd;
-       struct sw_bd *rx_buf;
+       struct bnx2_tx_bd *txbd;
+       struct bnx2_sw_bd *rx_buf;
        struct l2_fhdr *rx_hdr;
        int ret = -ENODEV;
        struct bnx2_napi *bnapi = &bp->bnx2_napi[0], *tx_napi;
@@ -5784,17 +5790,17 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
                return -EIO;
        }
 
-       REG_WR(bp, BNX2_HC_COMMAND,
-              bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+       BNX2_WR(bp, BNX2_HC_COMMAND,
+               bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
 
-       REG_RD(bp, BNX2_HC_COMMAND);
+       BNX2_RD(bp, BNX2_HC_COMMAND);
 
        udelay(5);
        rx_start_idx = bnx2_get_hw_rx_cons(bnapi);
 
        num_pkts = 0;
 
-       txbd = &txr->tx_desc_ring[TX_RING_IDX(txr->tx_prod)];
+       txbd = &txr->tx_desc_ring[BNX2_TX_RING_IDX(txr->tx_prod)];
 
        txbd->tx_bd_haddr_hi = (u64) map >> 32;
        txbd->tx_bd_haddr_lo = (u64) map & 0xffffffff;
@@ -5802,18 +5808,18 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode)
        txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
 
        num_pkts++;
-       txr->tx_prod = NEXT_TX_BD(txr->tx_prod);
+       txr->tx_prod = BNX2_NEXT_TX_BD(txr->tx_prod);
        txr->tx_prod_bseq += pkt_size;
 
-       REG_WR16(bp, txr->tx_bidx_addr, txr->tx_prod);
-       REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
+       BNX2_WR16(bp, txr->tx_bidx_addr, txr->tx_prod);
+       BNX2_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
 
        udelay(100);
 
-       REG_WR(bp, BNX2_HC_COMMAND,
-              bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
+       BNX2_WR(bp, BNX2_HC_COMMAND,
+               bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
 
-       REG_RD(bp, BNX2_HC_COMMAND);
+       BNX2_RD(bp, BNX2_HC_COMMAND);
 
        udelay(5);
 
@@ -5962,14 +5968,14 @@ bnx2_test_intr(struct bnx2 *bp)
        if (!netif_running(bp->dev))
                return -ENODEV;
 
-       status_idx = REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
+       status_idx = BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff;
 
        /* This register is not touched during run-time. */
-       REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
-       REG_RD(bp, BNX2_HC_COMMAND);
+       BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW);
+       BNX2_RD(bp, BNX2_HC_COMMAND);
 
        for (i = 0; i < 10; i++) {
-               if ((REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) !=
+               if ((BNX2_RD(bp, BNX2_PCICFG_INT_ACK_CMD) & 0xffff) !=
                        status_idx) {
 
                        break;
@@ -6132,11 +6138,11 @@ bnx2_timer(unsigned long data)
 
        /* workaround occasional corrupted counters */
        if ((bp->flags & BNX2_FLAG_BROKEN_STATS) && bp->stats_ticks)
-               REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
-                                           BNX2_HC_COMMAND_STATS_NOW);
+               BNX2_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd |
+                       BNX2_HC_COMMAND_STATS_NOW);
 
        if (bp->phy_flags & BNX2_PHY_FLAG_SERDES) {
-               if (CHIP_NUM(bp) == CHIP_NUM_5706)
+               if (BNX2_CHIP(bp) == BNX2_CHIP_5706)
                        bnx2_5706_serdes_timer(bp);
                else
                        bnx2_5708_serdes_timer(bp);
@@ -6205,13 +6211,13 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
        const int len = sizeof(bp->irq_tbl[0].name);
 
        bnx2_setup_msix_tbl(bp);
-       REG_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1);
-       REG_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE);
-       REG_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE);
+       BNX2_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1);
+       BNX2_WR(bp, BNX2_PCI_MSIX_TBL_OFF_BIR, BNX2_PCI_GRC_WINDOW2_BASE);
+       BNX2_WR(bp, BNX2_PCI_MSIX_PBA_OFF_BIT, BNX2_PCI_GRC_WINDOW3_BASE);
 
        /*  Need to flush the previous three writes to ensure MSI-X
         *  is setup properly */
-       REG_RD(bp, BNX2_PCI_MSIX_CONTROL);
+       BNX2_RD(bp, BNX2_PCI_MSIX_CONTROL);
 
        for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) {
                msix_ent[i].entry = i;
@@ -6274,7 +6280,7 @@ bnx2_setup_int_mode(struct bnx2 *bp, int dis_msi)
            !(bp->flags & BNX2_FLAG_USING_MSIX)) {
                if (pci_enable_msi(bp->pdev) == 0) {
                        bp->flags |= BNX2_FLAG_USING_MSI;
-                       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+                       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                                bp->flags |= BNX2_FLAG_ONE_SHOT_MSI;
                                bp->irq_tbl[0].handler = bnx2_msi_1shot;
                        } else
@@ -6464,22 +6470,22 @@ bnx2_dump_ftq(struct bnx2 *bp)
        netdev_err(dev, "<--- end FTQ dump --->\n");
        netdev_err(dev, "<--- start TBDC dump --->\n");
        netdev_err(dev, "TBDC free cnt: %ld\n",
-                  REG_RD(bp, BNX2_TBDC_STATUS) & BNX2_TBDC_STATUS_FREE_CNT);
+                  BNX2_RD(bp, BNX2_TBDC_STATUS) & BNX2_TBDC_STATUS_FREE_CNT);
        netdev_err(dev, "LINE     CID  BIDX   CMD  VALIDS\n");
        for (i = 0; i < 0x20; i++) {
                int j = 0;
 
-               REG_WR(bp, BNX2_TBDC_BD_ADDR, i);
-               REG_WR(bp, BNX2_TBDC_CAM_OPCODE,
-                      BNX2_TBDC_CAM_OPCODE_OPCODE_CAM_READ);
-               REG_WR(bp, BNX2_TBDC_COMMAND, BNX2_TBDC_COMMAND_CMD_REG_ARB);
-               while ((REG_RD(bp, BNX2_TBDC_COMMAND) &
+               BNX2_WR(bp, BNX2_TBDC_BD_ADDR, i);
+               BNX2_WR(bp, BNX2_TBDC_CAM_OPCODE,
+                       BNX2_TBDC_CAM_OPCODE_OPCODE_CAM_READ);
+               BNX2_WR(bp, BNX2_TBDC_COMMAND, BNX2_TBDC_COMMAND_CMD_REG_ARB);
+               while ((BNX2_RD(bp, BNX2_TBDC_COMMAND) &
                        BNX2_TBDC_COMMAND_CMD_REG_ARB) && j < 100)
                        j++;
 
-               cid = REG_RD(bp, BNX2_TBDC_CID);
-               bdidx = REG_RD(bp, BNX2_TBDC_BIDX);
-               valid = REG_RD(bp, BNX2_TBDC_CAM_OPCODE);
+               cid = BNX2_RD(bp, BNX2_TBDC_CID);
+               bdidx = BNX2_RD(bp, BNX2_TBDC_BIDX);
+               valid = BNX2_RD(bp, BNX2_TBDC_CAM_OPCODE);
                netdev_err(dev, "%02x    %06x  %04lx   %02x    [%x]\n",
                           i, cid, bdidx & BNX2_TBDC_BDIDX_BDIDX,
                           bdidx >> 24, (valid >> 8) & 0x0ff);
@@ -6500,15 +6506,15 @@ bnx2_dump_state(struct bnx2 *bp)
        pci_read_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG, &val2);
        netdev_err(dev, "DEBUG: PCI_PM[%08x] PCI_MISC_CFG[%08x]\n", val1, val2);
        netdev_err(dev, "DEBUG: EMAC_TX_STATUS[%08x] EMAC_RX_STATUS[%08x]\n",
-                  REG_RD(bp, BNX2_EMAC_TX_STATUS),
-                  REG_RD(bp, BNX2_EMAC_RX_STATUS));
+                  BNX2_RD(bp, BNX2_EMAC_TX_STATUS),
+                  BNX2_RD(bp, BNX2_EMAC_RX_STATUS));
        netdev_err(dev, "DEBUG: RPM_MGMT_PKT_CTRL[%08x]\n",
-                  REG_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
+                  BNX2_RD(bp, BNX2_RPM_MGMT_PKT_CTRL));
        netdev_err(dev, "DEBUG: HC_STATS_INTERRUPT_STATUS[%08x]\n",
-                  REG_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
+                  BNX2_RD(bp, BNX2_HC_STATS_INTERRUPT_STATUS));
        if (bp->flags & BNX2_FLAG_USING_MSIX)
                netdev_err(dev, "DEBUG: PBA[%08x]\n",
-                          REG_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE));
+                          BNX2_RD(bp, BNX2_PCI_GRC_WINDOW3_BASE));
 }
 
 static void
@@ -6533,8 +6539,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct bnx2 *bp = netdev_priv(dev);
        dma_addr_t mapping;
-       struct tx_bd *txbd;
-       struct sw_tx_bd *tx_buf;
+       struct bnx2_tx_bd *txbd;
+       struct bnx2_sw_tx_bd *tx_buf;
        u32 len, vlan_tag_flags, last_frag, mss;
        u16 prod, ring_prod;
        int i;
@@ -6557,7 +6563,7 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
        }
        len = skb_headlen(skb);
        prod = txr->tx_prod;
-       ring_prod = TX_RING_IDX(prod);
+       ring_prod = BNX2_TX_RING_IDX(prod);
 
        vlan_tag_flags = 0;
        if (skb->ip_summed == CHECKSUM_PARTIAL) {
@@ -6627,8 +6633,8 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
        for (i = 0; i < last_frag; i++) {
                const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
 
-               prod = NEXT_TX_BD(prod);
-               ring_prod = TX_RING_IDX(prod);
+               prod = BNX2_NEXT_TX_BD(prod);
+               ring_prod = BNX2_TX_RING_IDX(prod);
                txbd = &txr->tx_desc_ring[ring_prod];
 
                len = skb_frag_size(frag);
@@ -6652,11 +6658,11 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        netdev_tx_sent_queue(txq, skb->len);
 
-       prod = NEXT_TX_BD(prod);
+       prod = BNX2_NEXT_TX_BD(prod);
        txr->tx_prod_bseq += skb->len;
 
-       REG_WR16(bp, txr->tx_bidx_addr, prod);
-       REG_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
+       BNX2_WR16(bp, txr->tx_bidx_addr, prod);
+       BNX2_WR(bp, txr->tx_bseq_addr, txr->tx_prod_bseq);
 
        mmiowb();
 
@@ -6682,7 +6688,7 @@ dma_error:
 
        /* start back at beginning and unmap skb */
        prod = txr->tx_prod;
-       ring_prod = TX_RING_IDX(prod);
+       ring_prod = BNX2_TX_RING_IDX(prod);
        tx_buf = &txr->tx_buf_ring[ring_prod];
        tx_buf->skb = NULL;
        dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
@@ -6690,8 +6696,8 @@ dma_error:
 
        /* unmap remaining mapped pages */
        for (i = 0; i < last_frag; i++) {
-               prod = NEXT_TX_BD(prod);
-               ring_prod = TX_RING_IDX(prod);
+               prod = BNX2_NEXT_TX_BD(prod);
+               ring_prod = BNX2_TX_RING_IDX(prod);
                tx_buf = &txr->tx_buf_ring[ring_prod];
                dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping),
                               skb_frag_size(&skb_shinfo(skb)->frags[i]),
@@ -6810,8 +6816,8 @@ bnx2_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
                GET_32BIT_NET_STATS(stat_Dot3StatsExcessiveCollisions) +
                GET_32BIT_NET_STATS(stat_Dot3StatsLateCollisions);
 
-       if ((CHIP_NUM(bp) == CHIP_NUM_5706) ||
-           (CHIP_ID(bp) == CHIP_ID_5708_A0))
+       if ((BNX2_CHIP(bp) == BNX2_CHIP_5706) ||
+           (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0))
                net_stats->tx_carrier_errors = 0;
        else {
                net_stats->tx_carrier_errors =
@@ -7030,7 +7036,7 @@ bnx2_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *_p)
        offset = reg_boundaries[0];
        p += offset;
        while (offset < BNX2_REGDUMP_LEN) {
-               *p++ = REG_RD(bp, offset);
+               *p++ = BNX2_RD(bp, offset);
                offset += 4;
                if (offset == reg_boundaries[i + 1]) {
                        offset = reg_boundaries[i + 2];
@@ -7254,13 +7260,13 @@ bnx2_get_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
 {
        struct bnx2 *bp = netdev_priv(dev);
 
-       ering->rx_max_pending = MAX_TOTAL_RX_DESC_CNT;
-       ering->rx_jumbo_max_pending = MAX_TOTAL_RX_PG_DESC_CNT;
+       ering->rx_max_pending = BNX2_MAX_TOTAL_RX_DESC_CNT;
+       ering->rx_jumbo_max_pending = BNX2_MAX_TOTAL_RX_PG_DESC_CNT;
 
        ering->rx_pending = bp->rx_ring_size;
        ering->rx_jumbo_pending = bp->rx_pg_ring_size;
 
-       ering->tx_max_pending = MAX_TX_DESC_CNT;
+       ering->tx_max_pending = BNX2_MAX_TX_DESC_CNT;
        ering->tx_pending = bp->tx_ring_size;
 }
 
@@ -7326,8 +7332,8 @@ bnx2_set_ringparam(struct net_device *dev, struct ethtool_ringparam *ering)
        struct bnx2 *bp = netdev_priv(dev);
        int rc;
 
-       if ((ering->rx_pending > MAX_TOTAL_RX_DESC_CNT) ||
-               (ering->tx_pending > MAX_TX_DESC_CNT) ||
+       if ((ering->rx_pending > BNX2_MAX_TOTAL_RX_DESC_CNT) ||
+               (ering->tx_pending > BNX2_MAX_TX_DESC_CNT) ||
                (ering->tx_pending <= MAX_SKB_FRAGS)) {
 
                return -EINVAL;
@@ -7614,10 +7620,10 @@ bnx2_get_ethtool_stats(struct net_device *dev,
                return;
        }
 
-       if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
-           (CHIP_ID(bp) == CHIP_ID_5706_A1) ||
-           (CHIP_ID(bp) == CHIP_ID_5706_A2) ||
-           (CHIP_ID(bp) == CHIP_ID_5708_A0))
+       if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) ||
+           (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) ||
+           (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A2) ||
+           (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0))
                stats_len_arr = bnx2_5706_stats_len_arr;
        else
                stats_len_arr = bnx2_5708_stats_len_arr;
@@ -7655,26 +7661,26 @@ bnx2_set_phys_id(struct net_device *dev, enum ethtool_phys_id_state state)
        case ETHTOOL_ID_ACTIVE:
                bnx2_set_power_state(bp, PCI_D0);
 
-               bp->leds_save = REG_RD(bp, BNX2_MISC_CFG);
-               REG_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
+               bp->leds_save = BNX2_RD(bp, BNX2_MISC_CFG);
+               BNX2_WR(bp, BNX2_MISC_CFG, BNX2_MISC_CFG_LEDMODE_MAC);
                return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_ON:
-               REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
-                      BNX2_EMAC_LED_1000MB_OVERRIDE |
-                      BNX2_EMAC_LED_100MB_OVERRIDE |
-                      BNX2_EMAC_LED_10MB_OVERRIDE |
-                      BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
-                      BNX2_EMAC_LED_TRAFFIC);
+               BNX2_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE |
+                       BNX2_EMAC_LED_1000MB_OVERRIDE |
+                       BNX2_EMAC_LED_100MB_OVERRIDE |
+                       BNX2_EMAC_LED_10MB_OVERRIDE |
+                       BNX2_EMAC_LED_TRAFFIC_OVERRIDE |
+                       BNX2_EMAC_LED_TRAFFIC);
                break;
 
        case ETHTOOL_ID_OFF:
-               REG_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
+               BNX2_WR(bp, BNX2_EMAC_LED, BNX2_EMAC_LED_OVERRIDE);
                break;
 
        case ETHTOOL_ID_INACTIVE:
-               REG_WR(bp, BNX2_EMAC_LED, 0);
-               REG_WR(bp, BNX2_MISC_CFG, bp->leds_save);
+               BNX2_WR(bp, BNX2_EMAC_LED, 0);
+               BNX2_WR(bp, BNX2_MISC_CFG, bp->leds_save);
 
                if (!netif_running(dev))
                        bnx2_set_power_state(bp, PCI_D3hot);
@@ -7896,10 +7902,10 @@ poll_bnx2(struct net_device *dev)
 }
 #endif
 
-static void __devinit
+static void
 bnx2_get_5709_media(struct bnx2 *bp)
 {
-       u32 val = REG_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
+       u32 val = BNX2_RD(bp, BNX2_MISC_DUAL_MEDIA_CTRL);
        u32 bond_id = val & BNX2_MISC_DUAL_MEDIA_CTRL_BOND_ID;
        u32 strap;
 
@@ -7934,18 +7940,18 @@ bnx2_get_5709_media(struct bnx2 *bp)
        }
 }
 
-static void __devinit
+static void
 bnx2_get_pci_speed(struct bnx2 *bp)
 {
        u32 reg;
 
-       reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
+       reg = BNX2_RD(bp, BNX2_PCICFG_MISC_STATUS);
        if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
                u32 clkreg;
 
                bp->flags |= BNX2_FLAG_PCIX;
 
-               clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
+               clkreg = BNX2_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
 
                clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
                switch (clkreg) {
@@ -7986,7 +7992,7 @@ bnx2_get_pci_speed(struct bnx2 *bp)
 
 }
 
-static void __devinit
+static void
 bnx2_read_vpd_fw_ver(struct bnx2 *bp)
 {
        int rc, i, j;
@@ -8054,7 +8060,7 @@ vpd_done:
        kfree(data);
 }
 
-static int __devinit
+static int
 bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
 {
        struct bnx2 *bp;
@@ -8131,20 +8137,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
         * Rely on CPU to do target byte swapping on big endian systems
         * The chip's target access swapping will not swap all accesses
         */
-       REG_WR(bp, BNX2_PCICFG_MISC_CONFIG,
-                  BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
-                  BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
+       BNX2_WR(bp, BNX2_PCICFG_MISC_CONFIG,
+               BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
+               BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
 
-       bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
+       bp->chip_id = BNX2_RD(bp, BNX2_MISC_ID);
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709) {
                if (!pci_is_pcie(pdev)) {
                        dev_err(&pdev->dev, "Not PCIE, aborting\n");
                        rc = -EIO;
                        goto err_out_unmap;
                }
                bp->flags |= BNX2_FLAG_PCIE;
-               if (CHIP_REV(bp) == CHIP_REV_Ax)
+               if (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax)
                        bp->flags |= BNX2_FLAG_JUMBO_BROKEN;
 
                /* AER (Advanced Error Reporting) hooks */
@@ -8163,18 +8169,20 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                bp->flags |= BNX2_FLAG_BROKEN_STATS;
        }
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709 && CHIP_REV(bp) != CHIP_REV_Ax) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709 &&
+           BNX2_CHIP_REV(bp) != BNX2_CHIP_REV_Ax) {
                if (pci_find_capability(pdev, PCI_CAP_ID_MSIX))
                        bp->flags |= BNX2_FLAG_MSIX_CAP;
        }
 
-       if (CHIP_ID(bp) != CHIP_ID_5706_A0 && CHIP_ID(bp) != CHIP_ID_5706_A1) {
+       if (BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A0 &&
+           BNX2_CHIP_ID(bp) != BNX2_CHIP_ID_5706_A1) {
                if (pci_find_capability(pdev, PCI_CAP_ID_MSI))
                        bp->flags |= BNX2_FLAG_MSI_CAP;
        }
 
        /* 5708 cannot support DMA addresses > 40-bit.  */
-       if (CHIP_NUM(bp) == CHIP_NUM_5708)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5708)
                persist_dma_mask = dma_mask = DMA_BIT_MASK(40);
        else
                persist_dma_mask = dma_mask = DMA_BIT_MASK(64);
@@ -8197,12 +8205,11 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                bnx2_get_pci_speed(bp);
 
        /* 5706A0 may falsely detect SERR and PERR. */
-       if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
-               reg = REG_RD(bp, PCI_COMMAND);
+       if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
+               reg = BNX2_RD(bp, PCI_COMMAND);
                reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
-               REG_WR(bp, PCI_COMMAND, reg);
-       }
-       else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
+               BNX2_WR(bp, PCI_COMMAND, reg);
+       } else if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) &&
                !(bp->flags & BNX2_FLAG_PCIX)) {
 
                dev_err(&pdev->dev,
@@ -8299,7 +8306,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        bp->mac_addr[4] = (u8) (reg >> 8);
        bp->mac_addr[5] = (u8) reg;
 
-       bp->tx_ring_size = MAX_TX_DESC_CNT;
+       bp->tx_ring_size = BNX2_MAX_TX_DESC_CNT;
        bnx2_set_rx_ring_size(bp, 255);
 
        bp->tx_quick_cons_trip_int = 2;
@@ -8319,9 +8326,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
        bp->phy_addr = 1;
 
        /* Disable WOL support if we are running on a SERDES chip. */
-       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                bnx2_get_5709_media(bp);
-       else if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT)
+       else if (BNX2_CHIP_BOND(bp) & BNX2_CHIP_BOND_SERDES_BIT)
                bp->phy_flags |= BNX2_PHY_FLAG_SERDES;
 
        bp->phy_port = PORT_TP;
@@ -8332,7 +8339,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                        bp->flags |= BNX2_FLAG_NO_WOL;
                        bp->wol = 0;
                }
-               if (CHIP_NUM(bp) == CHIP_NUM_5706) {
+               if (BNX2_CHIP(bp) == BNX2_CHIP_5706) {
                        /* Don't do parallel detect on this board because of
                         * some board problems.  The link will not go down
                         * if we do parallel detect.
@@ -8345,25 +8352,25 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                        if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
                                bp->phy_flags |= BNX2_PHY_FLAG_2_5G_CAPABLE;
                }
-       } else if (CHIP_NUM(bp) == CHIP_NUM_5706 ||
-                  CHIP_NUM(bp) == CHIP_NUM_5708)
+       } else if (BNX2_CHIP(bp) == BNX2_CHIP_5706 ||
+                  BNX2_CHIP(bp) == BNX2_CHIP_5708)
                bp->phy_flags |= BNX2_PHY_FLAG_CRC_FIX;
-       else if (CHIP_NUM(bp) == CHIP_NUM_5709 &&
-                (CHIP_REV(bp) == CHIP_REV_Ax ||
-                 CHIP_REV(bp) == CHIP_REV_Bx))
+       else if (BNX2_CHIP(bp) == BNX2_CHIP_5709 &&
+                (BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Ax ||
+                 BNX2_CHIP_REV(bp) == BNX2_CHIP_REV_Bx))
                bp->phy_flags |= BNX2_PHY_FLAG_DIS_EARLY_DAC;
 
        bnx2_init_fw_cap(bp);
 
-       if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
-           (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
-           (CHIP_ID(bp) == CHIP_ID_5708_B1) ||
-           !(REG_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) {
+       if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_A0) ||
+           (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B0) ||
+           (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5708_B1) ||
+           !(BNX2_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) {
                bp->flags |= BNX2_FLAG_NO_WOL;
                bp->wol = 0;
        }
 
-       if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
+       if (BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A0) {
                bp->tx_quick_cons_trip_int =
                        bp->tx_quick_cons_trip;
                bp->tx_ticks_int = bp->tx_ticks;
@@ -8385,7 +8392,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
         * AMD believes this incompatibility is unique to the 5706, and
         * prefers to locally disable MSI rather than globally disabling it.
         */
-       if (CHIP_NUM(bp) == CHIP_NUM_5706 && disable_msi == 0) {
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5706 && disable_msi == 0) {
                struct pci_dev *amd_8132 = NULL;
 
                while ((amd_8132 = pci_get_device(PCI_VENDOR_ID_AMD,
@@ -8414,6 +8421,7 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                bp->cnic_eth_dev.max_iscsi_conn =
                        (bnx2_shmem_rd(bp, BNX2_ISCSI_MAX_CONN) &
                         BNX2_ISCSI_MAX_CONN_MASK) >> BNX2_ISCSI_MAX_CONN_SHIFT;
+       bp->cnic_probe = bnx2_cnic_probe;
 #endif
        pci_save_state(pdev);
 
@@ -8439,7 +8447,7 @@ err_out:
        return rc;
 }
 
-static char * __devinit
+static char *
 bnx2_bus_string(struct bnx2 *bp, char *str)
 {
        char *s = str;
@@ -8505,7 +8513,7 @@ static const struct net_device_ops bnx2_netdev_ops = {
 #endif
 };
 
-static int __devinit
+static int
 bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int version_printed = 0;
@@ -8541,7 +8549,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                NETIF_F_TSO | NETIF_F_TSO_ECN |
                NETIF_F_RXHASH | NETIF_F_RXCSUM;
 
-       if (CHIP_NUM(bp) == CHIP_NUM_5709)
+       if (BNX2_CHIP(bp) == BNX2_CHIP_5709)
                dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
 
        dev->vlan_features = dev->hw_features;
@@ -8556,15 +8564,15 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        netdev_info(dev, "%s (%c%d) %s found at mem %lx, IRQ %d, "
                    "node addr %pM\n", board_info[ent->driver_data].name,
-                   ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
-                   ((CHIP_ID(bp) & 0x0ff0) >> 4),
+                   ((BNX2_CHIP_ID(bp) & 0xf000) >> 12) + 'A',
+                   ((BNX2_CHIP_ID(bp) & 0x0ff0) >> 4),
                    bnx2_bus_string(bp, str), (long)pci_resource_start(pdev, 0),
                    pdev->irq, dev->dev_addr);
 
        return 0;
 
 error:
-       pci_iounmap(pdev, bp->regview);
+       iounmap(bp->regview);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
@@ -8573,7 +8581,7 @@ err_free:
        return rc;
 }
 
-static void __devexit
+static void
 bnx2_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
@@ -8742,7 +8750,7 @@ static void bnx2_io_resume(struct pci_dev *pdev)
        rtnl_unlock();
 }
 
-static const struct pci_error_handlers bnx2_err_handler = {
+static struct pci_error_handlers bnx2_err_handler = {
        .error_detected = bnx2_io_error_detected,
        .slot_reset     = bnx2_io_slot_reset,
        .resume         = bnx2_io_resume,
@@ -8752,7 +8760,7 @@ static struct pci_driver bnx2_pci_driver = {
        .name           = DRV_MODULE_NAME,
        .id_table       = bnx2_pci_tbl,
        .probe          = bnx2_init_one,
-       .remove         = __devexit_p(bnx2_remove_one),
+       .remove         = bnx2_remove_one,
        .suspend        = bnx2_suspend,
        .resume         = bnx2_resume,
        .err_handler    = &bnx2_err_handler,
index af6451dec2954aedce75ef45cd9f26b9edd88b94..172efbecfea2b502c26cf8043770575b229743d4 100644 (file)
@@ -20,7 +20,7 @@
 /*
  *  tx_bd definition
  */
-struct tx_bd {
+struct bnx2_tx_bd {
        u32 tx_bd_haddr_hi;
        u32 tx_bd_haddr_lo;
        u32 tx_bd_mss_nbytes;
@@ -48,7 +48,7 @@ struct tx_bd {
 /*
  *  rx_bd definition
  */
-struct rx_bd {
+struct bnx2_rx_bd {
        u32 rx_bd_haddr_hi;
        u32 rx_bd_haddr_lo;
        u32 rx_bd_len;
@@ -6538,37 +6538,38 @@ struct l2_fhdr {
 
 /* Use CPU native page size up to 16K for the ring sizes.  */
 #if (PAGE_SHIFT > 14)
-#define BCM_PAGE_BITS  14
+#define BNX2_PAGE_BITS 14
 #else
-#define BCM_PAGE_BITS  PAGE_SHIFT
+#define BNX2_PAGE_BITS PAGE_SHIFT
 #endif
-#define BCM_PAGE_SIZE  (1 << BCM_PAGE_BITS)
+#define BNX2_PAGE_SIZE (1 << BNX2_PAGE_BITS)
 
-#define TX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct tx_bd))
-#define MAX_TX_DESC_CNT (TX_DESC_CNT - 1)
+#define BNX2_TX_DESC_CNT  (BNX2_PAGE_SIZE / sizeof(struct bnx2_tx_bd))
+#define BNX2_MAX_TX_DESC_CNT (BNX2_TX_DESC_CNT - 1)
 
-#define MAX_RX_RINGS   8
-#define MAX_RX_PG_RINGS        32
-#define RX_DESC_CNT  (BCM_PAGE_SIZE / sizeof(struct rx_bd))
-#define MAX_RX_DESC_CNT (RX_DESC_CNT - 1)
-#define MAX_TOTAL_RX_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_RINGS)
-#define MAX_TOTAL_RX_PG_DESC_CNT (MAX_RX_DESC_CNT * MAX_RX_PG_RINGS)
+#define BNX2_MAX_RX_RINGS      8
+#define BNX2_MAX_RX_PG_RINGS   32
+#define BNX2_RX_DESC_CNT  (BNX2_PAGE_SIZE / sizeof(struct bnx2_rx_bd))
+#define BNX2_MAX_RX_DESC_CNT (BNX2_RX_DESC_CNT - 1)
+#define BNX2_MAX_TOTAL_RX_DESC_CNT (BNX2_MAX_RX_DESC_CNT * BNX2_MAX_RX_RINGS)
+#define BNX2_MAX_TOTAL_RX_PG_DESC_CNT  \
+       (BNX2_MAX_RX_DESC_CNT * BNX2_MAX_RX_PG_RINGS)
 
-#define NEXT_TX_BD(x) (((x) & (MAX_TX_DESC_CNT - 1)) ==                        \
-               (MAX_TX_DESC_CNT - 1)) ?                                \
+#define BNX2_NEXT_TX_BD(x) (((x) & (BNX2_MAX_TX_DESC_CNT - 1)) ==      \
+               (BNX2_MAX_TX_DESC_CNT - 1)) ?                           \
        (x) + 2 : (x) + 1
 
-#define TX_RING_IDX(x) ((x) & MAX_TX_DESC_CNT)
+#define BNX2_TX_RING_IDX(x) ((x) & BNX2_MAX_TX_DESC_CNT)
 
-#define NEXT_RX_BD(x) (((x) & (MAX_RX_DESC_CNT - 1)) ==                        \
-               (MAX_RX_DESC_CNT - 1)) ?                                \
+#define BNX2_NEXT_RX_BD(x) (((x) & (BNX2_MAX_RX_DESC_CNT - 1)) ==      \
+               (BNX2_MAX_RX_DESC_CNT - 1)) ?                           \
        (x) + 2 : (x) + 1
 
-#define RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
-#define RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx)
+#define BNX2_RX_RING_IDX(x) ((x) & bp->rx_max_ring_idx)
+#define BNX2_RX_PG_RING_IDX(x) ((x) & bp->rx_max_pg_ring_idx)
 
-#define RX_RING(x) (((x) & ~MAX_RX_DESC_CNT) >> (BCM_PAGE_BITS - 4))
-#define RX_IDX(x) ((x) & MAX_RX_DESC_CNT)
+#define BNX2_RX_RING(x) (((x) & ~BNX2_MAX_RX_DESC_CNT) >> (BNX2_PAGE_BITS - 4))
+#define BNX2_RX_IDX(x) ((x) & BNX2_MAX_RX_DESC_CNT)
 
 /* Context size. */
 #define CTX_SHIFT                   7
@@ -6609,7 +6610,7 @@ struct l2_fhdr {
  * RX ring buffer contains pointer to kmalloc() data only,
  * skb are built only after Hardware filled the frame.
  */
-struct sw_bd {
+struct bnx2_sw_bd {
        u8                      *data;
        DEFINE_DMA_UNMAP_ADDR(mapping);
 };
@@ -6623,23 +6624,23 @@ static inline struct l2_fhdr *get_l2_fhdr(u8 *data)
 }
 
 
-struct sw_pg {
+struct bnx2_sw_pg {
        struct page             *page;
        DEFINE_DMA_UNMAP_ADDR(mapping);
 };
 
-struct sw_tx_bd {
+struct bnx2_sw_tx_bd {
        struct sk_buff          *skb;
        DEFINE_DMA_UNMAP_ADDR(mapping);
        unsigned short          is_gso;
        unsigned short          nr_frags;
 };
 
-#define SW_RXBD_RING_SIZE (sizeof(struct sw_bd) * RX_DESC_CNT)
-#define SW_RXPG_RING_SIZE (sizeof(struct sw_pg) * RX_DESC_CNT)
-#define RXBD_RING_SIZE (sizeof(struct rx_bd) * RX_DESC_CNT)
-#define SW_TXBD_RING_SIZE (sizeof(struct sw_tx_bd) * TX_DESC_CNT)
-#define TXBD_RING_SIZE (sizeof(struct tx_bd) * TX_DESC_CNT)
+#define SW_RXBD_RING_SIZE (sizeof(struct bnx2_sw_bd) * BNX2_RX_DESC_CNT)
+#define SW_RXPG_RING_SIZE (sizeof(struct bnx2_sw_pg) * BNX2_RX_DESC_CNT)
+#define RXBD_RING_SIZE (sizeof(struct bnx2_rx_bd) * BNX2_RX_DESC_CNT)
+#define SW_TXBD_RING_SIZE (sizeof(struct bnx2_sw_tx_bd) * BNX2_TX_DESC_CNT)
+#define TXBD_RING_SIZE (sizeof(struct bnx2_tx_bd) * BNX2_TX_DESC_CNT)
 
 /* Buffered flash (Atmel: AT45DB011B) specific information */
 #define SEEPROM_PAGE_BITS                      2
@@ -6720,8 +6721,8 @@ struct bnx2_tx_ring_info {
        u32                     tx_bidx_addr;
        u32                     tx_bseq_addr;
 
-       struct tx_bd            *tx_desc_ring;
-       struct sw_tx_bd         *tx_buf_ring;
+       struct bnx2_tx_bd       *tx_desc_ring;
+       struct bnx2_sw_tx_bd    *tx_buf_ring;
 
        u16                     tx_cons;
        u16                     hw_tx_cons;
@@ -6741,13 +6742,13 @@ struct bnx2_rx_ring_info {
        u16                     rx_pg_prod;
        u16                     rx_pg_cons;
 
-       struct sw_bd            *rx_buf_ring;
-       struct rx_bd            *rx_desc_ring[MAX_RX_RINGS];
-       struct sw_pg            *rx_pg_ring;
-       struct rx_bd            *rx_pg_desc_ring[MAX_RX_PG_RINGS];
+       struct bnx2_sw_bd       *rx_buf_ring;
+       struct bnx2_rx_bd       *rx_desc_ring[BNX2_MAX_RX_RINGS];
+       struct bnx2_sw_pg       *rx_pg_ring;
+       struct bnx2_rx_bd       *rx_pg_desc_ring[BNX2_MAX_RX_PG_RINGS];
 
-       dma_addr_t              rx_desc_mapping[MAX_RX_RINGS];
-       dma_addr_t              rx_pg_desc_mapping[MAX_RX_PG_RINGS];
+       dma_addr_t              rx_desc_mapping[BNX2_MAX_RX_RINGS];
+       dma_addr_t              rx_pg_desc_mapping[BNX2_MAX_RX_PG_RINGS];
 };
 
 struct bnx2_napi {
@@ -6853,33 +6854,31 @@ struct bnx2 {
 
        u32                     chip_id;
        /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
-#define CHIP_NUM(bp)                   (((bp)->chip_id) & 0xffff0000)
-#define CHIP_NUM_5706                  0x57060000
-#define CHIP_NUM_5708                  0x57080000
-#define CHIP_NUM_5709                  0x57090000
-
-#define CHIP_REV(bp)                   (((bp)->chip_id) & 0x0000f000)
-#define CHIP_REV_Ax                    0x00000000
-#define CHIP_REV_Bx                    0x00001000
-#define CHIP_REV_Cx                    0x00002000
-
-#define CHIP_METAL(bp)                 (((bp)->chip_id) & 0x00000ff0)
-#define CHIP_BONDING(bp)               (((bp)->chip_id) & 0x0000000f)
-
-#define CHIP_ID(bp)                    (((bp)->chip_id) & 0xfffffff0)
-#define CHIP_ID_5706_A0                        0x57060000
-#define CHIP_ID_5706_A1                        0x57060010
-#define CHIP_ID_5706_A2                        0x57060020
-#define CHIP_ID_5708_A0                        0x57080000
-#define CHIP_ID_5708_B0                        0x57081000
-#define CHIP_ID_5708_B1                        0x57081010
-#define CHIP_ID_5709_A0                        0x57090000
-#define CHIP_ID_5709_A1                        0x57090010
-
-#define CHIP_BOND_ID(bp)               (((bp)->chip_id) & 0xf)
+#define BNX2_CHIP(bp)                  (((bp)->chip_id) & 0xffff0000)
+#define BNX2_CHIP_5706                 0x57060000
+#define BNX2_CHIP_5708                 0x57080000
+#define BNX2_CHIP_5709                 0x57090000
+
+#define BNX2_CHIP_REV(bp)              (((bp)->chip_id) & 0x0000f000)
+#define BNX2_CHIP_REV_Ax               0x00000000
+#define BNX2_CHIP_REV_Bx               0x00001000
+#define BNX2_CHIP_REV_Cx               0x00002000
+
+#define BNX2_CHIP_METAL(bp)            (((bp)->chip_id) & 0x00000ff0)
+#define BNX2_CHIP_BOND(bp)             (((bp)->chip_id) & 0x0000000f)
+
+#define BNX2_CHIP_ID(bp)               (((bp)->chip_id) & 0xfffffff0)
+#define BNX2_CHIP_ID_5706_A0           0x57060000
+#define BNX2_CHIP_ID_5706_A1                   0x57060010
+#define BNX2_CHIP_ID_5706_A2                   0x57060020
+#define BNX2_CHIP_ID_5708_A0                   0x57080000
+#define BNX2_CHIP_ID_5708_B0                   0x57081000
+#define BNX2_CHIP_ID_5708_B1                   0x57081010
+#define BNX2_CHIP_ID_5709_A0                   0x57090000
+#define BNX2_CHIP_ID_5709_A1                   0x57090010
 
 /* A serdes chip will have the first bit of the bond id set. */
-#define CHIP_BOND_ID_SERDES_BIT                0x01
+#define BNX2_CHIP_BOND_SERDES_BIT              0x01
 
        u32                     phy_addr;
        u32                     phy_id;
@@ -6985,19 +6984,20 @@ struct bnx2 {
 #ifdef BCM_CNIC
        struct mutex            cnic_lock;
        struct cnic_eth_dev     cnic_eth_dev;
+       struct cnic_eth_dev     *(*cnic_probe)(struct net_device *);
 #endif
 
        const struct firmware   *mips_firmware;
        const struct firmware   *rv2p_firmware;
 };
 
-#define REG_RD(bp, offset)                                     \
+#define BNX2_RD(bp, offset)                                    \
        readl(bp->regview + offset)
 
-#define REG_WR(bp, offset, val)                                        \
+#define BNX2_WR(bp, offset, val)                                       \
        writel(val, bp->regview + offset)
 
-#define REG_WR16(bp, offset, val)                              \
+#define BNX2_WR16(bp, offset, val)                             \
        writew(val, bp->regview + offset)
 
 struct cpu_reg {
@@ -7052,7 +7052,7 @@ struct bnx2_rv2p_fw_file {
 
 #define RV2P_P1_FIXUP_PAGE_SIZE_IDX            0
 #define RV2P_BD_PAGE_SIZE_MSK                  0xffff
-#define RV2P_BD_PAGE_SIZE                      ((BCM_PAGE_SIZE / 16) - 1)
+#define RV2P_BD_PAGE_SIZE                      ((BNX2_PAGE_SIZE / 16) - 1)
 
 #define RV2P_PROC1                              0
 #define RV2P_PROC2                              1
index 72897c47b8c849c31cf387c6cd63f42d624be07c..e8d4db10c8f318dacac488af5f41510c7f3c68dc 100644 (file)
 
 #include "bnx2x_hsi.h"
 
-#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
-#define BCM_CNIC 1
 #include "../cnic_if.h"
-#endif
 
-#ifdef BCM_CNIC
-#define BNX2X_MIN_MSIX_VEC_CNT 3
-#define BNX2X_MSIX_VEC_FP_START 2
-#else
-#define BNX2X_MIN_MSIX_VEC_CNT 2
-#define BNX2X_MSIX_VEC_FP_START 1
-#endif
+
+#define BNX2X_MIN_MSIX_VEC_CNT(bp)             ((bp)->min_msix_vec_cnt)
 
 #include <linux/mdio.h>
 
 #include "bnx2x_reg.h"
 #include "bnx2x_fw_defs.h"
 #include "bnx2x_mfw_req.h"
-#include "bnx2x_hsi.h"
 #include "bnx2x_link.h"
 #include "bnx2x_sp.h"
 #include "bnx2x_dcb.h"
@@ -256,15 +247,10 @@ enum {
        /* FCoE L2 */
 #define        BNX2X_FCOE_ETH_CID(bp)          (BNX2X_CNIC_START_ETH_CID(bp) + 1)
 
-/** Additional rings budgeting */
-#ifdef BCM_CNIC
-#define CNIC_PRESENT                   1
-#define FCOE_PRESENT                   1
-#else
-#define CNIC_PRESENT                   0
-#define FCOE_PRESENT                   0
-#endif /* BCM_CNIC */
-#define NON_ETH_CONTEXT_USE    (FCOE_PRESENT)
+#define CNIC_SUPPORT(bp)               ((bp)->cnic_support)
+#define CNIC_ENABLED(bp)               ((bp)->cnic_enabled)
+#define CNIC_LOADED(bp)                        ((bp)->cnic_loaded)
+#define FCOE_INIT(bp)                  ((bp)->fcoe_init)
 
 #define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
        AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
@@ -297,9 +283,7 @@ enum {
        OOO_TXQ_IDX_OFFSET,
 };
 #define MAX_ETH_TXQ_IDX(bp)    (BNX2X_NUM_NON_CNIC_QUEUES(bp) * (bp)->max_cos)
-#ifdef BCM_CNIC
 #define FCOE_TXQ_IDX(bp)       (MAX_ETH_TXQ_IDX(bp) + FCOE_TXQ_IDX_OFFSET)
-#endif
 
 /* fast path */
 /*
@@ -505,7 +489,7 @@ struct bnx2x_fastpath {
        u32                     ustorm_rx_prods_offset;
 
        u32                     rx_buf_size;
-
+       u32                     rx_frag_size; /* 0 if kmalloced(), or rx_buf_size + NET_SKB_PAD */
        dma_addr_t              status_blk_mapping;
 
        enum bnx2x_tpa_mode_t   mode;
@@ -585,15 +569,9 @@ struct bnx2x_fastpath {
                                                ->var)
 
 
-#define IS_ETH_FP(fp)                  (fp->index < \
-                                        BNX2X_NUM_ETH_QUEUES(fp->bp))
-#ifdef BCM_CNIC
-#define IS_FCOE_FP(fp)                 (fp->index == FCOE_IDX(fp->bp))
-#define IS_FCOE_IDX(idx)               ((idx) == FCOE_IDX(bp))
-#else
-#define IS_FCOE_FP(fp)         false
-#define IS_FCOE_IDX(idx)       false
-#endif
+#define IS_ETH_FP(fp)          ((fp)->index < BNX2X_NUM_ETH_QUEUES((fp)->bp))
+#define IS_FCOE_FP(fp)         ((fp)->index == FCOE_IDX((fp)->bp))
+#define IS_FCOE_IDX(idx)       ((idx) == FCOE_IDX(bp))
 
 
 /* MC hsi */
@@ -886,6 +864,18 @@ struct bnx2x_common {
                                         (CHIP_REV(bp) == CHIP_REV_Bx))
 #define CHIP_IS_E3A0(bp)               (CHIP_IS_E3(bp) && \
                                         (CHIP_REV(bp) == CHIP_REV_Ax))
+/* This define is used in two main places:
+ * 1. In the early stages of nic_load, to know if to configrue Parser / Searcher
+ * to nic-only mode or to offload mode. Offload mode is configured if either the
+ * chip is E1x (where MIC_MODE register is not applicable), or if cnic already
+ * registered for this port (which means that the user wants storage services).
+ * 2. During cnic-related load, to know if offload mode is already configured in
+ * the HW or needs to be configrued.
+ * Since the transition from nic-mode to offload-mode in HW causes traffic
+ * coruption, nic-mode is configured only in ports on which storage services
+ * where never requested.
+ */
+#define CONFIGURE_NIC_MODE(bp)         (!CHIP_IS_E1x(bp) && !CNIC_ENABLED(bp))
 
        int                     flash_size;
 #define BNX2X_NVRAM_1MB_SIZE                   0x20000 /* 1M bit in bytes */
@@ -925,6 +915,7 @@ struct bnx2x_common {
 #define BNX2X_IGU_STAS_MSG_VF_CNT 64
 #define BNX2X_IGU_STAS_MSG_PF_CNT 4
 
+#define MAX_IGU_ATTN_ACK_TO       100
 /* end of common */
 
 /* port */
@@ -946,7 +937,6 @@ struct bnx2x_port {
 
        /* used to synchronize phy accesses */
        struct mutex            phy_mutex;
-       int                     need_hw_lock;
 
        u32                     port_stx;
 
@@ -1003,18 +993,15 @@ union cdu_context {
 #define CDU_ILT_PAGE_SZ                (8192 << CDU_ILT_PAGE_SZ_HW) /* 32K */
 #define ILT_PAGE_CIDS          (CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
 
-#ifdef BCM_CNIC
 #define CNIC_ISCSI_CID_MAX     256
 #define CNIC_FCOE_CID_MAX      2048
 #define CNIC_CID_MAX           (CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX)
 #define CNIC_ILT_LINES         DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
-#endif
 
 #define QM_ILT_PAGE_SZ_HW      0
 #define QM_ILT_PAGE_SZ         (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
 #define QM_CID_ROUND           1024
 
-#ifdef BCM_CNIC
 /* TM (timers) host DB constants */
 #define TM_ILT_PAGE_SZ_HW      0
 #define TM_ILT_PAGE_SZ         (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
@@ -1032,8 +1019,6 @@ union cdu_context {
 #define SRC_T2_SZ              SRC_ILT_SZ
 #define SRC_ILT_LINES          DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
 
-#endif
-
 #define MAX_DMAE_C             8
 
 /* DMA memory not used in fastpath */
@@ -1201,6 +1186,7 @@ struct bnx2x_prev_path_list {
        u8 slot;
        u8 path;
        struct list_head list;
+       u8 undi;
 };
 
 struct bnx2x_sp_objs {
@@ -1227,7 +1213,6 @@ struct bnx2x {
        struct bnx2x_sp_objs    *sp_objs;
        struct bnx2x_fp_stats   *fp_stats;
        struct bnx2x_fp_txdata  *bnx2x_txq;
-       int                     bnx2x_txq_size;
        void __iomem            *regview;
        void __iomem            *doorbells;
        u16                     db_size;
@@ -1350,6 +1335,16 @@ struct bnx2x {
 #define NO_ISCSI_OOO(bp)       ((bp)->flags & NO_ISCSI_OOO_FLAG)
 #define NO_FCOE(bp)            ((bp)->flags & NO_FCOE_FLAG)
 
+       u8                      cnic_support;
+       bool                    cnic_enabled;
+       bool                    cnic_loaded;
+       struct cnic_eth_dev     *(*cnic_probe)(struct net_device *);
+
+       /* Flag that indicates that we can start looking for FCoE L2 queue
+        * completions in the default status block.
+        */
+       bool                    fcoe_init;
+
        int                     pm_cap;
        int                     mrrs;
 
@@ -1420,6 +1415,8 @@ struct bnx2x {
 #define BNX2X_MAX_COS                  3
 #define BNX2X_MAX_TX_COS               2
        int                     num_queues;
+       uint                    num_ethernet_queues;
+       uint                    num_cnic_queues;
        int                     num_napi_queues;
        int                     disable_tpa;
 
@@ -1433,6 +1430,7 @@ struct bnx2x {
        u8                      igu_dsb_id;
        u8                      igu_base_sb;
        u8                      igu_sb_cnt;
+       u8                      min_msix_vec_cnt;
 
        dma_addr_t              def_status_blk_mapping;
 
@@ -1478,26 +1476,23 @@ struct bnx2x {
  * Maximum supported number of RSS queues: number of IGU SBs minus one that goes
  * to CNIC.
  */
-#define BNX2X_MAX_RSS_COUNT(bp)        ((bp)->igu_sb_cnt - CNIC_PRESENT)
+#define BNX2X_MAX_RSS_COUNT(bp)        ((bp)->igu_sb_cnt - CNIC_SUPPORT(bp))
 
 /*
  * Maximum CID count that might be required by the bnx2x:
  * Max RSS * Max_Tx_Multi_Cos + FCoE + iSCSI
  */
 #define BNX2X_L2_CID_COUNT(bp) (BNX2X_NUM_ETH_QUEUES(bp) * BNX2X_MULTI_TX_COS \
-                               + NON_ETH_CONTEXT_USE + CNIC_PRESENT)
+                               + 2 * CNIC_SUPPORT(bp))
 #define BNX2X_L2_MAX_CID(bp)   (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS \
-                               + NON_ETH_CONTEXT_USE + CNIC_PRESENT)
+                               + 2 * CNIC_SUPPORT(bp))
 #define L2_ILT_LINES(bp)       (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
                                        ILT_PAGE_CIDS))
 
        int                     qm_cid_count;
 
-       int                     dropless_fc;
+       bool                    dropless_fc;
 
-#ifdef BCM_CNIC
-       u32                     cnic_flags;
-#define BNX2X_CNIC_FLAG_MAC_SET                1
        void                    *t2;
        dma_addr_t              t2_mapping;
        struct cnic_ops __rcu   *cnic_ops;
@@ -1518,7 +1513,6 @@ struct bnx2x {
 
        /* Start index of the "special" (CNIC related) L2 cleints */
        u8                              cnic_base_cl_id;
-#endif
 
        int                     dmae_ready;
        /* used to synchronize dmae accesses */
@@ -1647,9 +1641,9 @@ struct bnx2x {
 /* Tx queues may be less or equal to Rx queues */
 extern int num_queues;
 #define BNX2X_NUM_QUEUES(bp)   (bp->num_queues)
-#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE)
+#define BNX2X_NUM_ETH_QUEUES(bp) ((bp)->num_ethernet_queues)
 #define BNX2X_NUM_NON_CNIC_QUEUES(bp)  (BNX2X_NUM_QUEUES(bp) - \
-                                        NON_ETH_CONTEXT_USE)
+                                        (bp)->num_cnic_queues)
 #define BNX2X_NUM_RX_QUEUES(bp)        BNX2X_NUM_QUEUES(bp)
 
 #define is_multi(bp)           (BNX2X_NUM_QUEUES(bp) > 1)
@@ -1689,6 +1683,13 @@ struct bnx2x_func_init_params {
        u16             spq_prod;       /* valid iff FUNC_FLG_SPQ */
 };
 
+#define for_each_cnic_queue(bp, var) \
+       for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+            (var)++) \
+               if (skip_queue(bp, var))        \
+                       continue;               \
+               else
+
 #define for_each_eth_queue(bp, var) \
        for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
 
@@ -1702,6 +1703,22 @@ struct bnx2x_func_init_params {
                else
 
 /* Skip forwarding FP */
+#define for_each_valid_rx_queue(bp, var)                       \
+       for ((var) = 0;                                         \
+            (var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) :  \
+                     BNX2X_NUM_ETH_QUEUES(bp));                \
+            (var)++)                                           \
+               if (skip_rx_queue(bp, var))                     \
+                       continue;                               \
+               else
+
+#define for_each_rx_queue_cnic(bp, var) \
+       for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+            (var)++) \
+               if (skip_rx_queue(bp, var))     \
+                       continue;               \
+               else
+
 #define for_each_rx_queue(bp, var) \
        for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
                if (skip_rx_queue(bp, var))     \
@@ -1709,6 +1726,22 @@ struct bnx2x_func_init_params {
                else
 
 /* Skip OOO FP */
+#define for_each_valid_tx_queue(bp, var)                       \
+       for ((var) = 0;                                         \
+            (var) < (CNIC_LOADED(bp) ? BNX2X_NUM_QUEUES(bp) :  \
+                     BNX2X_NUM_ETH_QUEUES(bp));                \
+            (var)++)                                           \
+               if (skip_tx_queue(bp, var))                     \
+                       continue;                               \
+               else
+
+#define for_each_tx_queue_cnic(bp, var) \
+       for ((var) = BNX2X_NUM_ETH_QUEUES(bp); (var) < BNX2X_NUM_QUEUES(bp); \
+            (var)++) \
+               if (skip_tx_queue(bp, var))     \
+                       continue;               \
+               else
+
 #define for_each_tx_queue(bp, var) \
        for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
                if (skip_tx_queue(bp, var))     \
@@ -2179,7 +2212,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
 #define BNX2X_MF_SD_PROTOCOL(bp) \
        ((bp)->mf_config[BP_VN(bp)] & FUNC_MF_CFG_PROTOCOL_MASK)
 
-#ifdef BCM_CNIC
 #define BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) \
        (BNX2X_MF_SD_PROTOCOL(bp) == FUNC_MF_CFG_PROTOCOL_ISCSI)
 
@@ -2196,9 +2228,12 @@ void bnx2x_notify_link_changed(struct bnx2x *bp);
 #define IS_MF_STORAGE_SD(bp) (IS_MF_SD(bp) && \
                                (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp) || \
                                 BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)))
-#else
-#define IS_MF_FCOE_AFEX(bp)    false
-#endif
 
+enum {
+       SWITCH_UPDATE,
+       AFEX_UPDATE,
+};
+
+#define NUM_MACS       8
 
 #endif /* bnx2x.h */
index 24220992413ff95fd391e785b4e9edba221422bc..a2998bea5d4b42690ca1334322d5ebe396ef0805 100644 (file)
@@ -552,6 +552,23 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        return 0;
 }
 
+static void bnx2x_frag_free(const struct bnx2x_fastpath *fp, void *data)
+{
+       if (fp->rx_frag_size)
+               put_page(virt_to_head_page(data));
+       else
+               kfree(data);
+}
+
+static void *bnx2x_frag_alloc(const struct bnx2x_fastpath *fp)
+{
+       if (fp->rx_frag_size)
+               return netdev_alloc_frag(fp->rx_frag_size);
+
+       return kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC);
+}
+
+
 static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                           struct bnx2x_agg_info *tpa_info,
                           u16 pages,
@@ -574,15 +591,14 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                goto drop;
 
        /* Try to allocate the new data */
-       new_data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC);
-
+       new_data = bnx2x_frag_alloc(fp);
        /* Unmap skb in the pool anyway, as we are going to change
           pool entry status to BNX2X_TPA_STOP even if new skb allocation
           fails. */
        dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping),
                         fp->rx_buf_size, DMA_FROM_DEVICE);
        if (likely(new_data))
-               skb = build_skb(data, 0);
+               skb = build_skb(data, fp->rx_frag_size);
 
        if (likely(skb)) {
 #ifdef BNX2X_STOP_ON_ERROR
@@ -619,7 +635,7 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 
                return;
        }
-       kfree(new_data);
+       bnx2x_frag_free(fp, new_data);
 drop:
        /* drop the packet and keep the buffer in the bin */
        DP(NETIF_MSG_RX_STATUS,
@@ -635,7 +651,7 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp,
        struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
        dma_addr_t mapping;
 
-       data = kmalloc(fp->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC);
+       data = bnx2x_frag_alloc(fp);
        if (unlikely(data == NULL))
                return -ENOMEM;
 
@@ -643,7 +659,7 @@ static int bnx2x_alloc_rx_data(struct bnx2x *bp,
                                 fp->rx_buf_size,
                                 DMA_FROM_DEVICE);
        if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
-               kfree(data);
+               bnx2x_frag_free(fp, data);
                BNX2X_ERR("Can't map rx data\n");
                return -ENOMEM;
        }
@@ -845,9 +861,9 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget)
                                                 dma_unmap_addr(rx_buf, mapping),
                                                 fp->rx_buf_size,
                                                 DMA_FROM_DEVICE);
-                               skb = build_skb(data, 0);
+                               skb = build_skb(data, fp->rx_frag_size);
                                if (unlikely(!skb)) {
-                                       kfree(data);
+                                       bnx2x_frag_free(fp, data);
                                        bnx2x_fp_qstats(bp, fp)->
                                                        rx_skb_alloc_failed++;
                                        goto next_rx;
@@ -948,14 +964,12 @@ void bnx2x_acquire_phy_lock(struct bnx2x *bp)
 {
        mutex_lock(&bp->port.phy_mutex);
 
-       if (bp->port.need_hw_lock)
-               bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
+       bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
 }
 
 void bnx2x_release_phy_lock(struct bnx2x *bp)
 {
-       if (bp->port.need_hw_lock)
-               bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
+       bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_MDIO);
 
        mutex_unlock(&bp->port.phy_mutex);
 }
@@ -1147,11 +1161,30 @@ static void bnx2x_free_tpa_pool(struct bnx2x *bp,
                        dma_unmap_single(&bp->pdev->dev,
                                         dma_unmap_addr(first_buf, mapping),
                                         fp->rx_buf_size, DMA_FROM_DEVICE);
-               kfree(data);
+               bnx2x_frag_free(fp, data);
                first_buf->data = NULL;
        }
 }
 
+void bnx2x_init_rx_rings_cnic(struct bnx2x *bp)
+{
+       int j;
+
+       for_each_rx_queue_cnic(bp, j) {
+               struct bnx2x_fastpath *fp = &bp->fp[j];
+
+               fp->rx_bd_cons = 0;
+
+               /* Activate BD ring */
+               /* Warning!
+                * this will generate an interrupt (to the TSTORM)
+                * must only be done after chip is initialized
+                */
+               bnx2x_update_rx_prod(bp, fp, fp->rx_bd_prod, fp->rx_comp_prod,
+                                    fp->rx_sge_prod);
+       }
+}
+
 void bnx2x_init_rx_rings(struct bnx2x *bp)
 {
        int func = BP_FUNC(bp);
@@ -1159,7 +1192,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
        int i, j;
 
        /* Allocate TPA resources */
-       for_each_rx_queue(bp, j) {
+       for_each_eth_queue(bp, j) {
                struct bnx2x_fastpath *fp = &bp->fp[j];
 
                DP(NETIF_MSG_IFUP,
@@ -1173,8 +1206,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
                                struct sw_rx_bd *first_buf =
                                        &tpa_info->first_buf;
 
-                               first_buf->data = kmalloc(fp->rx_buf_size + NET_SKB_PAD,
-                                                         GFP_ATOMIC);
+                               first_buf->data = bnx2x_frag_alloc(fp);
                                if (!first_buf->data) {
                                        BNX2X_ERR("Failed to allocate TPA skb pool for queue[%d] - disabling TPA on this queue!\n",
                                                  j);
@@ -1217,7 +1249,7 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
                }
        }
 
-       for_each_rx_queue(bp, j) {
+       for_each_eth_queue(bp, j) {
                struct bnx2x_fastpath *fp = &bp->fp[j];
 
                fp->rx_bd_cons = 0;
@@ -1244,29 +1276,45 @@ void bnx2x_init_rx_rings(struct bnx2x *bp)
        }
 }
 
-static void bnx2x_free_tx_skbs(struct bnx2x *bp)
+static void bnx2x_free_tx_skbs_queue(struct bnx2x_fastpath *fp)
 {
-       int i;
        u8 cos;
+       struct bnx2x *bp = fp->bp;
 
-       for_each_tx_queue(bp, i) {
-               struct bnx2x_fastpath *fp = &bp->fp[i];
-               for_each_cos_in_tx_queue(fp, cos) {
-                       struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
-                       unsigned pkts_compl = 0, bytes_compl = 0;
+       for_each_cos_in_tx_queue(fp, cos) {
+               struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
+               unsigned pkts_compl = 0, bytes_compl = 0;
 
-                       u16 sw_prod = txdata->tx_pkt_prod;
-                       u16 sw_cons = txdata->tx_pkt_cons;
+               u16 sw_prod = txdata->tx_pkt_prod;
+               u16 sw_cons = txdata->tx_pkt_cons;
 
-                       while (sw_cons != sw_prod) {
-                               bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons),
-                                   &pkts_compl, &bytes_compl);
-                               sw_cons++;
-                       }
-                       netdev_tx_reset_queue(
-                               netdev_get_tx_queue(bp->dev,
-                                                   txdata->txq_index));
+               while (sw_cons != sw_prod) {
+                       bnx2x_free_tx_pkt(bp, txdata, TX_BD(sw_cons),
+                                         &pkts_compl, &bytes_compl);
+                       sw_cons++;
                }
+
+               netdev_tx_reset_queue(
+                       netdev_get_tx_queue(bp->dev,
+                                           txdata->txq_index));
+       }
+}
+
+static void bnx2x_free_tx_skbs_cnic(struct bnx2x *bp)
+{
+       int i;
+
+       for_each_tx_queue_cnic(bp, i) {
+               bnx2x_free_tx_skbs_queue(&bp->fp[i]);
+       }
+}
+
+static void bnx2x_free_tx_skbs(struct bnx2x *bp)
+{
+       int i;
+
+       for_each_eth_queue(bp, i) {
+               bnx2x_free_tx_skbs_queue(&bp->fp[i]);
        }
 }
 
@@ -1290,7 +1338,16 @@ static void bnx2x_free_rx_bds(struct bnx2x_fastpath *fp)
                                 fp->rx_buf_size, DMA_FROM_DEVICE);
 
                rx_buf->data = NULL;
-               kfree(data);
+               bnx2x_frag_free(fp, data);
+       }
+}
+
+static void bnx2x_free_rx_skbs_cnic(struct bnx2x *bp)
+{
+       int j;
+
+       for_each_rx_queue_cnic(bp, j) {
+               bnx2x_free_rx_bds(&bp->fp[j]);
        }
 }
 
@@ -1298,7 +1355,7 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
 {
        int j;
 
-       for_each_rx_queue(bp, j) {
+       for_each_eth_queue(bp, j) {
                struct bnx2x_fastpath *fp = &bp->fp[j];
 
                bnx2x_free_rx_bds(fp);
@@ -1308,6 +1365,12 @@ static void bnx2x_free_rx_skbs(struct bnx2x *bp)
        }
 }
 
+void bnx2x_free_skbs_cnic(struct bnx2x *bp)
+{
+       bnx2x_free_tx_skbs_cnic(bp);
+       bnx2x_free_rx_skbs_cnic(bp);
+}
+
 void bnx2x_free_skbs(struct bnx2x *bp)
 {
        bnx2x_free_tx_skbs(bp);
@@ -1347,11 +1410,12 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp, int nvecs)
        DP(NETIF_MSG_IFDOWN, "released sp irq (%d)\n",
           bp->msix_table[offset].vector);
        offset++;
-#ifdef BCM_CNIC
-       if (nvecs == offset)
-               return;
-       offset++;
-#endif
+
+       if (CNIC_SUPPORT(bp)) {
+               if (nvecs == offset)
+                       return;
+               offset++;
+       }
 
        for_each_eth_queue(bp, i) {
                if (nvecs == offset)
@@ -1368,7 +1432,7 @@ void bnx2x_free_irq(struct bnx2x *bp)
        if (bp->flags & USING_MSIX_FLAG &&
            !(bp->flags & USING_SINGLE_MSIX_FLAG))
                bnx2x_free_msix_irqs(bp, BNX2X_NUM_ETH_QUEUES(bp) +
-                                    CNIC_PRESENT + 1);
+                                    CNIC_SUPPORT(bp) + 1);
        else
                free_irq(bp->dev->irq, bp->dev);
 }
@@ -1382,12 +1446,14 @@ int bnx2x_enable_msix(struct bnx2x *bp)
           bp->msix_table[0].entry);
        msix_vec++;
 
-#ifdef BCM_CNIC
-       bp->msix_table[msix_vec].entry = msix_vec;
-       BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n",
-          bp->msix_table[msix_vec].entry, bp->msix_table[msix_vec].entry);
-       msix_vec++;
-#endif
+       /* Cnic requires an msix vector for itself */
+       if (CNIC_SUPPORT(bp)) {
+               bp->msix_table[msix_vec].entry = msix_vec;
+               BNX2X_DEV_INFO("msix_table[%d].entry = %d (CNIC)\n",
+                              msix_vec, bp->msix_table[msix_vec].entry);
+               msix_vec++;
+       }
+
        /* We need separate vectors for ETH queues only (not FCoE) */
        for_each_eth_queue(bp, i) {
                bp->msix_table[msix_vec].entry = msix_vec;
@@ -1396,7 +1462,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
                msix_vec++;
        }
 
-       req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_PRESENT + 1;
+       req_cnt = BNX2X_NUM_ETH_QUEUES(bp) + CNIC_SUPPORT(bp) + 1;
 
        rc = pci_enable_msix(bp->pdev, &bp->msix_table[0], req_cnt);
 
@@ -1404,7 +1470,7 @@ int bnx2x_enable_msix(struct bnx2x *bp)
         * reconfigure number of tx/rx queues according to available
         * MSI-X vectors
         */
-       if (rc >= BNX2X_MIN_MSIX_VEC_CNT) {
+       if (rc >= BNX2X_MIN_MSIX_VEC_CNT(bp)) {
                /* how less vectors we will have? */
                int diff = req_cnt - rc;
 
@@ -1419,7 +1485,8 @@ int bnx2x_enable_msix(struct bnx2x *bp)
                /*
                 * decrease number of queues by number of unallocated entries
                 */
-               bp->num_queues -= diff;
+               bp->num_ethernet_queues -= diff;
+               bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 
                BNX2X_DEV_INFO("New queue configuration set: %d\n",
                               bp->num_queues);
@@ -1435,6 +1502,9 @@ int bnx2x_enable_msix(struct bnx2x *bp)
                BNX2X_DEV_INFO("Using single MSI-X vector\n");
                bp->flags |= USING_SINGLE_MSIX_FLAG;
 
+               BNX2X_DEV_INFO("set number of queues to 1\n");
+               bp->num_ethernet_queues = 1;
+               bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
        } else if (rc < 0) {
                BNX2X_DEV_INFO("MSI-X is not attainable  rc %d\n", rc);
                goto no_msix;
@@ -1464,9 +1534,9 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
                return -EBUSY;
        }
 
-#ifdef BCM_CNIC
-       offset++;
-#endif
+       if (CNIC_SUPPORT(bp))
+               offset++;
+
        for_each_eth_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
                snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
@@ -1485,7 +1555,7 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp)
        }
 
        i = BNX2X_NUM_ETH_QUEUES(bp);
-       offset = 1 + CNIC_PRESENT;
+       offset = 1 + CNIC_SUPPORT(bp);
        netdev_info(bp->dev, "using MSI-X  IRQs: sp %d  fp[%d] %d ... fp[%d] %d\n",
               bp->msix_table[0].vector,
               0, bp->msix_table[offset].vector,
@@ -1556,19 +1626,35 @@ static int bnx2x_setup_irqs(struct bnx2x *bp)
        return 0;
 }
 
+static void bnx2x_napi_enable_cnic(struct bnx2x *bp)
+{
+       int i;
+
+       for_each_rx_queue_cnic(bp, i)
+               napi_enable(&bnx2x_fp(bp, i, napi));
+}
+
 static void bnx2x_napi_enable(struct bnx2x *bp)
 {
        int i;
 
-       for_each_rx_queue(bp, i)
+       for_each_eth_queue(bp, i)
                napi_enable(&bnx2x_fp(bp, i, napi));
 }
 
+static void bnx2x_napi_disable_cnic(struct bnx2x *bp)
+{
+       int i;
+
+       for_each_rx_queue_cnic(bp, i)
+               napi_disable(&bnx2x_fp(bp, i, napi));
+}
+
 static void bnx2x_napi_disable(struct bnx2x *bp)
 {
        int i;
 
-       for_each_rx_queue(bp, i)
+       for_each_eth_queue(bp, i)
                napi_disable(&bnx2x_fp(bp, i, napi));
 }
 
@@ -1576,6 +1662,8 @@ void bnx2x_netif_start(struct bnx2x *bp)
 {
        if (netif_running(bp->dev)) {
                bnx2x_napi_enable(bp);
+               if (CNIC_LOADED(bp))
+                       bnx2x_napi_enable_cnic(bp);
                bnx2x_int_enable(bp);
                if (bp->state == BNX2X_STATE_OPEN)
                        netif_tx_wake_all_queues(bp->dev);
@@ -1586,14 +1674,15 @@ void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw)
 {
        bnx2x_int_disable_sync(bp, disable_hw);
        bnx2x_napi_disable(bp);
+       if (CNIC_LOADED(bp))
+               bnx2x_napi_disable_cnic(bp);
 }
 
 u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
        struct bnx2x *bp = netdev_priv(dev);
 
-#ifdef BCM_CNIC
-       if (!NO_FCOE(bp)) {
+       if (CNIC_LOADED(bp) && !NO_FCOE(bp)) {
                struct ethhdr *hdr = (struct ethhdr *)skb->data;
                u16 ether_type = ntohs(hdr->h_proto);
 
@@ -1609,7 +1698,7 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
                if ((ether_type == ETH_P_FCOE) || (ether_type == ETH_P_FIP))
                        return bnx2x_fcoe_tx(bp, txq_index);
        }
-#endif
+
        /* select a non-FCoE queue */
        return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
 }
@@ -1618,15 +1707,15 @@ u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb)
 void bnx2x_set_num_queues(struct bnx2x *bp)
 {
        /* RSS queues */
-       bp->num_queues = bnx2x_calc_num_queues(bp);
+       bp->num_ethernet_queues = bnx2x_calc_num_queues(bp);
 
-#ifdef BCM_CNIC
        /* override in STORAGE SD modes */
        if (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))
-               bp->num_queues = 1;
-#endif
+               bp->num_ethernet_queues = 1;
+
        /* Add special queues */
-       bp->num_queues += NON_ETH_CONTEXT_USE;
+       bp->num_cnic_queues = CNIC_SUPPORT(bp); /* For FCOE */
+       bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
 
        BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
 }
@@ -1653,20 +1742,18 @@ void bnx2x_set_num_queues(struct bnx2x *bp)
  * bnx2x_setup_tc() takes care of the proper TC mappings so that __skb_tx_hash()
  * will return a proper Tx index if TC is enabled (netdev->num_tc > 0).
  */
-static int bnx2x_set_real_num_queues(struct bnx2x *bp)
+static int bnx2x_set_real_num_queues(struct bnx2x *bp, int include_cnic)
 {
        int rc, tx, rx;
 
        tx = BNX2X_NUM_ETH_QUEUES(bp) * bp->max_cos;
-       rx = BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE;
+       rx = BNX2X_NUM_ETH_QUEUES(bp);
 
 /* account for fcoe queue */
-#ifdef BCM_CNIC
-       if (!NO_FCOE(bp)) {
-               rx += FCOE_PRESENT;
-               tx += FCOE_PRESENT;
+       if (include_cnic && !NO_FCOE(bp)) {
+               rx++;
+               tx++;
        }
-#endif
 
        rc = netif_set_real_num_tx_queues(bp->dev, tx);
        if (rc) {
@@ -1710,6 +1797,10 @@ static void bnx2x_set_rx_buf_size(struct bnx2x *bp)
                                  mtu +
                                  BNX2X_FW_RX_ALIGN_END;
                /* Note : rx_buf_size doesnt take into account NET_SKB_PAD */
+               if (fp->rx_buf_size + NET_SKB_PAD <= PAGE_SIZE)
+                       fp->rx_frag_size = fp->rx_buf_size + NET_SKB_PAD;
+               else
+                       fp->rx_frag_size = 0;
        }
 }
 
@@ -1859,14 +1950,26 @@ static void bnx2x_squeeze_objects(struct bnx2x *bp)
                (bp)->state = BNX2X_STATE_ERROR; \
                goto label; \
        } while (0)
-#else
+
+#define LOAD_ERROR_EXIT_CNIC(bp, label) \
+       do { \
+               bp->cnic_loaded = false; \
+               goto label; \
+       } while (0)
+#else /*BNX2X_STOP_ON_ERROR*/
 #define LOAD_ERROR_EXIT(bp, label) \
        do { \
                (bp)->state = BNX2X_STATE_ERROR; \
                (bp)->panic = 1; \
                return -EBUSY; \
        } while (0)
-#endif
+#define LOAD_ERROR_EXIT_CNIC(bp, label) \
+       do { \
+               bp->cnic_loaded = false; \
+               (bp)->panic = 1; \
+               return -EBUSY; \
+       } while (0)
+#endif /*BNX2X_STOP_ON_ERROR*/
 
 bool bnx2x_test_firmware_version(struct bnx2x *bp, bool is_err)
 {
@@ -1959,10 +2062,8 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
                fp->max_cos = 1;
 
        /* Init txdata pointers */
-#ifdef BCM_CNIC
        if (IS_FCOE_FP(fp))
                fp->txdata_ptr[0] = &bp->bnx2x_txq[FCOE_TXQ_IDX(bp)];
-#endif
        if (IS_ETH_FP(fp))
                for_each_cos_in_tx_queue(fp, cos)
                        fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos *
@@ -1980,11 +2081,95 @@ static void bnx2x_bz_fp(struct bnx2x *bp, int index)
        else if (bp->flags & GRO_ENABLE_FLAG)
                fp->mode = TPA_MODE_GRO;
 
-#ifdef BCM_CNIC
        /* We don't want TPA on an FCoE L2 ring */
        if (IS_FCOE_FP(fp))
                fp->disable_tpa = 1;
-#endif
+}
+
+int bnx2x_load_cnic(struct bnx2x *bp)
+{
+       int i, rc, port = BP_PORT(bp);
+
+       DP(NETIF_MSG_IFUP, "Starting CNIC-related load\n");
+
+       mutex_init(&bp->cnic_mutex);
+
+       rc = bnx2x_alloc_mem_cnic(bp);
+       if (rc) {
+               BNX2X_ERR("Unable to allocate bp memory for cnic\n");
+               LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+       }
+
+       rc = bnx2x_alloc_fp_mem_cnic(bp);
+       if (rc) {
+               BNX2X_ERR("Unable to allocate memory for cnic fps\n");
+               LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+       }
+
+       /* Update the number of queues with the cnic queues */
+       rc = bnx2x_set_real_num_queues(bp, 1);
+       if (rc) {
+               BNX2X_ERR("Unable to set real_num_queues including cnic\n");
+               LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic0);
+       }
+
+       /* Add all CNIC NAPI objects */
+       bnx2x_add_all_napi_cnic(bp);
+       DP(NETIF_MSG_IFUP, "cnic napi added\n");
+       bnx2x_napi_enable_cnic(bp);
+
+       rc = bnx2x_init_hw_func_cnic(bp);
+       if (rc)
+               LOAD_ERROR_EXIT_CNIC(bp, load_error_cnic1);
+
+       bnx2x_nic_init_cnic(bp);
+
+       /* Enable Timer scan */
+       REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
+
+       for_each_cnic_queue(bp, i) {
+               rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
+               if (rc) {
+                       BNX2X_ERR("Queue setup failed\n");
+                       LOAD_ERROR_EXIT(bp, load_error_cnic2);
+               }
+       }
+
+       /* Initialize Rx filter. */
+       netif_addr_lock_bh(bp->dev);
+       bnx2x_set_rx_mode(bp->dev);
+       netif_addr_unlock_bh(bp->dev);
+
+       /* re-read iscsi info */
+       bnx2x_get_iscsi_info(bp);
+       bnx2x_setup_cnic_irq_info(bp);
+       bnx2x_setup_cnic_info(bp);
+       bp->cnic_loaded = true;
+       if (bp->state == BNX2X_STATE_OPEN)
+               bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
+
+
+       DP(NETIF_MSG_IFUP, "Ending successfully CNIC-related load\n");
+
+       return 0;
+
+#ifndef BNX2X_STOP_ON_ERROR
+load_error_cnic2:
+       /* Disable Timer scan */
+       REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
+
+load_error_cnic1:
+       bnx2x_napi_disable_cnic(bp);
+       /* Update the number of queues without the cnic queues */
+       rc = bnx2x_set_real_num_queues(bp, 0);
+       if (rc)
+               BNX2X_ERR("Unable to set real_num_queues not including cnic\n");
+load_error_cnic0:
+       BNX2X_ERR("CNIC-related load failed\n");
+       bnx2x_free_fp_mem_cnic(bp);
+       bnx2x_free_mem_cnic(bp);
+       return rc;
+#endif /* ! BNX2X_STOP_ON_ERROR */
 }
 
 
@@ -1995,6 +2180,10 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        u32 load_code;
        int i, rc;
 
+       DP(NETIF_MSG_IFUP, "Starting NIC load\n");
+       DP(NETIF_MSG_IFUP,
+          "CNIC is %s\n", CNIC_ENABLED(bp) ? "enabled" : "disabled");
+
 #ifdef BNX2X_STOP_ON_ERROR
        if (unlikely(bp->panic)) {
                BNX2X_ERR("Can't load NIC when there is panic\n");
@@ -2022,9 +2211,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        DP(NETIF_MSG_IFUP, "num queues: %d", bp->num_queues);
        for_each_queue(bp, i)
                bnx2x_bz_fp(bp, i);
-       memset(bp->bnx2x_txq, 0, bp->bnx2x_txq_size *
-              sizeof(struct bnx2x_fp_txdata));
+       memset(bp->bnx2x_txq, 0, (BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS +
+                                 bp->num_cnic_queues) *
+                                 sizeof(struct bnx2x_fp_txdata));
 
+       bp->fcoe_init = false;
 
        /* Set the receive queues buffer size */
        bnx2x_set_rx_buf_size(bp);
@@ -2034,9 +2225,9 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
        /* As long as bnx2x_alloc_mem() may possibly update
         * bp->num_queues, bnx2x_set_real_num_queues() should always
-        * come after it.
+        * come after it. At this stage cnic queues are not counted.
         */
-       rc = bnx2x_set_real_num_queues(bp);
+       rc = bnx2x_set_real_num_queues(bp, 0);
        if (rc) {
                BNX2X_ERR("Unable to set real_num_queues\n");
                LOAD_ERROR_EXIT(bp, load_error0);
@@ -2050,6 +2241,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
        /* Add all NAPI objects */
        bnx2x_add_all_napi(bp);
+       DP(NETIF_MSG_IFUP, "napi added\n");
        bnx2x_napi_enable(bp);
 
        /* set pf load just before approaching the MCP */
@@ -2073,7 +2265,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                         DRV_PULSE_SEQ_MASK);
                BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
 
-               load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, 0);
+               load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ,
+                                            DRV_MSG_CODE_LOAD_REQ_WITH_LFA);
                if (!load_code) {
                        BNX2X_ERR("MCP response failure, aborting\n");
                        rc = -EBUSY;
@@ -2191,23 +2384,18 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
                LOAD_ERROR_EXIT(bp, load_error3);
        }
 
-#ifdef BCM_CNIC
-       /* Enable Timer scan */
-       REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 1);
-#endif
-
-       for_each_nondefault_queue(bp, i) {
+       for_each_nondefault_eth_queue(bp, i) {
                rc = bnx2x_setup_queue(bp, &bp->fp[i], 0);
                if (rc) {
                        BNX2X_ERR("Queue setup failed\n");
-                       LOAD_ERROR_EXIT(bp, load_error4);
+                       LOAD_ERROR_EXIT(bp, load_error3);
                }
        }
 
        rc = bnx2x_init_rss_pf(bp);
        if (rc) {
                BNX2X_ERR("PF RSS init failed\n");
-               LOAD_ERROR_EXIT(bp, load_error4);
+               LOAD_ERROR_EXIT(bp, load_error3);
        }
 
        /* Now when Clients are configured we are ready to work */
@@ -2217,7 +2405,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        rc = bnx2x_set_eth_mac(bp, true);
        if (rc) {
                BNX2X_ERR("Setting Ethernet MAC failed\n");
-               LOAD_ERROR_EXIT(bp, load_error4);
+               LOAD_ERROR_EXIT(bp, load_error3);
        }
 
        if (bp->pending_max) {
@@ -2227,6 +2415,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 
        if (bp->port.pmf)
                bnx2x_initial_phy_init(bp, load_mode);
+       bp->link_params.feature_config_flags &= ~FEATURE_CONFIG_BOOT_FROM_SAN;
 
        /* Start fast path */
 
@@ -2257,21 +2446,15 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        }
 
        if (bp->port.pmf)
-               bnx2x_update_drv_flags(bp, 1 << DRV_FLAGS_DCB_CONFIGURED, 0);
+               bnx2x_update_drv_flags(bp, 1 << DRV_FLAGS_PORT_MASK, 0);
        else
                bnx2x__link_status_update(bp);
 
        /* start the timer */
        mod_timer(&bp->timer, jiffies + bp->current_interval);
 
-#ifdef BCM_CNIC
-       /* re-read iscsi info */
-       bnx2x_get_iscsi_info(bp);
-       bnx2x_setup_cnic_irq_info(bp);
-       bnx2x_setup_cnic_info(bp);
-       if (bp->state == BNX2X_STATE_OPEN)
-               bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
-#endif
+       if (CNIC_ENABLED(bp))
+               bnx2x_load_cnic(bp);
 
        /* mark driver is loaded in shmem2 */
        if (SHMEM2_HAS(bp, drv_capabilities_flag)) {
@@ -2293,14 +2476,11 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
        if (bp->port.pmf && (bp->state != BNX2X_STATE_DIAG))
                bnx2x_dcbx_init(bp, false);
 
+       DP(NETIF_MSG_IFUP, "Ending successfully NIC load\n");
+
        return 0;
 
 #ifndef BNX2X_STOP_ON_ERROR
-load_error4:
-#ifdef BCM_CNIC
-       /* Disable Timer scan */
-       REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
-#endif
 load_error3:
        bnx2x_int_disable_sync(bp, 1);
 
@@ -2338,6 +2518,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        int i;
        bool global = false;
 
+       DP(NETIF_MSG_IFUP, "Starting NIC unload\n");
+
        /* mark driver is unloaded in shmem2 */
        if (SHMEM2_HAS(bp, drv_capabilities_flag)) {
                u32 val;
@@ -2373,14 +2555,13 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT;
        smp_mb();
 
+       if (CNIC_LOADED(bp))
+               bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+
        /* Stop Tx */
        bnx2x_tx_disable(bp);
        netdev_reset_tc(bp->dev);
 
-#ifdef BCM_CNIC
-       bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
-#endif
-
        bp->rx_mode = BNX2X_RX_MODE_NONE;
 
        del_timer_sync(&bp->timer);
@@ -2414,7 +2595,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
                bnx2x_netif_stop(bp, 1);
                /* Delete all NAPI objects */
                bnx2x_del_all_napi(bp);
-
+               if (CNIC_LOADED(bp))
+                       bnx2x_del_all_napi_cnic(bp);
                /* Release IRQs */
                bnx2x_free_irq(bp);
 
@@ -2435,12 +2617,19 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
 
        /* Free SKBs, SGEs, TPA pool and driver internals */
        bnx2x_free_skbs(bp);
+       if (CNIC_LOADED(bp))
+               bnx2x_free_skbs_cnic(bp);
        for_each_rx_queue(bp, i)
                bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE);
 
+       if (CNIC_LOADED(bp)) {
+               bnx2x_free_fp_mem_cnic(bp);
+               bnx2x_free_mem_cnic(bp);
+       }
        bnx2x_free_mem(bp);
 
        bp->state = BNX2X_STATE_CLOSED;
+       bp->cnic_loaded = false;
 
        /* Check if there are pending parity attentions. If there are - set
         * RECOVERY_IN_PROGRESS.
@@ -2460,6 +2649,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode, bool keep_link)
        if (!bnx2x_clear_pf_load(bp) && bnx2x_reset_is_done(bp, BP_PATH(bp)))
                bnx2x_disable_close_the_gate(bp);
 
+       DP(NETIF_MSG_IFUP, "Ending NIC unload\n");
+
        return 0;
 }
 
@@ -2550,7 +2741,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
 
                /* Fall out from the NAPI loop if needed */
                if (!(bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
-#ifdef BCM_CNIC
+
                        /* No need to update SB for FCoE L2 ring as long as
                         * it's connected to the default SB and the SB
                         * has been updated when NAPI was scheduled.
@@ -2559,8 +2750,6 @@ int bnx2x_poll(struct napi_struct *napi, int budget)
                                napi_complete(napi);
                                break;
                        }
-#endif
-
                        bnx2x_update_fpsb_idx(fp);
                        /* bnx2x_has_rx_work() reads the status block,
                         * thus we need to ensure that status block indices
@@ -2940,7 +3129,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
        txq_index = skb_get_queue_mapping(skb);
        txq = netdev_get_tx_queue(dev, txq_index);
 
-       BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + FCOE_PRESENT);
+       BUG_ON(txq_index >= MAX_ETH_TXQ_IDX(bp) + (CNIC_LOADED(bp) ? 1 : 0));
 
        txdata = &bp->bnx2x_txq[txq_index];
 
@@ -2957,9 +3146,18 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        skb_shinfo(skb)->nr_frags +
                        BDS_PER_TX_PKT +
                        NEXT_CNT_PER_TX_PKT(MAX_BDS_PER_TX_PKT))) {
-               bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++;
-               netif_tx_stop_queue(txq);
+               /* Handle special storage cases separately */
+               if (txdata->tx_ring_size == 0) {
+                       struct bnx2x_eth_q_stats *q_stats =
+                               bnx2x_fp_qstats(bp, txdata->parent_fp);
+                       q_stats->driver_filtered_tx_pkt++;
+                       dev_kfree_skb(skb);
+                       return NETDEV_TX_OK;
+               }
+                       bnx2x_fp_qstats(bp, txdata->parent_fp)->driver_xoff++;
+                       netif_tx_stop_queue(txq);
                BNX2X_ERR("BUG! Tx ring full when queue awake!\n");
+
                return NETDEV_TX_BUSY;
        }
 
@@ -3335,13 +3533,11 @@ int bnx2x_change_mac_addr(struct net_device *dev, void *p)
                return -EINVAL;
        }
 
-#ifdef BCM_CNIC
        if ((IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)) &&
            !is_zero_ether_addr(addr->sa_data)) {
                BNX2X_ERR("Can't configure non-zero address on iSCSI or FCoE functions in MF-SD mode\n");
                return -EINVAL;
        }
-#endif
 
        if (netif_running(dev))  {
                rc = bnx2x_set_eth_mac(bp, false);
@@ -3365,13 +3561,11 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
        u8 cos;
 
        /* Common */
-#ifdef BCM_CNIC
+
        if (IS_FCOE_IDX(fp_index)) {
                memset(sb, 0, sizeof(union host_hc_status_block));
                fp->status_blk_mapping = 0;
-
        } else {
-#endif
                /* status blocks */
                if (!CHIP_IS_E1x(bp))
                        BNX2X_PCI_FREE(sb->e2_sb,
@@ -3383,9 +3577,8 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
                                       bnx2x_fp(bp, fp_index,
                                                status_blk_mapping),
                                       sizeof(struct host_hc_status_block_e1x));
-#ifdef BCM_CNIC
        }
-#endif
+
        /* Rx */
        if (!skip_rx_queue(bp, fp_index)) {
                bnx2x_free_rx_bds(fp);
@@ -3427,10 +3620,17 @@ static void bnx2x_free_fp_mem_at(struct bnx2x *bp, int fp_index)
        /* end of fastpath */
 }
 
+void bnx2x_free_fp_mem_cnic(struct bnx2x *bp)
+{
+       int i;
+       for_each_cnic_queue(bp, i)
+               bnx2x_free_fp_mem_at(bp, i);
+}
+
 void bnx2x_free_fp_mem(struct bnx2x *bp)
 {
        int i;
-       for_each_queue(bp, i)
+       for_each_eth_queue(bp, i)
                bnx2x_free_fp_mem_at(bp, i);
 }
 
@@ -3515,14 +3715,11 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
        u8 cos;
        int rx_ring_size = 0;
 
-#ifdef BCM_CNIC
        if (!bp->rx_ring_size &&
            (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
                rx_ring_size = MIN_RX_SIZE_NONTPA;
                bp->rx_ring_size = rx_ring_size;
-       } else
-#endif
-       if (!bp->rx_ring_size) {
+       } else if (!bp->rx_ring_size) {
                rx_ring_size = MAX_RX_AVAIL/BNX2X_NUM_RX_QUEUES(bp);
 
                if (CHIP_IS_E3(bp)) {
@@ -3546,9 +3743,8 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
 
        /* Common */
        sb = &bnx2x_fp(bp, index, status_blk);
-#ifdef BCM_CNIC
+
        if (!IS_FCOE_IDX(index)) {
-#endif
                /* status blocks */
                if (!CHIP_IS_E1x(bp))
                        BNX2X_PCI_ALLOC(sb->e2_sb,
@@ -3558,9 +3754,7 @@ static int bnx2x_alloc_fp_mem_at(struct bnx2x *bp, int index)
                        BNX2X_PCI_ALLOC(sb->e1x_sb,
                                &bnx2x_fp(bp, index, status_blk_mapping),
                            sizeof(struct host_hc_status_block_e1x));
-#ifdef BCM_CNIC
        }
-#endif
 
        /* FCoE Queue uses Default SB and doesn't ACK the SB, thus no need to
         * set shortcuts for it.
@@ -3637,31 +3831,31 @@ alloc_mem_err:
        return 0;
 }
 
+int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp)
+{
+       if (!NO_FCOE(bp))
+               /* FCoE */
+               if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp)))
+                       /* we will fail load process instead of mark
+                        * NO_FCOE_FLAG
+                        */
+                       return -ENOMEM;
+
+       return 0;
+}
+
 int bnx2x_alloc_fp_mem(struct bnx2x *bp)
 {
        int i;
 
-       /**
-        * 1. Allocate FP for leading - fatal if error
-        * 2. {CNIC} Allocate FCoE FP - fatal if error
-        * 3. {CNIC} Allocate OOO + FWD - disable OOO if error
-        * 4. Allocate RSS - fix number of queues if error
+       /* 1. Allocate FP for leading - fatal if error
+        * 2. Allocate RSS - fix number of queues if error
         */
 
        /* leading */
        if (bnx2x_alloc_fp_mem_at(bp, 0))
                return -ENOMEM;
 
-#ifdef BCM_CNIC
-       if (!NO_FCOE(bp))
-               /* FCoE */
-               if (bnx2x_alloc_fp_mem_at(bp, FCOE_IDX(bp)))
-                       /* we will fail load process instead of mark
-                        * NO_FCOE_FLAG
-                        */
-                       return -ENOMEM;
-#endif
-
        /* RSS */
        for_each_nondefault_eth_queue(bp, i)
                if (bnx2x_alloc_fp_mem_at(bp, i))
@@ -3672,17 +3866,17 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp)
                int delta = BNX2X_NUM_ETH_QUEUES(bp) - i;
 
                WARN_ON(delta < 0);
-#ifdef BCM_CNIC
-               /**
-                * move non eth FPs next to last eth FP
-                * must be done in that order
-                * FCOE_IDX < FWD_IDX < OOO_IDX
-                */
+               if (CNIC_SUPPORT(bp))
+                       /* move non eth FPs next to last eth FP
+                        * must be done in that order
+                        * FCOE_IDX < FWD_IDX < OOO_IDX
+                        */
 
-               /* move FCoE fp even NO_FCOE_FLAG is on */
-               bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta);
-#endif
-               bp->num_queues -= delta;
+                       /* move FCoE fp even NO_FCOE_FLAG is on */
+                       bnx2x_move_fp(bp, FCOE_IDX(bp), FCOE_IDX(bp) - delta);
+               bp->num_ethernet_queues -= delta;
+               bp->num_queues = bp->num_ethernet_queues +
+                                bp->num_cnic_queues;
                BNX2X_ERR("Adjusted num of queues from %d to %d\n",
                          bp->num_queues + delta, bp->num_queues);
        }
@@ -3701,13 +3895,13 @@ void bnx2x_free_mem_bp(struct bnx2x *bp)
        kfree(bp->ilt);
 }
 
-int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
+int bnx2x_alloc_mem_bp(struct bnx2x *bp)
 {
        struct bnx2x_fastpath *fp;
        struct msix_entry *tbl;
        struct bnx2x_ilt *ilt;
        int msix_table_size = 0;
-       int fp_array_size;
+       int fp_array_size, txq_array_size;
        int i;
 
        /*
@@ -3717,7 +3911,7 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
        msix_table_size = bp->igu_sb_cnt + 1;
 
        /* fp array: RSS plus CNIC related L2 queues */
-       fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + NON_ETH_CONTEXT_USE;
+       fp_array_size = BNX2X_MAX_RSS_COUNT(bp) + CNIC_SUPPORT(bp);
        BNX2X_DEV_INFO("fp_array_size %d", fp_array_size);
 
        fp = kcalloc(fp_array_size, sizeof(*fp), GFP_KERNEL);
@@ -3746,12 +3940,12 @@ int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp)
                goto alloc_err;
 
        /* Allocate memory for the transmission queues array */
-       bp->bnx2x_txq_size = BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS;
-#ifdef BCM_CNIC
-       bp->bnx2x_txq_size++;
-#endif
-       bp->bnx2x_txq = kcalloc(bp->bnx2x_txq_size,
-                               sizeof(struct bnx2x_fp_txdata), GFP_KERNEL);
+       txq_array_size =
+               BNX2X_MAX_RSS_COUNT(bp) * BNX2X_MULTI_TX_COS + CNIC_SUPPORT(bp);
+       BNX2X_DEV_INFO("txq_array_size %d", txq_array_size);
+
+       bp->bnx2x_txq = kcalloc(txq_array_size, sizeof(struct bnx2x_fp_txdata),
+                               GFP_KERNEL);
        if (!bp->bnx2x_txq)
                goto alloc_err;
 
@@ -3834,7 +4028,7 @@ int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
        return LINK_CONFIG_IDX(sel_phy_idx);
 }
 
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
 int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type)
 {
        struct bnx2x *bp = netdev_priv(dev);
index 9c5ea6c5b4c7597059644c57d27f2943cb65b792..0991534f61da18b276fd3d602259371cba84f87a 100644 (file)
@@ -144,7 +144,7 @@ u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
  * @bp:                driver handle
  * @load_mode: current mode
  */
-u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode);
+int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode);
 
 /**
  * bnx2x_link_set - configure hw according to link parameters structure.
@@ -238,7 +238,6 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance);
  * @dev_instance:      private instance
  */
 irqreturn_t bnx2x_interrupt(int irq, void *dev_instance);
-#ifdef BCM_CNIC
 
 /**
  * bnx2x_cnic_notify - send command to cnic driver
@@ -262,8 +261,6 @@ void bnx2x_setup_cnic_irq_info(struct bnx2x *bp);
  */
 void bnx2x_setup_cnic_info(struct bnx2x *bp);
 
-#endif
-
 /**
  * bnx2x_int_enable - enable HW interrupts.
  *
@@ -283,7 +280,7 @@ void bnx2x_int_enable(struct bnx2x *bp);
 void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
 
 /**
- * bnx2x_nic_init - init driver internals.
+ * bnx2x_nic_init_cnic - init driver internals for cnic.
  *
  * @bp:                driver handle
  * @load_code: COMMON, PORT or FUNCTION
@@ -293,8 +290,25 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
  *  - status blocks
  *  - etc.
  */
-void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
+void bnx2x_nic_init_cnic(struct bnx2x *bp);
 
+/**
+ * bnx2x_nic_init - init driver internals.
+ *
+ * @bp:                driver handle
+ *
+ * Initializes:
+ *  - rings
+ *  - status blocks
+ *  - etc.
+ */
+void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
+/**
+ * bnx2x_alloc_mem_cnic - allocate driver's memory for cnic.
+ *
+ * @bp:                driver handle
+ */
+int bnx2x_alloc_mem_cnic(struct bnx2x *bp);
 /**
  * bnx2x_alloc_mem - allocate driver's memory.
  *
@@ -302,6 +316,12 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
  */
 int bnx2x_alloc_mem(struct bnx2x *bp);
 
+/**
+ * bnx2x_free_mem_cnic - release driver's memory for cnic.
+ *
+ * @bp:                driver handle
+ */
+void bnx2x_free_mem_cnic(struct bnx2x *bp);
 /**
  * bnx2x_free_mem - release driver's memory.
  *
@@ -407,6 +427,7 @@ bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
 void bnx2x_set_reset_in_progress(struct bnx2x *bp);
 void bnx2x_set_reset_global(struct bnx2x *bp);
 void bnx2x_disable_close_the_gate(struct bnx2x *bp);
+int bnx2x_init_hw_func_cnic(struct bnx2x *bp);
 
 /**
  * bnx2x_sp_event - handle ramrods completion.
@@ -423,6 +444,14 @@ void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
  */
 void bnx2x_ilt_set_info(struct bnx2x *bp);
 
+/**
+ * bnx2x_ilt_set_cnic_info - prepare ILT configurations for SRC
+ * and TM.
+ *
+ * @bp:                driver handle
+ */
+void bnx2x_ilt_set_info_cnic(struct bnx2x *bp);
+
 /**
  * bnx2x_dcbx_init - initialize dcbx protocol.
  *
@@ -491,12 +520,17 @@ int bnx2x_resume(struct pci_dev *pdev);
 /* Release IRQ vectors */
 void bnx2x_free_irq(struct bnx2x *bp);
 
+void bnx2x_free_fp_mem_cnic(struct bnx2x *bp);
 void bnx2x_free_fp_mem(struct bnx2x *bp);
+int bnx2x_alloc_fp_mem_cnic(struct bnx2x *bp);
 int bnx2x_alloc_fp_mem(struct bnx2x *bp);
 void bnx2x_init_rx_rings(struct bnx2x *bp);
+void bnx2x_init_rx_rings_cnic(struct bnx2x *bp);
+void bnx2x_free_skbs_cnic(struct bnx2x *bp);
 void bnx2x_free_skbs(struct bnx2x *bp);
 void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
 void bnx2x_netif_start(struct bnx2x *bp);
+int bnx2x_load_cnic(struct bnx2x *bp);
 
 /**
  * bnx2x_enable_msix - set msix configuration.
@@ -529,7 +563,7 @@ int bnx2x_poll(struct napi_struct *napi, int budget);
  *
  * @bp:                driver handle
  */
-int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp);
+int bnx2x_alloc_mem_bp(struct bnx2x *bp);
 
 /**
  * bnx2x_free_mem_bp - release memories outsize main driver structure
@@ -547,7 +581,7 @@ void bnx2x_free_mem_bp(struct bnx2x *bp);
  */
 int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
 
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
 /**
  * bnx2x_fcoe_get_wwn - return the requested WWN value for this port
  *
@@ -793,23 +827,39 @@ static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
        sge->addr_lo = 0;
 }
 
-static inline void bnx2x_add_all_napi(struct bnx2x *bp)
+static inline void bnx2x_add_all_napi_cnic(struct bnx2x *bp)
 {
        int i;
 
-       bp->num_napi_queues = bp->num_queues;
+       /* Add NAPI objects */
+       for_each_rx_queue_cnic(bp, i)
+               netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
+                              bnx2x_poll, BNX2X_NAPI_WEIGHT);
+}
+
+static inline void bnx2x_add_all_napi(struct bnx2x *bp)
+{
+       int i;
 
        /* Add NAPI objects */
-       for_each_rx_queue(bp, i)
+       for_each_eth_queue(bp, i)
                netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
                               bnx2x_poll, BNX2X_NAPI_WEIGHT);
 }
 
+static inline void bnx2x_del_all_napi_cnic(struct bnx2x *bp)
+{
+       int i;
+
+       for_each_rx_queue_cnic(bp, i)
+               netif_napi_del(&bnx2x_fp(bp, i, napi));
+}
+
 static inline void bnx2x_del_all_napi(struct bnx2x *bp)
 {
        int i;
 
-       for_each_rx_queue(bp, i)
+       for_each_eth_queue(bp, i)
                netif_napi_del(&bnx2x_fp(bp, i, napi));
 }
 
@@ -979,11 +1029,9 @@ static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
 {
        struct bnx2x *bp = fp->bp;
        if (!CHIP_IS_E1x(bp)) {
-#ifdef BCM_CNIC
                /* there are special statistics counters for FCoE 136..140 */
                if (IS_FCOE_FP(fp))
                        return bp->cnic_base_cl_id + (bp->pf_num >> 1);
-#endif
                return fp->cl_id;
        }
        return fp->cl_id + BP_PORT(bp) * FP_SB_MAX_E1x;
@@ -1102,7 +1150,6 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,
           txdata->cid, txdata->txq_index);
 }
 
-#ifdef BCM_CNIC
 static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
 {
        return bp->cnic_base_cl_id + cl_idx +
@@ -1162,7 +1209,6 @@ static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
           fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
           fp->igu_sb_id);
 }
-#endif
 
 static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
                                       struct bnx2x_fp_txdata *txdata)
@@ -1280,7 +1326,7 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
         */
        return mtu <= SGE_PAGE_SIZE && (U_ETH_SGL_SIZE * fpp) <= MAX_SKB_FRAGS;
 }
-#ifdef BCM_CNIC
+
 /**
  * bnx2x_get_iscsi_info - update iSCSI params according to licensing info.
  *
@@ -1288,7 +1334,6 @@ static inline bool bnx2x_mtu_allows_gro(int mtu)
  *
  */
 void bnx2x_get_iscsi_info(struct bnx2x *bp);
-#endif
 
 /**
  * bnx2x_link_sync_notify - send notification to other functions.
@@ -1340,13 +1385,11 @@ static inline void bnx2x_update_drv_flags(struct bnx2x *bp, u32 flags, u32 set)
 
 static inline bool bnx2x_is_valid_ether_addr(struct bnx2x *bp, u8 *addr)
 {
-       if (is_valid_ether_addr(addr))
+       if (is_valid_ether_addr(addr) ||
+           (is_zero_ether_addr(addr) &&
+            (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))))
                return true;
-#ifdef BCM_CNIC
-       if (is_zero_ether_addr(addr) &&
-           (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp)))
-               return true;
-#endif
+
        return false;
 }
 
index 2245c3895409d149c402fa70bdff529790046e28..10bc093d2ca43d9c0dd9ae309734279ccf1661bb 100644 (file)
@@ -413,8 +413,11 @@ static int bnx2x_dcbx_read_mib(struct bnx2x *bp,
 
 static void bnx2x_pfc_set_pfc(struct bnx2x *bp)
 {
+       int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
+                            GET_FLAGS(SHMEM2_RD(bp, drv_flags),
+                                      1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
        if (bp->dcbx_port_params.pfc.enabled &&
-           !(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
+           (!(bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) || mfw_configured))
                /*
                 * 1. Fills up common PFC structures if required
                 * 2. Configure NIG, MAC and BRB via the elink
@@ -552,10 +555,13 @@ static void bnx2x_dcbx_update_ets_config(struct bnx2x *bp)
 
 static void bnx2x_dcbx_update_ets_params(struct bnx2x *bp)
 {
+       int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
+                            GET_FLAGS(SHMEM2_RD(bp, drv_flags),
+                                      1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
        bnx2x_ets_disabled(&bp->link_params, &bp->link_vars);
 
        if (!bp->dcbx_port_params.ets.enabled ||
-           (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR))
+           ((bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) && !mfw_configured))
                return;
 
        if (CHIP_IS_E3B0(bp))
@@ -1802,11 +1808,14 @@ static void bnx2x_dcbx_fw_struct(struct bnx2x *bp,
        u8 cos = 0, pri = 0;
        struct priority_cos *tt2cos;
        u32 *ttp = bp->dcbx_port_params.app.traffic_type_priority;
+       int mfw_configured = SHMEM2_HAS(bp, drv_flags) &&
+                            GET_FLAGS(SHMEM2_RD(bp, drv_flags),
+                                      1 << DRV_FLAGS_DCB_MFW_CONFIGURED);
 
        memset(pfc_fw_cfg, 0, sizeof(*pfc_fw_cfg));
 
        /* to disable DCB - the structure must be zeroed */
-       if (bp->dcbx_error & DCBX_REMOTE_MIB_ERROR)
+       if ((bp->dcbx_error & DCBX_REMOTE_MIB_ERROR) && !mfw_configured)
                return;
 
        /*shortcut*/
@@ -1895,6 +1904,11 @@ static u8 bnx2x_dcbnl_set_state(struct net_device *netdev, u8 state)
        struct bnx2x *bp = netdev_priv(netdev);
        DP(BNX2X_MSG_DCB, "state = %s\n", state ? "on" : "off");
 
+       if (state && ((bp->dcbx_enabled == BNX2X_DCBX_ENABLED_OFF) ||
+                     (bp->dcbx_enabled == BNX2X_DCBX_ENABLED_INVALID))) {
+               DP(BNX2X_MSG_DCB, "Can not set dcbx to enabled while it is disabled in nvm\n");
+               return 1;
+       }
        bnx2x_dcbx_set_state(bp, (state ? true : false), bp->dcbx_enabled);
        return 0;
 }
@@ -1908,10 +1922,10 @@ static void bnx2x_dcbnl_get_perm_hw_addr(struct net_device *netdev,
        /* first the HW mac address */
        memcpy(perm_addr, netdev->dev_addr, netdev->addr_len);
 
-#ifdef BCM_CNIC
-       /* second SAN address */
-       memcpy(perm_addr+netdev->addr_len, bp->fip_mac, netdev->addr_len);
-#endif
+       if (CNIC_LOADED(bp))
+               /* second SAN address */
+               memcpy(perm_addr+netdev->addr_len, bp->fip_mac,
+                      netdev->addr_len);
 }
 
 static void bnx2x_dcbnl_set_pg_tccfg_tx(struct net_device *netdev, int prio,
@@ -2038,10 +2052,13 @@ static void bnx2x_dcbnl_set_pfc_cfg(struct net_device *netdev, int prio,
        if (!bnx2x_dcbnl_set_valid(bp) || prio >= MAX_PFC_PRIORITIES)
                return;
 
-       bp->dcbx_config_params.admin_pfc_bitmap |= ((setting ? 1 : 0) << prio);
 
-       if (setting)
+       if (setting) {
+               bp->dcbx_config_params.admin_pfc_bitmap |= (1 << prio);
                bp->dcbx_config_params.admin_pfc_tx_enable = 1;
+       } else {
+               bp->dcbx_config_params.admin_pfc_bitmap &= ~(1 << prio);
+       }
 }
 
 static void bnx2x_dcbnl_get_pfc_cfg(struct net_device *netdev, int prio,
@@ -2073,8 +2090,12 @@ static u8 bnx2x_dcbnl_set_all(struct net_device *netdev)
                           "Handling parity error recovery. Try again later\n");
                return 1;
        }
-       if (netif_running(bp->dev))
+       if (netif_running(bp->dev)) {
+               bnx2x_update_drv_flags(bp,
+                                      1 << DRV_FLAGS_DCB_MFW_CONFIGURED,
+                                      1);
                bnx2x_dcbx_init(bp, true);
+       }
        DP(BNX2X_MSG_DCB, "set_dcbx_params done (%d)\n", rc);
        if (rc)
                return 1;
index c65295dded39aa5b1965a9dd07e00974863ca297..277f17e3c8f850bac954db7d99c55b7f06d194eb 100644 (file)
@@ -62,7 +62,9 @@ static const struct {
                                                8, "[%s]: tpa_aggregations" },
        { Q_STATS_OFFSET32(total_tpa_aggregated_frames_hi),
                                        8, "[%s]: tpa_aggregated_frames"},
-       { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"}
+       { Q_STATS_OFFSET32(total_tpa_bytes_hi), 8, "[%s]: tpa_bytes"},
+       { Q_STATS_OFFSET32(driver_filtered_tx_pkt),
+                                       4, "[%s]: driver_filtered_tx_pkt" }
 };
 
 #define BNX2X_NUM_Q_STATS ARRAY_SIZE(bnx2x_q_stats_arr)
@@ -177,6 +179,8 @@ static const struct {
                        4, STATS_FLAGS_FUNC, "recoverable_errors" },
        { STATS_OFFSET32(unrecoverable_error),
                        4, STATS_FLAGS_FUNC, "unrecoverable_errors" },
+       { STATS_OFFSET32(driver_filtered_tx_pkt),
+                       4, STATS_FLAGS_FUNC, "driver_filtered_tx_pkt" },
        { STATS_OFFSET32(eee_tx_lpi),
                        4, STATS_FLAGS_PORT, "Tx LPI entry count"}
 };
@@ -227,18 +231,14 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                cmd->advertising &= ~(ADVERTISED_10000baseT_Full);
        }
 
-       if ((bp->state == BNX2X_STATE_OPEN) && (bp->link_vars.link_up)) {
-               if (!(bp->flags & MF_FUNC_DIS)) {
-                       ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed);
+       if ((bp->state == BNX2X_STATE_OPEN) && bp->link_vars.link_up &&
+           !(bp->flags & MF_FUNC_DIS)) {
                        cmd->duplex = bp->link_vars.duplex;
-               } else {
-                       ethtool_cmd_speed_set(
-                               cmd, bp->link_params.req_line_speed[cfg_idx]);
-                       cmd->duplex = bp->link_params.req_duplex[cfg_idx];
-               }
 
                if (IS_MF(bp) && !BP_NOMCP(bp))
                        ethtool_cmd_speed_set(cmd, bnx2x_get_mf_speed(bp));
+               else
+                       ethtool_cmd_speed_set(cmd, bp->link_vars.line_speed);
        } else {
                cmd->duplex = DUPLEX_UNKNOWN;
                ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
@@ -1702,7 +1702,7 @@ static int bnx2x_set_eee(struct net_device *dev, struct ethtool_eee *edata)
                                      SHMEM_EEE_ADV_STATUS_SHIFT);
        if ((advertised != (eee_cfg & SHMEM_EEE_ADV_STATUS_MASK))) {
                DP(BNX2X_MSG_ETHTOOL,
-                  "Direct manipulation of EEE advertisment is not supported\n");
+                  "Direct manipulation of EEE advertisement is not supported\n");
                return -EINVAL;
        }
 
@@ -2660,20 +2660,25 @@ static int bnx2x_set_phys_id(struct net_device *dev,
                return 1;       /* cycle on/off once per second */
 
        case ETHTOOL_ID_ON:
+               bnx2x_acquire_phy_lock(bp);
                bnx2x_set_led(&bp->link_params, &bp->link_vars,
                              LED_MODE_ON, SPEED_1000);
+               bnx2x_release_phy_lock(bp);
                break;
 
        case ETHTOOL_ID_OFF:
+               bnx2x_acquire_phy_lock(bp);
                bnx2x_set_led(&bp->link_params, &bp->link_vars,
                              LED_MODE_FRONT_PANEL_OFF, 0);
-
+               bnx2x_release_phy_lock(bp);
                break;
 
        case ETHTOOL_ID_INACTIVE:
+               bnx2x_acquire_phy_lock(bp);
                bnx2x_set_led(&bp->link_params, &bp->link_vars,
                              LED_MODE_OPER,
                              bp->link_vars.line_speed);
+               bnx2x_release_phy_lock(bp);
        }
 
        return 0;
@@ -2901,7 +2906,9 @@ static void bnx2x_get_channels(struct net_device *dev,
 static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss)
 {
        bnx2x_disable_msi(bp);
-       BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE;
+       bp->num_ethernet_queues = num_rss;
+       bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
+       BNX2X_DEV_INFO("set number of queues to %d\n", bp->num_queues);
        bnx2x_set_int_mode(bp);
 }
 
index 620fe939ecfd357ed1e852bd0350c3687886a8b5..60a83ad103700602814842e8d3f47e40386801e8 100644 (file)
        (IRO[159].base + ((funcId) * IRO[159].m1))
 #define CSTORM_FUNC_EN_OFFSET(funcId) \
        (IRO[149].base + ((funcId) * IRO[149].m1))
+#define CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hcIndex, sbId) \
+       (IRO[139].base + ((hcIndex) * IRO[139].m1) + ((sbId) * IRO[139].m2))
+#define CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hcIndex, sbId) \
+       (IRO[138].base + (((hcIndex)>>2) * IRO[138].m1) + (((hcIndex)&3) \
+       * IRO[138].m2) + ((sbId) * IRO[138].m3))
 #define CSTORM_IGU_MODE_OFFSET (IRO[157].base)
 #define CSTORM_ISCSI_CQ_SIZE_OFFSET(pfId) \
        (IRO[316].base + ((pfId) * IRO[316].m1))
index 18704929e6422ec15f0c59ec8c4abcee8802e532..3369a50ac6b4fbe087860883c9dd9afc951c3238 100644 (file)
@@ -500,7 +500,15 @@ struct port_hw_cfg {                   /* port 0: 0x12c  port 1: 0x2bc */
        u32 e3_cmn_pin_cfg1;                                /* 0x170 */
        #define PORT_HW_CFG_E3_OVER_CURRENT_MASK            0x000000FF
        #define PORT_HW_CFG_E3_OVER_CURRENT_SHIFT                    0
-       u32 reserved0[7];                                   /* 0x174 */
+
+       /*  pause on host ring */
+       u32 generic_features;                               /* 0x174 */
+       #define PORT_HW_CFG_PAUSE_ON_HOST_RING_MASK                   0x00000001
+       #define PORT_HW_CFG_PAUSE_ON_HOST_RING_SHIFT                  0
+       #define PORT_HW_CFG_PAUSE_ON_HOST_RING_DISABLED               0x00000000
+       #define PORT_HW_CFG_PAUSE_ON_HOST_RING_ENABLED                0x00000001
+
+       u32 reserved0[6];                                   /* 0x178 */
 
        u32 aeu_int_mask;                                   /* 0x190 */
 
@@ -695,6 +703,7 @@ struct port_hw_cfg {                    /* port 0: 0x12c  port 1: 0x2bc */
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54618SE    0x00000e00
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM8722       0x00000f00
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM54616      0x00001000
+               #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_BCM84834      0x00001100
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_FAILURE       0x0000fd00
                #define PORT_HW_CFG_XGXS_EXT_PHY2_TYPE_NOT_CONN      0x0000ff00
 
@@ -751,6 +760,7 @@ struct port_hw_cfg {                    /* port 0: 0x12c  port 1: 0x2bc */
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE     0x00000e00
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8722        0x00000f00
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616       0x00001000
+               #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834       0x00001100
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT_WC      0x0000fc00
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE        0x0000fd00
                #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN       0x0000ff00
@@ -1246,6 +1256,7 @@ struct drv_func_mb {
        #define DRV_MSG_CODE_VRFY_AFEX_SUPPORTED        0xa2000000
        #define REQ_BC_VER_4_VRFY_AFEX_SUPPORTED        0x00070002
        #define REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED   0x00070014
+       #define REQ_BC_VER_4_MT_SUPPORTED               0x00070201
        #define REQ_BC_VER_4_PFC_STATS_SUPPORTED        0x00070201
        #define REQ_BC_VER_4_FCOE_FEATURES              0x00070209
 
@@ -1515,12 +1526,13 @@ enum mf_cfg_afex_vlan_mode {
 /* This structure is not applicable and should not be accessed on 57711 */
 struct func_ext_cfg {
        u32 func_cfg;
-       #define MACP_FUNC_CFG_FLAGS_MASK                0x000000FF
+       #define MACP_FUNC_CFG_FLAGS_MASK                0x0000007F
        #define MACP_FUNC_CFG_FLAGS_SHIFT               0
        #define MACP_FUNC_CFG_FLAGS_ENABLED             0x00000001
        #define MACP_FUNC_CFG_FLAGS_ETHERNET            0x00000002
        #define MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD       0x00000004
        #define MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD        0x00000008
+       #define MACP_FUNC_CFG_PAUSE_ON_HOST_RING        0x00000080
 
        u32 iscsi_mac_addr_upper;
        u32 iscsi_mac_addr_lower;
@@ -2085,8 +2097,13 @@ struct shmem2_region {
 
        /* generic flags controlled by the driver */
        u32 drv_flags;
-       #define DRV_FLAGS_DCB_CONFIGURED                0x1
+       #define DRV_FLAGS_DCB_CONFIGURED                0x0
+       #define DRV_FLAGS_DCB_CONFIGURATION_ABORTED     0x1
+       #define DRV_FLAGS_DCB_MFW_CONFIGURED    0x2
 
+       #define DRV_FLAGS_PORT_MASK     ((1 << DRV_FLAGS_DCB_CONFIGURED) | \
+                       (1 << DRV_FLAGS_DCB_CONFIGURATION_ABORTED) | \
+                       (1 << DRV_FLAGS_DCB_MFW_CONFIGURED))
        /* pointer to extended dev_info shared data copied from nvm image */
        u32 extended_dev_info_shared_addr;
        u32 ncsi_oem_data_addr;
@@ -2159,6 +2176,16 @@ struct shmem2_region {
        #define SHMEM_EEE_TIME_OUTPUT_BIT          0x80000000
 
        u32 sizeof_port_stats;
+
+       /* Link Flap Avoidance */
+       u32 lfa_host_addr[PORT_MAX];
+       u32 reserved1;
+
+       u32 reserved2;                          /* Offset 0x148 */
+       u32 reserved3;                          /* Offset 0x14C */
+       u32 reserved4;                          /* Offset 0x150 */
+       u32 link_attr_sync[PORT_MAX];           /* Offset 0x154 */
+       #define LINK_ATTR_SYNC_KR2_ENABLE       (1<<0)
 };
 
 
@@ -4845,9 +4872,17 @@ struct vif_list_event_data {
        __le32 reserved2;
 };
 
-/*
- * union for all event ring message types
- */
+/* function update event data */
+struct function_update_event_data {
+       u8 echo;
+       u8 reserved;
+       __le16 reserved0;
+       __le32 reserved1;
+       __le32 reserved2;
+};
+
+
+/* union for all event ring message types */
 union event_data {
        struct vf_pf_event_data vf_pf_event;
        struct eth_event_data eth_event;
@@ -4855,6 +4890,7 @@ union event_data {
        struct vf_flr_event_data vf_flr_event;
        struct malicious_vf_event_data malicious_vf_event;
        struct vif_list_event_data vif_list_event;
+       struct function_update_event_data function_update_event;
 };
 
 
@@ -4984,8 +5020,10 @@ struct function_update_data {
        u8 allowed_priorities;
        u8 network_cos_mode;
        u8 lb_mode_en;
-       u8 reserved0;
-       __le32 reserved1;
+       u8 tx_switch_suspend_change_flg;
+       u8 tx_switch_suspend;
+       u8 echo;
+       __le16 reserved1;
 };
 
 
index fe66d902dc6224b8199dbd856ef0eebf9f2dde3b..d755acfe7a4076d71a5f03d6fcdd491c12d53cba 100644 (file)
@@ -648,15 +648,25 @@ static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num,
        return rc;
 }
 
+static int bnx2x_ilt_mem_op_cnic(struct bnx2x *bp, u8 memop)
+{
+       int rc = 0;
+
+       if (CONFIGURE_NIC_MODE(bp))
+               rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
+       if (!rc)
+               rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
+
+       return rc;
+}
+
 static int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop)
 {
        int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop);
        if (!rc)
                rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop);
-       if (!rc)
+       if (!rc && CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))
                rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop);
-       if (!rc)
-               rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop);
 
        return rc;
 }
@@ -781,12 +791,19 @@ static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp,
        bnx2x_ilt_client_init_op(bp, ilt_cli, initop);
 }
 
+static void bnx2x_ilt_init_op_cnic(struct bnx2x *bp, u8 initop)
+{
+       if (CONFIGURE_NIC_MODE(bp))
+               bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
+       bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
+}
+
 static void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop)
 {
        bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop);
        bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop);
-       bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
-       bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop);
+       if (CNIC_SUPPORT(bp) && !CONFIGURE_NIC_MODE(bp))
+               bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop);
 }
 
 static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num,
@@ -890,7 +907,6 @@ static void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count,
 /****************************************************************************
 * SRC initializations
 ****************************************************************************/
-#ifdef BCM_CNIC
 /* called during init func stage */
 static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
                              dma_addr_t t2_mapping, int src_cid_count)
@@ -915,5 +931,4 @@ static void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2,
                    U64_HI((u64)t2_mapping +
                           (src_cid_count-1) * sizeof(struct src_ent)));
 }
-#endif
 #endif /* BNX2X_INIT_OPS_H */
index e2e45ee5df33fcc75c491c78643dfe406297aabb..09096b43a6e9f7da5a9304093da121fe2e7aeb12 100644 (file)
 #define        GP_STATUS_10G_XFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
 #define        GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
 #define        GP_STATUS_10G_SFI   MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
+#define        GP_STATUS_20G_KR2 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2
 #define LINK_10THD             LINK_STATUS_SPEED_AND_DUPLEX_10THD
 #define LINK_10TFD             LINK_STATUS_SPEED_AND_DUPLEX_10TFD
 #define LINK_100TXHD           LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
 #define LINK_20GTFD            LINK_STATUS_SPEED_AND_DUPLEX_20GTFD
 #define LINK_20GXFD            LINK_STATUS_SPEED_AND_DUPLEX_20GXFD
 
-
+#define LINK_UPDATE_MASK \
+                       (LINK_STATUS_SPEED_AND_DUPLEX_MASK | \
+                        LINK_STATUS_LINK_UP | \
+                        LINK_STATUS_PHYSICAL_LINK_FLAG | \
+                        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 | \
+                        LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \
+                        LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)
 
 #define SFP_EEPROM_CON_TYPE_ADDR               0x2
        #define SFP_EEPROM_CON_TYPE_VAL_LC      0x7
@@ -244,6 +254,12 @@ static int bnx2x_check_lfa(struct link_params *params)
        if (!(link_status & LINK_STATUS_LINK_UP))
                return LFA_LINK_DOWN;
 
+       /* if loaded after BOOT from SAN, don't flap the link in any case and
+        * rely on link set by preboot driver
+        */
+       if (params->feature_config_flags & FEATURE_CONFIG_BOOT_FROM_SAN)
+               return 0;
+
        /* Verify that loopback mode is not set */
        if (params->loopback_mode)
                return LFA_LOOPBACK_ENABLED;
@@ -1431,30 +1447,47 @@ void bnx2x_pfc_statistic(struct link_params *params, struct link_vars *vars,
 /******************************************************************/
 /*                     MAC/PBF section                           */
 /******************************************************************/
-static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id, u8 port)
+static void bnx2x_set_mdio_clk(struct bnx2x *bp, u32 chip_id,
+                              u32 emac_base)
 {
-       u32 mode, emac_base;
+       u32 new_mode, cur_mode;
+       u32 clc_cnt;
        /* Set clause 45 mode, slow down the MDIO clock to 2.5MHz
         * (a value of 49==0x31) and make sure that the AUTO poll is off
         */
+       cur_mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
 
-       if (CHIP_IS_E2(bp))
-               emac_base = GRCBASE_EMAC0;
-       else
-               emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
-       mode = REG_RD(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE);
-       mode &= ~(EMAC_MDIO_MODE_AUTO_POLL |
-                 EMAC_MDIO_MODE_CLOCK_CNT);
        if (USES_WARPCORE(bp))
-               mode |= (74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+               clc_cnt = 74L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
        else
-               mode |= (49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT);
+               clc_cnt = 49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT;
 
-       mode |= (EMAC_MDIO_MODE_CLAUSE_45);
-       REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, mode);
+       if (((cur_mode & EMAC_MDIO_MODE_CLOCK_CNT) == clc_cnt) &&
+           (cur_mode & (EMAC_MDIO_MODE_CLAUSE_45)))
+               return;
+
+       new_mode = cur_mode &
+               ~(EMAC_MDIO_MODE_AUTO_POLL | EMAC_MDIO_MODE_CLOCK_CNT);
+       new_mode |= clc_cnt;
+       new_mode |= (EMAC_MDIO_MODE_CLAUSE_45);
 
+       DP(NETIF_MSG_LINK, "Changing emac_mode from 0x%x to 0x%x\n",
+          cur_mode, new_mode);
+       REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_MODE, new_mode);
        udelay(40);
 }
+
+static void bnx2x_set_mdio_emac_per_phy(struct bnx2x *bp,
+                                       struct link_params *params)
+{
+       u8 phy_index;
+       /* Set mdio clock per phy */
+       for (phy_index = INT_PHY; phy_index < params->num_phys;
+             phy_index++)
+               bnx2x_set_mdio_clk(bp, params->chip_id,
+                                  params->phy[phy_index].mdio_ctrl);
+}
+
 static u8 bnx2x_is_4_port_mode(struct bnx2x *bp)
 {
        u32 port4mode_ovwr_val;
@@ -1499,7 +1532,8 @@ static void bnx2x_emac_init(struct link_params *params,
                }
                timeout--;
        } while (val & EMAC_MODE_RESET);
-       bnx2x_set_mdio_clk(bp, params->chip_id, port);
+
+       bnx2x_set_mdio_emac_per_phy(bp, params);
        /* Set mac address */
        val = ((params->mac_addr[0] << 8) |
                params->mac_addr[1]);
@@ -1655,7 +1689,10 @@ static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
         * ports of the path
         */
 
-       if ((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) &&
+       if (((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) ||
+            (CHIP_NUM(bp) == CHIP_NUM_57840_2_20) ||
+            (CHIP_NUM(bp) == CHIP_NUM_57840_OBSOLETE)) &&
+           is_port4mode &&
            (REG_RD(bp, MISC_REG_RESET_REG_2) &
             MISC_REGISTERS_RESET_REG_2_XMAC)) {
                DP(NETIF_MSG_LINK,
@@ -1751,6 +1788,18 @@ static int bnx2x_xmac_enable(struct link_params *params,
         */
        REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
 
+       /* When XMAC is in XLGMII mode, disable sending idles for fault
+        * detection.
+        */
+       if (!(params->phy[INT_PHY].flags & FLAGS_TX_ERROR_CHECK)) {
+               REG_WR(bp, xmac_base + XMAC_REG_RX_LSS_CTRL,
+                      (XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE |
+                       XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE));
+               REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
+               REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
+                      XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
+                      XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
+       }
        /* Set Max packet size */
        REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
 
@@ -1771,6 +1820,12 @@ static int bnx2x_xmac_enable(struct link_params *params,
        /* Enable TX and RX */
        val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
 
+       /* Set MAC in XLGMII mode for dual-mode */
+       if ((vars->line_speed == SPEED_20000) &&
+           (params->phy[INT_PHY].supported &
+            SUPPORTED_20000baseKR2_Full))
+               val |= XMAC_CTRL_REG_XLGMII_ALIGN_ENB;
+
        /* Check loopback mode */
        if (lb)
                val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK;
@@ -2087,6 +2142,16 @@ static void bnx2x_update_mng(struct link_params *params, u32 link_status)
                        port_mb[params->port].link_status), link_status);
 }
 
+static void bnx2x_update_link_attr(struct link_params *params, u32 link_attr)
+{
+       struct bnx2x *bp = params->bp;
+
+       if (SHMEM2_HAS(bp, link_attr_sync))
+               REG_WR(bp, params->shmem2_base +
+                      offsetof(struct shmem2_region,
+                               link_attr_sync[params->port]), link_attr);
+}
+
 static void bnx2x_update_pfc_nig(struct link_params *params,
                struct link_vars *vars,
                struct bnx2x_nig_brb_pfc_port_params *nig_params)
@@ -2117,7 +2182,7 @@ static void bnx2x_update_pfc_nig(struct link_params *params,
                if (CHIP_IS_E3(bp))
                        ppp_enable = 0;
                else
-               ppp_enable = 1;
+                       ppp_enable = 1;
                xcm_mask &= ~(port ? NIG_LLH1_XCM_MASK_REG_LLH1_XCM_MASK_BCN :
                                     NIG_LLH0_XCM_MASK_REG_LLH0_XCM_MASK_BCN);
                xcm_out_en = 0;
@@ -2238,7 +2303,6 @@ int bnx2x_update_pfc(struct link_params *params,
        return bnx2x_status;
 }
 
-
 static int bnx2x_bmac1_enable(struct link_params *params,
                              struct link_vars *vars,
                              u8 is_lb)
@@ -2642,6 +2706,13 @@ static int bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
        u32 val;
        u16 i;
        int rc = 0;
+       u32 chip_id;
+       if (phy->flags & FLAGS_MDC_MDIO_WA_G) {
+               chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+                         ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+               bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl);
+       }
+
        if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
                bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
                              EMAC_MDIO_STATUS_10MB);
@@ -2710,6 +2781,13 @@ static int bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
        u32 tmp;
        u8 i;
        int rc = 0;
+       u32 chip_id;
+       if (phy->flags & FLAGS_MDC_MDIO_WA_G) {
+               chip_id = (REG_RD(bp, MISC_REG_CHIP_NUM) << 16) |
+                         ((REG_RD(bp, MISC_REG_CHIP_REV) & 0xf) << 12);
+               bnx2x_set_mdio_clk(bp, chip_id, phy->mdio_ctrl);
+       }
+
        if (phy->flags & FLAGS_MDC_MDIO_WA_B0)
                bnx2x_bits_en(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_STATUS,
                              EMAC_MDIO_STATUS_10MB);
@@ -3138,6 +3216,15 @@ static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
        bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
 }
 
+static void bnx2x_cl45_read_and_write(struct bnx2x *bp,
+                                     struct bnx2x_phy *phy,
+                                     u8 devad, u16 reg, u16 and_val)
+{
+       u16 val;
+       bnx2x_cl45_read(bp, phy, devad, reg, &val);
+       bnx2x_cl45_write(bp, phy, devad, reg, val & and_val);
+}
+
 int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
                   u8 devad, u16 reg, u16 *ret_val)
 {
@@ -3295,6 +3382,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)
               DEFAULT_PHY_DEV_ADDR);
 }
 
+static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy,
+                                    struct link_params *params,
+                                    u32 action)
+{
+       struct bnx2x *bp = params->bp;
+       switch (action) {
+       case PHY_INIT:
+               /* Set correct devad */
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0);
+               REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18,
+                      phy->def_md_devad);
+               break;
+       }
+}
+
 static void bnx2x_xgxs_deassert(struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
@@ -3309,10 +3411,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);
        udelay(500);
        REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
-
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
-       REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-              params->phy[INT_PHY].def_md_devad);
+       bnx2x_xgxs_specific_func(&params->phy[INT_PHY], params,
+                                PHY_INIT);
 }
 
 static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
@@ -3529,6 +3629,44 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
  * init configuration, and set/clear SGMII flag. Internal
  * phy init is done purely in phy_init stage.
  */
+static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
+                                        struct link_params *params,
+                                        struct link_vars *vars)
+{
+       struct bnx2x *bp = params->bp;
+       u16 i;
+       static struct bnx2x_reg_set reg_set[] = {
+               /* Step 1 - Program the TX/RX alignment markers */
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0xa157},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xcbe2},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0x7537},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0xa157},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xcbe2},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0x7537},
+               /* Step 2 - Configure the NP registers */
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000a},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6400},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0620},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0157},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x6464},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x3150},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x3150},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0157},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0620}
+       };
+       DP(NETIF_MSG_LINK, "Enabling 20G-KR2\n");
+
+       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_CL49_USERB0_CTRL, (3<<6));
+
+       for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+               bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+                                reg_set[i].val);
+
+       /* Start KR2 work-around timer which handles BCM8073 link-parner */
+       vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
+       bnx2x_update_link_attr(params, vars->link_attr_sync);
+}
 
 static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
                                               struct link_params *params)
@@ -3542,22 +3680,36 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
                                 MDIO_WC_REG_DIGITAL4_MISC5, 0xc000);
 }
 
+static void bnx2x_warpcore_restart_AN_KR(struct bnx2x_phy *phy,
+                                        struct link_params *params)
+{
+       /* Restart autoneg on the leading lane only */
+       struct bnx2x *bp = params->bp;
+       u16 lane = bnx2x_get_warpcore_lane(phy, params);
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, lane);
+       bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+                        MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
+
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
+}
+
 static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                                        struct link_params *params,
                                        struct link_vars *vars) {
-       u16 val16 = 0, lane, i;
+       u16 lane, i, cl72_ctrl, an_adv = 0;
+       u16 ucode_ver;
        struct bnx2x *bp = params->bp;
        static struct bnx2x_reg_set reg_set[] = {
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff},
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},
                {MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
                /* Disable Autoneg: re-enable it after adv is done. */
-               {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0}
+               {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0},
+               {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0},
        };
        DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
        /* Set to default registers that may be overriden by 10G force */
@@ -3565,12 +3717,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
+       cl72_ctrl &= 0x08ff;
+       cl72_ctrl |= 0x3800;
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
+
        /* 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)) {
                u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2;
-               val16 |= (1<<5);
+               an_adv |= (1<<5);
 
                /* Enable CL37 1G Parallel Detect */
                bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1);
@@ -3580,11 +3739,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
             (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);
+               an_adv |= (1<<7);
                /* Enable 10G Parallel Detect */
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, 0);
+
                bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
                                 MDIO_WC_REG_PAR_DET_10G_CTRL, 1);
-
+               bnx2x_set_aer_mmd(params, phy);
                DP(NETIF_MSG_LINK, "Advertize 10G\n");
        }
 
@@ -3595,6 +3757,16 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
                     ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
                      (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
                      (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
+       /* Configure the next lane if dual mode */
+       if (phy->flags & FLAGS_WC_DUAL_MODE)
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_TX0_TX_DRIVER + 0x10*(lane+1),
+                                ((0x02 <<
+                                MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
+                                 (0x06 <<
+                                  MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
+                                 (0x09 <<
+                               MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
        bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
                         MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
                         0x03f0);
@@ -3604,7 +3776,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
 
        /* Advertised speeds */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16);
+                        MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);
 
        /* Advertised and set FEC (Forward Error Correction) */
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
@@ -3628,9 +3800,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        /* Set KR Autoneg Work-Around flag for Warpcore version older than D108
         */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_UC_INFO_B1_VERSION, &val16);
-       if (val16 < 0xd108) {
-               DP(NETIF_MSG_LINK, "Enable AN KR work-around\n");
+                       MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver);
+       if (ucode_ver < 0xd108) {
+               DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n",
+                              ucode_ver);
                vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;
        }
        bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
@@ -3640,10 +3813,26 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
        bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
                        MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
 
-       /* Enable Autoneg */
-       bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
-                        MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
+       if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
+            (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) ||
+           (phy->req_line_speed == SPEED_20000)) {
+
+               CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                                 MDIO_AER_BLOCK_AER_REG, lane);
+
+               bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+                                        MDIO_WC_REG_RX1_PCI_CTRL + (0x10*lane),
+                                        (1<<11));
 
+               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7);
+               bnx2x_set_aer_mmd(params, phy);
+
+               bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+       }
+
+       /* Enable Autoneg: only on the main lane */
+       bnx2x_warpcore_restart_AN_KR(phy, params);
 }
 
 static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
@@ -3651,36 +3840,42 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
                                      struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u16 i;
+       u16 val16, i, lane;
        static struct bnx2x_reg_set reg_set[] = {
                /* Disable Autoneg */
                {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7},
-               {MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
                        0x3f00},
                {MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},
                {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
                {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
-               /* Disable CL36 PCS Tx */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0},
-               /* Double Wide Single Data Rate @ pll rate */
-               {MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},
                /* Leave cl72 training enable, needed for KR */
-               {MDIO_PMA_DEVAD,
-               MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
-               0x2}
+               {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2}
        };
 
        for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
                bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
                                 reg_set[i].val);
 
-       /* Leave CL72 enabled */
-       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
-                                MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,
-                                0x3800);
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Global registers */
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, 0);
+       /* Disable CL36 PCS Tx */
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 &= ~(0x0011 << lane);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
 
+       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 |= (0x0303 << (lane << 1));
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
        /* Set speed via PMA/PMD register */
        bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,
                         MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040);
@@ -3726,27 +3921,21 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
        bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0);
 
        /* Disable 100FX Enable and Auto-Detect */
-       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_FX100_CTRL1, &val);
-       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_FX100_CTRL1, (val & 0xFFFA));
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_FX100_CTRL1, 0xFFFA);
 
        /* Disable 100FX Idle detect */
        bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
                                 MDIO_WC_REG_FX100_CTRL3, 0x0080);
 
        /* Set Block address to Remote PHY & Clear forced_speed[5] */
-       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_DIGITAL4_MISC3, &val);
-       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_DIGITAL4_MISC3, (val & 0xFF7F));
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_DIGITAL4_MISC3, 0xFF7F);
 
        /* Turn off auto-detect & fiber mode */
-       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1, &val);
-       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
-                        (val & 0xFFEE));
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X1,
+                                 0xFFEE);
 
        /* Set filter_force_link, disable_false_link and parallel_detect */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -3808,22 +3997,65 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
                         MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x100);
 
        /* Release tx_fifo_reset */
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3,
+                                 0xFFFE);
+       /* Release rxSeqStart */
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, 0x7FFF);
+}
+
+static void bnx2x_warpcore_set_20G_force_KR2(struct bnx2x_phy *phy,
+                                            struct link_params *params)
+{
+       u16 val;
+       struct bnx2x *bp = params->bp;
+       /* Set global registers, so set AER lane to 0 */
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, 0);
+
+       /* Disable sequencer */
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, ~(1<<13));
+
+       bnx2x_set_aer_mmd(params, phy);
+
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_PMA_DEVAD,
+                                 MDIO_WC_REG_PMD_KR_CONTROL, ~(1<<1));
+       bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
+                        MDIO_AN_REG_CTRL, 0);
+       /* Turn off CL73 */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, &val);
+                       MDIO_WC_REG_CL73_USERB0_CTRL, &val);
+       val &= ~(1<<5);
+       val |= (1<<6);
        bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X3, val & 0xFFFE);
+                        MDIO_WC_REG_CL73_USERB0_CTRL, val);
+
+       /* Set 20G KR2 force speed */
+       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x1f);
+
+       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_DIGITAL4_MISC3, (1<<7));
 
-       /* Release rxSeqStart */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, &val);
+                       MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &val);
+       val &= ~(3<<14);
+       val |= (1<<15);
        bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
-}
+                        MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, val);
+       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
+                        MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0x835A);
 
-static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp,
-                                      struct bnx2x_phy *phy)
-{
-       DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n");
+       /* Enable sequencer (over lane 0) */
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, 0);
+
+       bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+                                MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, (1<<13));
+
+       bnx2x_set_aer_mmd(params, phy);
 }
 
 static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
@@ -3893,20 +4125,16 @@ static void bnx2x_warpcore_set_sgmii_speed(struct bnx2x_phy *phy,
        u16 val16, digctrl_kx1, digctrl_kx2;
 
        /* Clear XFI clock comp in non-10G single lane mode. */
-       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_RX66_CONTROL, &val16);
-       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_RX66_CONTROL, val16 & ~(3<<13));
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_RX66_CONTROL, ~(3<<13));
 
        bnx2x_warpcore_set_lpi_passthrough(phy, params);
 
        if (always_autoneg || phy->req_line_speed == SPEED_AUTO_NEG) {
                /* SGMII Autoneg */
-               bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                               MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-               bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                                MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
-                                val16 | 0x1000);
+               bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
+                                        MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
+                                        0x1000);
                DP(NETIF_MSG_LINK, "set SGMII AUTONEG\n");
        } else {
                bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
@@ -4048,7 +4276,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
                if ((cfg_pin < PIN_CFG_GPIO0_P0) ||
                    (cfg_pin > PIN_CFG_GPIO3_P1)) {
                        DP(NETIF_MSG_LINK,
-                          "ERROR: Invalid cfg pin %x for module detect indication\n",
+                          "No cfg pin %x for module detect indication\n",
                           cfg_pin);
                        return -EINVAL;
                }
@@ -4059,7 +4287,7 @@ static int bnx2x_get_mod_abs_int_cfg(struct bnx2x *bp,
                *gpio_num = MISC_REGISTERS_GPIO_3;
                *gpio_port = port;
        }
-       DP(NETIF_MSG_LINK, "MOD_ABS int GPIO%d_P%d\n", *gpio_num, *gpio_port);
+
        return 0;
 }
 
@@ -4082,7 +4310,7 @@ static int bnx2x_is_sfp_module_plugged(struct bnx2x_phy *phy,
                return 0;
 }
 static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
-                                       struct link_params *params)
+                                    struct link_params *params)
 {
        u16 gp2_status_reg0, lane;
        struct bnx2x *bp = params->bp;
@@ -4096,8 +4324,8 @@ static int bnx2x_warpcore_get_sigdet(struct bnx2x_phy *phy,
 }
 
 static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
-                                      struct link_params *params,
-                                      struct link_vars *vars)
+                                         struct link_params *params,
+                                         struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        u32 serdes_net_if;
@@ -4125,7 +4353,7 @@ static void bnx2x_warpcore_config_runtime(struct bnx2x_phy *phy,
                case PORT_HW_CFG_NET_SERDES_IF_KR:
                        /* Do we get link yet? */
                        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 0x81d1,
-                                                               &gp_status1);
+                                       &gp_status1);
                        lnkup = (gp_status1 >> (8+lane)) & 0x1;/* 1G */
                                /*10G KR*/
                        lnkup_kr = (gp_status1 >> (12+lane)) & 0x1;
@@ -4177,6 +4405,27 @@ static void bnx2x_warpcore_config_sfi(struct bnx2x_phy *phy,
        }
 }
 
+static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
+                                        struct bnx2x_phy *phy,
+                                        u8 tx_en)
+{
+       struct bnx2x *bp = params->bp;
+       u32 cfg_pin;
+       u8 port = params->port;
+
+       cfg_pin = REG_RD(bp, params->shmem_base +
+                        offsetof(struct shmem_region,
+                                 dev_info.port_hw_config[port].e3_sfp_ctrl)) &
+               PORT_HW_CFG_E3_TX_LASER_MASK;
+       /* Set the !tx_en since this pin is DISABLE_TX_LASER */
+       DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
+
+       /* For 20G, the expected pin to be used is 3 pins after the current */
+       bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
+       if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
+               bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
+}
+
 static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                                       struct link_params *params,
                                       struct link_vars *vars)
@@ -4237,9 +4486,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
                        break;
 
                case PORT_HW_CFG_NET_SERDES_IF_SFI:
-                       /* Issue Module detection */
+                       /* Issue Module detection if module is plugged, or
+                        * enabled transmitter to avoid current leakage in case
+                        * no module is connected
+                        */
                        if (bnx2x_is_sfp_module_plugged(phy, params))
                                bnx2x_sfp_module_detection(phy, params);
+                       else
+                               bnx2x_sfp_e3_set_transmitter(params, phy, 1);
 
                        bnx2x_warpcore_config_sfi(phy, params);
                        break;
@@ -4255,16 +4509,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
 
                        bnx2x_sfp_module_detection(phy, params);
                        break;
-
                case PORT_HW_CFG_NET_SERDES_IF_KR2:
-                       if (vars->line_speed != SPEED_20000) {
-                               DP(NETIF_MSG_LINK, "Speed not supported yet\n");
-                               return;
+                       if (!params->loopback_mode) {
+                               bnx2x_warpcore_enable_AN_KR(phy, params, vars);
+                       } else {
+                               DP(NETIF_MSG_LINK, "Setting KR 20G-Force\n");
+                               bnx2x_warpcore_set_20G_force_KR2(phy, params);
                        }
-                       DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
-                       bnx2x_warpcore_set_20G_KR2(bp, phy);
                        break;
-
                default:
                        DP(NETIF_MSG_LINK,
                           "Unsupported Serdes Net Interface 0x%x\n",
@@ -4278,67 +4530,58 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
        DP(NETIF_MSG_LINK, "Exit config init\n");
 }
 
-static void bnx2x_sfp_e3_set_transmitter(struct link_params *params,
-                                        struct bnx2x_phy *phy,
-                                        u8 tx_en)
-{
-       struct bnx2x *bp = params->bp;
-       u32 cfg_pin;
-       u8 port = params->port;
-
-       cfg_pin = REG_RD(bp, params->shmem_base +
-                               offsetof(struct shmem_region,
-                               dev_info.port_hw_config[port].e3_sfp_ctrl)) &
-                               PORT_HW_CFG_TX_LASER_MASK;
-       /* Set the !tx_en since this pin is DISABLE_TX_LASER */
-       DP(NETIF_MSG_LINK, "Setting WC TX to %d\n", tx_en);
-       /* For 20G, the expected pin to be used is 3 pins after the current */
-
-       bnx2x_set_cfg_pin(bp, cfg_pin, tx_en ^ 1);
-       if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)
-               bnx2x_set_cfg_pin(bp, cfg_pin + 3, tx_en ^ 1);
-}
-
 static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,
                                      struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
-       u16 val16;
+       u16 val16, lane;
        bnx2x_sfp_e3_set_transmitter(params, phy, 0);
-       bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+       bnx2x_set_mdio_emac_per_phy(bp, params);
        bnx2x_set_aer_mmd(params, phy);
        /* Global register */
        bnx2x_warpcore_reset_lane(bp, phy, 1);
 
        /* Clear loopback settings (if any) */
        /* 10G & 20G */
-       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_COMBO_IEEE0_MIICTRL, &val16);
-       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_COMBO_IEEE0_MIICTRL, val16 &
-                        0xBFFF);
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 0xBFFF);
 
-       bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_IEEE0BLK_MIICNTL, &val16);
-       bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_IEEE0BLK_MIICNTL, val16 & 0xfffe);
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0xfffe);
 
        /* Update those 1-copy registers */
        CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
                          MDIO_AER_BLOCK_AER_REG, 0);
        /* Enable 1G MDIO (1-copy) */
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
+                                 ~0x10);
+
+       bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
+                                 MDIO_WC_REG_XGXSBLK1_LANECTRL2, 0xff00);
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       /* Disable CL36 PCS Tx */
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
-                       &val16);
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16);
+       val16 |= (0x11 << lane);
+       if (phy->flags & FLAGS_WC_DUAL_MODE)
+               val16 |= (0x22 << lane);
        bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_XGXSBLK0_XGXSCONTROL,
-                        val16 & ~0x10);
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16);
 
        bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                       MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+                       MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16);
+       val16 &= ~(0x0303 << (lane << 1));
+       val16 |= (0x0101 << (lane << 1));
+       if (phy->flags & FLAGS_WC_DUAL_MODE) {
+               val16 &= ~(0x0c0c << (lane << 1));
+               val16 |= (0x0404 << (lane << 1));
+       }
+
        bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                        MDIO_WC_REG_XGXSBLK1_LANECTRL2,
-                        val16 & 0xff00);
+                        MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16);
+       /* Restore AER */
+       bnx2x_set_aer_mmd(params, phy);
 
 }
 
@@ -4351,8 +4594,9 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
        DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
                       params->loopback_mode, phy->req_line_speed);
 
-       if (phy->req_line_speed < SPEED_10000) {
-               /* 10/100/1000 */
+       if (phy->req_line_speed < SPEED_10000 ||
+           phy->supported & SUPPORTED_20000baseKR2_Full) {
+               /* 10/100/1000/20G-KR2 */
 
                /* Update those 1-copy registers */
                CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
@@ -4365,18 +4609,20 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
                lane = bnx2x_get_warpcore_lane(phy, params);
                bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                                MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
+               val16 |= (1<<lane);
+               if (phy->flags & FLAGS_WC_DUAL_MODE)
+                       val16 |= (2<<lane);
                bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
-                               MDIO_WC_REG_XGXSBLK1_LANECTRL2,
-                               val16 | (1<<lane));
+                                MDIO_WC_REG_XGXSBLK1_LANECTRL2,
+                                val16);
 
                /* Switch back to 4-copy registers */
                bnx2x_set_aer_mmd(params, phy);
        } else {
-               /* 10G & 20G */
+               /* 10G / 20G-DXGXS */
                bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
                                         MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
                                         0x4000);
-
                bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
                                         MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1);
        }
@@ -4541,6 +4787,10 @@ void bnx2x_link_status_update(struct link_params *params,
                params->feature_config_flags &=
                                        ~FEATURE_CONFIG_PFC_ENABLED;
 
+       if (SHMEM2_HAS(bp, link_attr_sync))
+               vars->link_attr_sync = SHMEM2_RD(bp,
+                                                link_attr_sync[params->port]);
+
        DP(NETIF_MSG_LINK, "link_status 0x%x  phy_link_up %x int_mask 0x%x\n",
                 vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
        DP(NETIF_MSG_LINK, "line_speed %x  duplex %x  flow_ctrl 0x%x\n",
@@ -5270,6 +5520,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
                        vars->link_status |= LINK_10GTFD;
                        break;
                case GP_STATUS_20G_DXGXS:
+               case GP_STATUS_20G_KR2:
                        vars->line_speed = SPEED_20000;
                        vars->link_status |= LINK_20GTFD;
                        break;
@@ -5377,7 +5628,15 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
        int rc = 0;
        lane = bnx2x_get_warpcore_lane(phy, params);
        /* Read gp_status */
-       if (phy->req_line_speed > SPEED_10000) {
+       if ((params->loopback_mode) &&
+           (phy->flags & FLAGS_WC_DUAL_MODE)) {
+               bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                               MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
+               bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
+                               MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
+               link_up &= 0x1;
+       } else if ((phy->req_line_speed > SPEED_10000) &&
+               (phy->supported & SUPPORTED_20000baseMLD2_Full)) {
                u16 temp_link_up;
                bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
                                1, &temp_link_up);
@@ -5390,12 +5649,22 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
                        bnx2x_ext_phy_resolve_fc(phy, params, vars);
        } else {
                bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
-                               MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1);
+                               MDIO_WC_REG_GP2_STATUS_GP_2_1,
+                               &gp_status1);
                DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
-               /* Check for either KR or generic link up. */
-               gp_status1 = ((gp_status1 >> 8) & 0xf) |
-                       ((gp_status1 >> 12) & 0xf);
-               link_up = gp_status1 & (1 << lane);
+               /* Check for either KR, 1G, or AN up. */
+               link_up = ((gp_status1 >> 8) |
+                          (gp_status1 >> 12) |
+                          (gp_status1)) &
+                       (1 << lane);
+               if (phy->supported & SUPPORTED_20000baseKR2_Full) {
+                       u16 an_link;
+                       bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                                       MDIO_AN_REG_STATUS, &an_link);
+                       bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                                       MDIO_AN_REG_STATUS, &an_link);
+                       link_up |= (an_link & (1<<2));
+               }
                if (link_up && SINGLE_MEDIA_DIRECT(params)) {
                        u16 pd, gp_status4;
                        if (phy->req_line_speed == SPEED_AUTO_NEG) {
@@ -5460,7 +5729,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
        if ((lane & 1) == 0)
                gp_speed <<= 8;
        gp_speed &= 0x3f00;
-
+       link_up = !!link_up;
 
        rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
                                         duplex);
@@ -6296,15 +6565,7 @@ static int bnx2x_update_link_down(struct link_params *params,
        vars->mac_type = MAC_TYPE_NONE;
 
        /* Update shared memory */
-       vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK |
-                              LINK_STATUS_LINK_UP |
-                              LINK_STATUS_PHYSICAL_LINK_FLAG |
-                              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 |
-                              LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE |
-                              LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE);
+       vars->link_status &= ~LINK_UPDATE_MASK;
        vars->line_speed = 0;
        bnx2x_update_mng(params, vars->link_status);
 
@@ -6452,6 +6713,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
        u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;
        u8 active_external_phy = INT_PHY;
        vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG;
+       vars->link_status &= ~LINK_UPDATE_MASK;
        for (phy_index = INT_PHY; phy_index < params->num_phys;
              phy_index++) {
                phy_vars[phy_index].flow_ctrl = 0;
@@ -6628,7 +6890,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)
                } else if (prev_line_speed != vars->line_speed) {
                        REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4,
                               0);
-                        usleep_range(1000, 2000);
+                       usleep_range(1000, 2000);
                }
        }
 
@@ -6698,7 +6960,7 @@ void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
 {
        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
                       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
-        usleep_range(1000, 2000);
+       usleep_range(1000, 2000);
        bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
                       MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
 }
@@ -6839,7 +7101,7 @@ static int bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp,
                                MDIO_PMA_DEVAD,
                                MDIO_PMA_REG_M8051_MSGOUT_REG, &fw_msgout);
 
-                usleep_range(1000, 2000);
+               usleep_range(1000, 2000);
        } while (fw_ver1 == 0 || fw_ver1 == 0x4321 ||
                        ((fw_msgout & 0xff) != 0x03 && (phy->type ==
                        PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)));
@@ -7549,13 +7811,12 @@ static int bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
                if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
                    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
                        return 0;
-                usleep_range(1000, 2000);
+               usleep_range(1000, 2000);
        }
        return -EINVAL;
 }
 
 static void bnx2x_warpcore_power_module(struct link_params *params,
-                                       struct bnx2x_phy *phy,
                                        u8 power)
 {
        u32 pin_cfg;
@@ -7579,7 +7840,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,
 static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
                                                 struct link_params *params,
                                                 u16 addr, u8 byte_cnt,
-                                                u8 *o_buf)
+                                                u8 *o_buf, u8 is_init)
 {
        int rc = 0;
        u8 i, j = 0, cnt = 0;
@@ -7596,11 +7857,11 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        /* 4 byte aligned address */
        addr32 = addr & (~0x3);
        do {
-               if (cnt == I2C_WA_PWR_ITER) {
-                       bnx2x_warpcore_power_module(params, phy, 0);
+               if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {
+                       bnx2x_warpcore_power_module(params, 0);
                        /* Note that 100us are not enough here */
-                       usleep_range(1000,1000);
-                       bnx2x_warpcore_power_module(params, phy, 1);
+                       usleep_range(1000, 2000);
+                       bnx2x_warpcore_power_module(params, 1);
                }
                rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt,
                                    data_array);
@@ -7660,7 +7921,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        /* Wait appropriate time for two-wire command to finish before
         * polling the status register
         */
-        usleep_range(1000, 2000);
+       usleep_range(1000, 2000);
 
        /* Wait up to 500us for command complete status */
        for (i = 0; i < 100; i++) {
@@ -7696,7 +7957,7 @@ static int bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
                if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
                    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
                        return 0;
-                usleep_range(1000, 2000);
+               usleep_range(1000, 2000);
        }
 
        return -EINVAL;
@@ -7719,7 +7980,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
        break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
                rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr,
-                                                          byte_cnt, o_buf);
+                                                          byte_cnt, o_buf, 0);
        break;
        }
        return rc;
@@ -7731,9 +7992,8 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 {
        struct bnx2x *bp = params->bp;
        u32 sync_offset = 0, phy_idx, media_types;
-       u8 val[2], check_limiting_mode = 0;
+       u8 gport, val[2], check_limiting_mode = 0;
        *edc_mode = EDC_MODE_LIMITING;
-
        phy->media_type = ETH_PHY_UNSPECIFIED;
        /* First check for copper cable */
        if (bnx2x_read_sfp_module_eeprom(phy,
@@ -7788,8 +8048,15 @@ static int bnx2x_get_edc_mode(struct bnx2x_phy *phy,
                               SFP_EEPROM_COMP_CODE_LR_MASK |
                               SFP_EEPROM_COMP_CODE_LRM_MASK)) == 0) {
                        DP(NETIF_MSG_LINK, "1G Optic module detected\n");
+                       gport = params->port;
                        phy->media_type = ETH_PHY_SFP_1G_FIBER;
                        phy->req_line_speed = SPEED_1000;
+                       if (!CHIP_IS_E1x(bp))
+                               gport = BP_PATH(bp) + (params->port << 1);
+                       netdev_err(bp->dev, "Warning: Link speed was forced to 1000Mbps."
+                             " Current SFP module in port %d is not"
+                             " compliant with 10G Ethernet\n",
+                        gport);
                } else {
                        int idx, cfg_idx = 0;
                        DP(NETIF_MSG_LINK, "10G Optic module detected\n");
@@ -7923,6 +8190,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
 
 {
        u8 val;
+       int rc;
        struct bnx2x *bp = params->bp;
        u16 timeout;
        /* Initialization time after hot-plug may take up to 300ms for
@@ -7930,8 +8198,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
         */
 
        for (timeout = 0; timeout < 60; timeout++) {
-               if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
-                   == 0) {
+               if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT)
+                       rc = bnx2x_warpcore_read_sfp_module_eeprom(phy,
+                                                                  params, 1,
+                                                                  1, &val, 1);
+               else
+                       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1,
+                                                         &val);
+               if (rc == 0) {
                        DP(NETIF_MSG_LINK,
                           "SFP+ module initialization took %d ms\n",
                           timeout * 5);
@@ -7939,7 +8213,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,
                }
                usleep_range(5000, 10000);
        }
-       return -EINVAL;
+       rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val);
+       return rc;
 }
 
 static void bnx2x_8727_power_module(struct bnx2x *bp,
@@ -8178,7 +8453,7 @@ static void bnx2x_warpcore_hw_reset(struct bnx2x_phy *phy,
                                    struct link_params *params)
 {
        struct bnx2x *bp = params->bp;
-       bnx2x_warpcore_power_module(params, phy, 0);
+       bnx2x_warpcore_power_module(params, 0);
        /* Put Warpcore in low power mode */
        REG_WR(bp, MISC_REG_WC0_RESET, 0x0c0e);
 
@@ -8201,7 +8476,7 @@ static void bnx2x_power_sfp_module(struct link_params *params,
                bnx2x_8727_power_module(params->bp, phy, power);
                break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:
-               bnx2x_warpcore_power_module(params, phy, power);
+               bnx2x_warpcore_power_module(params, power);
                break;
        default:
                break;
@@ -8274,7 +8549,8 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
        u32 val = REG_RD(bp, params->shmem_base +
                             offsetof(struct shmem_region, dev_info.
                                     port_feature_config[params->port].config));
-
+       /* Enabled transmitter by default */
+       bnx2x_sfp_set_transmitter(params, phy, 1);
        DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n",
                 params->port);
        /* Power up module */
@@ -8307,14 +8583,12 @@ int bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
         */
        bnx2x_set_limiting_mode(params, phy, edc_mode);
 
-       /* Enable transmit for this module if the module is approved, or
-        * if unapproved modules should also enable the Tx laser
+       /* Disable transmit for this module if the module is not approved, and
+        * laser needs to be disabled.
         */
-       if (rc == 0 ||
-           (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
-           PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-               bnx2x_sfp_set_transmitter(params, phy, 1);
-       else
+       if ((rc) &&
+           ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
+            PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER))
                bnx2x_sfp_set_transmitter(params, phy, 0);
 
        return rc;
@@ -8326,11 +8600,13 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
        struct bnx2x_phy *phy;
        u32 gpio_val;
        u8 gpio_num, gpio_port;
-       if (CHIP_IS_E3(bp))
+       if (CHIP_IS_E3(bp)) {
                phy = &params->phy[INT_PHY];
-       else
+               /* Always enable TX laser,will be disabled in case of fault */
+               bnx2x_sfp_set_transmitter(params, phy, 1);
+       } else {
                phy = &params->phy[EXT_PHY1];
-
+       }
        if (bnx2x_get_mod_abs_int_cfg(bp, params->chip_id, params->shmem_base,
                                      params->port, &gpio_num, &gpio_port) ==
            -EINVAL) {
@@ -8346,7 +8622,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
 
        /* Call the handling function in case module is detected */
        if (gpio_val == 0) {
-               bnx2x_set_mdio_clk(bp, params->chip_id, params->port);
+               bnx2x_set_mdio_emac_per_phy(bp, params);
                bnx2x_set_aer_mmd(params, phy);
 
                bnx2x_power_sfp_module(params, phy, 1);
@@ -8375,10 +8651,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                        DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
                }
        } else {
-               u32 val = REG_RD(bp, params->shmem_base +
-                                offsetof(struct shmem_region, dev_info.
-                                         port_feature_config[params->port].
-                                         config));
                bnx2x_set_gpio_int(bp, gpio_num,
                                   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
                                   gpio_port);
@@ -8386,10 +8658,6 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                 * Disable transmit for this module
                 */
                phy->media_type = ETH_PHY_NOT_PRESENT;
-               if (((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
-                    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) ||
-                   CHIP_IS_E3(bp))
-                       bnx2x_sfp_set_transmitter(params, phy, 0);
        }
 }
 
@@ -9129,6 +9397,7 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
                        bnx2x_cl45_read(bp, phy,
                                MDIO_PMA_DEVAD,
                                MDIO_PMA_LASI_RXSTAT, &rx_alarm_status);
+                       bnx2x_8727_power_module(params->bp, phy, 0);
                        return 0;
                }
        } /* Over current check */
@@ -9233,20 +9502,28 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
                                            struct bnx2x *bp,
                                            u8 port)
 {
-       u16 val, fw_ver1, fw_ver2, cnt;
+       u16 val, fw_ver2, cnt, i;
+       static struct bnx2x_reg_set reg_set[] = {
+               {MDIO_PMA_DEVAD, 0xA819, 0x0014},
+               {MDIO_PMA_DEVAD, 0xA81A, 0xc200},
+               {MDIO_PMA_DEVAD, 0xA81B, 0x0000},
+               {MDIO_PMA_DEVAD, 0xA81C, 0x0300},
+               {MDIO_PMA_DEVAD, 0xA817, 0x0009}
+       };
+       u16 fw_ver1;
 
-       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+       if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+           (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
                bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD, 0x400f, &fw_ver1);
                bnx2x_save_spirom_version(bp, port, fw_ver1 & 0xfff,
                                phy->ver_addr);
        } else {
                /* For 32-bit registers in 848xx, access via MDIO2ARM i/f. */
                /* (1) set reg 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
-               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
-               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
-               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
-               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
-               bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
+               for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set);
+                     i++)
+                       bnx2x_cl45_write(bp, phy, reg_set[i].devad,
+                                        reg_set[i].reg, reg_set[i].val);
 
                for (cnt = 0; cnt < 100; cnt++) {
                        bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
@@ -9294,8 +9571,16 @@ static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
                                struct bnx2x_phy *phy)
 {
-       u16 val, offset;
-
+       u16 val, offset, i;
+       static struct bnx2x_reg_set reg_set[] = {
+               {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED1_MASK, 0x0080},
+               {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED2_MASK, 0x0018},
+               {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_MASK, 0x0006},
+               {MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_LED3_BLINK, 0x0000},
+               {MDIO_PMA_DEVAD, MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
+                       MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ},
+               {MDIO_AN_DEVAD, 0xFFFB, 0xFFFD}
+       };
        /* PHYC_CTL_LED_CTL */
        bnx2x_cl45_read(bp, phy,
                        MDIO_PMA_DEVAD,
@@ -9307,49 +9592,20 @@ static void bnx2x_848xx_set_led(struct bnx2x *bp,
                         MDIO_PMA_DEVAD,
                         MDIO_PMA_REG_8481_LINK_SIGNAL, val);
 
-       bnx2x_cl45_write(bp, phy,
-                        MDIO_PMA_DEVAD,
-                        MDIO_PMA_REG_8481_LED1_MASK,
-                        0x80);
-
-       bnx2x_cl45_write(bp, phy,
-                        MDIO_PMA_DEVAD,
-                        MDIO_PMA_REG_8481_LED2_MASK,
-                        0x18);
-
-       /* Select activity source by Tx and Rx, as suggested by PHY AE */
-       bnx2x_cl45_write(bp, phy,
-                        MDIO_PMA_DEVAD,
-                        MDIO_PMA_REG_8481_LED3_MASK,
-                        0x0006);
-
-       /* Select the closest activity blink rate to that in 10/100/1000 */
-       bnx2x_cl45_write(bp, phy,
-                       MDIO_PMA_DEVAD,
-                       MDIO_PMA_REG_8481_LED3_BLINK,
-                       0);
-
-       /* Configure the blink rate to ~15.9 Hz */
-       bnx2x_cl45_write(bp, phy,
-                       MDIO_PMA_DEVAD,
-                       MDIO_PMA_REG_84823_CTL_SLOW_CLK_CNT_HIGH,
-                       MDIO_PMA_REG_84823_BLINK_RATE_VAL_15P9HZ);
+       for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+               bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+                                reg_set[i].val);
 
-       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+       if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+           (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834))
                offset = MDIO_PMA_REG_84833_CTL_LED_CTL_1;
        else
                offset = MDIO_PMA_REG_84823_CTL_LED_CTL_1;
 
-       bnx2x_cl45_read(bp, phy,
-                       MDIO_PMA_DEVAD, offset, &val);
-       val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
-       bnx2x_cl45_write(bp, phy,
-                        MDIO_PMA_DEVAD, offset, val);
-
-       /* 'Interrupt Mask' */
-       bnx2x_cl45_write(bp, phy,
-                        MDIO_AN_DEVAD,
-                        0xFFFB, 0xFFFD);
+       /* stretch_en for LED3*/
+       bnx2x_cl45_read_or_write(bp, phy,
+                                MDIO_PMA_DEVAD, offset,
+                                MDIO_PMA_REG_84823_LED3_STRETCH_EN);
 }
 
 static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
@@ -9359,7 +9615,8 @@ static void bnx2x_848xx_specific_func(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        switch (action) {
        case PHY_INIT:
-               if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+               if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+                   (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
                        /* Save spirom version */
                        bnx2x_save_848xx_spirom_version(phy, bp, params->port);
                }
@@ -9380,7 +9637,7 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                                       struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-       u16 autoneg_val, an_1000_val, an_10_100_val, an_10g_val;
+       u16 autoneg_val, an_1000_val, an_10_100_val;
 
        bnx2x_848xx_specific_func(phy, params, PHY_INIT);
        bnx2x_cl45_write(bp, phy,
@@ -9479,11 +9736,12 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
        if (phy->req_duplex == DUPLEX_FULL)
                autoneg_val |= (1<<8);
 
-       /* Always write this if this is not 84833.
-        * For 84833, write it only when it's a forced speed.
+       /* Always write this if this is not 84833/4.
+        * For 84833/4, write it only when it's a forced speed.
         */
-       if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
-               ((autoneg_val & (1<<12)) == 0))
+       if (((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+            (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) ||
+           ((autoneg_val & (1<<12)) == 0))
                bnx2x_cl45_write(bp, phy,
                         MDIO_AN_DEVAD,
                         MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val);
@@ -9495,14 +9753,11 @@ static int bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy,
                        DP(NETIF_MSG_LINK, "Advertising 10G\n");
                        /* Restart autoneg for 10G*/
 
-                       bnx2x_cl45_read(bp, phy,
-                                       MDIO_AN_DEVAD,
-                                       MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
-                                       &an_10g_val);
-                       bnx2x_cl45_write(bp, phy,
-                                        MDIO_AN_DEVAD,
-                                        MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
-                                        an_10g_val | 0x1000);
+                       bnx2x_cl45_read_or_write(
+                               bp, phy,
+                               MDIO_AN_DEVAD,
+                               MDIO_AN_REG_8481_10GBASE_T_AN_CTRL,
+                               0x1000);
                        bnx2x_cl45_write(bp, phy,
                                         MDIO_AN_DEVAD, MDIO_AN_REG_CTRL,
                                         0x3200);
@@ -9535,9 +9790,8 @@ static int bnx2x_8481_config_init(struct bnx2x_phy *phy,
 #define PHY84833_CMDHDLR_WAIT 300
 #define PHY84833_CMDHDLR_MAX_ARGS 5
 static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
-                                  struct link_params *params,
-                  u16 fw_cmd,
-                  u16 cmd_args[], int argc)
+                               struct link_params *params, u16 fw_cmd,
+                               u16 cmd_args[], int argc)
 {
        int idx;
        u16 val;
@@ -9551,7 +9805,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
                                MDIO_84833_CMD_HDLR_STATUS, &val);
                if (val == PHY84833_STATUS_CMD_OPEN_FOR_CMDS)
                        break;
-                usleep_range(1000, 2000);
+               usleep_range(1000, 2000);
        }
        if (idx >= PHY84833_CMDHDLR_WAIT) {
                DP(NETIF_MSG_LINK, "FW cmd: FW not ready.\n");
@@ -9572,7 +9826,7 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
                if ((val == PHY84833_STATUS_CMD_COMPLETE_PASS) ||
                        (val == PHY84833_STATUS_CMD_COMPLETE_ERROR))
                        break;
-                usleep_range(1000, 2000);
+               usleep_range(1000, 2000);
        }
        if ((idx >= PHY84833_CMDHDLR_WAIT) ||
                (val == PHY84833_STATUS_CMD_COMPLETE_ERROR)) {
@@ -9591,7 +9845,6 @@ static int bnx2x_84833_cmd_hdlr(struct bnx2x_phy *phy,
        return 0;
 }
 
-
 static int bnx2x_84833_pair_swap_cfg(struct bnx2x_phy *phy,
                                   struct link_params *params,
                                   struct link_vars *vars)
@@ -9739,11 +9992,11 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
        struct bnx2x *bp = params->bp;
        u8 port, initialize = 1;
        u16 val;
-       u32 actual_phy_selection, cms_enable;
+       u32 actual_phy_selection;
        u16 cmd_args[PHY84833_CMDHDLR_MAX_ARGS];
        int rc = 0;
 
-        usleep_range(1000, 2000);
+       usleep_range(1000, 2000);
 
        if (!(CHIP_IS_E1x(bp)))
                port = BP_PATH(bp);
@@ -9765,7 +10018,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
 
        /* Wait for GPHY to come out of reset */
        msleep(50);
-       if (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+       if ((phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+           (phy->type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
                /* BCM84823 requires that XGXS links up first @ 10G for normal
                 * behavior.
                 */
@@ -9821,7 +10075,8 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
        DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
                   params->multi_phy_config, val);
 
-       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+       if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+           (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
                bnx2x_84833_pair_swap_cfg(phy, params, vars);
 
                /* Keep AutogrEEEn disabled. */
@@ -9841,7 +10096,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                bnx2x_save_848xx_spirom_version(phy, bp, params->port);
        /* 84833 PHY has a better feature and doesn't need to support this. */
        if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823) {
-               cms_enable = REG_RD(bp, params->shmem_base +
+               u32 cms_enable = REG_RD(bp, params->shmem_base +
                        offsetof(struct shmem_region,
                        dev_info.port_hw_config[params->port].default_cfg)) &
                        PORT_HW_CFG_ENABLE_CMS_MASK;
@@ -9870,7 +10125,7 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                        return rc;
                }
 
-               if ((params->req_duplex[actual_phy_selection] == DUPLEX_FULL) &&
+               if ((phy->req_duplex == DUPLEX_FULL) &&
                    (params->eee_mode & EEE_MODE_ADV_LPI) &&
                    (bnx2x_eee_calc_timer(params) ||
                     !(params->eee_mode & EEE_MODE_ENABLE_LPI)))
@@ -9878,22 +10133,20 @@ static int bnx2x_848x3_config_init(struct bnx2x_phy *phy,
                else
                        rc = bnx2x_8483x_disable_eee(phy, params, vars);
                if (rc) {
-                       DP(NETIF_MSG_LINK, "Failed to set EEE advertisment\n");
+                       DP(NETIF_MSG_LINK, "Failed to set EEE advertisement\n");
                        return rc;
                }
        } else {
                vars->eee_status &= ~SHMEM_EEE_SUPPORTED_MASK;
        }
 
-       if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) {
+       if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+           (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) {
                /* Bring PHY out of super isolate mode as the final step. */
-               bnx2x_cl45_read(bp, phy,
-                               MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, &val);
-               val &= ~MDIO_84833_SUPER_ISOLATE;
-               bnx2x_cl45_write(bp, phy,
-                               MDIO_CTL_DEVAD,
-                               MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
+               bnx2x_cl45_read_and_write(bp, phy,
+                                         MDIO_CTL_DEVAD,
+                                         MDIO_84833_TOP_CFG_XGPHY_STRAP1,
+                                         (u16)~MDIO_84833_SUPER_ISOLATE);
        }
        return rc;
 }
@@ -10027,7 +10280,6 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
        return link_up;
 }
 
-
 static int bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len)
 {
        int status = 0;
@@ -10899,7 +11151,7 @@ static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
 /*                     STATIC PHY DECLARATION                    */
 /******************************************************************/
 
-static struct bnx2x_phy phy_null = {
+static const struct bnx2x_phy phy_null = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN,
        .addr           = 0,
        .def_md_devad   = 0,
@@ -10925,7 +11177,7 @@ static struct bnx2x_phy phy_null = {
        .phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_serdes = {
+static const struct bnx2x_phy phy_serdes = {
        .type           = PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -10960,7 +11212,7 @@ static struct bnx2x_phy phy_serdes = {
        .phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_xgxs = {
+static const struct bnx2x_phy phy_xgxs = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -10993,14 +11245,13 @@ static struct bnx2x_phy phy_xgxs = {
        .format_fw_ver  = (format_fw_ver_t)NULL,
        .hw_reset       = (hw_reset_t)NULL,
        .set_link_led   = (set_link_led_t)NULL,
-       .phy_specific_func = (phy_specific_func_t)NULL
+       .phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func
 };
-static struct bnx2x_phy phy_warpcore = {
+static const struct bnx2x_phy phy_warpcore = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT,
        .addr           = 0xff,
        .def_md_devad   = 0,
-       .flags          = (FLAGS_HW_LOCK_REQUIRED |
-                          FLAGS_TX_ERROR_CHECK),
+       .flags          = FLAGS_TX_ERROR_CHECK,
        .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .mdio_ctrl      = 0,
@@ -11034,7 +11285,7 @@ static struct bnx2x_phy phy_warpcore = {
 };
 
 
-static struct bnx2x_phy phy_7101 = {
+static const struct bnx2x_phy phy_7101 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -11063,11 +11314,11 @@ static struct bnx2x_phy phy_7101 = {
        .set_link_led   = (set_link_led_t)bnx2x_7101_set_link_led,
        .phy_specific_func = (phy_specific_func_t)NULL
 };
-static struct bnx2x_phy phy_8073 = {
+static const struct bnx2x_phy phy_8073 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
        .addr           = 0xff,
        .def_md_devad   = 0,
-       .flags          = FLAGS_HW_LOCK_REQUIRED,
+       .flags          = 0,
        .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .mdio_ctrl      = 0,
@@ -11094,7 +11345,7 @@ static struct bnx2x_phy phy_8073 = {
        .set_link_led   = (set_link_led_t)NULL,
        .phy_specific_func = (phy_specific_func_t)bnx2x_8073_specific_func
 };
-static struct bnx2x_phy phy_8705 = {
+static const struct bnx2x_phy phy_8705 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -11122,7 +11373,7 @@ static struct bnx2x_phy phy_8705 = {
        .set_link_led   = (set_link_led_t)NULL,
        .phy_specific_func = (phy_specific_func_t)NULL
 };
-static struct bnx2x_phy phy_8706 = {
+static const struct bnx2x_phy phy_8706 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -11152,12 +11403,11 @@ static struct bnx2x_phy phy_8706 = {
        .phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_8726 = {
+static const struct bnx2x_phy phy_8726 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726,
        .addr           = 0xff,
        .def_md_devad   = 0,
-       .flags          = (FLAGS_HW_LOCK_REQUIRED |
-                          FLAGS_INIT_XGXS_FIRST |
+       .flags          = (FLAGS_INIT_XGXS_FIRST |
                           FLAGS_TX_ERROR_CHECK),
        .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
        .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
@@ -11185,7 +11435,7 @@ static struct bnx2x_phy phy_8726 = {
        .phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_8727 = {
+static const struct bnx2x_phy phy_8727 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -11215,7 +11465,7 @@ static struct bnx2x_phy phy_8727 = {
        .set_link_led   = (set_link_led_t)bnx2x_8727_set_link_led,
        .phy_specific_func = (phy_specific_func_t)bnx2x_8727_specific_func
 };
-static struct bnx2x_phy phy_8481 = {
+static const struct bnx2x_phy phy_8481 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -11251,7 +11501,7 @@ static struct bnx2x_phy phy_8481 = {
        .phy_specific_func = (phy_specific_func_t)NULL
 };
 
-static struct bnx2x_phy phy_84823 = {
+static const struct bnx2x_phy phy_84823 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -11288,7 +11538,7 @@ static struct bnx2x_phy phy_84823 = {
        .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
 };
 
-static struct bnx2x_phy phy_84833 = {
+static const struct bnx2x_phy phy_84833 = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -11323,7 +11573,41 @@ static struct bnx2x_phy phy_84833 = {
        .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
 };
 
-static struct bnx2x_phy phy_54618se = {
+static const struct bnx2x_phy phy_84834 = {
+       .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834,
+       .addr           = 0xff,
+       .def_md_devad   = 0,
+       .flags          = FLAGS_FAN_FAILURE_DET_REQ |
+                           FLAGS_REARM_LATCH_SIGNAL,
+       .rx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .tx_preemphasis = {0xffff, 0xffff, 0xffff, 0xffff},
+       .mdio_ctrl      = 0,
+       .supported      = (SUPPORTED_100baseT_Half |
+                          SUPPORTED_100baseT_Full |
+                          SUPPORTED_1000baseT_Full |
+                          SUPPORTED_10000baseT_Full |
+                          SUPPORTED_TP |
+                          SUPPORTED_Autoneg |
+                          SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .media_type     = ETH_PHY_BASE_T,
+       .ver_addr       = 0,
+       .req_flow_ctrl  = 0,
+       .req_line_speed = 0,
+       .speed_cap_mask = 0,
+       .req_duplex     = 0,
+       .rsrv           = 0,
+       .config_init    = (config_init_t)bnx2x_848x3_config_init,
+       .read_status    = (read_status_t)bnx2x_848xx_read_status,
+       .link_reset     = (link_reset_t)bnx2x_848x3_link_reset,
+       .config_loopback = (config_loopback_t)NULL,
+       .format_fw_ver  = (format_fw_ver_t)bnx2x_848xx_format_ver,
+       .hw_reset       = (hw_reset_t)bnx2x_84833_hw_reset_phy,
+       .set_link_led   = (set_link_led_t)bnx2x_848xx_set_link_led,
+       .phy_specific_func = (phy_specific_func_t)bnx2x_848xx_specific_func
+};
+
+static const struct bnx2x_phy phy_54618se = {
        .type           = PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE,
        .addr           = 0xff,
        .def_md_devad   = 0,
@@ -11465,6 +11749,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                        phy->media_type = ETH_PHY_BASE_T;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_XFI:
+                       phy->supported &= (SUPPORTED_1000baseT_Full |
+                                          SUPPORTED_10000baseT_Full |
+                                          SUPPORTED_FIBRE |
+                                          SUPPORTED_Pause |
+                                          SUPPORTED_Asym_Pause);
                        phy->media_type = ETH_PHY_XFP_FIBER;
                        break;
                case PORT_HW_CFG_NET_SERDES_IF_SFI:
@@ -11496,9 +11785,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
                        phy->media_type = ETH_PHY_KR;
                        phy->flags |= FLAGS_WC_DUAL_MODE;
                        phy->supported &= (SUPPORTED_20000baseKR2_Full |
+                                          SUPPORTED_Autoneg |
                                           SUPPORTED_FIBRE |
                                           SUPPORTED_Pause |
                                           SUPPORTED_Asym_Pause);
+                       phy->flags &= ~FLAGS_TX_ERROR_CHECK;
                        break;
                default:
                        DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
@@ -11597,6 +11888,9 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
                *phy = phy_84833;
                break;
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
+               *phy = phy_84834;
+               break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54616:
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM54618SE:
                *phy = phy_54618se;
@@ -11653,9 +11947,10 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
        }
        phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
 
-       if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) &&
+       if (((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833) ||
+            (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834)) &&
            (phy->ver_addr)) {
-               /* Remove 100Mb link supported for BCM84833 when phy fw
+               /* Remove 100Mb link supported for BCM84833/4 when phy fw
                 * version lower than or equal to 1.39
                 */
                u32 raw_ver = REG_RD(bp, phy->ver_addr);
@@ -11665,12 +11960,6 @@ static int bnx2x_populate_ext_phy(struct bnx2x *bp,
                                            SUPPORTED_100baseT_Full);
        }
 
-       /* In case mdc/mdio_access of the external phy is different than the
-        * mdc/mdio access of the XGXS, a HW lock must be taken in each access
-        * to prevent one port interfere with another port's CL45 operations.
-        */
-       if (mdc_mdio_access != SHARED_HW_CFG_MDC_MDIO_ACCESS1_BOTH)
-               phy->flags |= FLAGS_HW_LOCK_REQUIRED;
        DP(NETIF_MSG_LINK, "phy_type 0x%x port %d found in index %d\n",
                   phy_type, port, phy_index);
        DP(NETIF_MSG_LINK, "             addr=0x%x, mdio_ctl=0x%x\n",
@@ -11795,7 +12084,6 @@ u32 bnx2x_phy_selection(struct link_params *params)
        return return_cfg;
 }
 
-
 int bnx2x_phy_probe(struct link_params *params)
 {
        u8 phy_index, actual_phy_idx;
@@ -11839,6 +12127,10 @@ int bnx2x_phy_probe(struct link_params *params)
                    FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET)
                        phy->flags &= ~FLAGS_TX_ERROR_CHECK;
 
+               if (!(params->feature_config_flags &
+                     FEATURE_CONFIG_MT_SUPPORT))
+                       phy->flags |= FLAGS_MDC_MDIO_WA_G;
+
                sync_offset = params->shmem_base +
                        offsetof(struct shmem_region,
                        dev_info.port_hw_config[params->port].media_type);
@@ -11866,8 +12158,8 @@ int bnx2x_phy_probe(struct link_params *params)
        return 0;
 }
 
-void bnx2x_init_bmac_loopback(struct link_params *params,
-                             struct link_vars *vars)
+static void bnx2x_init_bmac_loopback(struct link_params *params,
+                                    struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
                vars->link_up = 1;
@@ -11886,8 +12178,8 @@ void bnx2x_init_bmac_loopback(struct link_params *params,
                REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
 
-void bnx2x_init_emac_loopback(struct link_params *params,
-                             struct link_vars *vars)
+static void bnx2x_init_emac_loopback(struct link_params *params,
+                                    struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
                vars->link_up = 1;
@@ -11905,8 +12197,8 @@ void bnx2x_init_emac_loopback(struct link_params *params,
                REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
 
-void bnx2x_init_xmac_loopback(struct link_params *params,
-                             struct link_vars *vars)
+static void bnx2x_init_xmac_loopback(struct link_params *params,
+                                    struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        vars->link_up = 1;
@@ -11931,8 +12223,8 @@ void bnx2x_init_xmac_loopback(struct link_params *params,
        REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
 
-void bnx2x_init_umac_loopback(struct link_params *params,
-                             struct link_vars *vars)
+static void bnx2x_init_umac_loopback(struct link_params *params,
+                                    struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
        vars->link_up = 1;
@@ -11946,17 +12238,21 @@ void bnx2x_init_umac_loopback(struct link_params *params,
        REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 }
 
-void bnx2x_init_xgxs_loopback(struct link_params *params,
-                             struct link_vars *vars)
+static void bnx2x_init_xgxs_loopback(struct link_params *params,
+                                    struct link_vars *vars)
 {
        struct bnx2x *bp = params->bp;
-               vars->link_up = 1;
-               vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-               vars->duplex = DUPLEX_FULL;
+       struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
+       vars->link_up = 1;
+       vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
+       vars->duplex = DUPLEX_FULL;
        if (params->req_line_speed[0] == SPEED_1000)
-                       vars->line_speed = SPEED_1000;
+               vars->line_speed = SPEED_1000;
+       else if ((params->req_line_speed[0] == SPEED_20000) ||
+                (int_phy->flags & FLAGS_WC_DUAL_MODE))
+               vars->line_speed = SPEED_20000;
        else
-                       vars->line_speed = SPEED_10000;
+               vars->line_speed = SPEED_10000;
 
        if (!USES_WARPCORE(bp))
                bnx2x_xgxs_deassert(params);
@@ -11976,34 +12272,30 @@ void bnx2x_init_xgxs_loopback(struct link_params *params,
                        bnx2x_bmac_enable(params, vars, 0, 1);
        }
 
-               if (params->loopback_mode == LOOPBACK_XGXS) {
-                       /* set 10G XGXS loopback */
-                       params->phy[INT_PHY].config_loopback(
-                               &params->phy[INT_PHY],
-                               params);
-
-               } else {
-                       /* set external phy loopback */
-                       u8 phy_index;
-                       for (phy_index = EXT_PHY1;
-                             phy_index < params->num_phys; phy_index++) {
-                               if (params->phy[phy_index].config_loopback)
-                                       params->phy[phy_index].config_loopback(
-                                               &params->phy[phy_index],
-                                               params);
-                       }
-               }
-               REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
+       if (params->loopback_mode == LOOPBACK_XGXS) {
+               /* Set 10G XGXS loopback */
+               int_phy->config_loopback(int_phy, params);
+       } else {
+               /* Set external phy loopback */
+               u8 phy_index;
+               for (phy_index = EXT_PHY1;
+                     phy_index < params->num_phys; phy_index++)
+                       if (params->phy[phy_index].config_loopback)
+                               params->phy[phy_index].config_loopback(
+                                       &params->phy[phy_index],
+                                       params);
+       }
+       REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
        bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
 }
 
-static void bnx2x_set_rx_filter(struct link_params *params, u8 en)
+void bnx2x_set_rx_filter(struct link_params *params, u8 en)
 {
        struct bnx2x *bp = params->bp;
        u8 val = en * 0x1F;
 
-       /* Open the gate between the NIG to the BRB */
+       /* Open / close the gate between the NIG and the BRB */
        if (!CHIP_IS_E1x(bp))
                val |= en * 0x20;
        REG_WR(bp, NIG_REG_LLH0_BRB1_DRV_MASK + params->port*4, val);
@@ -12277,7 +12569,7 @@ int bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
         * Hold it as vars low
         */
         /* Clear link led */
-       bnx2x_set_mdio_clk(bp, params->chip_id, port);
+       bnx2x_set_mdio_emac_per_phy(bp, params);
        bnx2x_set_led(params, vars, LED_MODE_OFF, 0);
 
        if (reset_ext_phy) {
@@ -12628,7 +12920,7 @@ static int bnx2x_8727_common_init_phy(struct bnx2x *bp,
        /* Initiate PHY reset*/
        bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW,
                       port);
-        usleep_range(1000, 2000);
+       usleep_range(1000, 2000);
        bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH,
                       port);
 
@@ -12716,7 +13008,8 @@ static int bnx2x_84833_common_init_phy(struct bnx2x *bp,
 }
 
 static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
-                                              struct bnx2x_phy *phy)
+                                   struct bnx2x_phy *phy,
+                                   u8 port)
 {
        u16 val, cnt;
        /* Wait for FW completing its initialization. */
@@ -12726,7 +13019,7 @@ static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
                                MDIO_PMA_REG_CTRL, &val);
                if (!(val & (1<<15)))
                        break;
-                usleep_range(1000, 2000);
+               usleep_range(1000, 2000);
        }
        if (cnt >= 1500) {
                DP(NETIF_MSG_LINK, "84833 reset timeout\n");
@@ -12743,26 +13036,28 @@ static int bnx2x_84833_pre_init_phy(struct bnx2x *bp,
                         MDIO_84833_TOP_CFG_XGPHY_STRAP1, val);
 
        /* Save spirom version */
-       bnx2x_save_848xx_spirom_version(phy, bp, PORT_0);
+       bnx2x_save_848xx_spirom_version(phy, bp, port);
        return 0;
 }
 
 int bnx2x_pre_init_phy(struct bnx2x *bp,
                                  u32 shmem_base,
                                  u32 shmem2_base,
-                                 u32 chip_id)
+                                 u32 chip_id,
+                                 u8 port)
 {
        int rc = 0;
        struct bnx2x_phy phy;
-       bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
        if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, shmem2_base,
-                              PORT_0, &phy)) {
+                              port, &phy) != 0) {
                DP(NETIF_MSG_LINK, "populate_phy failed\n");
                return -EINVAL;
        }
+       bnx2x_set_mdio_clk(bp, chip_id, phy.mdio_ctrl);
        switch (phy.type) {
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
-               rc = bnx2x_84833_pre_init_phy(bp, &phy);
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
+               rc = bnx2x_84833_pre_init_phy(bp, &phy, port);
                break;
        default:
                break;
@@ -12799,6 +13094,7 @@ static int bnx2x_ext_phy_common_init(struct bnx2x *bp, u32 shmem_base_path[],
                                                phy_index, chip_id);
                break;
        case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+       case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834:
                /* GPIO3's are linked, and so both need to be toggled
                 * to obtain required 2us pulse.
                 */
@@ -12830,8 +13126,9 @@ int bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base_path[],
        u32 phy_ver, val;
        u8 phy_index = 0;
        u32 ext_phy_type, ext_phy_config;
-       bnx2x_set_mdio_clk(bp, chip_id, PORT_0);
-       bnx2x_set_mdio_clk(bp, chip_id, PORT_1);
+
+       bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC0);
+       bnx2x_set_mdio_clk(bp, chip_id, GRCBASE_EMAC1);
        DP(NETIF_MSG_LINK, "Begin common phy init\n");
        if (CHIP_IS_E3(bp)) {
                /* Enable EPIO */
@@ -12892,6 +13189,7 @@ static void bnx2x_check_over_curr(struct link_params *params,
                                            " error.\n",
                         params->port);
                        vars->phy_flags |= PHY_OVER_CURRENT_FLAG;
+                       bnx2x_warpcore_power_module(params, 0);
                }
        } else
                vars->phy_flags &= ~PHY_OVER_CURRENT_FLAG;
@@ -12919,7 +13217,7 @@ static u8 bnx2x_analyze_link_error(struct link_params *params,
                DP(NETIF_MSG_LINK, "Analyze TX Fault\n");
                break;
        default:
-               DP(NETIF_MSG_LINK, "Analyze UNKOWN\n");
+               DP(NETIF_MSG_LINK, "Analyze UNKNOWN\n");
        }
        DP(NETIF_MSG_LINK, "Link changed:[%x %x]->%x\n", vars->link_up,
           old_status, status);
@@ -13071,6 +13369,108 @@ static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy,
                }
        }
 }
+static void bnx2x_disable_kr2(struct link_params *params,
+                             struct link_vars *vars,
+                             struct bnx2x_phy *phy)
+{
+       struct bnx2x *bp = params->bp;
+       int i;
+       static struct bnx2x_reg_set reg_set[] = {
+               /* Step 1 - Program the TX/RX alignment markers */
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
+               {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
+       };
+       DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
+
+       for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
+               bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
+                                reg_set[i].val);
+       vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
+       bnx2x_update_link_attr(params, vars->link_attr_sync);
+
+       /* Restart AN on leading lane */
+       bnx2x_warpcore_restart_AN_KR(phy, params);
+}
+
+static void bnx2x_kr2_recovery(struct link_params *params,
+                              struct link_vars *vars,
+                              struct bnx2x_phy *phy)
+{
+       struct bnx2x *bp = params->bp;
+       DP(NETIF_MSG_LINK, "KR2 recovery\n");
+       bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
+       bnx2x_warpcore_restart_AN_KR(phy, params);
+}
+
+static void bnx2x_check_kr2_wa(struct link_params *params,
+                              struct link_vars *vars,
+                              struct bnx2x_phy *phy)
+{
+       struct bnx2x *bp = params->bp;
+       u16 base_page, next_page, not_kr2_device, lane;
+       int sigdet = bnx2x_warpcore_get_sigdet(phy, params);
+
+       if (!sigdet) {
+               if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
+                       bnx2x_kr2_recovery(params, vars, phy);
+               return;
+       }
+
+       lane = bnx2x_get_warpcore_lane(phy, params);
+       CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+                         MDIO_AER_BLOCK_AER_REG, lane);
+       bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                       MDIO_AN_REG_LP_AUTO_NEG, &base_page);
+       bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
+                       MDIO_AN_REG_LP_AUTO_NEG2, &next_page);
+       bnx2x_set_aer_mmd(params, phy);
+
+       /* CL73 has not begun yet */
+       if (base_page == 0) {
+               if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
+                       bnx2x_kr2_recovery(params, vars, phy);
+               return;
+       }
+
+       /* In case NP bit is not set in the BasePage, or it is set,
+        * but only KX is advertised, declare this link partner as non-KR2
+        * device.
+        */
+       not_kr2_device = (((base_page & 0x8000) == 0) ||
+                         (((base_page & 0x8000) &&
+                           ((next_page & 0xe0) == 0x2))));
+
+       /* In case KR2 is already disabled, check if we need to re-enable it */
+       if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
+               if (!not_kr2_device) {
+                       DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page,
+                                      next_page);
+                       bnx2x_kr2_recovery(params, vars, phy);
+               }
+               return;
+       }
+       /* KR2 is enabled, but not KR2 device */
+       if (not_kr2_device) {
+               /* Disable KR2 on both lanes */
+               DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, next_page);
+               bnx2x_disable_kr2(params, vars, phy);
+               return;
+       }
+}
+
 void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
 {
        u16 phy_idx;
@@ -13088,6 +13488,9 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
        if (CHIP_IS_E3(bp)) {
                struct bnx2x_phy *phy = &params->phy[INT_PHY];
                bnx2x_set_aer_mmd(params, phy);
+               if ((phy->supported & SUPPORTED_20000baseKR2_Full) &&
+                   (phy->speed_cap_mask & SPEED_20000))
+                       bnx2x_check_kr2_wa(params, vars, phy);
                bnx2x_check_over_curr(params, vars);
                if (vars->rx_tx_asic_rst)
                        bnx2x_warpcore_config_runtime(phy, params, vars);
@@ -13108,27 +13511,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
                                bnx2x_update_mng(params, vars->link_status);
                        }
                }
-
-       }
-
-}
-
-u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base, u32 shmem2_base)
-{
-       u8 phy_index;
-       struct bnx2x_phy phy;
-       for (phy_index = INT_PHY; phy_index < MAX_PHYS;
-             phy_index++) {
-               if (bnx2x_populate_phy(bp, phy_index, shmem_base, shmem2_base,
-                                      0, &phy) != 0) {
-                       DP(NETIF_MSG_LINK, "populate phy failed\n");
-                       return 0;
-               }
-
-               if (phy.flags & FLAGS_HW_LOCK_REQUIRED)
-                       return 1;
        }
-       return 0;
 }
 
 u8 bnx2x_fan_failure_det_req(struct bnx2x *bp,
index 9165b89a4b1923d6948bcefba018f2d6cc707633..ee6e7ec854577b8687bb1e8688ed7e83261664cc 100644 (file)
@@ -139,8 +139,6 @@ struct bnx2x_phy {
        u8 addr;
        u8 def_md_devad;
        u16 flags;
-       /* Require HW lock */
-#define FLAGS_HW_LOCK_REQUIRED         (1<<0)
        /* No Over-Current detection */
 #define FLAGS_NOC                      (1<<1)
        /* Fan failure detection required */
@@ -156,6 +154,7 @@ struct bnx2x_phy {
 #define FLAGS_MDC_MDIO_WA_B0           (1<<10)
 #define FLAGS_TX_ERROR_CHECK           (1<<12)
 #define FLAGS_EEE                      (1<<13)
+#define FLAGS_MDC_MDIO_WA_G            (1<<15)
 
        /* preemphasis values for the rx side */
        u16 rx_preemphasis[4];
@@ -267,6 +266,9 @@ struct link_params {
 #define FEATURE_CONFIG_AUTOGREEEN_ENABLED                      (1<<9)
 #define FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED             (1<<10)
 #define FEATURE_CONFIG_DISABLE_REMOTE_FAULT_DET                (1<<11)
+#define FEATURE_CONFIG_MT_SUPPORT                      (1<<13)
+#define FEATURE_CONFIG_BOOT_FROM_SAN                   (1<<14)
+
        /* Will be populated during common init */
        struct bnx2x_phy phy[MAX_PHYS];
 
@@ -347,6 +349,8 @@ struct link_vars {
        u8 rx_tx_asic_rst;
        u8 turn_to_run_wc_rt;
        u16 rsrv2;
+       /* The same definitions as the shmem2 parameter */
+       u32 link_attr_sync;
 };
 
 /***********************************************************/
@@ -418,10 +422,6 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 
 void bnx2x_hw_reset_phy(struct link_params *params);
 
-/* Checks if HW lock is required for this phy/board type */
-u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base,
-                         u32 shmem2_base);
-
 /* Check swap bit and adjust PHY order */
 u32 bnx2x_phy_selection(struct link_params *params);
 
@@ -432,7 +432,8 @@ int bnx2x_phy_probe(struct link_params *params);
 u8 bnx2x_fan_failure_det_req(struct bnx2x *bp, u32 shmem_base,
                             u32 shmem2_base, u8 port);
 
-
+/* Open / close the gate between the NIG and the BRB */
+void bnx2x_set_rx_filter(struct link_params *params, u8 en);
 
 /* DCBX structs */
 
@@ -459,9 +460,6 @@ struct bnx2x_nig_brb_pfc_port_params {
        u32 rx_cos_priority_mask[DCBX_MAX_NUM_COS];
        u32 llfc_high_priority_classes;
        u32 llfc_low_priority_classes;
-       /* BRB */
-       u32 cos0_pauseable;
-       u32 cos1_pauseable;
 };
 
 
index d5648fc666bdf6f663505bbb433abebac08dbd48..940ef859dc6054338b884abce2c519e0ba4a89ea 100644 (file)
@@ -79,7 +79,7 @@
 /* Time in jiffies before concluding the transmitter is hung */
 #define TX_TIMEOUT             (5*HZ)
 
-static char version[] __devinitdata =
+static char version[] =
        "Broadcom NetXtreme II 5771x/578xx 10/20-Gigabit Ethernet Driver "
        DRV_MODULE_NAME " " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
@@ -149,7 +149,7 @@ enum bnx2x_board_type {
 /* indexed by board_type, above */
 static struct {
        char *name;
-} board_info[] __devinitdata = {
+} board_info[] = {
        { "Broadcom NetXtreme II BCM57710 10 Gigabit PCIe [Everest]" },
        { "Broadcom NetXtreme II BCM57711 10 Gigabit PCIe" },
        { "Broadcom NetXtreme II BCM57711E 10 Gigabit PCIe" },
@@ -791,10 +791,9 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 
                /* host sb data */
 
-#ifdef BCM_CNIC
                if (IS_FCOE_FP(fp))
                        continue;
-#endif
+
                BNX2X_ERR("     run indexes (");
                for (j = 0; j < HC_SB_MAX_SM; j++)
                        pr_cont("0x%x%s",
@@ -859,7 +858,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
 #ifdef BNX2X_STOP_ON_ERROR
        /* Rings */
        /* Rx */
-       for_each_rx_queue(bp, i) {
+       for_each_valid_rx_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
 
                start = RX_BD(le16_to_cpu(*fp->rx_cons_sb) - 10);
@@ -893,7 +892,7 @@ void bnx2x_panic_dump(struct bnx2x *bp)
        }
 
        /* Tx */
-       for_each_tx_queue(bp, i) {
+       for_each_valid_tx_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
                for_each_cos_in_tx_queue(fp, cos) {
                        struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
@@ -1483,7 +1482,7 @@ static void bnx2x_igu_int_disable(struct bnx2x *bp)
                BNX2X_ERR("BUG! proper val not read from IGU!\n");
 }
 
-void bnx2x_int_disable(struct bnx2x *bp)
+static void bnx2x_int_disable(struct bnx2x *bp)
 {
        if (bp->common.int_block == INT_BLOCK_HC)
                bnx2x_hc_int_disable(bp);
@@ -1504,9 +1503,8 @@ void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw)
        if (msix) {
                synchronize_irq(bp->msix_table[0].vector);
                offset = 1;
-#ifdef BCM_CNIC
-               offset++;
-#endif
+               if (CNIC_SUPPORT(bp))
+                       offset++;
                for_each_eth_queue(bp, i)
                        synchronize_irq(bp->msix_table[offset++].vector);
        } else
@@ -1588,9 +1586,8 @@ static bool bnx2x_trylock_leader_lock(struct bnx2x *bp)
        return bnx2x_trylock_hw_lock(bp, bnx2x_get_leader_lock_resource(bp));
 }
 
-#ifdef BCM_CNIC
 static void bnx2x_cnic_cfc_comp(struct bnx2x *bp, int cid, u8 err);
-#endif
+
 
 void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe)
 {
@@ -1720,7 +1717,7 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
        for_each_eth_queue(bp, i) {
                struct bnx2x_fastpath *fp = &bp->fp[i];
 
-               mask = 0x2 << (fp->index + CNIC_PRESENT);
+               mask = 0x2 << (fp->index + CNIC_SUPPORT(bp));
                if (status & mask) {
                        /* Handle Rx or Tx according to SB id */
                        prefetch(fp->rx_cons_sb);
@@ -1732,22 +1729,23 @@ irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
                }
        }
 
-#ifdef BCM_CNIC
-       mask = 0x2;
-       if (status & (mask | 0x1)) {
-               struct cnic_ops *c_ops = NULL;
+       if (CNIC_SUPPORT(bp)) {
+               mask = 0x2;
+               if (status & (mask | 0x1)) {
+                       struct cnic_ops *c_ops = NULL;
 
-               if (likely(bp->state == BNX2X_STATE_OPEN)) {
-                       rcu_read_lock();
-                       c_ops = rcu_dereference(bp->cnic_ops);
-                       if (c_ops)
-                               c_ops->cnic_handler(bp->cnic_data, NULL);
-                       rcu_read_unlock();
-               }
+                       if (likely(bp->state == BNX2X_STATE_OPEN)) {
+                               rcu_read_lock();
+                               c_ops = rcu_dereference(bp->cnic_ops);
+                               if (c_ops)
+                                       c_ops->cnic_handler(bp->cnic_data,
+                                                           NULL);
+                               rcu_read_unlock();
+                       }
 
-               status &= ~mask;
+                       status &= ~mask;
+               }
        }
-#endif
 
        if (unlikely(status & 0x1)) {
                queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
@@ -2034,40 +2032,39 @@ int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port)
        return 0;
 }
 
-static int bnx2x_set_spio(struct bnx2x *bp, int spio_num, u32 mode)
+static int bnx2x_set_spio(struct bnx2x *bp, int spio, u32 mode)
 {
-       u32 spio_mask = (1 << spio_num);
        u32 spio_reg;
 
-       if ((spio_num < MISC_REGISTERS_SPIO_4) ||
-           (spio_num > MISC_REGISTERS_SPIO_7)) {
-               BNX2X_ERR("Invalid SPIO %d\n", spio_num);
+       /* Only 2 SPIOs are configurable */
+       if ((spio != MISC_SPIO_SPIO4) && (spio != MISC_SPIO_SPIO5)) {
+               BNX2X_ERR("Invalid SPIO 0x%x\n", spio);
                return -EINVAL;
        }
 
        bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_SPIO);
        /* read SPIO and mask except the float bits */
-       spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_REGISTERS_SPIO_FLOAT);
+       spio_reg = (REG_RD(bp, MISC_REG_SPIO) & MISC_SPIO_FLOAT);
 
        switch (mode) {
-       case MISC_REGISTERS_SPIO_OUTPUT_LOW:
-               DP(NETIF_MSG_HW, "Set SPIO %d -> output low\n", spio_num);
+       case MISC_SPIO_OUTPUT_LOW:
+               DP(NETIF_MSG_HW, "Set SPIO 0x%x -> output low\n", spio);
                /* clear FLOAT and set CLR */
-               spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
-               spio_reg |=  (spio_mask << MISC_REGISTERS_SPIO_CLR_POS);
+               spio_reg &= ~(spio << MISC_SPIO_FLOAT_POS);
+               spio_reg |=  (spio << MISC_SPIO_CLR_POS);
                break;
 
-       case MISC_REGISTERS_SPIO_OUTPUT_HIGH:
-               DP(NETIF_MSG_HW, "Set SPIO %d -> output high\n", spio_num);
+       case MISC_SPIO_OUTPUT_HIGH:
+               DP(NETIF_MSG_HW, "Set SPIO 0x%x -> output high\n", spio);
                /* clear FLOAT and set SET */
-               spio_reg &= ~(spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
-               spio_reg |=  (spio_mask << MISC_REGISTERS_SPIO_SET_POS);
+               spio_reg &= ~(spio << MISC_SPIO_FLOAT_POS);
+               spio_reg |=  (spio << MISC_SPIO_SET_POS);
                break;
 
-       case MISC_REGISTERS_SPIO_INPUT_HI_Z:
-               DP(NETIF_MSG_HW, "Set SPIO %d -> input\n", spio_num);
+       case MISC_SPIO_INPUT_HI_Z:
+               DP(NETIF_MSG_HW, "Set SPIO 0x%x -> input\n", spio);
                /* set FLOAT */
-               spio_reg |= (spio_mask << MISC_REGISTERS_SPIO_FLOAT_POS);
+               spio_reg |= (spio << MISC_SPIO_FLOAT_POS);
                break;
 
        default:
@@ -2106,22 +2103,25 @@ void bnx2x_calc_fc_adv(struct bnx2x *bp)
        }
 }
 
-u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
+static void bnx2x_set_requested_fc(struct bnx2x *bp)
 {
-       if (!BP_NOMCP(bp)) {
-               u8 rc;
-               int cfx_idx = bnx2x_get_link_cfg_idx(bp);
-               u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
-               /*
-                * Initialize link parameters structure variables
-                * It is recommended to turn off RX FC for jumbo frames
-                * for better performance
-                */
-               if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000))
-                       bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
-               else
-                       bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
+       /* Initialize link parameters structure variables
+        * It is recommended to turn off RX FC for jumbo frames
+        *  for better performance
+        */
+       if (CHIP_IS_E1x(bp) && (bp->dev->mtu > 5000))
+               bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
+       else
+               bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
+}
 
+int bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
+{
+       int rc, cfx_idx = bnx2x_get_link_cfg_idx(bp);
+       u16 req_line_speed = bp->link_params.req_line_speed[cfx_idx];
+
+       if (!BP_NOMCP(bp)) {
+               bnx2x_set_requested_fc(bp);
                bnx2x_acquire_phy_lock(bp);
 
                if (load_mode == LOAD_DIAG) {
@@ -2150,11 +2150,11 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode)
 
                bnx2x_calc_fc_adv(bp);
 
-               if (CHIP_REV_IS_SLOW(bp) && bp->link_vars.link_up) {
+               if (bp->link_vars.link_up) {
                        bnx2x_stats_handle(bp, STATS_EVENT_LINK_UP);
                        bnx2x_link_report(bp);
-               } else
-                       queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
+               }
+               queue_delayed_work(bnx2x_wq, &bp->period_task, 0);
                bp->link_params.req_line_speed[cfx_idx] = req_line_speed;
                return rc;
        }
@@ -3075,11 +3075,13 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
 
 static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
 {
-#ifdef BCM_CNIC
        struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app;
        struct fcoe_stats_info *fcoe_stat =
                &bp->slowpath->drv_info_to_mcp.fcoe_stat;
 
+       if (!CNIC_LOADED(bp))
+               return;
+
        memcpy(fcoe_stat->mac_local + MAC_LEADING_ZERO_CNT,
               bp->fip_mac, ETH_ALEN);
 
@@ -3162,16 +3164,17 @@ static void bnx2x_drv_info_fcoe_stat(struct bnx2x *bp)
 
        /* ask L5 driver to add data to the struct */
        bnx2x_cnic_notify(bp, CNIC_CTL_FCOE_STATS_GET_CMD);
-#endif
 }
 
 static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
 {
-#ifdef BCM_CNIC
        struct bnx2x_dcbx_app_params *app = &bp->dcbx_port_params.app;
        struct iscsi_stats_info *iscsi_stat =
                &bp->slowpath->drv_info_to_mcp.iscsi_stat;
 
+       if (!CNIC_LOADED(bp))
+               return;
+
        memcpy(iscsi_stat->mac_local + MAC_LEADING_ZERO_CNT,
               bp->cnic_eth_dev.iscsi_mac, ETH_ALEN);
 
@@ -3180,7 +3183,6 @@ static void bnx2x_drv_info_iscsi_stat(struct bnx2x *bp)
 
        /* ask L5 driver to add data to the struct */
        bnx2x_cnic_notify(bp, CNIC_CTL_ISCSI_STATS_GET_CMD);
-#endif
 }
 
 /* called due to MCP event (on pmf):
@@ -3589,6 +3591,21 @@ static void bnx2x_attn_int_asserted(struct bnx2x *bp, u32 asserted)
 
        /* now set back the mask */
        if (asserted & ATTN_NIG_FOR_FUNC) {
+               /* Verify that IGU ack through BAR was written before restoring
+                * NIG mask. This loop should exit after 2-3 iterations max.
+                */
+               if (bp->common.int_block != INT_BLOCK_HC) {
+                       u32 cnt = 0, igu_acked;
+                       do {
+                               igu_acked = REG_RD(bp,
+                                                  IGU_REG_ATTENTION_ACK_BITS);
+                       } while (((igu_acked & ATTN_NIG_FOR_FUNC) == 0) &&
+                                (++cnt < MAX_IGU_ATTN_ACK_TO));
+                       if (!igu_acked)
+                               DP(NETIF_MSG_HW,
+                                  "Failed to verify IGU ack on time\n");
+                       barrier();
+               }
                REG_WR(bp, nig_int_mask_addr, nig_mask);
                bnx2x_release_phy_lock(bp);
        }
@@ -4572,7 +4589,6 @@ static void bnx2x_update_eq_prod(struct bnx2x *bp, u16 prod)
        mmiowb(); /* keep prod updates ordered */
 }
 
-#ifdef BCM_CNIC
 static int  bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
                                      union event_ring_elem *elem)
 {
@@ -4594,7 +4610,6 @@ static int  bnx2x_cnic_handle_cfc_del(struct bnx2x *bp, u32 cid,
        bnx2x_cnic_cfc_comp(bp, cid, err);
        return 0;
 }
-#endif
 
 static void bnx2x_handle_mcast_eqe(struct bnx2x *bp)
 {
@@ -4635,11 +4650,9 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
        switch (elem->message.data.eth_event.echo >> BNX2X_SWCID_SHIFT) {
        case BNX2X_FILTER_MAC_PENDING:
                DP(BNX2X_MSG_SP, "Got SETUP_MAC completions\n");
-#ifdef BCM_CNIC
-               if (cid == BNX2X_ISCSI_ETH_CID(bp))
+               if (CNIC_LOADED(bp) && (cid == BNX2X_ISCSI_ETH_CID(bp)))
                        vlan_mac_obj = &bp->iscsi_l2_mac_obj;
                else
-#endif
                        vlan_mac_obj = &bp->sp_objs[cid].mac_obj;
 
                break;
@@ -4665,9 +4678,7 @@ static void bnx2x_handle_classification_eqe(struct bnx2x *bp,
 
 }
 
-#ifdef BCM_CNIC
 static void bnx2x_set_iscsi_eth_rx_mode(struct bnx2x *bp, bool start);
-#endif
 
 static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
 {
@@ -4678,14 +4689,12 @@ static void bnx2x_handle_rx_mode_eqe(struct bnx2x *bp)
        /* Send rx_mode command again if was requested */
        if (test_and_clear_bit(BNX2X_FILTER_RX_MODE_SCHED, &bp->sp_state))
                bnx2x_set_storm_rx_mode(bp);
-#ifdef BCM_CNIC
        else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_START_SCHED,
                                    &bp->sp_state))
                bnx2x_set_iscsi_eth_rx_mode(bp, true);
        else if (test_and_clear_bit(BNX2X_FILTER_ISCSI_ETH_STOP_SCHED,
                                    &bp->sp_state))
                bnx2x_set_iscsi_eth_rx_mode(bp, false);
-#endif
 
        netif_addr_unlock_bh(bp->dev);
 }
@@ -4747,7 +4756,6 @@ static void bnx2x_after_function_update(struct bnx2x *bp)
                                  q);
        }
 
-#ifdef BCM_CNIC
        if (!NO_FCOE(bp)) {
                fp = &bp->fp[FCOE_IDX(bp)];
                queue_params.q_obj = &bnx2x_sp_obj(bp, fp).q_obj;
@@ -4770,22 +4778,16 @@ static void bnx2x_after_function_update(struct bnx2x *bp)
                bnx2x_link_report(bp);
                bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
        }
-#else
-       /* If no FCoE ring - ACK MCP now */
-       bnx2x_link_report(bp);
-       bnx2x_fw_command(bp, DRV_MSG_CODE_AFEX_VIFSET_ACK, 0);
-#endif /* BCM_CNIC */
 }
 
 static struct bnx2x_queue_sp_obj *bnx2x_cid_to_q_obj(
        struct bnx2x *bp, u32 cid)
 {
        DP(BNX2X_MSG_SP, "retrieving fp from cid %d\n", cid);
-#ifdef BCM_CNIC
-       if (cid == BNX2X_FCOE_ETH_CID(bp))
+
+       if (CNIC_LOADED(bp) && (cid == BNX2X_FCOE_ETH_CID(bp)))
                return &bnx2x_fcoe_sp_obj(bp, q_obj);
        else
-#endif
                return &bp->sp_objs[CID_TO_FP(cid, bp)].q_obj;
 }
 
@@ -4793,6 +4795,7 @@ static void bnx2x_eq_int(struct bnx2x *bp)
 {
        u16 hw_cons, sw_cons, sw_prod;
        union event_ring_elem *elem;
+       u8 echo;
        u32 cid;
        u8 opcode;
        int spqe_cnt = 0;
@@ -4847,10 +4850,11 @@ static void bnx2x_eq_int(struct bnx2x *bp)
                         */
                        DP(BNX2X_MSG_SP,
                           "got delete ramrod for MULTI[%d]\n", cid);
-#ifdef BCM_CNIC
-                       if (!bnx2x_cnic_handle_cfc_del(bp, cid, elem))
+
+                       if (CNIC_LOADED(bp) &&
+                           !bnx2x_cnic_handle_cfc_del(bp, cid, elem))
                                goto next_spqe;
-#endif
+
                        q_obj = bnx2x_cid_to_q_obj(bp, cid);
 
                        if (q_obj->complete_cmd(bp, q_obj, BNX2X_Q_CMD_CFC_DEL))
@@ -4875,21 +4879,34 @@ static void bnx2x_eq_int(struct bnx2x *bp)
                                break;
                        bnx2x_dcbx_set_params(bp, BNX2X_DCBX_STATE_TX_RELEASED);
                        goto next_spqe;
+
                case EVENT_RING_OPCODE_FUNCTION_UPDATE:
-                       DP(BNX2X_MSG_SP | BNX2X_MSG_MCP,
-                          "AFEX: ramrod completed FUNCTION_UPDATE\n");
-                       f_obj->complete_cmd(bp, f_obj, BNX2X_F_CMD_AFEX_UPDATE);
+                       echo = elem->message.data.function_update_event.echo;
+                       if (echo == SWITCH_UPDATE) {
+                               DP(BNX2X_MSG_SP | NETIF_MSG_IFUP,
+                                  "got FUNC_SWITCH_UPDATE ramrod\n");
+                               if (f_obj->complete_cmd(
+                                       bp, f_obj, BNX2X_F_CMD_SWITCH_UPDATE))
+                                       break;
 
-                       /* We will perform the Queues update from sp_rtnl task
-                        * as all Queue SP operations should run under
-                        * rtnl_lock.
-                        */
-                       smp_mb__before_clear_bit();
-                       set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE,
-                               &bp->sp_rtnl_state);
-                       smp_mb__after_clear_bit();
+                       } else {
+                               DP(BNX2X_MSG_SP | BNX2X_MSG_MCP,
+                                  "AFEX: ramrod completed FUNCTION_UPDATE\n");
+                               f_obj->complete_cmd(bp, f_obj,
+                                                   BNX2X_F_CMD_AFEX_UPDATE);
+
+                               /* We will perform the Queues update from
+                                * sp_rtnl task as all Queue SP operations
+                                * should run under rtnl_lock.
+                                */
+                               smp_mb__before_clear_bit();
+                               set_bit(BNX2X_SP_RTNL_AFEX_F_UPDATE,
+                                       &bp->sp_rtnl_state);
+                               smp_mb__after_clear_bit();
+
+                               schedule_delayed_work(&bp->sp_rtnl_task, 0);
+                       }
 
-                       schedule_delayed_work(&bp->sp_rtnl_task, 0);
                        goto next_spqe;
 
                case EVENT_RING_OPCODE_AFEX_VIF_LISTS:
@@ -4999,11 +5016,10 @@ static void bnx2x_sp_task(struct work_struct *work)
 
        /* SP events: STAT_QUERY and others */
        if (status & BNX2X_DEF_SB_IDX) {
-#ifdef BCM_CNIC
                struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
 
-               if ((!NO_FCOE(bp)) &&
-                       (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
+               if (FCOE_INIT(bp) &&
+                   (bnx2x_has_rx_work(fp) || bnx2x_has_tx_work(fp))) {
                        /*
                         * Prevent local bottom-halves from running as
                         * we are going to change the local NAPI list.
@@ -5012,7 +5028,7 @@ static void bnx2x_sp_task(struct work_struct *work)
                        napi_schedule(&bnx2x_fcoe(bp, napi));
                        local_bh_enable();
                }
-#endif
+
                /* Handle EQ completions */
                bnx2x_eq_int(bp);
 
@@ -5050,8 +5066,7 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
                return IRQ_HANDLED;
 #endif
 
-#ifdef BCM_CNIC
-       {
+       if (CNIC_LOADED(bp)) {
                struct cnic_ops *c_ops;
 
                rcu_read_lock();
@@ -5060,7 +5075,7 @@ irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance)
                        c_ops->cnic_handler(bp->cnic_data, NULL);
                rcu_read_unlock();
        }
-#endif
+
        queue_delayed_work(bnx2x_wq, &bp->sp_task, 0);
 
        return IRQ_HANDLED;
@@ -5498,12 +5513,10 @@ void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
        unsigned long rx_mode_flags = 0, ramrod_flags = 0;
        unsigned long rx_accept_flags = 0, tx_accept_flags = 0;
 
-#ifdef BCM_CNIC
        if (!NO_FCOE(bp))
 
                /* Configure rx_mode of FCoE Queue */
                __set_bit(BNX2X_RX_MODE_FCOE_ETH, &rx_mode_flags);
-#endif
 
        switch (bp->rx_mode) {
        case BNX2X_RX_MODE_NONE:
@@ -5624,12 +5637,12 @@ static void bnx2x_init_internal(struct bnx2x *bp, u32 load_code)
 
 static inline u8 bnx2x_fp_igu_sb_id(struct bnx2x_fastpath *fp)
 {
-       return fp->bp->igu_base_sb + fp->index + CNIC_PRESENT;
+       return fp->bp->igu_base_sb + fp->index + CNIC_SUPPORT(fp->bp);
 }
 
 static inline u8 bnx2x_fp_fw_sb_id(struct bnx2x_fastpath *fp)
 {
-       return fp->bp->base_fw_ndsb + fp->index + CNIC_PRESENT;
+       return fp->bp->base_fw_ndsb + fp->index + CNIC_SUPPORT(fp->bp);
 }
 
 static u8 bnx2x_fp_cl_id(struct bnx2x_fastpath *fp)
@@ -5720,23 +5733,25 @@ static void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
        txdata->tx_pkt = 0;
 }
 
+static void bnx2x_init_tx_rings_cnic(struct bnx2x *bp)
+{
+       int i;
+
+       for_each_tx_queue_cnic(bp, i)
+               bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[0]);
+}
 static void bnx2x_init_tx_rings(struct bnx2x *bp)
 {
        int i;
        u8 cos;
 
-       for_each_tx_queue(bp, i)
+       for_each_eth_queue(bp, i)
                for_each_cos_in_tx_queue(&bp->fp[i], cos)
                        bnx2x_init_tx_ring_one(bp->fp[i].txdata_ptr[cos]);
 }
 
-void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
+void bnx2x_nic_init_cnic(struct bnx2x *bp)
 {
-       int i;
-
-       for_each_eth_queue(bp, i)
-               bnx2x_init_eth_fp(bp, i);
-#ifdef BCM_CNIC
        if (!NO_FCOE(bp))
                bnx2x_init_fcoe_fp(bp);
 
@@ -5744,8 +5759,22 @@ void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
                      BNX2X_VF_ID_INVALID, false,
                      bnx2x_cnic_fw_sb_id(bp), bnx2x_cnic_igu_sb_id(bp));
 
-#endif
+       /* ensure status block indices were read */
+       rmb();
+       bnx2x_init_rx_rings_cnic(bp);
+       bnx2x_init_tx_rings_cnic(bp);
 
+       /* flush all */
+       mb();
+       mmiowb();
+}
+
+void bnx2x_nic_init(struct bnx2x *bp, u32 load_code)
+{
+       int i;
+
+       for_each_eth_queue(bp, i)
+               bnx2x_init_eth_fp(bp, i);
        /* Initialize MOD_ABS interrupts */
        bnx2x_init_mod_abs_int(bp, &bp->link_vars, bp->common.chip_id,
                               bp->common.shmem_base, bp->common.shmem2_base,
@@ -6031,10 +6060,9 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
        msleep(50);
        bnx2x_init_block(bp, BLOCK_BRB1, PHASE_COMMON);
        bnx2x_init_block(bp, BLOCK_PRS, PHASE_COMMON);
-#ifndef BCM_CNIC
-       /* set NIC mode */
-       REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif
+       if (!CNIC_SUPPORT(bp))
+               /* set NIC mode */
+               REG_WR(bp, PRS_REG_NIC_MODE, 1);
 
        /* Enable inputs of parser neighbor blocks */
        REG_WR(bp, TSDM_REG_ENABLE_IN1, 0x7fffffff);
@@ -6049,6 +6077,8 @@ static int bnx2x_int_mem_test(struct bnx2x *bp)
 
 static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
 {
+       u32 val;
+
        REG_WR(bp, PXP_REG_PXP_INT_MASK_0, 0);
        if (!CHIP_IS_E1x(bp))
                REG_WR(bp, PXP_REG_PXP_INT_MASK_1, 0x40);
@@ -6082,17 +6112,14 @@ static void bnx2x_enable_blocks_attention(struct bnx2x *bp)
 /*     REG_WR(bp, CSEM_REG_CSEM_INT_MASK_0, 0); */
 /*     REG_WR(bp, CSEM_REG_CSEM_INT_MASK_1, 0); */
 
-       if (CHIP_REV_IS_FPGA(bp))
-               REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x580000);
-       else if (!CHIP_IS_E1x(bp))
-               REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0,
-                          (PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF
-                               | PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT
-                               | PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN
-                               | PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED
-                               | PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED));
-       else
-               REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, 0x480000);
+       val = PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_AFT  |
+               PXP2_PXP2_INT_MASK_0_REG_PGL_CPL_OF |
+               PXP2_PXP2_INT_MASK_0_REG_PGL_PCIE_ATTN;
+       if (!CHIP_IS_E1x(bp))
+               val |= PXP2_PXP2_INT_MASK_0_REG_PGL_READ_BLOCKED |
+                       PXP2_PXP2_INT_MASK_0_REG_PGL_WRITE_BLOCKED;
+       REG_WR(bp, PXP2_REG_PXP2_INT_MASK_0, val);
+
        REG_WR(bp, TSDM_REG_TSDM_INT_MASK_0, 0);
        REG_WR(bp, TSDM_REG_TSDM_INT_MASK_1, 0);
        REG_WR(bp, TCM_REG_TCM_INT_MASK, 0);
@@ -6185,18 +6212,16 @@ static void bnx2x_setup_fan_failure_detection(struct bnx2x *bp)
                return;
 
        /* Fan failure is indicated by SPIO 5 */
-       bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5,
-                      MISC_REGISTERS_SPIO_INPUT_HI_Z);
+       bnx2x_set_spio(bp, MISC_SPIO_SPIO5, MISC_SPIO_INPUT_HI_Z);
 
        /* set to active low mode */
        val = REG_RD(bp, MISC_REG_SPIO_INT);
-       val |= ((1 << MISC_REGISTERS_SPIO_5) <<
-                                       MISC_REGISTERS_SPIO_INT_OLD_SET_POS);
+       val |= (MISC_SPIO_SPIO5 << MISC_SPIO_INT_OLD_SET_POS);
        REG_WR(bp, MISC_REG_SPIO_INT, val);
 
        /* enable interrupt to signal the IGU */
        val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
-       val |= (1 << MISC_REGISTERS_SPIO_5);
+       val |= MISC_SPIO_SPIO5;
        REG_WR(bp, MISC_REG_SPIO_EVENT_EN, val);
 }
 
@@ -6256,6 +6281,10 @@ void bnx2x_pf_disable(struct bnx2x *bp)
 static void bnx2x__common_init_phy(struct bnx2x *bp)
 {
        u32 shmem_base[2], shmem2_base[2];
+       /* Avoid common init in case MFW supports LFA */
+       if (SHMEM2_RD(bp, size) >
+           (u32)offsetof(struct shmem2_region, lfa_host_addr[BP_PORT(bp)]))
+               return;
        shmem_base[0] =  bp->common.shmem_base;
        shmem2_base[0] = bp->common.shmem2_base;
        if (!CHIP_IS_E1x(bp)) {
@@ -6522,9 +6551,8 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
        REG_WR(bp, QM_REG_SOFT_RESET, 1);
        REG_WR(bp, QM_REG_SOFT_RESET, 0);
 
-#ifdef BCM_CNIC
-       bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
-#endif
+       if (CNIC_SUPPORT(bp))
+               bnx2x_init_block(bp, BLOCK_TM, PHASE_COMMON);
 
        bnx2x_init_block(bp, BLOCK_DORQ, PHASE_COMMON);
        REG_WR(bp, DORQ_REG_DPM_CID_OFST, BNX2X_DB_SHIFT);
@@ -6611,18 +6639,18 @@ static int bnx2x_init_hw_common(struct bnx2x *bp)
 
        bnx2x_init_block(bp, BLOCK_SRC, PHASE_COMMON);
 
-#ifdef BCM_CNIC
-       REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
-       REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
-       REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b);
-       REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a);
-       REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116);
-       REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b);
-       REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf);
-       REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09);
-       REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f);
-       REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7);
-#endif
+       if (CNIC_SUPPORT(bp)) {
+               REG_WR(bp, SRC_REG_KEYSEARCH_0, 0x63285672);
+               REG_WR(bp, SRC_REG_KEYSEARCH_1, 0x24b8f2cc);
+               REG_WR(bp, SRC_REG_KEYSEARCH_2, 0x223aef9b);
+               REG_WR(bp, SRC_REG_KEYSEARCH_3, 0x26001e3a);
+               REG_WR(bp, SRC_REG_KEYSEARCH_4, 0x7ae91116);
+               REG_WR(bp, SRC_REG_KEYSEARCH_5, 0x5ce5230b);
+               REG_WR(bp, SRC_REG_KEYSEARCH_6, 0x298d8adf);
+               REG_WR(bp, SRC_REG_KEYSEARCH_7, 0x6eb0ff09);
+               REG_WR(bp, SRC_REG_KEYSEARCH_8, 0x1830f82f);
+               REG_WR(bp, SRC_REG_KEYSEARCH_9, 0x01e46be7);
+       }
        REG_WR(bp, SRC_REG_SOFT_RST, 0);
 
        if (sizeof(union cdu_context) != 1024)
@@ -6786,16 +6814,17 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
        /* QM cid (connection) count */
        bnx2x_qm_init_cid_count(bp, bp->qm_cid_count, INITOP_SET);
 
-#ifdef BCM_CNIC
-       bnx2x_init_block(bp, BLOCK_TM, init_phase);
-       REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
-       REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
-#endif
+       if (CNIC_SUPPORT(bp)) {
+               bnx2x_init_block(bp, BLOCK_TM, init_phase);
+               REG_WR(bp, TM_REG_LIN0_SCAN_TIME + port*4, 20);
+               REG_WR(bp, TM_REG_LIN0_MAX_ACTIVE_CID + port*4, 31);
+       }
 
        bnx2x_init_block(bp, BLOCK_DORQ, init_phase);
 
+       bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
+
        if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) {
-               bnx2x_init_block(bp, BLOCK_BRB1, init_phase);
 
                if (IS_MF(bp))
                        low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246);
@@ -6876,9 +6905,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
                REG_WR(bp, PBF_REG_INIT_P0 + port*4, 0);
        }
 
-#ifdef BCM_CNIC
-       bnx2x_init_block(bp, BLOCK_SRC, init_phase);
-#endif
+       if (CNIC_SUPPORT(bp))
+               bnx2x_init_block(bp, BLOCK_SRC, init_phase);
+
        bnx2x_init_block(bp, BLOCK_CDU, init_phase);
        bnx2x_init_block(bp, BLOCK_CFC, init_phase);
 
@@ -6954,7 +6983,7 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)
 
        /* If SPIO5 is set to generate interrupts, enable it for this port */
        val = REG_RD(bp, MISC_REG_SPIO_EVENT_EN);
-       if (val & (1 << MISC_REGISTERS_SPIO_5)) {
+       if (val & MISC_SPIO_SPIO5) {
                u32 reg_addr = (port ? MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0 :
                                       MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0);
                val = REG_RD(bp, reg_addr);
@@ -7039,6 +7068,130 @@ static void bnx2x_clear_func_ilt(struct bnx2x *bp, u32 func)
                bnx2x_ilt_wr(bp, i, 0);
 }
 
+
+static void bnx2x_init_searcher(struct bnx2x *bp)
+{
+       int port = BP_PORT(bp);
+       bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
+       /* T1 hash bits value determines the T1 number of entries */
+       REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
+}
+
+static inline int bnx2x_func_switch_update(struct bnx2x *bp, int suspend)
+{
+       int rc;
+       struct bnx2x_func_state_params func_params = {NULL};
+       struct bnx2x_func_switch_update_params *switch_update_params =
+               &func_params.params.switch_update;
+
+       /* Prepare parameters for function state transitions */
+       __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
+       __set_bit(RAMROD_RETRY, &func_params.ramrod_flags);
+
+       func_params.f_obj = &bp->func_obj;
+       func_params.cmd = BNX2X_F_CMD_SWITCH_UPDATE;
+
+       /* Function parameters */
+       switch_update_params->suspend = suspend;
+
+       rc = bnx2x_func_state_change(bp, &func_params);
+
+       return rc;
+}
+
+static int bnx2x_reset_nic_mode(struct bnx2x *bp)
+{
+       int rc, i, port = BP_PORT(bp);
+       int vlan_en = 0, mac_en[NUM_MACS];
+
+
+       /* Close input from network */
+       if (bp->mf_mode == SINGLE_FUNCTION) {
+               bnx2x_set_rx_filter(&bp->link_params, 0);
+       } else {
+               vlan_en = REG_RD(bp, port ? NIG_REG_LLH1_FUNC_EN :
+                                  NIG_REG_LLH0_FUNC_EN);
+               REG_WR(bp, port ? NIG_REG_LLH1_FUNC_EN :
+                         NIG_REG_LLH0_FUNC_EN, 0);
+               for (i = 0; i < NUM_MACS; i++) {
+                       mac_en[i] = REG_RD(bp, port ?
+                                            (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+                                             4 * i) :
+                                            (NIG_REG_LLH0_FUNC_MEM_ENABLE +
+                                             4 * i));
+                       REG_WR(bp, port ? (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+                                             4 * i) :
+                                 (NIG_REG_LLH0_FUNC_MEM_ENABLE + 4 * i), 0);
+               }
+       }
+
+       /* Close BMC to host */
+       REG_WR(bp, port ? NIG_REG_P0_TX_MNG_HOST_ENABLE :
+              NIG_REG_P1_TX_MNG_HOST_ENABLE, 0);
+
+       /* Suspend Tx switching to the PF. Completion of this ramrod
+        * further guarantees that all the packets of that PF / child
+        * VFs in BRB were processed by the Parser, so it is safe to
+        * change the NIC_MODE register.
+        */
+       rc = bnx2x_func_switch_update(bp, 1);
+       if (rc) {
+               BNX2X_ERR("Can't suspend tx-switching!\n");
+               return rc;
+       }
+
+       /* Change NIC_MODE register */
+       REG_WR(bp, PRS_REG_NIC_MODE, 0);
+
+       /* Open input from network */
+       if (bp->mf_mode == SINGLE_FUNCTION) {
+               bnx2x_set_rx_filter(&bp->link_params, 1);
+       } else {
+               REG_WR(bp, port ? NIG_REG_LLH1_FUNC_EN :
+                         NIG_REG_LLH0_FUNC_EN, vlan_en);
+               for (i = 0; i < NUM_MACS; i++) {
+                       REG_WR(bp, port ? (NIG_REG_LLH1_FUNC_MEM_ENABLE +
+                                             4 * i) :
+                                 (NIG_REG_LLH0_FUNC_MEM_ENABLE + 4 * i),
+                                 mac_en[i]);
+               }
+       }
+
+       /* Enable BMC to host */
+       REG_WR(bp, port ? NIG_REG_P0_TX_MNG_HOST_ENABLE :
+              NIG_REG_P1_TX_MNG_HOST_ENABLE, 1);
+
+       /* Resume Tx switching to the PF */
+       rc = bnx2x_func_switch_update(bp, 0);
+       if (rc) {
+               BNX2X_ERR("Can't resume tx-switching!\n");
+               return rc;
+       }
+
+       DP(NETIF_MSG_IFUP, "NIC MODE disabled\n");
+       return 0;
+}
+
+int bnx2x_init_hw_func_cnic(struct bnx2x *bp)
+{
+       int rc;
+
+       bnx2x_ilt_init_op_cnic(bp, INITOP_SET);
+
+       if (CONFIGURE_NIC_MODE(bp)) {
+               /* Configrue searcher as part of function hw init */
+               bnx2x_init_searcher(bp);
+
+               /* Reset NIC mode */
+               rc = bnx2x_reset_nic_mode(bp);
+               if (rc)
+                       BNX2X_ERR("Can't change NIC mode!\n");
+               return rc;
+       }
+
+       return 0;
+}
+
 static int bnx2x_init_hw_func(struct bnx2x *bp)
 {
        int port = BP_PORT(bp);
@@ -7081,17 +7234,16 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
        }
        bnx2x_ilt_init_op(bp, INITOP_SET);
 
-#ifdef BCM_CNIC
-       bnx2x_src_init_t2(bp, bp->t2, bp->t2_mapping, SRC_CONN_NUM);
-
-       /* T1 hash bits value determines the T1 number of entries */
-       REG_WR(bp, SRC_REG_NUMBER_HASH_BITS0 + port*4, SRC_HASH_BITS);
-#endif
+       if (!CONFIGURE_NIC_MODE(bp)) {
+               bnx2x_init_searcher(bp);
+               REG_WR(bp, PRS_REG_NIC_MODE, 0);
+               DP(NETIF_MSG_IFUP, "NIC MODE disabled\n");
+       } else {
+               /* Set NIC mode */
+               REG_WR(bp, PRS_REG_NIC_MODE, 1);
+               DP(NETIF_MSG_IFUP, "NIC MODE configrued\n");
 
-#ifndef BCM_CNIC
-       /* set NIC mode */
-       REG_WR(bp, PRS_REG_NIC_MODE, 1);
-#endif  /* BCM_CNIC */
+       }
 
        if (!CHIP_IS_E1x(bp)) {
                u32 pf_conf = IGU_PF_CONF_FUNC_EN;
@@ -7342,6 +7494,20 @@ static int bnx2x_init_hw_func(struct bnx2x *bp)
 }
 
 
+void bnx2x_free_mem_cnic(struct bnx2x *bp)
+{
+       bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_FREE);
+
+       if (!CHIP_IS_E1x(bp))
+               BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
+                              sizeof(struct host_hc_status_block_e2));
+       else
+               BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
+                              sizeof(struct host_hc_status_block_e1x));
+
+       BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
+}
+
 void bnx2x_free_mem(struct bnx2x *bp)
 {
        int i;
@@ -7366,17 +7532,6 @@ void bnx2x_free_mem(struct bnx2x *bp)
 
        BNX2X_FREE(bp->ilt->lines);
 
-#ifdef BCM_CNIC
-       if (!CHIP_IS_E1x(bp))
-               BNX2X_PCI_FREE(bp->cnic_sb.e2_sb, bp->cnic_sb_mapping,
-                              sizeof(struct host_hc_status_block_e2));
-       else
-               BNX2X_PCI_FREE(bp->cnic_sb.e1x_sb, bp->cnic_sb_mapping,
-                              sizeof(struct host_hc_status_block_e1x));
-
-       BNX2X_PCI_FREE(bp->t2, bp->t2_mapping, SRC_T2_SZ);
-#endif
-
        BNX2X_PCI_FREE(bp->spq, bp->spq_mapping, BCM_PAGE_SIZE);
 
        BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
@@ -7444,24 +7599,44 @@ alloc_mem_err:
        return -ENOMEM;
 }
 
-
-int bnx2x_alloc_mem(struct bnx2x *bp)
+int bnx2x_alloc_mem_cnic(struct bnx2x *bp)
 {
-       int i, allocated, context_size;
-
-#ifdef BCM_CNIC
        if (!CHIP_IS_E1x(bp))
                /* size = the status block + ramrod buffers */
                BNX2X_PCI_ALLOC(bp->cnic_sb.e2_sb, &bp->cnic_sb_mapping,
                                sizeof(struct host_hc_status_block_e2));
        else
-               BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb, &bp->cnic_sb_mapping,
-                               sizeof(struct host_hc_status_block_e1x));
+               BNX2X_PCI_ALLOC(bp->cnic_sb.e1x_sb,
+                               &bp->cnic_sb_mapping,
+                               sizeof(struct
+                                      host_hc_status_block_e1x));
 
-       /* allocate searcher T2 table */
-       BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
-#endif
+       if (CONFIGURE_NIC_MODE(bp))
+               /* allocate searcher T2 table, as it wan't allocated before */
+               BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
+
+       /* write address to which L5 should insert its values */
+       bp->cnic_eth_dev.addr_drv_info_to_mcp =
+               &bp->slowpath->drv_info_to_mcp;
+
+       if (bnx2x_ilt_mem_op_cnic(bp, ILT_MEMOP_ALLOC))
+               goto alloc_mem_err;
+
+       return 0;
+
+alloc_mem_err:
+       bnx2x_free_mem_cnic(bp);
+       BNX2X_ERR("Can't allocate memory\n");
+       return -ENOMEM;
+}
+
+int bnx2x_alloc_mem(struct bnx2x *bp)
+{
+       int i, allocated, context_size;
 
+       if (!CONFIGURE_NIC_MODE(bp))
+               /* allocate searcher T2 table */
+               BNX2X_PCI_ALLOC(bp->t2, &bp->t2_mapping, SRC_T2_SZ);
 
        BNX2X_PCI_ALLOC(bp->def_status_blk, &bp->def_status_blk_mapping,
                        sizeof(struct host_sp_status_block));
@@ -7469,11 +7644,6 @@ int bnx2x_alloc_mem(struct bnx2x *bp)
        BNX2X_PCI_ALLOC(bp->slowpath, &bp->slowpath_mapping,
                        sizeof(struct bnx2x_slowpath));
 
-#ifdef BCM_CNIC
-       /* write address to which L5 should insert its values */
-       bp->cnic_eth_dev.addr_drv_info_to_mcp = &bp->slowpath->drv_info_to_mcp;
-#endif
-
        /* Allocated memory for FW statistics  */
        if (bnx2x_alloc_fw_stats_mem(bp))
                goto alloc_mem_err;
@@ -7595,14 +7765,12 @@ int bnx2x_set_eth_mac(struct bnx2x *bp, bool set)
 {
        unsigned long ramrod_flags = 0;
 
-#ifdef BCM_CNIC
        if (is_zero_ether_addr(bp->dev->dev_addr) &&
            (IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp))) {
                DP(NETIF_MSG_IFUP | NETIF_MSG_IFDOWN,
                   "Ignoring Zero MAC for STORAGE SD mode\n");
                return 0;
        }
-#endif
 
        DP(NETIF_MSG_IFUP, "Adding Eth MAC\n");
 
@@ -7631,7 +7799,8 @@ void bnx2x_set_int_mode(struct bnx2x *bp)
                bnx2x_enable_msi(bp);
                /* falling through... */
        case INT_MODE_INTx:
-               bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
+               bp->num_ethernet_queues = 1;
+               bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues;
                BNX2X_DEV_INFO("set number of queues to 1\n");
                break;
        default:
@@ -7643,9 +7812,10 @@ void bnx2x_set_int_mode(struct bnx2x *bp)
                    bp->flags & USING_SINGLE_MSIX_FLAG) {
                        /* failed to enable multiple MSI-X */
                        BNX2X_DEV_INFO("Failed to enable multiple MSI-X (%d), set number of queues to %d\n",
-                                      bp->num_queues, 1 + NON_ETH_CONTEXT_USE);
+                                      bp->num_queues,
+                                      1 + bp->num_cnic_queues);
 
-                       bp->num_queues = 1 + NON_ETH_CONTEXT_USE;
+                       bp->num_queues = 1 + bp->num_cnic_queues;
 
                        /* Try to enable MSI */
                        if (!(bp->flags & USING_SINGLE_MSIX_FLAG) &&
@@ -7678,9 +7848,9 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
        ilt_client->flags = ILT_CLIENT_SKIP_MEM;
        ilt_client->start = line;
        line += bnx2x_cid_ilt_lines(bp);
-#ifdef BCM_CNIC
-       line += CNIC_ILT_LINES;
-#endif
+
+       if (CNIC_SUPPORT(bp))
+               line += CNIC_ILT_LINES;
        ilt_client->end = line - 1;
 
        DP(NETIF_MSG_IFUP, "ilt client[CDU]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
@@ -7713,49 +7883,43 @@ void bnx2x_ilt_set_info(struct bnx2x *bp)
                   ilog2(ilt_client->page_size >> 12));
 
        }
-       /* SRC */
-       ilt_client = &ilt->clients[ILT_CLIENT_SRC];
-#ifdef BCM_CNIC
-       ilt_client->client_num = ILT_CLIENT_SRC;
-       ilt_client->page_size = SRC_ILT_PAGE_SZ;
-       ilt_client->flags = 0;
-       ilt_client->start = line;
-       line += SRC_ILT_LINES;
-       ilt_client->end = line - 1;
 
-       DP(NETIF_MSG_IFUP,
-          "ilt client[SRC]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
-          ilt_client->start,
-          ilt_client->end,
-          ilt_client->page_size,
-          ilt_client->flags,
-          ilog2(ilt_client->page_size >> 12));
+       if (CNIC_SUPPORT(bp)) {
+               /* SRC */
+               ilt_client = &ilt->clients[ILT_CLIENT_SRC];
+               ilt_client->client_num = ILT_CLIENT_SRC;
+               ilt_client->page_size = SRC_ILT_PAGE_SZ;
+               ilt_client->flags = 0;
+               ilt_client->start = line;
+               line += SRC_ILT_LINES;
+               ilt_client->end = line - 1;
 
-#else
-       ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
-#endif
+               DP(NETIF_MSG_IFUP,
+                  "ilt client[SRC]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
+                  ilt_client->start,
+                  ilt_client->end,
+                  ilt_client->page_size,
+                  ilt_client->flags,
+                  ilog2(ilt_client->page_size >> 12));
 
-       /* TM */
-       ilt_client = &ilt->clients[ILT_CLIENT_TM];
-#ifdef BCM_CNIC
-       ilt_client->client_num = ILT_CLIENT_TM;
-       ilt_client->page_size = TM_ILT_PAGE_SZ;
-       ilt_client->flags = 0;
-       ilt_client->start = line;
-       line += TM_ILT_LINES;
-       ilt_client->end = line - 1;
+               /* TM */
+               ilt_client = &ilt->clients[ILT_CLIENT_TM];
+               ilt_client->client_num = ILT_CLIENT_TM;
+               ilt_client->page_size = TM_ILT_PAGE_SZ;
+               ilt_client->flags = 0;
+               ilt_client->start = line;
+               line += TM_ILT_LINES;
+               ilt_client->end = line - 1;
 
-       DP(NETIF_MSG_IFUP,
-          "ilt client[TM]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
-          ilt_client->start,
-          ilt_client->end,
-          ilt_client->page_size,
-          ilt_client->flags,
-          ilog2(ilt_client->page_size >> 12));
+               DP(NETIF_MSG_IFUP,
+                  "ilt client[TM]: start %d, end %d, psz 0x%x, flags 0x%x, hw psz %d\n",
+                  ilt_client->start,
+                  ilt_client->end,
+                  ilt_client->page_size,
+                  ilt_client->flags,
+                  ilog2(ilt_client->page_size >> 12));
+       }
 
-#else
-       ilt_client->flags = (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM);
-#endif
        BUG_ON(line > ILT_MAX_LINES);
 }
 
@@ -7822,7 +7986,7 @@ static void bnx2x_pf_q_prep_init(struct bnx2x *bp,
        }
 }
 
-int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
+static int bnx2x_setup_tx_only(struct bnx2x *bp, struct bnx2x_fastpath *fp,
                        struct bnx2x_queue_state_params *q_params,
                        struct bnx2x_queue_setup_tx_only_params *tx_only_params,
                        int tx_index, bool leading)
@@ -7923,6 +8087,9 @@ int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
        /* Set the command */
        q_params.cmd = BNX2X_Q_CMD_SETUP;
 
+       if (IS_FCOE_FP(fp))
+               bp->fcoe_init = true;
+
        /* Change the state to SETUP */
        rc = bnx2x_queue_state_change(bp, &q_params);
        if (rc) {
@@ -8036,12 +8203,12 @@ static void bnx2x_reset_func(struct bnx2x *bp)
                           SB_DISABLED);
        }
 
-#ifdef BCM_CNIC
-       /* CNIC SB */
-       REG_WR8(bp, BAR_CSTRORM_INTMEM +
-               CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET(bnx2x_cnic_fw_sb_id(bp)),
-               SB_DISABLED);
-#endif
+       if (CNIC_LOADED(bp))
+               /* CNIC SB */
+               REG_WR8(bp, BAR_CSTRORM_INTMEM +
+                       CSTORM_STATUS_BLOCK_DATA_STATE_OFFSET
+                       (bnx2x_cnic_fw_sb_id(bp)), SB_DISABLED);
+
        /* SP SB */
        REG_WR8(bp, BAR_CSTRORM_INTMEM +
                   CSTORM_SP_STATUS_BLOCK_DATA_STATE_OFFSET(func),
@@ -8060,19 +8227,19 @@ static void bnx2x_reset_func(struct bnx2x *bp)
                REG_WR(bp, IGU_REG_TRAILING_EDGE_LATCH, 0);
        }
 
-#ifdef BCM_CNIC
-       /* Disable Timer scan */
-       REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
-       /*
-        * Wait for at least 10ms and up to 2 second for the timers scan to
-        * complete
-        */
-       for (i = 0; i < 200; i++) {
-               msleep(10);
-               if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4))
-                       break;
+       if (CNIC_LOADED(bp)) {
+               /* Disable Timer scan */
+               REG_WR(bp, TM_REG_EN_LINEAR0_TIMER + port*4, 0);
+               /*
+                * Wait for at least 10ms and up to 2 second for the timers
+                * scan to complete
+                */
+               for (i = 0; i < 200; i++) {
+                       msleep(10);
+                       if (!REG_RD(bp, TM_REG_LIN0_SCAN_ON + port*4))
+                               break;
+               }
        }
-#endif
        /* Clear ILT */
        bnx2x_clear_func_ilt(bp, func);
 
@@ -8408,13 +8575,24 @@ void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode, bool keep_link)
        /* Close multi and leading connections
         * Completions for ramrods are collected in a synchronous way
         */
-       for_each_queue(bp, i)
+       for_each_eth_queue(bp, i)
                if (bnx2x_stop_queue(bp, i))
 #ifdef BNX2X_STOP_ON_ERROR
                        return;
 #else
                        goto unload_error;
 #endif
+
+       if (CNIC_LOADED(bp)) {
+               for_each_cnic_queue(bp, i)
+                       if (bnx2x_stop_queue(bp, i))
+#ifdef BNX2X_STOP_ON_ERROR
+                               return;
+#else
+                               goto unload_error;
+#endif
+       }
+
        /* If SP settings didn't get completed so far - something
         * very wrong has happen.
         */
@@ -8436,6 +8614,8 @@ unload_error:
        bnx2x_netif_stop(bp, 1);
        /* Delete all NAPI objects */
        bnx2x_del_all_napi(bp);
+       if (CNIC_LOADED(bp))
+               bnx2x_del_all_napi_cnic(bp);
 
        /* Release IRQs */
        bnx2x_free_irq(bp);
@@ -8557,7 +8737,8 @@ static void bnx2x_reset_mcp_prep(struct bnx2x *bp, u32 *magic_val)
 
        /* Get shmem offset */
        shmem = REG_RD(bp, MISC_REG_SHARED_MEM_ADDR);
-       validity_offset = offsetof(struct shmem_region, validity_map[0]);
+       validity_offset =
+               offsetof(struct shmem_region, validity_map[BP_PORT(bp)]);
 
        /* Clear validity map flags */
        if (shmem > 0)
@@ -8650,7 +8831,11 @@ static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global)
                MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU |
                MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE;
 
-       /* Don't reset the following blocks */
+       /* Don't reset the following blocks.
+        * Important: per port blocks (such as EMAC, BMAC, UMAC) can't be
+        *            reset, as in 4 port device they might still be owned
+        *            by the MCP (there is only one leader per path).
+        */
        not_reset_mask1 =
                MISC_REGISTERS_RESET_REG_1_RST_HC |
                MISC_REGISTERS_RESET_REG_1_RST_PXPV |
@@ -8666,19 +8851,19 @@ static void bnx2x_process_kill_chip_reset(struct bnx2x *bp, bool global)
                MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE |
                MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B |
                MISC_REGISTERS_RESET_REG_2_RST_ATC |
-               MISC_REGISTERS_RESET_REG_2_PGLC;
+               MISC_REGISTERS_RESET_REG_2_PGLC |
+               MISC_REGISTERS_RESET_REG_2_RST_BMAC0 |
+               MISC_REGISTERS_RESET_REG_2_RST_BMAC1 |
+               MISC_REGISTERS_RESET_REG_2_RST_EMAC0 |
+               MISC_REGISTERS_RESET_REG_2_RST_EMAC1 |
+               MISC_REGISTERS_RESET_REG_2_UMAC0 |
+               MISC_REGISTERS_RESET_REG_2_UMAC1;
 
        /*
         * Keep the following blocks in reset:
         *  - all xxMACs are handled by the bnx2x_link code.
         */
        stay_reset2 =
-               MISC_REGISTERS_RESET_REG_2_RST_BMAC0 |
-               MISC_REGISTERS_RESET_REG_2_RST_BMAC1 |
-               MISC_REGISTERS_RESET_REG_2_RST_EMAC0 |
-               MISC_REGISTERS_RESET_REG_2_RST_EMAC1 |
-               MISC_REGISTERS_RESET_REG_2_UMAC0 |
-               MISC_REGISTERS_RESET_REG_2_UMAC1 |
                MISC_REGISTERS_RESET_REG_2_XMAC |
                MISC_REGISTERS_RESET_REG_2_XMAC_SOFT;
 
@@ -8768,6 +8953,7 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
        int cnt = 1000;
        u32 val = 0;
        u32 sr_cnt, blk_cnt, port_is_idle_0, port_is_idle_1, pgl_exp_rom2;
+               u32 tags_63_32 = 0;
 
 
        /* Empty the Tetris buffer, wait for 1s */
@@ -8777,10 +8963,14 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
                port_is_idle_0 = REG_RD(bp, PXP2_REG_RD_PORT_IS_IDLE_0);
                port_is_idle_1 = REG_RD(bp, PXP2_REG_RD_PORT_IS_IDLE_1);
                pgl_exp_rom2 = REG_RD(bp, PXP2_REG_PGL_EXP_ROM2);
+               if (CHIP_IS_E3(bp))
+                       tags_63_32 = REG_RD(bp, PGLUE_B_REG_TAGS_63_32);
+
                if ((sr_cnt == 0x7e) && (blk_cnt == 0xa0) &&
                    ((port_is_idle_0 & 0x1) == 0x1) &&
                    ((port_is_idle_1 & 0x1) == 0x1) &&
-                   (pgl_exp_rom2 == 0xffffffff))
+                   (pgl_exp_rom2 == 0xffffffff) &&
+                   (!CHIP_IS_E3(bp) || (tags_63_32 == 0xffffffff)))
                        break;
                usleep_range(1000, 1000);
        } while (cnt-- > 0);
@@ -8837,9 +9027,6 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
 
        /* TBD: Add resetting the NO_MCP mode DB here */
 
-       /* PXP */
-       bnx2x_pxp_prep(bp);
-
        /* Open the gates #2, #3 and #4 */
        bnx2x_set_234_gates(bp, false);
 
@@ -8849,7 +9036,7 @@ static int bnx2x_process_kill(struct bnx2x *bp, bool global)
        return 0;
 }
 
-int bnx2x_leader_reset(struct bnx2x *bp)
+static int bnx2x_leader_reset(struct bnx2x *bp)
 {
        int rc = 0;
        bool global = bnx2x_reset_is_global(bp);
@@ -9233,7 +9420,7 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp)
                bnx2x_undi_int_disable_e1h(bp);
 }
 
-static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
+static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)
 {
        u32 val, base_addr, offset, mask, reset_reg;
        bool mac_stopped = false;
@@ -9300,8 +9487,7 @@ static void __devinit bnx2x_prev_unload_close_mac(struct bnx2x *bp)
 #define BNX2X_PREV_UNDI_BD(val)                ((val) >> 16 & 0xffff)
 #define BNX2X_PREV_UNDI_PROD(rcq, bd)  ((bd) << 16 | (rcq))
 
-static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
-                                                u8 inc)
+static void bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port, u8 inc)
 {
        u16 rcq, bd;
        u32 tmp_reg = REG_RD(bp, BNX2X_PREV_UNDI_PROD_ADDR(port));
@@ -9316,7 +9502,7 @@ static void __devinit bnx2x_prev_unload_undi_inc(struct bnx2x *bp, u8 port,
                       port, bd, rcq);
 }
 
-static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
+static int bnx2x_prev_mcp_done(struct bnx2x *bp)
 {
        u32 rc = bnx2x_fw_command(bp, DRV_MSG_CODE_UNLOAD_DONE,
                                  DRV_MSG_CODE_UNLOAD_SKIP_LINK_RESET);
@@ -9328,7 +9514,21 @@ static int __devinit bnx2x_prev_mcp_done(struct bnx2x *bp)
        return 0;
 }
 
-static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
+static struct bnx2x_prev_path_list *
+               bnx2x_prev_path_get_entry(struct bnx2x *bp)
+{
+       struct bnx2x_prev_path_list *tmp_list;
+
+       list_for_each_entry(tmp_list, &bnx2x_prev_list, list)
+               if (PCI_SLOT(bp->pdev->devfn) == tmp_list->slot &&
+                   bp->pdev->bus->number == tmp_list->bus &&
+                   BP_PATH(bp) == tmp_list->path)
+                       return tmp_list;
+
+       return NULL;
+}
+
+static bool bnx2x_prev_is_path_marked(struct bnx2x *bp)
 {
        struct bnx2x_prev_path_list *tmp_list;
        int rc = false;
@@ -9352,7 +9552,7 @@ static bool __devinit bnx2x_prev_is_path_marked(struct bnx2x *bp)
        return rc;
 }
 
-static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
+static int bnx2x_prev_mark_path(struct bnx2x *bp, bool after_undi)
 {
        struct bnx2x_prev_path_list *tmp_list;
        int rc;
@@ -9366,6 +9566,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
        tmp_list->bus = bp->pdev->bus->number;
        tmp_list->slot = PCI_SLOT(bp->pdev->devfn);
        tmp_list->path = BP_PATH(bp);
+       tmp_list->undi = after_undi ? (1 << BP_PORT(bp)) : 0;
 
        rc = down_interruptible(&bnx2x_prev_sem);
        if (rc) {
@@ -9381,7 +9582,7 @@ static int __devinit bnx2x_prev_mark_path(struct bnx2x *bp)
        return rc;
 }
 
-static int __devinit bnx2x_do_flr(struct bnx2x *bp)
+static int bnx2x_do_flr(struct bnx2x *bp)
 {
        int i;
        u16 status;
@@ -9421,7 +9622,7 @@ clear:
        return 0;
 }
 
-static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
+static int bnx2x_prev_unload_uncommon(struct bnx2x *bp)
 {
        int rc;
 
@@ -9459,9 +9660,10 @@ static int __devinit bnx2x_prev_unload_uncommon(struct bnx2x *bp)
        return rc;
 }
 
-static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
+static int bnx2x_prev_unload_common(struct bnx2x *bp)
 {
        u32 reset_reg, tmp_reg = 0, rc;
+       bool prev_undi = false;
        /* It is possible a previous function received 'common' answer,
         * but hasn't loaded yet, therefore creating a scenario of
         * multiple functions receiving 'common' on the same path.
@@ -9476,7 +9678,6 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
        /* Reset should be performed after BRB is emptied */
        if (reset_reg & MISC_REGISTERS_RESET_REG_1_RST_BRB1) {
                u32 timer_count = 1000;
-               bool prev_undi = false;
 
                /* Close the MAC Rx to prevent BRB from filling up */
                bnx2x_prev_unload_close_mac(bp);
@@ -9526,7 +9727,7 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
        /* No packets are in the pipeline, path is ready for reset */
        bnx2x_reset_common(bp);
 
-       rc = bnx2x_prev_mark_path(bp);
+       rc = bnx2x_prev_mark_path(bp, prev_undi);
        if (rc) {
                bnx2x_prev_mcp_done(bp);
                return rc;
@@ -9542,19 +9743,23 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
  * to clear the interrupt which detected this from the pglueb and the was done
  * bit
  */
-static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
+static void bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
 {
-       u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
-       if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
-               BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
-               REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp));
+       if (!CHIP_IS_E1x(bp)) {
+               u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
+               if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
+                       BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
+                       REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR,
+                              1 << BP_FUNC(bp));
+               }
        }
 }
 
-static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
+static int bnx2x_prev_unload(struct bnx2x *bp)
 {
        int time_counter = 10;
        u32 rc, fw, hw_lock_reg, hw_lock_val;
+       struct bnx2x_prev_path_list *prev_list;
        BNX2X_DEV_INFO("Entering Previous Unload Flow\n");
 
        /* clear hw from errors which may have resulted from an interrupted
@@ -9613,12 +9818,18 @@ static int __devinit bnx2x_prev_unload(struct bnx2x *bp)
                rc = -EBUSY;
        }
 
+       /* Mark function if its port was used to boot from SAN */
+       prev_list = bnx2x_prev_path_get_entry(bp);
+       if (prev_list && (prev_list->undi & (1 << BP_PORT(bp))))
+               bp->link_params.feature_config_flags |=
+                       FEATURE_CONFIG_BOOT_FROM_SAN;
+
        BNX2X_DEV_INFO("Finished Previous Unload Flow [%d]\n", rc);
 
        return rc;
 }
 
-static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
+static void bnx2x_get_common_hwinfo(struct bnx2x *bp)
 {
        u32 val, val2, val3, val4, id, boot_mode;
        u16 pmc;
@@ -9697,6 +9908,14 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 
        bp->link_params.shmem_base = bp->common.shmem_base;
        bp->link_params.shmem2_base = bp->common.shmem2_base;
+       if (SHMEM2_RD(bp, size) >
+           (u32)offsetof(struct shmem2_region, lfa_host_addr[BP_PORT(bp)]))
+               bp->link_params.lfa_base =
+               REG_RD(bp, bp->common.shmem2_base +
+                      (u32)offsetof(struct shmem2_region,
+                                    lfa_host_addr[BP_PORT(bp)]));
+       else
+               bp->link_params.lfa_base = 0;
        BNX2X_DEV_INFO("shmem offset 0x%x  shmem2 offset 0x%x\n",
                       bp->common.shmem_base, bp->common.shmem2_base);
 
@@ -9744,6 +9963,11 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
        bp->link_params.feature_config_flags |=
                (val >= REQ_BC_VER_4_SFP_TX_DISABLE_SUPPORTED) ?
                FEATURE_CONFIG_BC_SUPPORTS_SFP_TX_DISABLED : 0;
+
+       bp->link_params.feature_config_flags |=
+               (val >= REQ_BC_VER_4_MT_SUPPORTED) ?
+               FEATURE_CONFIG_MT_SUPPORT : 0;
+
        bp->flags |= (val >= REQ_BC_VER_4_PFC_STATS_SUPPORTED) ?
                        BC_SUPPORTS_PFC_STATS : 0;
 
@@ -9788,7 +10012,7 @@ static void __devinit bnx2x_get_common_hwinfo(struct bnx2x *bp)
 #define IGU_FID(val)   GET_FIELD((val), IGU_REG_MAPPING_MEMORY_FID)
 #define IGU_VEC(val)   GET_FIELD((val), IGU_REG_MAPPING_MEMORY_VECTOR)
 
-static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
+static int bnx2x_get_igu_cam_info(struct bnx2x *bp)
 {
        int pfid = BP_FUNC(bp);
        int igu_sb_id;
@@ -9805,7 +10029,7 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
                bp->igu_dsb_id =  E1HVN_MAX * FP_SB_MAX_E1x +
                        (CHIP_MODE_IS_4_PORT(bp) ? pfid : vn);
 
-               return;
+               return 0;
        }
 
        /* IGU in normal mode - read CAM */
@@ -9839,12 +10063,15 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
        bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt);
 #endif
 
-       if (igu_sb_cnt == 0)
+       if (igu_sb_cnt == 0) {
                BNX2X_ERR("CAM configuration error\n");
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
-static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
-                                                   u32 switch_cfg)
+static void bnx2x_link_settings_supported(struct bnx2x *bp, u32 switch_cfg)
 {
        int cfg_size = 0, idx, port = BP_PORT(bp);
 
@@ -9942,7 +10169,7 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp,
                       bp->port.supported[1]);
 }
 
-static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
+static void bnx2x_link_settings_requested(struct bnx2x *bp)
 {
        u32 link_config, idx, cfg_size = 0;
        bp->port.advertising[0] = 0;
@@ -10111,11 +10338,13 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
 
                bp->link_params.req_flow_ctrl[idx] = (link_config &
                                         PORT_FEATURE_FLOW_CONTROL_MASK);
-               if ((bp->link_params.req_flow_ctrl[idx] ==
-                    BNX2X_FLOW_CTRL_AUTO) &&
-                   !(bp->port.supported[idx] & SUPPORTED_Autoneg)) {
-                       bp->link_params.req_flow_ctrl[idx] =
-                               BNX2X_FLOW_CTRL_NONE;
+               if (bp->link_params.req_flow_ctrl[idx] ==
+                   BNX2X_FLOW_CTRL_AUTO) {
+                       if (!(bp->port.supported[idx] & SUPPORTED_Autoneg))
+                               bp->link_params.req_flow_ctrl[idx] =
+                                                       BNX2X_FLOW_CTRL_NONE;
+                       else
+                               bnx2x_set_requested_fc(bp);
                }
 
                BNX2X_DEV_INFO("req_line_speed %d  req_duplex %d req_flow_ctrl 0x%x advertising 0x%x\n",
@@ -10126,7 +10355,7 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
        }
 }
 
-static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
+static void bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
 {
        mac_hi = cpu_to_be16(mac_hi);
        mac_lo = cpu_to_be32(mac_lo);
@@ -10134,7 +10363,7 @@ static void __devinit bnx2x_set_mac_buf(u8 *mac_buf, u32 mac_lo, u16 mac_hi)
        memcpy(mac_buf + sizeof(mac_hi), &mac_lo, sizeof(mac_lo));
 }
 
-static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
+static void bnx2x_get_port_hwinfo(struct bnx2x *bp)
 {
        int port = BP_PORT(bp);
        u32 config;
@@ -10195,17 +10424,6 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
                bp->mdio.prtad =
                        XGXS_EXT_PHY_ADDR(ext_phy_config);
 
-       /*
-        * Check if hw lock is required to access MDC/MDIO bus to the PHY(s)
-        * In MF mode, it is set to cover self test cases
-        */
-       if (IS_MF(bp))
-               bp->port.need_hw_lock = 1;
-       else
-               bp->port.need_hw_lock = bnx2x_hw_lock_required(bp,
-                                                       bp->common.shmem_base,
-                                                       bp->common.shmem2_base);
-
        /* Configure link feature according to nvram value */
        eee_mode = (((SHMEM_RD(bp, dev_info.
                      port_feature_config[port].eee_power_mode)) &
@@ -10223,12 +10441,15 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp)
 void bnx2x_get_iscsi_info(struct bnx2x *bp)
 {
        u32 no_flags = NO_ISCSI_FLAG;
-#ifdef BCM_CNIC
        int port = BP_PORT(bp);
-
        u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
                                drv_lic_key[port].max_iscsi_conn);
 
+       if (!CNIC_SUPPORT(bp)) {
+               bp->flags |= no_flags;
+               return;
+       }
+
        /* Get the number of maximum allowed iSCSI connections */
        bp->cnic_eth_dev.max_iscsi_conn =
                (max_iscsi_conn & BNX2X_MAX_ISCSI_INIT_CONN_MASK) >>
@@ -10243,13 +10464,10 @@ void bnx2x_get_iscsi_info(struct bnx2x *bp)
         */
        if (!bp->cnic_eth_dev.max_iscsi_conn)
                bp->flags |= no_flags;
-#else
-       bp->flags |= no_flags;
-#endif
+
 }
 
-#ifdef BCM_CNIC
-static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
+static void bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
 {
        /* Port info */
        bp->cnic_eth_dev.fcoe_wwn_port_name_hi =
@@ -10263,16 +10481,18 @@ static void __devinit bnx2x_get_ext_wwn_info(struct bnx2x *bp, int func)
        bp->cnic_eth_dev.fcoe_wwn_node_name_lo =
                MF_CFG_RD(bp, func_ext_config[func].fcoe_wwn_node_name_lower);
 }
-#endif
-static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
+static void bnx2x_get_fcoe_info(struct bnx2x *bp)
 {
-#ifdef BCM_CNIC
        int port = BP_PORT(bp);
        int func = BP_ABS_FUNC(bp);
-
        u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
                                drv_lic_key[port].max_fcoe_conn);
 
+       if (!CNIC_SUPPORT(bp)) {
+               bp->flags |= NO_FCOE_FLAG;
+               return;
+       }
+
        /* Get the number of maximum allowed FCoE connections */
        bp->cnic_eth_dev.max_fcoe_conn =
                (max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >>
@@ -10307,8 +10527,9 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
                if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp))
                        bnx2x_get_ext_wwn_info(bp, func);
 
-       } else if (IS_MF_FCOE_SD(bp))
+       } else if (IS_MF_FCOE_SD(bp) && !CHIP_IS_E1x(bp)) {
                bnx2x_get_ext_wwn_info(bp, func);
+       }
 
        BNX2X_DEV_INFO("max_fcoe_conn 0x%x\n", bp->cnic_eth_dev.max_fcoe_conn);
 
@@ -10318,12 +10539,9 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
         */
        if (!bp->cnic_eth_dev.max_fcoe_conn)
                bp->flags |= NO_FCOE_FLAG;
-#else
-       bp->flags |= NO_FCOE_FLAG;
-#endif
 }
 
-static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
+static void bnx2x_get_cnic_info(struct bnx2x *bp)
 {
        /*
         * iSCSI may be dynamically disabled but reading
@@ -10334,143 +10552,162 @@ static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
        bnx2x_get_fcoe_info(bp);
 }
 
-static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+static void bnx2x_get_cnic_mac_hwinfo(struct bnx2x *bp)
 {
        u32 val, val2;
        int func = BP_ABS_FUNC(bp);
        int port = BP_PORT(bp);
-#ifdef BCM_CNIC
        u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
        u8 *fip_mac = bp->fip_mac;
-#endif
 
-       /* Zero primary MAC configuration */
-       memset(bp->dev->dev_addr, 0, ETH_ALEN);
-
-       if (BP_NOMCP(bp)) {
-               BNX2X_ERROR("warning: random MAC workaround active\n");
-               eth_hw_addr_random(bp->dev);
-       } else if (IS_MF(bp)) {
-               val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
-               val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
-               if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
-                   (val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
-                       bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
-
-#ifdef BCM_CNIC
-               /*
-                * iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
+       if (IS_MF(bp)) {
+               /* iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
                 * FCoE MAC then the appropriate feature should be disabled.
-                *
-                * In non SD mode features configuration comes from
-                * struct func_ext_config.
+                * In non SD mode features configuration comes from struct
+                * func_ext_config.
                 */
-               if (!IS_MF_SD(bp)) {
+               if (!IS_MF_SD(bp) && !CHIP_IS_E1x(bp)) {
                        u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
                        if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) {
                                val2 = MF_CFG_RD(bp, func_ext_config[func].
-                                                    iscsi_mac_addr_upper);
+                                                iscsi_mac_addr_upper);
                                val = MF_CFG_RD(bp, func_ext_config[func].
-                                                   iscsi_mac_addr_lower);
+                                               iscsi_mac_addr_lower);
                                bnx2x_set_mac_buf(iscsi_mac, val, val2);
-                               BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n",
-                                              iscsi_mac);
-                       } else
+                               BNX2X_DEV_INFO
+                                       ("Read iSCSI MAC: %pM\n", iscsi_mac);
+                       } else {
                                bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+                       }
 
                        if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
                                val2 = MF_CFG_RD(bp, func_ext_config[func].
-                                                    fcoe_mac_addr_upper);
+                                                fcoe_mac_addr_upper);
                                val = MF_CFG_RD(bp, func_ext_config[func].
-                                                   fcoe_mac_addr_lower);
+                                               fcoe_mac_addr_lower);
                                bnx2x_set_mac_buf(fip_mac, val, val2);
-                               BNX2X_DEV_INFO("Read FCoE L2 MAC: %pM\n",
-                                              fip_mac);
-
-                       } else
+                               BNX2X_DEV_INFO
+                                       ("Read FCoE L2 MAC: %pM\n", fip_mac);
+                       } else {
                                bp->flags |= NO_FCOE_FLAG;
+                       }
 
                        bp->mf_ext_config = cfg;
 
                } else { /* SD MODE */
-                       if (IS_MF_STORAGE_SD(bp)) {
-                               if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) {
-                                       /* use primary mac as iscsi mac */
-                                       memcpy(iscsi_mac, bp->dev->dev_addr,
-                                              ETH_ALEN);
-
-                                       BNX2X_DEV_INFO("SD ISCSI MODE\n");
-                                       BNX2X_DEV_INFO("Read iSCSI MAC: %pM\n",
-                                                      iscsi_mac);
-                               } else { /* FCoE */
-                                       memcpy(fip_mac, bp->dev->dev_addr,
-                                              ETH_ALEN);
-                                       BNX2X_DEV_INFO("SD FCoE MODE\n");
-                                       BNX2X_DEV_INFO("Read FIP MAC: %pM\n",
-                                                      fip_mac);
-                               }
-                               /* Zero primary MAC configuration */
-                               memset(bp->dev->dev_addr, 0, ETH_ALEN);
+                       if (BNX2X_IS_MF_SD_PROTOCOL_ISCSI(bp)) {
+                               /* use primary mac as iscsi mac */
+                               memcpy(iscsi_mac, bp->dev->dev_addr, ETH_ALEN);
+
+                               BNX2X_DEV_INFO("SD ISCSI MODE\n");
+                               BNX2X_DEV_INFO
+                                       ("Read iSCSI MAC: %pM\n", iscsi_mac);
+                       } else if (BNX2X_IS_MF_SD_PROTOCOL_FCOE(bp)) {
+                               /* use primary mac as fip mac */
+                               memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
+                               BNX2X_DEV_INFO("SD FCoE MODE\n");
+                               BNX2X_DEV_INFO
+                                       ("Read FIP MAC: %pM\n", fip_mac);
                        }
                }
 
+               if (IS_MF_STORAGE_SD(bp))
+                       /* Zero primary MAC configuration */
+                       memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
                if (IS_MF_FCOE_AFEX(bp))
                        /* use FIP MAC as primary MAC */
                        memcpy(bp->dev->dev_addr, fip_mac, ETH_ALEN);
 
-#endif
        } else {
-               /* in SF read MACs from port configuration */
-               val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
-               val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
-               bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
-
-#ifdef BCM_CNIC
                val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
-                                   iscsi_mac_upper);
+                               iscsi_mac_upper);
                val = SHMEM_RD(bp, dev_info.port_hw_config[port].
-                                  iscsi_mac_lower);
+                              iscsi_mac_lower);
                bnx2x_set_mac_buf(iscsi_mac, val, val2);
 
                val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].
-                                   fcoe_fip_mac_upper);
+                               fcoe_fip_mac_upper);
                val = SHMEM_RD(bp, dev_info.port_hw_config[port].
-                                  fcoe_fip_mac_lower);
+                              fcoe_fip_mac_lower);
                bnx2x_set_mac_buf(fip_mac, val, val2);
-#endif
        }
 
-       memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
-       memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
-
-#ifdef BCM_CNIC
-       /* Disable iSCSI if MAC configuration is
-        * invalid.
-        */
+       /* Disable iSCSI OOO if MAC configuration is invalid. */
        if (!is_valid_ether_addr(iscsi_mac)) {
-               bp->flags |= NO_ISCSI_FLAG;
+               bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
                memset(iscsi_mac, 0, ETH_ALEN);
        }
 
-       /* Disable FCoE if MAC configuration is
-        * invalid.
-        */
+       /* Disable FCoE if MAC configuration is invalid. */
        if (!is_valid_ether_addr(fip_mac)) {
                bp->flags |= NO_FCOE_FLAG;
                memset(bp->fip_mac, 0, ETH_ALEN);
        }
-#endif
+}
+
+static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
+{
+       u32 val, val2;
+       int func = BP_ABS_FUNC(bp);
+       int port = BP_PORT(bp);
+
+       /* Zero primary MAC configuration */
+       memset(bp->dev->dev_addr, 0, ETH_ALEN);
+
+       if (BP_NOMCP(bp)) {
+               BNX2X_ERROR("warning: random MAC workaround active\n");
+               eth_hw_addr_random(bp->dev);
+       } else if (IS_MF(bp)) {
+               val2 = MF_CFG_RD(bp, func_mf_config[func].mac_upper);
+               val = MF_CFG_RD(bp, func_mf_config[func].mac_lower);
+               if ((val2 != FUNC_MF_CFG_UPPERMAC_DEFAULT) &&
+                   (val != FUNC_MF_CFG_LOWERMAC_DEFAULT))
+                       bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+
+               if (CNIC_SUPPORT(bp))
+                       bnx2x_get_cnic_mac_hwinfo(bp);
+       } else {
+               /* in SF read MACs from port configuration */
+               val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
+               val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
+               bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
+
+               if (CNIC_SUPPORT(bp))
+                       bnx2x_get_cnic_mac_hwinfo(bp);
+       }
+
+       memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
+       memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
 
        if (!bnx2x_is_valid_ether_addr(bp, bp->dev->dev_addr))
                dev_err(&bp->pdev->dev,
                        "bad Ethernet MAC address configuration: %pM\n"
                        "change it manually before bringing up the appropriate network interface\n",
                        bp->dev->dev_addr);
+}
 
+static bool bnx2x_get_dropless_info(struct bnx2x *bp)
+{
+       int tmp;
+       u32 cfg;
 
+       if (IS_MF(bp) && !CHIP_IS_E1x(bp)) {
+               /* Take function: tmp = func */
+               tmp = BP_ABS_FUNC(bp);
+               cfg = MF_CFG_RD(bp, func_ext_config[tmp].func_cfg);
+               cfg = !!(cfg & MACP_FUNC_CFG_PAUSE_ON_HOST_RING);
+       } else {
+               /* Take port: tmp = port */
+               tmp = BP_PORT(bp);
+               cfg = SHMEM_RD(bp,
+                              dev_info.port_hw_config[tmp].generic_features);
+               cfg = !!(cfg & PORT_HW_CFG_PAUSE_ON_HOST_RING_ENABLED);
+       }
+       return cfg;
 }
 
-static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
+static int bnx2x_get_hwinfo(struct bnx2x *bp)
 {
        int /*abs*/func = BP_ABS_FUNC(bp);
        int vn;
@@ -10512,6 +10749,8 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
                        if (REG_RD(bp, IGU_REG_RESET_MEMORIES)) {
                                dev_err(&bp->pdev->dev,
                                        "FORCING Normal Mode failed!!!\n");
+                               bnx2x_release_hw_lock(bp,
+                                                     HW_LOCK_RESOURCE_RESET);
                                return -EPERM;
                        }
                }
@@ -10522,9 +10761,10 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
                } else
                        BNX2X_DEV_INFO("IGU Normal Mode\n");
 
-               bnx2x_get_igu_cam_info(bp);
-
+               rc = bnx2x_get_igu_cam_info(bp);
                bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_RESET);
+               if (rc)
+                       return rc;
        }
 
        /*
@@ -10693,7 +10933,7 @@ static int __devinit bnx2x_get_hwinfo(struct bnx2x *bp)
        return rc;
 }
 
-static void __devinit bnx2x_read_fwinfo(struct bnx2x *bp)
+static void bnx2x_read_fwinfo(struct bnx2x *bp)
 {
        int cnt, i, block_end, rodi;
        char vpd_start[BNX2X_VPD_LEN+1];
@@ -10778,7 +11018,7 @@ out_not_found:
        return;
 }
 
-static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
+static void bnx2x_set_modes_bitmap(struct bnx2x *bp)
 {
        u32 flags = 0;
 
@@ -10828,7 +11068,7 @@ static void __devinit bnx2x_set_modes_bitmap(struct bnx2x *bp)
        INIT_MODE_FLAGS(bp) = flags;
 }
 
-static int __devinit bnx2x_init_bp(struct bnx2x *bp)
+static int bnx2x_init_bp(struct bnx2x *bp)
 {
        int func;
        int rc;
@@ -10836,9 +11076,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
        mutex_init(&bp->port.phy_mutex);
        mutex_init(&bp->fw_mb_mutex);
        spin_lock_init(&bp->stats_lock);
-#ifdef BCM_CNIC
-       mutex_init(&bp->cnic_mutex);
-#endif
+
 
        INIT_DELAYED_WORK(&bp->sp_task, bnx2x_sp_task);
        INIT_DELAYED_WORK(&bp->sp_rtnl_task, bnx2x_sp_rtnl_task);
@@ -10876,10 +11114,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
                dev_err(&bp->pdev->dev, "MCP disabled, must load devices in order!\n");
 
        bp->disable_tpa = disable_tpa;
-
-#ifdef BCM_CNIC
        bp->disable_tpa |= IS_MF_STORAGE_SD(bp) || IS_MF_FCOE_AFEX(bp);
-#endif
 
        /* Set TPA flags */
        if (bp->disable_tpa) {
@@ -10893,7 +11128,7 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
        if (CHIP_IS_E1(bp))
                bp->dropless_fc = 0;
        else
-               bp->dropless_fc = dropless_fc;
+               bp->dropless_fc = dropless_fc | bnx2x_get_dropless_info(bp);
 
        bp->mrrs = mrrs;
 
@@ -10910,15 +11145,20 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
        bp->timer.data = (unsigned long) bp;
        bp->timer.function = bnx2x_timer;
 
-       bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
-       bnx2x_dcbx_init_params(bp);
+       if (SHMEM2_HAS(bp, dcbx_lldp_params_offset) &&
+           SHMEM2_HAS(bp, dcbx_lldp_dcbx_stat_offset) &&
+           SHMEM2_RD(bp, dcbx_lldp_params_offset) &&
+           SHMEM2_RD(bp, dcbx_lldp_dcbx_stat_offset)) {
+               bnx2x_dcbx_set_state(bp, true, BNX2X_DCBX_ENABLED_ON_NEG_ON);
+               bnx2x_dcbx_init_params(bp);
+       } else {
+               bnx2x_dcbx_set_state(bp, false, BNX2X_DCBX_ENABLED_OFF);
+       }
 
-#ifdef BCM_CNIC
        if (CHIP_IS_E1x(bp))
                bp->cnic_base_cl_id = FP_SB_MAX_E1x;
        else
                bp->cnic_base_cl_id = FP_SB_MAX_E2;
-#endif
 
        /* multiple tx priority */
        if (CHIP_IS_E1x(bp))
@@ -10928,6 +11168,16 @@ static int __devinit bnx2x_init_bp(struct bnx2x *bp)
        if (CHIP_IS_E3B0(bp))
                bp->max_cos = BNX2X_MULTI_TX_COS_E3B0;
 
+       /* We need at least one default status block for slow-path events,
+        * second status block for the L2 queue, and a third status block for
+        * CNIC if supproted.
+        */
+       if (CNIC_SUPPORT(bp))
+               bp->min_msix_vec_cnt = 3;
+       else
+               bp->min_msix_vec_cnt = 2;
+       BNX2X_DEV_INFO("bp->min_msix_vec_cnt %d", bp->min_msix_vec_cnt);
+
        return rc;
 }
 
@@ -11164,11 +11414,9 @@ void bnx2x_set_rx_mode(struct net_device *dev)
        }
 
        bp->rx_mode = rx_mode;
-#ifdef BCM_CNIC
        /* handle ISCSI SD mode */
        if (IS_MF_ISCSI_SD(bp))
                bp->rx_mode = BNX2X_RX_MODE_NONE;
-#endif
 
        /* Schedule the rx_mode command */
        if (test_bit(BNX2X_FILTER_RX_MODE_PENDING, &bp->sp_state)) {
@@ -11280,7 +11528,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
 #endif
        .ndo_setup_tc           = bnx2x_setup_tc,
 
-#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
+#ifdef NETDEV_FCOE_WWNN
        .ndo_fcoe_get_wwn       = bnx2x_fcoe_get_wwn,
 #endif
 };
@@ -11303,9 +11551,8 @@ static int bnx2x_set_coherency_mask(struct bnx2x *bp)
        return 0;
 }
 
-static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
-                                   struct net_device *dev,
-                                   unsigned long board_type)
+static int bnx2x_init_dev(struct pci_dev *pdev, struct net_device *dev,
+                         unsigned long board_type)
 {
        struct bnx2x *bp;
        int rc;
@@ -11342,6 +11589,14 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
                goto err_out_disable;
        }
 
+       pci_read_config_dword(pdev, PCICFG_REVISION_ID_OFFSET, &pci_cfg_dword);
+       if ((pci_cfg_dword & PCICFG_REVESION_ID_MASK) ==
+           PCICFG_REVESION_ID_ERROR_VAL) {
+               pr_err("PCI device error, probably due to fan failure, aborting\n");
+               rc = -ENODEV;
+               goto err_out_disable;
+       }
+
        if (atomic_read(&pdev->enable_cnt) == 1) {
                rc = pci_request_regions(pdev, DRV_MODULE_NAME);
                if (rc) {
@@ -11477,8 +11732,7 @@ err_out:
        return rc;
 }
 
-static void __devinit bnx2x_get_pcie_width_speed(struct bnx2x *bp,
-                                                int *width, int *speed)
+static void bnx2x_get_pcie_width_speed(struct bnx2x *bp, int *width, int *speed)
 {
        u32 val = REG_RD(bp, PCICFG_OFFSET + PCICFG_LINK_CONTROL);
 
@@ -11746,9 +12000,8 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
 {
        int cid_count = BNX2X_L2_MAX_CID(bp);
 
-#ifdef BCM_CNIC
-       cid_count += CNIC_CID_MAX;
-#endif
+       if (CNIC_SUPPORT(bp))
+               cid_count += CNIC_CID_MAX;
        return roundup(cid_count, QM_CID_ROUND);
 }
 
@@ -11758,7 +12011,8 @@ static int bnx2x_set_qm_cid_count(struct bnx2x *bp)
  * @dev:       pci device
  *
  */
-static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
+static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev,
+                                    int cnic_cnt)
 {
        int pos;
        u16 control;
@@ -11770,7 +12024,7 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
         * one fast path queue: one FP queue + SB for CNIC
         */
        if (!pos)
-               return 1 + CNIC_PRESENT;
+               return 1 + cnic_cnt;
 
        /*
         * The value in the PCI configuration space is the index of the last
@@ -11782,14 +12036,16 @@ static int bnx2x_get_num_non_def_sbs(struct pci_dev *pdev)
        return control & PCI_MSIX_FLAGS_QSIZE;
 }
 
-static int __devinit bnx2x_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *);
+
+static int bnx2x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev = NULL;
        struct bnx2x *bp;
        int pcie_width, pcie_speed;
        int rc, max_non_def_sbs;
        int rx_count, tx_count, rss_count, doorbell_size;
+       int cnic_cnt;
        /*
         * An estimated maximum supported CoS number according to the chip
         * version.
@@ -11833,21 +12089,22 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
                return -ENODEV;
        }
 
-       max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev);
+       cnic_cnt = 1;
+       max_non_def_sbs = bnx2x_get_num_non_def_sbs(pdev, cnic_cnt);
 
        WARN_ON(!max_non_def_sbs);
 
        /* Maximum number of RSS queues: one IGU SB goes to CNIC */
-       rss_count = max_non_def_sbs - CNIC_PRESENT;
+       rss_count = max_non_def_sbs - cnic_cnt;
 
        /* Maximum number of netdev Rx queues: RSS + FCoE L2 */
-       rx_count = rss_count + FCOE_PRESENT;
+       rx_count = rss_count + cnic_cnt;
 
        /*
         * Maximum number of netdev Tx queues:
         * Maximum TSS queues * Maximum supported number of CoS  + FCoE L2
         */
-       tx_count = rss_count * max_cos_est + FCOE_PRESENT;
+       tx_count = rss_count * max_cos_est + cnic_cnt;
 
        /* dev zeroed in init_etherdev */
        dev = alloc_etherdev_mqs(sizeof(*bp), tx_count, rx_count);
@@ -11858,6 +12115,9 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
 
        bp->igu_sb_cnt = max_non_def_sbs;
        bp->msg_enable = debug;
+       bp->cnic_support = cnic_cnt;
+       bp->cnic_probe = bnx2x_cnic_probe;
+
        pci_set_drvdata(pdev, dev);
 
        rc = bnx2x_init_dev(pdev, dev, ent->driver_data);
@@ -11866,6 +12126,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
                return rc;
        }
 
+       BNX2X_DEV_INFO("Cnic support is %s\n", CNIC_SUPPORT(bp) ? "on" : "off");
        BNX2X_DEV_INFO("max_non_def_sbs %d\n", max_non_def_sbs);
 
        BNX2X_DEV_INFO("Allocated netdev with %d tx and %d rx queues\n",
@@ -11898,13 +12159,19 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
        /* calc qm_cid_count */
        bp->qm_cid_count = bnx2x_set_qm_cid_count(bp);
 
-#ifdef BCM_CNIC
-       /* disable FCOE L2 queue for E1x */
+       /* disable FCOE L2 queue for E1x*/
        if (CHIP_IS_E1x(bp))
                bp->flags |= NO_FCOE_FLAG;
 
-#endif
-
+       /* disable FCOE for 57840 device, until FW supports it */
+       switch (ent->driver_data) {
+       case BCM57840_O:
+       case BCM57840_4_10:
+       case BCM57840_2_20:
+       case BCM57840_MFO:
+       case BCM57840_MF:
+               bp->flags |= NO_FCOE_FLAG;
+       }
 
        /* Set bp->num_queues for MSI-X mode*/
        bnx2x_set_num_queues(bp);
@@ -11920,14 +12187,13 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
                goto init_one_exit;
        }
 
-#ifdef BCM_CNIC
+
        if (!NO_FCOE(bp)) {
                /* Add storage MAC address */
                rtnl_lock();
                dev_addr_add(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
                rtnl_unlock();
        }
-#endif
 
        bnx2x_get_pcie_width_speed(bp, &pcie_width, &pcie_speed);
 
@@ -11961,7 +12227,7 @@ init_one_exit:
        return rc;
 }
 
-static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
+static void bnx2x_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct bnx2x *bp;
@@ -11972,14 +12238,12 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
        }
        bp = netdev_priv(dev);
 
-#ifdef BCM_CNIC
        /* Delete storage MAC address */
        if (!NO_FCOE(bp)) {
                rtnl_lock();
                dev_addr_del(bp->dev, bp->fip_mac, NETDEV_HW_ADDR_T_SAN);
                rtnl_unlock();
        }
-#endif
 
 #ifdef BCM_DCBNL
        /* Delete app tlvs from dcbnl */
@@ -12027,15 +12291,17 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
 
        bp->rx_mode = BNX2X_RX_MODE_NONE;
 
-#ifdef BCM_CNIC
-       bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
-#endif
+       if (CNIC_LOADED(bp))
+               bnx2x_cnic_notify(bp, CNIC_CTL_STOP_CMD);
+
        /* Stop Tx */
        bnx2x_tx_disable(bp);
 
        bnx2x_netif_stop(bp, 0);
        /* Delete all NAPI objects */
        bnx2x_del_all_napi(bp);
+       if (CNIC_LOADED(bp))
+               bnx2x_del_all_napi_cnic(bp);
 
        del_timer_sync(&bp->timer);
 
@@ -12176,7 +12442,7 @@ static struct pci_driver bnx2x_pci_driver = {
        .name        = DRV_MODULE_NAME,
        .id_table    = bnx2x_pci_tbl,
        .probe       = bnx2x_init_one,
-       .remove      = __devexit_p(bnx2x_remove_one),
+       .remove      = bnx2x_remove_one,
        .suspend     = bnx2x_suspend,
        .resume      = bnx2x_resume,
        .err_handler = &bnx2x_err_handler,
@@ -12226,7 +12492,6 @@ void bnx2x_notify_link_changed(struct bnx2x *bp)
 module_init(bnx2x_init);
 module_exit(bnx2x_cleanup);
 
-#ifdef BCM_CNIC
 /**
  * bnx2x_set_iscsi_eth_mac_addr - set iSCSI MAC(s).
  *
@@ -12679,12 +12944,31 @@ static int bnx2x_register_cnic(struct net_device *dev, struct cnic_ops *ops,
 {
        struct bnx2x *bp = netdev_priv(dev);
        struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
+       int rc;
+
+       DP(NETIF_MSG_IFUP, "Register_cnic called\n");
 
        if (ops == NULL) {
                BNX2X_ERR("NULL ops received\n");
                return -EINVAL;
        }
 
+       if (!CNIC_SUPPORT(bp)) {
+               BNX2X_ERR("Can't register CNIC when not supported\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (!CNIC_LOADED(bp)) {
+               rc = bnx2x_load_cnic(bp);
+               if (rc) {
+                       BNX2X_ERR("CNIC-related load failed\n");
+                       return rc;
+               }
+
+       }
+
+       bp->cnic_enabled = true;
+
        bp->cnic_kwq = kzalloc(PAGE_SIZE, GFP_KERNEL);
        if (!bp->cnic_kwq)
                return -ENOMEM;
@@ -12774,7 +13058,5 @@ struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev)
           cp->starting_cid);
        return cp;
 }
-EXPORT_SYMBOL(bnx2x_cnic_probe);
 
-#endif /* BCM_CNIC */
 
index 1b1999d34c7180f41649b606695ecccfbcb237c5..bc2f65b32649de1dcbd5b456a4b915fdea9d1ef3 100644 (file)
 #define NIG_REG_LLH1_ERROR_MASK                                 0x10090
 /* [RW 8] event id for llh1 */
 #define NIG_REG_LLH1_EVENT_ID                                   0x10088
+#define NIG_REG_LLH1_FUNC_EN                                    0x16104
 #define NIG_REG_LLH1_FUNC_MEM                                   0x161c0
 #define NIG_REG_LLH1_FUNC_MEM_ENABLE                            0x16160
 #define NIG_REG_LLH1_FUNC_MEM_SIZE                              16
  * set to 0x345678021. This is a new register (with 2_) added in E3 B0 to
  * accommodate the 9 input clients to ETS arbiter. */
 #define NIG_REG_P0_TX_ARB_PRIORITY_CLIENT2_MSB                  0x18684
+/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP
+ * packets to BRB LB interface to forward the packet to the host. All
+ * packets from MCP are forwarded to the network when this bit is cleared -
+ * regardless of the configured destination in tx_mng_destination register.
+ * When MCP-to-host paths for both ports 0 and 1 are disabled - the arbiter
+ * for BRB LB interface is bypassed and PBF LB traffic is always selected to
+ * send to BRB LB.
+ */
+#define NIG_REG_P0_TX_MNG_HOST_ENABLE                           0x182f4
 #define NIG_REG_P1_HWPFC_ENABLE                                         0x181d0
 #define NIG_REG_P1_MAC_IN_EN                                    0x185c0
 /* [RW 1] Output enable for TX MAC interface */
 #define NIG_REG_P1_TX_ARB_PRIORITY_CLIENT2_MSB                  0x186e4
 /* [R 1] TX FIFO for transmitting data to MAC is empty. */
 #define NIG_REG_P1_TX_MACFIFO_EMPTY                             0x18594
+/* [RW 1] MCP-to-host path enable. Set this bit to enable the routing of MCP
+ * packets to BRB LB interface to forward the packet to the host. All
+ * packets from MCP are forwarded to the network when this bit is cleared -
+ * regardless of the configured destination in tx_mng_destination register.
+ */
+#define NIG_REG_P1_TX_MNG_HOST_ENABLE                           0x182f8
 /* [R 1] FIFO empty status of the MCP TX FIFO used for storing MCP packets
    forwarded to the host. */
 #define NIG_REG_P1_TX_MNG_HOST_FIFO_EMPTY                       0x182b8
 #define XMAC_CTRL_REG_RX_EN                                     (0x1<<1)
 #define XMAC_CTRL_REG_SOFT_RESET                                (0x1<<6)
 #define XMAC_CTRL_REG_TX_EN                                     (0x1<<0)
+#define XMAC_CTRL_REG_XLGMII_ALIGN_ENB                          (0x1<<7)
 #define XMAC_PAUSE_CTRL_REG_RX_PAUSE_EN                                 (0x1<<18)
 #define XMAC_PAUSE_CTRL_REG_TX_PAUSE_EN                                 (0x1<<17)
 #define XMAC_PFC_CTRL_HI_REG_FORCE_PFC_XON                      (0x1<<1)
 #define XMAC_REG_PAUSE_CTRL                                     0x68
 #define XMAC_REG_PFC_CTRL                                       0x70
 #define XMAC_REG_PFC_CTRL_HI                                    0x74
+#define XMAC_REG_RX_LSS_CTRL                                    0x50
 #define XMAC_REG_RX_LSS_STATUS                                  0x58
 /* [RW 14] Maximum packet size in receive direction; exclusive of preamble &
  * CRC in strip mode */
 #define XMAC_REG_RX_MAX_SIZE                                    0x40
 #define XMAC_REG_TX_CTRL                                        0x20
+#define XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE                (0x1<<0)
+#define XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE               (0x1<<1)
 /* [RW 16] Indirect access to the XX table of the XX protection mechanism.
    The fields are:[4:0] - tail pointer; 9:5] - Link List size; 14:10] -
    header pointer. */
 #define MISC_REGISTERS_SPIO_OUTPUT_HIGH                         1
 #define MISC_REGISTERS_SPIO_OUTPUT_LOW                          0
 #define MISC_REGISTERS_SPIO_SET_POS                             8
+#define MISC_SPIO_CLR_POS                                       16
+#define MISC_SPIO_FLOAT                                         (0xffL<<24)
+#define MISC_SPIO_FLOAT_POS                                     24
+#define MISC_SPIO_INPUT_HI_Z                                    2
+#define MISC_SPIO_INT_OLD_SET_POS                               16
+#define MISC_SPIO_OUTPUT_HIGH                                   1
+#define MISC_SPIO_OUTPUT_LOW                                    0
+#define MISC_SPIO_SET_POS                                       8
+#define MISC_SPIO_SPIO4                                         0x10
+#define MISC_SPIO_SPIO5                                         0x20
 #define HW_LOCK_MAX_RESOURCE_VALUE                              31
 #define HW_LOCK_RESOURCE_DCBX_ADMIN_MIB                                 13
 #define HW_LOCK_RESOURCE_DRV_FLAGS                              10
 #define PCICFG_COMMAND_INT_DISABLE             (1<<10)
 #define PCICFG_COMMAND_RESERVED                (0x1f<<11)
 #define PCICFG_STATUS_OFFSET                           0x06
-#define PCICFG_REVESION_ID_OFFSET                      0x08
+#define PCICFG_REVISION_ID_OFFSET                      0x08
+#define PCICFG_REVESION_ID_MASK                        0xff
+#define PCICFG_REVESION_ID_ERROR_VAL           0xff
 #define PCICFG_CACHE_LINE_SIZE                         0x0c
 #define PCICFG_LATENCY_TIMER                           0x0d
 #define PCICFG_BAR_1_LOW                               0x10
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI     0x1B00
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS   0x1E00
 #define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI     0x1F00
+#define MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2     0x3900
 
 
 #define MDIO_REG_BANK_10G_PARALLEL_DETECT              0x8130
@@ -7046,7 +7079,8 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT2      0x12
 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_ABILITY    0x4000
 #define MDIO_WC_REG_AN_IEEE1BLK_AN_ADV2_FEC_REQ                0x8000
-#define MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150  0x96
+#define MDIO_WC_REG_PCS_STATUS2                                0x0021
+#define MDIO_WC_REG_PMD_KR_CONTROL                     0x0096
 #define MDIO_WC_REG_XGXSBLK0_XGXSCONTROL               0x8000
 #define MDIO_WC_REG_XGXSBLK0_MISCCONTROL1              0x800e
 #define MDIO_WC_REG_XGXSBLK1_DESKEW                    0x8010
@@ -7078,6 +7112,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_PAR_DET_10G_STATUS                 0x8130
 #define MDIO_WC_REG_PAR_DET_10G_CTRL                   0x8131
 #define MDIO_WC_REG_XGXS_X2_CONTROL2                   0x8141
+#define MDIO_WC_REG_XGXS_X2_CONTROL3                   0x8142
 #define MDIO_WC_REG_XGXS_RX_LN_SWAP1                   0x816B
 #define MDIO_WC_REG_XGXS_TX_LN_SWAP1                   0x8169
 #define MDIO_WC_REG_GP2_STATUS_GP_2_0                  0x81d0
@@ -7112,6 +7147,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_OFFSET         0x0a
 #define MDIO_WC_REG_TX_FIR_TAP_POST_TAP_MASK           0x7c00
 #define MDIO_WC_REG_TX_FIR_TAP_ENABLE          0x8000
+#define MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP                0x82e2
 #define MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL     0x82e3
 #define MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL       0x82e6
 #define MDIO_WC_REG_CL72_USERB0_CL72_BR_DEF_CTRL       0x82e7
@@ -7129,9 +7165,16 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_DIGITAL4_MISC5                     0x833e
 #define MDIO_WC_REG_DIGITAL5_MISC6                     0x8345
 #define MDIO_WC_REG_DIGITAL5_MISC7                     0x8349
+#define MDIO_WC_REG_DIGITAL5_LINK_STATUS               0x834d
 #define MDIO_WC_REG_DIGITAL5_ACTUAL_SPEED              0x834e
 #define MDIO_WC_REG_DIGITAL6_MP5_NEXTPAGECTRL          0x8350
 #define MDIO_WC_REG_CL49_USERB0_CTRL                   0x8368
+#define MDIO_WC_REG_CL73_USERB0_CTRL                   0x8370
+#define MDIO_WC_REG_CL73_USERB0_USTAT                  0x8371
+#define MDIO_WC_REG_CL73_BAM_CTRL1                     0x8372
+#define MDIO_WC_REG_CL73_BAM_CTRL2                     0x8373
+#define MDIO_WC_REG_CL73_BAM_CTRL3                     0x8374
+#define MDIO_WC_REG_CL73_BAM_CODE_FIELD                        0x837b
 #define MDIO_WC_REG_EEE_COMBO_CONTROL0                 0x8390
 #define MDIO_WC_REG_TX66_CONTROL                       0x83b0
 #define MDIO_WC_REG_RX66_CONTROL                       0x83c0
@@ -7145,7 +7188,17 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_WC_REG_RX66_SCW3_MASK                     0x83c9
 #define MDIO_WC_REG_FX100_CTRL1                                0x8400
 #define MDIO_WC_REG_FX100_CTRL3                                0x8402
-
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL5               0x8436
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL6               0x8437
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL7               0x8438
+#define MDIO_WC_REG_CL82_USERB1_TX_CTRL9               0x8439
+#define MDIO_WC_REG_CL82_USERB1_RX_CTRL10              0x843a
+#define MDIO_WC_REG_CL82_USERB1_RX_CTRL11              0x843b
+#define MDIO_WC_REG_ETA_CL73_OUI1                      0x8453
+#define MDIO_WC_REG_ETA_CL73_OUI2                      0x8454
+#define MDIO_WC_REG_ETA_CL73_OUI3                      0x8455
+#define MDIO_WC_REG_ETA_CL73_LD_BAM_CODE               0x8456
+#define MDIO_WC_REG_ETA_CL73_LD_UD_CODE                        0x8457
 #define MDIO_WC_REG_MICROBLK_CMD                       0xffc2
 #define MDIO_WC_REG_MICROBLK_DL_STATUS                 0xffc5
 #define MDIO_WC_REG_MICROBLK_CMD3                      0xffcc
index 71971a161bd199746595d501691f19300c5ff2ad..b8b4b749daab7d8f5a954c679422035182c0df30 100644 (file)
@@ -126,7 +126,7 @@ static inline int bnx2x_exe_queue_add(struct bnx2x *bp,
                /* Check if this request is ok */
                rc = o->validate(bp, o->owner, elem);
                if (rc) {
-                       BNX2X_ERR("Preamble failed: %d\n", rc);
+                       DP(BNX2X_MSG_SP, "Preamble failed: %d\n", rc);
                        goto free_and_exit;
                }
        }
@@ -5350,12 +5350,24 @@ static int bnx2x_func_chk_transition(struct bnx2x *bp,
                else if ((cmd == BNX2X_F_CMD_AFEX_VIFLISTS) &&
                         (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
                        next_state = BNX2X_F_STATE_STARTED;
+
+               /* Switch_update ramrod can be sent in either started or
+                * tx_stopped state, and it doesn't change the state.
+                */
+               else if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
+                        (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
+                       next_state = BNX2X_F_STATE_STARTED;
+
                else if (cmd == BNX2X_F_CMD_TX_STOP)
                        next_state = BNX2X_F_STATE_TX_STOPPED;
 
                break;
        case BNX2X_F_STATE_TX_STOPPED:
-               if (cmd == BNX2X_F_CMD_TX_START)
+               if ((cmd == BNX2X_F_CMD_SWITCH_UPDATE) &&
+                   (!test_bit(BNX2X_F_CMD_STOP, &o->pending)))
+                       next_state = BNX2X_F_STATE_TX_STOPPED;
+
+               else if (cmd == BNX2X_F_CMD_TX_START)
                        next_state = BNX2X_F_STATE_STARTED;
 
                break;
@@ -5637,6 +5649,28 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,
                             U64_LO(data_mapping), NONE_CONNECTION_TYPE);
 }
 
+static inline int bnx2x_func_send_switch_update(struct bnx2x *bp,
+                                       struct bnx2x_func_state_params *params)
+{
+       struct bnx2x_func_sp_obj *o = params->f_obj;
+       struct function_update_data *rdata =
+               (struct function_update_data *)o->rdata;
+       dma_addr_t data_mapping = o->rdata_mapping;
+       struct bnx2x_func_switch_update_params *switch_update_params =
+               &params->params.switch_update;
+
+       memset(rdata, 0, sizeof(*rdata));
+
+       /* Fill the ramrod data with provided parameters */
+       rdata->tx_switch_suspend_change_flg = 1;
+       rdata->tx_switch_suspend = switch_update_params->suspend;
+       rdata->echo = SWITCH_UPDATE;
+
+       return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_FUNCTION_UPDATE, 0,
+                            U64_HI(data_mapping),
+                            U64_LO(data_mapping), NONE_CONNECTION_TYPE);
+}
+
 static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
                                         struct bnx2x_func_state_params *params)
 {
@@ -5657,6 +5691,7 @@ static inline int bnx2x_func_send_afex_update(struct bnx2x *bp,
                cpu_to_le16(afex_update_params->afex_default_vlan);
        rdata->allowed_priorities_change_flg = 1;
        rdata->allowed_priorities = afex_update_params->allowed_priorities;
+       rdata->echo = AFEX_UPDATE;
 
        /*  No need for an explicit memory barrier here as long we would
         *  need to ensure the ordering of writing to the SPQ element
@@ -5773,6 +5808,8 @@ static int bnx2x_func_send_cmd(struct bnx2x *bp,
                return bnx2x_func_send_tx_stop(bp, params);
        case BNX2X_F_CMD_TX_START:
                return bnx2x_func_send_tx_start(bp, params);
+       case BNX2X_F_CMD_SWITCH_UPDATE:
+               return bnx2x_func_send_switch_update(bp, params);
        default:
                BNX2X_ERR("Unknown command: %d\n", params->cmd);
                return -EINVAL;
@@ -5818,16 +5855,30 @@ int bnx2x_func_state_change(struct bnx2x *bp,
                            struct bnx2x_func_state_params *params)
 {
        struct bnx2x_func_sp_obj *o = params->f_obj;
-       int rc;
+       int rc, cnt = 300;
        enum bnx2x_func_cmd cmd = params->cmd;
        unsigned long *pending = &o->pending;
 
        mutex_lock(&o->one_pending_mutex);
 
        /* Check that the requested transition is legal */
-       if (o->check_transition(bp, o, params)) {
+       rc = o->check_transition(bp, o, params);
+       if ((rc == -EBUSY) &&
+           (test_bit(RAMROD_RETRY, &params->ramrod_flags))) {
+               while ((rc == -EBUSY) && (--cnt > 0)) {
+                       mutex_unlock(&o->one_pending_mutex);
+                       msleep(10);
+                       mutex_lock(&o->one_pending_mutex);
+                       rc = o->check_transition(bp, o, params);
+               }
+               if (rc == -EBUSY) {
+                       mutex_unlock(&o->one_pending_mutex);
+                       BNX2X_ERR("timeout waiting for previous ramrod completion\n");
+                       return rc;
+               }
+       } else if (rc) {
                mutex_unlock(&o->one_pending_mutex);
-               return -EINVAL;
+               return rc;
        }
 
        /* Set "pending" bit */
index acf2fe4ca60851091c39c2e8ed8ec6fb71aa2d78..adbd91b1bdfc56a6edc93c3409f798e27de1d84c 100644 (file)
@@ -40,6 +40,12 @@ enum {
         * pending commands list.
         */
        RAMROD_CONT,
+       /* If there is another pending ramrod, wait until it finishes and
+        * re-try to submit this one. This flag can be set only in sleepable
+        * context, and should not be set from the context that completes the
+        * ramrods as deadlock will occur.
+        */
+       RAMROD_RETRY,
 };
 
 typedef enum {
@@ -1061,6 +1067,7 @@ enum bnx2x_func_cmd {
        BNX2X_F_CMD_AFEX_VIFLISTS,
        BNX2X_F_CMD_TX_STOP,
        BNX2X_F_CMD_TX_START,
+       BNX2X_F_CMD_SWITCH_UPDATE,
        BNX2X_F_CMD_MAX,
 };
 
@@ -1103,6 +1110,10 @@ struct bnx2x_func_start_params {
        u8 network_cos_mode;
 };
 
+struct bnx2x_func_switch_update_params {
+       u8 suspend;
+};
+
 struct bnx2x_func_afex_update_params {
        u16 vif_id;
        u16 afex_default_vlan;
@@ -1136,6 +1147,7 @@ struct bnx2x_func_state_params {
                struct bnx2x_func_hw_init_params hw_init;
                struct bnx2x_func_hw_reset_params hw_reset;
                struct bnx2x_func_start_params start;
+               struct bnx2x_func_switch_update_params switch_update;
                struct bnx2x_func_afex_update_params afex_update;
                struct bnx2x_func_afex_viflists_params afex_viflists;
                struct bnx2x_func_tx_start_params tx_start;
index 348ed02d3c69928c3991d7c8de046ccf95c0a3c9..89ec0667140a02dc67f16b2ae79a59eaeaccff5e 100644 (file)
@@ -1149,6 +1149,7 @@ static void bnx2x_drv_stats_update(struct bnx2x *bp)
                UPDATE_ESTAT_QSTAT(rx_err_discard_pkt);
                UPDATE_ESTAT_QSTAT(rx_skb_alloc_failed);
                UPDATE_ESTAT_QSTAT(hw_csum_err);
+               UPDATE_ESTAT_QSTAT(driver_filtered_tx_pkt);
        }
 }
 
index 24b8e505b60c941e8b75f2e45efa3201347c7e1c..b4d7b26c7fe78906be5998608c3b0d46b7e1df84 100644 (file)
@@ -203,6 +203,7 @@ struct bnx2x_eth_stats {
        /* Recovery */
        u32 recoverable_error;
        u32 unrecoverable_error;
+       u32 driver_filtered_tx_pkt;
        /* src: Clear-on-Read register; Will not survive PMF Migration */
        u32 eee_tx_lpi;
 };
@@ -264,6 +265,7 @@ struct bnx2x_eth_q_stats {
        u32 total_tpa_aggregated_frames_lo;
        u32 total_tpa_bytes_hi;
        u32 total_tpa_bytes_lo;
+       u32 driver_filtered_tx_pkt;
 };
 
 struct bnx2x_eth_stats_old {
@@ -315,6 +317,7 @@ struct bnx2x_eth_q_stats_old {
        u32 rx_err_discard_pkt_old;
        u32 rx_skb_alloc_failed_old;
        u32 hw_csum_err_old;
+       u32 driver_filtered_tx_pkt_old;
 };
 
 struct bnx2x_net_stats_old {
index cc8434fd606e2a089e20708f4ee12794fdfdd1e1..df8c30d1a52cc4d1fc35e6fb8f7cf6c1b73d31c3 100644 (file)
 #include <net/ip6_checksum.h>
 #include <scsi/iscsi_if.h>
 
+#define BCM_CNIC       1
 #include "cnic_if.h"
 #include "bnx2.h"
+#include "bnx2x/bnx2x.h"
 #include "bnx2x/bnx2x_reg.h"
 #include "bnx2x/bnx2x_fw_defs.h"
 #include "bnx2x/bnx2x_hsi.h"
 #include "cnic.h"
 #include "cnic_defs.h"
 
-#define DRV_MODULE_NAME                "cnic"
+#define CNIC_MODULE_NAME       "cnic"
 
-static char version[] __devinitdata =
-       "Broadcom NetXtreme II CNIC Driver " DRV_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
+static char version[] =
+       "Broadcom NetXtreme II CNIC Driver " CNIC_MODULE_NAME " v" CNIC_MODULE_VERSION " (" CNIC_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("Michael Chan <mchan@broadcom.com> and John(Zongxi) "
              "Chen (zongxi@broadcom.com");
@@ -724,7 +726,7 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma)
 
        for (i = 0; i < dma->num_pages; i++) {
                if (dma->pg_arr[i]) {
-                       dma_free_coherent(&dev->pcidev->dev, BCM_PAGE_SIZE,
+                       dma_free_coherent(&dev->pcidev->dev, BNX2_PAGE_SIZE,
                                          dma->pg_arr[i], dma->pg_map_arr[i]);
                        dma->pg_arr[i] = NULL;
                }
@@ -783,7 +785,7 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
 
        for (i = 0; i < pages; i++) {
                dma->pg_arr[i] = dma_alloc_coherent(&dev->pcidev->dev,
-                                                   BCM_PAGE_SIZE,
+                                                   BNX2_PAGE_SIZE,
                                                    &dma->pg_map_arr[i],
                                                    GFP_ATOMIC);
                if (dma->pg_arr[i] == NULL)
@@ -792,8 +794,8 @@ static int cnic_alloc_dma(struct cnic_dev *dev, struct cnic_dma *dma,
        if (!use_pg_tbl)
                return 0;
 
-       dma->pgtbl_size = ((pages * 8) + BCM_PAGE_SIZE - 1) &
-                         ~(BCM_PAGE_SIZE - 1);
+       dma->pgtbl_size = ((pages * 8) + BNX2_PAGE_SIZE - 1) &
+                         ~(BNX2_PAGE_SIZE - 1);
        dma->pgtbl = dma_alloc_coherent(&dev->pcidev->dev, dma->pgtbl_size,
                                        &dma->pgtbl_map, GFP_ATOMIC);
        if (dma->pgtbl == NULL)
@@ -895,11 +897,11 @@ static int cnic_alloc_context(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
 
-       if (CHIP_NUM(cp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(cp) == BNX2_CHIP_5709) {
                int i, k, arr_size;
 
-               cp->ctx_blk_size = BCM_PAGE_SIZE;
-               cp->cids_per_blk = BCM_PAGE_SIZE / 128;
+               cp->ctx_blk_size = BNX2_PAGE_SIZE;
+               cp->cids_per_blk = BNX2_PAGE_SIZE / 128;
                arr_size = BNX2_MAX_CID / cp->cids_per_blk *
                           sizeof(struct cnic_ctx);
                cp->ctx_arr = kzalloc(arr_size, GFP_KERNEL);
@@ -931,7 +933,7 @@ static int cnic_alloc_context(struct cnic_dev *dev)
                for (i = 0; i < cp->ctx_blks; i++) {
                        cp->ctx_arr[i].ctx =
                                dma_alloc_coherent(&dev->pcidev->dev,
-                                                  BCM_PAGE_SIZE,
+                                                  BNX2_PAGE_SIZE,
                                                   &cp->ctx_arr[i].mapping,
                                                   GFP_KERNEL);
                        if (cp->ctx_arr[i].ctx == NULL)
@@ -1011,7 +1013,7 @@ static int __cnic_alloc_uio_rings(struct cnic_uio_dev *udev, int pages)
        if (udev->l2_ring)
                return 0;
 
-       udev->l2_ring_size = pages * BCM_PAGE_SIZE;
+       udev->l2_ring_size = pages * BNX2_PAGE_SIZE;
        udev->l2_ring = dma_alloc_coherent(&udev->pdev->dev, udev->l2_ring_size,
                                           &udev->l2_ring_map,
                                           GFP_KERNEL | __GFP_COMP);
@@ -1234,8 +1236,6 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
        int i, j, n, ret, pages;
        struct cnic_dma *kwq_16_dma = &cp->kwq_16_data_info;
 
-       cp->iro_arr = ethdev->iro_arr;
-
        cp->max_cid_space = MAX_ISCSI_TBL_SZ;
        cp->iscsi_start_cid = start_cid;
        cp->fcoe_start_cid = start_cid + MAX_ISCSI_TBL_SZ;
@@ -1430,6 +1430,7 @@ static void cnic_reply_bnx2x_kcqes(struct cnic_dev *dev, int ulp_type,
 static int cnic_bnx2x_iscsi_init1(struct cnic_dev *dev, struct kwqe *kwqe)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        struct iscsi_kwqe_init1 *req1 = (struct iscsi_kwqe_init1 *) kwqe;
        int hq_bds, pages;
        u32 pfid = cp->pfid;
@@ -1512,6 +1513,7 @@ static int cnic_bnx2x_iscsi_init2(struct cnic_dev *dev, struct kwqe *kwqe)
 {
        struct iscsi_kwqe_init2 *req2 = (struct iscsi_kwqe_init2 *) kwqe;
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        u32 pfid = cp->pfid;
        struct iscsi_kcqe kcqe;
        struct kcqe *cqes[1];
@@ -2048,6 +2050,7 @@ static void cnic_init_storm_conn_bufs(struct cnic_dev *dev,
 static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        u32 pfid = cp->pfid;
        u8 *mac = dev->mac_addr;
 
@@ -2084,6 +2087,7 @@ static void cnic_init_bnx2x_mac(struct cnic_dev *dev)
 static void cnic_bnx2x_set_tcp_timestamp(struct cnic_dev *dev, int tcp_ts)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        u8 xstorm_flags = XSTORM_L5CM_TCP_FLAGS_WND_SCL_EN;
        u16 tstorm_flags = 0;
 
@@ -2103,6 +2107,7 @@ static int cnic_bnx2x_connect(struct cnic_dev *dev, struct kwqe *wqes[],
                              u32 num, int *work)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        struct l4_kwq_connect_req1 *kwqe1 =
                (struct l4_kwq_connect_req1 *) wqes[0];
        struct l4_kwq_connect_req3 *kwqe3;
@@ -2898,7 +2903,7 @@ static int cnic_l2_completion(struct cnic_local *cp)
        u16 hw_cons, sw_cons;
        struct cnic_uio_dev *udev = cp->udev;
        union eth_rx_cqe *cqe, *cqe_ring = (union eth_rx_cqe *)
-                                       (udev->l2_ring + (2 * BCM_PAGE_SIZE));
+                                       (udev->l2_ring + (2 * BNX2_PAGE_SIZE));
        u32 cmd;
        int comp = 0;
 
@@ -3853,12 +3858,17 @@ static int cnic_cm_abort(struct cnic_sock *csk)
                return cnic_cm_abort_req(csk);
 
        /* Getting here means that we haven't started connect, or
-        * connect was not successful.
+        * connect was not successful, or it has been reset by the target.
         */
 
        cp->close_conn(csk, opcode);
-       if (csk->state != opcode)
+       if (csk->state != opcode) {
+               /* Wait for remote reset sequence to complete */
+               while (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags))
+                       msleep(1);
+
                return -EALREADY;
+       }
 
        return 0;
 }
@@ -3872,6 +3882,10 @@ static int cnic_cm_close(struct cnic_sock *csk)
                csk->state = L4_KCQE_OPCODE_VALUE_CLOSE_COMP;
                return cnic_cm_close_req(csk);
        } else {
+               /* Wait for remote reset sequence to complete */
+               while (test_bit(SK_F_PG_OFFLD_COMPLETE, &csk->flags))
+                       msleep(1);
+
                return -EALREADY;
        }
        return 0;
@@ -4200,6 +4214,7 @@ static void cnic_cm_stop_bnx2x_hw(struct cnic_dev *dev)
 static int cnic_cm_init_bnx2x_hw(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        u32 pfid = cp->pfid;
        u32 port = CNIC_PORT(cp);
 
@@ -4349,7 +4364,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid)
        int ret = 0, i;
        u32 valid_bit = valid ? BNX2_CTX_HOST_PAGE_TBL_DATA0_VALID : 0;
 
-       if (CHIP_NUM(cp) != CHIP_NUM_5709)
+       if (BNX2_CHIP(cp) != BNX2_CHIP_5709)
                return 0;
 
        for (i = 0; i < cp->ctx_blks; i++) {
@@ -4357,7 +4372,7 @@ static int cnic_setup_5709_context(struct cnic_dev *dev, int valid)
                u32 idx = cp->ctx_arr[i].cid / cp->cids_per_blk;
                u32 val;
 
-               memset(cp->ctx_arr[i].ctx, 0, BCM_PAGE_SIZE);
+               memset(cp->ctx_arr[i].ctx, 0, BNX2_PAGE_SIZE);
 
                CNIC_WR(dev, BNX2_CTX_HOST_PAGE_TBL_DATA0,
                        (cp->ctx_arr[i].mapping & 0xffffffff) | valid_bit);
@@ -4499,7 +4514,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
        u32 cid_addr, tx_cid, sb_id;
        u32 val, offset0, offset1, offset2, offset3;
        int i;
-       struct tx_bd *txbd;
+       struct bnx2_tx_bd *txbd;
        dma_addr_t buf_map, ring_map = udev->l2_ring_map;
        struct status_block *s_blk = cp->status_blk.gen;
 
@@ -4517,7 +4532,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
        cp->tx_cons = *cp->tx_cons_ptr;
 
        cid_addr = GET_CID_ADDR(tx_cid);
-       if (CHIP_NUM(cp) == CHIP_NUM_5709) {
+       if (BNX2_CHIP(cp) == BNX2_CHIP_5709) {
                u32 cid_addr2 = GET_CID_ADDR(tx_cid + 4) + 0x40;
 
                for (i = 0; i < PHY_CTX_SIZE; i += 4)
@@ -4545,7 +4560,7 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev)
        txbd = udev->l2_ring;
 
        buf_map = udev->l2_buf_map;
-       for (i = 0; i < MAX_TX_DESC_CNT; i++, txbd++) {
+       for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i++, txbd++) {
                txbd->tx_bd_haddr_hi = (u64) buf_map >> 32;
                txbd->tx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
        }
@@ -4565,7 +4580,7 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
        struct cnic_uio_dev *udev = cp->udev;
        u32 cid_addr, sb_id, val, coal_reg, coal_val;
        int i;
-       struct rx_bd *rxbd;
+       struct bnx2_rx_bd *rxbd;
        struct status_block *s_blk = cp->status_blk.gen;
        dma_addr_t ring_map = udev->l2_ring_map;
 
@@ -4601,8 +4616,8 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
                val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
        cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
 
-       rxbd = udev->l2_ring + BCM_PAGE_SIZE;
-       for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
+       rxbd = udev->l2_ring + BNX2_PAGE_SIZE;
+       for (i = 0; i < BNX2_MAX_RX_DESC_CNT; i++, rxbd++) {
                dma_addr_t buf_map;
                int n = (i % cp->l2_rx_ring_size) + 1;
 
@@ -4612,11 +4627,11 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
                rxbd->rx_bd_haddr_hi = (u64) buf_map >> 32;
                rxbd->rx_bd_haddr_lo = (u64) buf_map & 0xffffffff;
        }
-       val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
+       val = (u64) (ring_map + BNX2_PAGE_SIZE) >> 32;
        cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_HI, val);
        rxbd->rx_bd_haddr_hi = val;
 
-       val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+       val = (u64) (ring_map + BNX2_PAGE_SIZE) & 0xffffffff;
        cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_NX_BDHADDR_LO, val);
        rxbd->rx_bd_haddr_lo = val;
 
@@ -4662,7 +4677,7 @@ static void cnic_set_bnx2_mac(struct cnic_dev *dev)
        CNIC_WR(dev, BNX2_EMAC_MAC_MATCH5, val);
 
        val = 4 | BNX2_RPM_SORT_USER2_BC_EN;
-       if (CHIP_NUM(cp) != CHIP_NUM_5709)
+       if (BNX2_CHIP(cp) != BNX2_CHIP_5709)
                val |= BNX2_RPM_SORT_USER2_PROM_VLAN;
 
        CNIC_WR(dev, BNX2_RPM_SORT_USER2, 0x0);
@@ -4682,10 +4697,10 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 
        val = CNIC_RD(dev, BNX2_MQ_CONFIG);
        val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
-       if (BCM_PAGE_BITS > 12)
+       if (BNX2_PAGE_BITS > 12)
                val |= (12 - 8)  << 4;
        else
-               val |= (BCM_PAGE_BITS - 8)  << 4;
+               val |= (BNX2_PAGE_BITS - 8)  << 4;
 
        CNIC_WR(dev, BNX2_MQ_CONFIG, val);
 
@@ -4708,20 +4723,20 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
        cp->kwq_con_idx = 0;
        set_bit(CNIC_LCL_FL_KWQ_INIT, &cp->cnic_local_flags);
 
-       if (CHIP_NUM(cp) == CHIP_NUM_5706 || CHIP_NUM(cp) == CHIP_NUM_5708)
+       if (BNX2_CHIP(cp) == BNX2_CHIP_5706 || BNX2_CHIP(cp) == BNX2_CHIP_5708)
                cp->kwq_con_idx_ptr = &sblk->status_rx_quick_consumer_index15;
        else
                cp->kwq_con_idx_ptr = &sblk->status_cmd_consumer_index;
 
        /* Initialize the kernel work queue context. */
        val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
-             (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
+             (BNX2_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
        cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_TYPE, val);
 
-       val = (BCM_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
+       val = (BNX2_PAGE_SIZE / sizeof(struct kwqe) - 1) << 16;
        cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
 
-       val = ((BCM_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
+       val = ((BNX2_PAGE_SIZE / sizeof(struct kwqe)) << 16) | KWQ_PAGE_CNT;
        cnic_ctx_wr(dev, kwq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
 
        val = (u32) ((u64) cp->kwq_info.pgtbl_map >> 32);
@@ -4741,13 +4756,13 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
 
        /* Initialize the kernel complete queue context. */
        val = KRNLQ_TYPE_TYPE_KRNLQ | KRNLQ_SIZE_TYPE_SIZE |
-             (BCM_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
+             (BNX2_PAGE_BITS - 8) | KRNLQ_FLAGS_QE_SELF_SEQ;
        cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_TYPE, val);
 
-       val = (BCM_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
+       val = (BNX2_PAGE_SIZE / sizeof(struct kcqe) - 1) << 16;
        cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_QE_SELF_SEQ_MAX, val);
 
-       val = ((BCM_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
+       val = ((BNX2_PAGE_SIZE / sizeof(struct kcqe)) << 16) | KCQ_PAGE_CNT;
        cnic_ctx_wr(dev, kcq_cid_addr, L5_KRNLQ_PGTBL_NPAGES, val);
 
        val = (u32) ((u64) cp->kcq1.dma.pgtbl_map >> 32);
@@ -4843,6 +4858,7 @@ static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev,
                                                u16 sb_id, u8 sb_index,
                                                u8 disable)
 {
+       struct bnx2x *bp = netdev_priv(dev->netdev);
 
        u32 addr = BAR_CSTRORM_INTMEM +
                        CSTORM_STATUS_BLOCK_DATA_OFFSET(sb_id) +
@@ -4860,6 +4876,7 @@ static inline void cnic_storm_memset_hc_disable(struct cnic_dev *dev,
 static void cnic_enable_bnx2x_int(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        u8 sb_id = cp->status_blk_num;
 
        CNIC_WR8(dev, BAR_CSTRORM_INTMEM +
@@ -4886,10 +4903,10 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
        u32 cli = cp->ethdev->iscsi_l2_client_id;
        u32 val;
 
-       memset(txbd, 0, BCM_PAGE_SIZE);
+       memset(txbd, 0, BNX2_PAGE_SIZE);
 
        buf_map = udev->l2_buf_map;
-       for (i = 0; i < MAX_TX_DESC_CNT; i += 3, txbd += 3) {
+       for (i = 0; i < BNX2_MAX_TX_DESC_CNT; i += 3, txbd += 3) {
                struct eth_tx_start_bd *start_bd = &txbd->start_bd;
                struct eth_tx_parse_bd_e1x *pbd_e1x =
                        &((txbd + 1)->parse_bd_e1x);
@@ -4908,9 +4925,9 @@ static void cnic_init_bnx2x_tx_ring(struct cnic_dev *dev,
 
                if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id))
                        pbd_e2->parsing_data = (UNICAST_ADDRESS <<
-                                ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT);
+                               ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT);
                else
-                        pbd_e1x->global_data = (UNICAST_ADDRESS <<
+                       pbd_e1x->global_data = (UNICAST_ADDRESS <<
                                ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT);
        }
 
@@ -4945,9 +4962,9 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
        struct cnic_local *cp = dev->cnic_priv;
        struct cnic_uio_dev *udev = cp->udev;
        struct eth_rx_bd *rxbd = (struct eth_rx_bd *) (udev->l2_ring +
-                               BCM_PAGE_SIZE);
+                               BNX2_PAGE_SIZE);
        struct eth_rx_cqe_next_page *rxcqe = (struct eth_rx_cqe_next_page *)
-                               (udev->l2_ring + (2 * BCM_PAGE_SIZE));
+                               (udev->l2_ring + (2 * BNX2_PAGE_SIZE));
        struct host_sp_status_block *sb = cp->bnx2x_def_status_blk;
        int i;
        u32 cli = cp->ethdev->iscsi_l2_client_id;
@@ -4971,20 +4988,20 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
                rxbd->addr_lo = cpu_to_le32(buf_map & 0xffffffff);
        }
 
-       val = (u64) (ring_map + BCM_PAGE_SIZE) >> 32;
+       val = (u64) (ring_map + BNX2_PAGE_SIZE) >> 32;
        rxbd->addr_hi = cpu_to_le32(val);
        data->rx.bd_page_base.hi = cpu_to_le32(val);
 
-       val = (u64) (ring_map + BCM_PAGE_SIZE) & 0xffffffff;
+       val = (u64) (ring_map + BNX2_PAGE_SIZE) & 0xffffffff;
        rxbd->addr_lo = cpu_to_le32(val);
        data->rx.bd_page_base.lo = cpu_to_le32(val);
 
        rxcqe += BNX2X_MAX_RCQ_DESC_CNT;
-       val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) >> 32;
+       val = (u64) (ring_map + (2 * BNX2_PAGE_SIZE)) >> 32;
        rxcqe->addr_hi = cpu_to_le32(val);
        data->rx.cqe_page_base.hi = cpu_to_le32(val);
 
-       val = (u64) (ring_map + (2 * BCM_PAGE_SIZE)) & 0xffffffff;
+       val = (u64) (ring_map + (2 * BNX2_PAGE_SIZE)) & 0xffffffff;
        rxcqe->addr_lo = cpu_to_le32(val);
        data->rx.cqe_page_base.lo = cpu_to_le32(val);
 
@@ -5009,6 +5026,7 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev,
 static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        u32 pfid = cp->pfid;
 
        cp->kcq1.io_addr = BAR_CSTRORM_INTMEM +
@@ -5047,37 +5065,17 @@ static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
 static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        struct cnic_eth_dev *ethdev = cp->ethdev;
-       int func = CNIC_FUNC(cp), ret;
+       int func, ret;
        u32 pfid;
 
        dev->stats_addr = ethdev->addr_drv_info_to_mcp;
-       cp->port_mode = CHIP_PORT_MODE_NONE;
-
-       if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
-               u32 val;
+       cp->port_mode = bp->common.chip_port_mode;
+       cp->pfid = bp->pfid;
+       cp->func = bp->pf_num;
 
-               pci_read_config_dword(dev->pcidev, PCICFG_ME_REGISTER, &val);
-               cp->func = (u8) ((val & ME_REG_ABS_PF_NUM) >>
-                                ME_REG_ABS_PF_NUM_SHIFT);
-               func = CNIC_FUNC(cp);
-
-               val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN_OVWR);
-               if (!(val & 1))
-                       val = CNIC_RD(dev, MISC_REG_PORT4MODE_EN);
-               else
-                       val = (val >> 1) & 1;
-
-               if (val) {
-                       cp->port_mode = CHIP_4_PORT_MODE;
-                       cp->pfid = func >> 1;
-               } else {
-                       cp->port_mode = CHIP_2_PORT_MODE;
-                       cp->pfid = func & 0x6;
-               }
-       } else {
-               cp->pfid = func;
-       }
+       func = CNIC_FUNC(cp);
        pfid = cp->pfid;
 
        ret = cnic_init_id_tbl(&cp->cid_tbl, MAX_ISCSI_TBL_SZ,
@@ -5144,6 +5142,7 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev)
 static void cnic_init_rings(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
        struct cnic_uio_dev *udev = cp->udev;
 
        if (test_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags))
@@ -5249,8 +5248,8 @@ static void cnic_shutdown_rings(struct cnic_dev *dev)
                msleep(10);
        }
        clear_bit(CNIC_LCL_FL_RINGS_INITED, &cp->cnic_local_flags);
-       rx_ring = udev->l2_ring + BCM_PAGE_SIZE;
-       memset(rx_ring, 0, BCM_PAGE_SIZE);
+       rx_ring = udev->l2_ring + BNX2_PAGE_SIZE;
+       memset(rx_ring, 0, BNX2_PAGE_SIZE);
 }
 
 static int cnic_register_netdev(struct cnic_dev *dev)
@@ -5344,8 +5343,28 @@ static void cnic_stop_bnx2_hw(struct cnic_dev *dev)
 static void cnic_stop_bnx2x_hw(struct cnic_dev *dev)
 {
        struct cnic_local *cp = dev->cnic_priv;
+       struct bnx2x *bp = netdev_priv(dev->netdev);
+       u32 hc_index = HC_INDEX_ISCSI_EQ_CONS;
+       u32 sb_id = cp->status_blk_num;
+       u32 idx_off, syn_off;
 
        cnic_free_irq(dev);
+
+       if (BNX2X_CHIP_IS_E2_PLUS(cp->chip_id)) {
+               idx_off = offsetof(struct hc_status_block_e2, index_values) +
+                         (hc_index * sizeof(u16));
+
+               syn_off = CSTORM_HC_SYNC_LINE_INDEX_E2_OFFSET(hc_index, sb_id);
+       } else {
+               idx_off = offsetof(struct hc_status_block_e1x, index_values) +
+                         (hc_index * sizeof(u16));
+
+               syn_off = CSTORM_HC_SYNC_LINE_INDEX_E1X_OFFSET(hc_index, sb_id);
+       }
+       CNIC_WR16(dev, BAR_CSTRORM_INTMEM + syn_off, 0);
+       CNIC_WR16(dev, BAR_CSTRORM_INTMEM + CSTORM_STATUS_BLOCK_OFFSET(sb_id) +
+                 idx_off, 0);
+
        *cp->kcq1.hw_prod_idx_ptr = 0;
        CNIC_WR(dev, BAR_CSTRORM_INTMEM +
                CSTORM_ISCSI_EQ_CONS_OFFSET(cp->pfid, 0), 0);
@@ -5431,14 +5450,12 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev)
        struct pci_dev *pdev;
        struct cnic_dev *cdev;
        struct cnic_local *cp;
+       struct bnx2 *bp = netdev_priv(dev);
        struct cnic_eth_dev *ethdev = NULL;
-       struct cnic_eth_dev *(*probe)(struct net_device *) = NULL;
 
-       probe = symbol_get(bnx2_cnic_probe);
-       if (probe) {
-               ethdev = (*probe)(dev);
-               symbol_put(bnx2_cnic_probe);
-       }
+       if (bp->cnic_probe)
+               ethdev = (bp->cnic_probe)(dev);
+
        if (!ethdev)
                return NULL;
 
@@ -5493,14 +5510,12 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev)
        struct pci_dev *pdev;
        struct cnic_dev *cdev;
        struct cnic_local *cp;
+       struct bnx2x *bp = netdev_priv(dev);
        struct cnic_eth_dev *ethdev = NULL;
-       struct cnic_eth_dev *(*probe)(struct net_device *) = NULL;
 
-       probe = symbol_get(bnx2x_cnic_probe);
-       if (probe) {
-               ethdev = (*probe)(dev);
-               symbol_put(bnx2x_cnic_probe);
-       }
+       if (bp->cnic_probe)
+               ethdev = bp->cnic_probe(dev);
+
        if (!ethdev)
                return NULL;
 
index 148604c3fa0c79c51bf0fd1dc75edc3f7598c670..62c670619ae6600a631bad3a351ceb1abec08e5f 100644 (file)
 #define CNIC_LOCAL_PORT_MAX    61024
 #define CNIC_LOCAL_PORT_RANGE  (CNIC_LOCAL_PORT_MAX - CNIC_LOCAL_PORT_MIN)
 
-#define KWQE_CNT (BCM_PAGE_SIZE / sizeof(struct kwqe))
-#define KCQE_CNT (BCM_PAGE_SIZE / sizeof(struct kcqe))
+#define KWQE_CNT (BNX2_PAGE_SIZE / sizeof(struct kwqe))
+#define KCQE_CNT (BNX2_PAGE_SIZE / sizeof(struct kcqe))
 #define MAX_KWQE_CNT (KWQE_CNT - 1)
 #define MAX_KCQE_CNT (KCQE_CNT - 1)
 
 #define MAX_KWQ_IDX    ((KWQ_PAGE_CNT * KWQE_CNT) - 1)
 #define MAX_KCQ_IDX    ((KCQ_PAGE_CNT * KCQE_CNT) - 1)
 
-#define KWQ_PG(x) (((x) & ~MAX_KWQE_CNT) >> (BCM_PAGE_BITS - 5))
+#define KWQ_PG(x) (((x) & ~MAX_KWQE_CNT) >> (BNX2_PAGE_BITS - 5))
 #define KWQ_IDX(x) ((x) & MAX_KWQE_CNT)
 
-#define KCQ_PG(x) (((x) & ~MAX_KCQE_CNT) >> (BCM_PAGE_BITS - 5))
+#define KCQ_PG(x) (((x) & ~MAX_KCQE_CNT) >> (BNX2_PAGE_BITS - 5))
 #define KCQ_IDX(x) ((x) & MAX_KCQE_CNT)
 
 #define BNX2X_NEXT_KCQE(x) (((x) & (MAX_KCQE_CNT - 1)) ==              \
@@ -186,14 +186,6 @@ struct kcq_info {
        u16             (*hw_idx)(u16);
 };
 
-struct iro {
-       u32 base;
-       u16 m1;
-       u16 m2;
-       u16 m3;
-       u16 size;
-};
-
 struct cnic_uio_dev {
        struct uio_info         cnic_uinfo;
        u32                     uio_dev;
@@ -241,9 +233,6 @@ struct cnic_local {
        u16             rx_cons;
        u16             tx_cons;
 
-       const struct iro        *iro_arr;
-#define IRO (((struct cnic_local *) dev->cnic_priv)->iro_arr)
-
        struct cnic_dma         kwq_info;
        struct kwqe             **kwq;
 
@@ -316,9 +305,6 @@ struct cnic_local {
        int                     func;
        u32                     pfid;
        u8                      port_mode;
-#define CHIP_4_PORT_MODE       0
-#define CHIP_2_PORT_MODE       1
-#define CHIP_PORT_MODE_NONE    2
 
        u32                     shmem_base;
 
@@ -420,11 +406,11 @@ struct bnx2x_bd_chain_next {
         BNX2X_CHIP_IS_57840(x))
 #define BNX2X_CHIP_IS_E2_PLUS(x) (BNX2X_CHIP_IS_E2(x) || BNX2X_CHIP_IS_E3(x))
 
-#define IS_E1H_OFFSET                  BNX2X_CHIP_IS_E1H(cp->chip_id)
-
-#define BNX2X_RX_DESC_CNT              (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
+#define BNX2X_RX_DESC_CNT              (BNX2_PAGE_SIZE / \
+                                        sizeof(struct eth_rx_bd))
 #define BNX2X_MAX_RX_DESC_CNT          (BNX2X_RX_DESC_CNT - 2)
-#define BNX2X_RCQ_DESC_CNT             (BCM_PAGE_SIZE / sizeof(union eth_rx_cqe))
+#define BNX2X_RCQ_DESC_CNT             (BNX2_PAGE_SIZE / \
+                                        sizeof(union eth_rx_cqe))
 #define BNX2X_MAX_RCQ_DESC_CNT         (BNX2X_RCQ_DESC_CNT - 1)
 
 #define BNX2X_NEXT_RCQE(x) (((x) & BNX2X_MAX_RCQ_DESC_CNT) ==          \
index 865095aad1f6494d985f4dbe15ab1ae198e7e74f..2a35436f90956744a2efa443062001a4acde1727 100644 (file)
@@ -14,8 +14,8 @@
 
 #include "bnx2x/bnx2x_mfw_req.h"
 
-#define CNIC_MODULE_VERSION    "2.5.14"
-#define CNIC_MODULE_RELDATE    "Sep 30, 2012"
+#define CNIC_MODULE_VERSION    "2.5.16"
+#define CNIC_MODULE_RELDATE    "Dec 05, 2012"
 
 #define CNIC_ULP_RDMA          0
 #define CNIC_ULP_ISCSI         1
@@ -353,7 +353,4 @@ extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops);
 
 extern int cnic_unregister_driver(int ulp_type);
 
-extern struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev);
-extern struct cnic_eth_dev *bnx2x_cnic_probe(struct net_device *dev);
-
 #endif
index 49e7a258da8aa91554410900a4d23036e13e85c5..3a1c8a3cf7c91af5ada39f9ded17e604212b2c01 100644 (file)
@@ -2586,7 +2586,7 @@ static int sbmac_poll(struct napi_struct *napi, int budget)
 }
 
 
-static int __devinit sbmac_probe(struct platform_device *pldev)
+static int sbmac_probe(struct platform_device *pldev)
 {
        struct net_device *dev;
        struct sbmac_softc *sc;
index a8800ac10df970b280690272f8618247f80d0823..78ea90c40e1902af09272a80b09010da52ae6c6b 100644 (file)
@@ -54,6 +54,9 @@
 #include <asm/byteorder.h>
 #include <linux/uaccess.h>
 
+#include <uapi/linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+
 #ifdef CONFIG_SPARC
 #include <asm/idprom.h>
 #include <asm/prom.h>
@@ -90,10 +93,10 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 
 #define DRV_MODULE_NAME                "tg3"
 #define TG3_MAJ_NUM                    3
-#define TG3_MIN_NUM                    125
+#define TG3_MIN_NUM                    128
 #define DRV_MODULE_VERSION     \
        __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE     "September 26, 2012"
+#define DRV_MODULE_RELDATE     "December 03, 2012"
 
 #define RESET_KIND_SHUTDOWN    0
 #define RESET_KIND_INIT                1
@@ -211,7 +214,7 @@ static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 #define FIRMWARE_TG3TSO                "tigon/tg3_tso.bin"
 #define FIRMWARE_TG3TSO5       "tigon/tg3_tso5.bin"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
 
 MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)");
@@ -226,6 +229,9 @@ static int tg3_debug = -1;  /* -1 == use TG3_DEF_MSG_ENABLE as value */
 module_param(tg3_debug, int, 0);
 MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
 
+#define TG3_DRV_DATA_FLAG_10_100_ONLY  0x0001
+#define TG3_DRV_DATA_FLAG_5705_10_100  0x0002
+
 static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
@@ -245,20 +251,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+                       TG3_DRV_DATA_FLAG_5705_10_100},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+                       TG3_DRV_DATA_FLAG_5705_10_100},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY |
+                       TG3_DRV_DATA_FLAG_5705_10_100},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
@@ -266,8 +280,13 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
+       {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5787M,
+                       PCI_VENDOR_ID_LENOVO,
+                       TG3PCI_SUBDEVICE_ID_LENOVO_5787M),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
@@ -286,18 +305,28 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)},
+       {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
+                       PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_A),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
+       {PCI_DEVICE_SUB(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780,
+                       PCI_VENDOR_ID_AI, TG3PCI_SUBDEVICE_ID_ACER_57780_B),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717_C)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
-       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
+       {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795),
+        .driver_data = TG3_DRV_DATA_FLAG_10_100_ONLY},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)},
        {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)},
@@ -398,19 +427,27 @@ static const struct {
 };
 
 #define TG3_NUM_STATS  ARRAY_SIZE(ethtool_stats_keys)
+#define TG3_NVRAM_TEST         0
+#define TG3_LINK_TEST          1
+#define TG3_REGISTER_TEST      2
+#define TG3_MEMORY_TEST                3
+#define TG3_MAC_LOOPB_TEST     4
+#define TG3_PHY_LOOPB_TEST     5
+#define TG3_EXT_LOOPB_TEST     6
+#define TG3_INTERRUPT_TEST     7
 
 
 static const struct {
        const char string[ETH_GSTRING_LEN];
 } ethtool_test_keys[] = {
-       { "nvram test        (online) " },
-       { "link test         (online) " },
-       { "register test     (offline)" },
-       { "memory test       (offline)" },
-       { "mac loopback test (offline)" },
-       { "phy loopback test (offline)" },
-       { "ext loopback test (offline)" },
-       { "interrupt test    (offline)" },
+       [TG3_NVRAM_TEST]        = { "nvram test        (online) " },
+       [TG3_LINK_TEST]         = { "link test         (online) " },
+       [TG3_REGISTER_TEST]     = { "register test     (offline)" },
+       [TG3_MEMORY_TEST]       = { "memory test       (offline)" },
+       [TG3_MAC_LOOPB_TEST]    = { "mac loopback test (offline)" },
+       [TG3_PHY_LOOPB_TEST]    = { "phy loopback test (offline)" },
+       [TG3_EXT_LOOPB_TEST]    = { "ext loopback test (offline)" },
+       [TG3_INTERRUPT_TEST]    = { "interrupt test    (offline)" },
 };
 
 #define TG3_NUM_TEST   ARRAY_SIZE(ethtool_test_keys)
@@ -2447,6 +2484,18 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
        return err;
 }
 
+static void tg3_carrier_on(struct tg3 *tp)
+{
+       netif_carrier_on(tp->dev);
+       tp->link_up = true;
+}
+
+static void tg3_carrier_off(struct tg3 *tp)
+{
+       netif_carrier_off(tp->dev);
+       tp->link_up = false;
+}
+
 /* This will reset the tigon3 PHY if there is no valid
  * link unless the FORCE argument is non-zero.
  */
@@ -2465,8 +2514,8 @@ static int tg3_phy_reset(struct tg3 *tp)
        if (err != 0)
                return -EBUSY;
 
-       if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
-               netif_carrier_off(tp->dev);
+       if (netif_running(tp->dev) && tp->link_up) {
+               tg3_carrier_off(tp);
                tg3_link_report(tp);
        }
 
@@ -4160,6 +4209,24 @@ static bool tg3_phy_copper_fetch_rmtadv(struct tg3 *tp, u32 *rmtadv)
        return true;
 }
 
+static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
+{
+       if (curr_link_up != tp->link_up) {
+               if (curr_link_up) {
+                       tg3_carrier_on(tp);
+               } else {
+                       tg3_carrier_off(tp);
+                       if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
+                               tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
+               }
+
+               tg3_link_report(tp);
+               return true;
+       }
+
+       return false;
+}
+
 static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 {
        int current_link_up;
@@ -4192,7 +4259,7 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
        if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
             GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
-           netif_carrier_ok(tp->dev)) {
+           tp->link_up) {
                tg3_readphy(tp, MII_BMSR, &bmsr);
                if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
                    !(bmsr & BMSR_LSTATUS))
@@ -4434,13 +4501,7 @@ relink:
                                                 PCI_EXP_LNKCTL_CLKREQ_EN);
        }
 
-       if (current_link_up != netif_carrier_ok(tp->dev)) {
-               if (current_link_up)
-                       netif_carrier_on(tp->dev);
-               else
-                       netif_carrier_off(tp->dev);
-               tg3_link_report(tp);
-       }
+       tg3_test_and_report_link_chg(tp, current_link_up);
 
        return 0;
 }
@@ -5080,7 +5141,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
        orig_active_duplex = tp->link_config.active_duplex;
 
        if (!tg3_flag(tp, HW_AUTONEG) &&
-           netif_carrier_ok(tp->dev) &&
+           tp->link_up &&
            tg3_flag(tp, INIT_COMPLETE)) {
                mac_status = tr32(MAC_STATUS);
                mac_status &= (MAC_STATUS_PCS_SYNCED |
@@ -5158,13 +5219,7 @@ static int tg3_setup_fiber_phy(struct tg3 *tp, int force_reset)
                                    LED_CTRL_TRAFFIC_OVERRIDE));
        }
 
-       if (current_link_up != netif_carrier_ok(tp->dev)) {
-               if (current_link_up)
-                       netif_carrier_on(tp->dev);
-               else
-                       netif_carrier_off(tp->dev);
-               tg3_link_report(tp);
-       } else {
+       if (!tg3_test_and_report_link_chg(tp, current_link_up)) {
                u32 now_pause_cfg = tp->link_config.active_flowctrl;
                if (orig_pause_cfg != now_pause_cfg ||
                    orig_active_speed != tp->link_config.active_speed ||
@@ -5257,7 +5312,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                        new_bmcr |= BMCR_SPEED1000;
 
                        /* Force a linkdown */
-                       if (netif_carrier_ok(tp->dev)) {
+                       if (tp->link_up) {
                                u32 adv;
 
                                err |= tg3_readphy(tp, MII_ADVERTISE, &adv);
@@ -5269,7 +5324,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
                                                           BMCR_ANRESTART |
                                                           BMCR_ANENABLE);
                                udelay(10);
-                               netif_carrier_off(tp->dev);
+                               tg3_carrier_off(tp);
                        }
                        tg3_writephy(tp, MII_BMCR, new_bmcr);
                        bmcr = new_bmcr;
@@ -5335,15 +5390,7 @@ static int tg3_setup_fiber_mii_phy(struct tg3 *tp, int force_reset)
        tp->link_config.active_speed = current_speed;
        tp->link_config.active_duplex = current_duplex;
 
-       if (current_link_up != netif_carrier_ok(tp->dev)) {
-               if (current_link_up)
-                       netif_carrier_on(tp->dev);
-               else {
-                       netif_carrier_off(tp->dev);
-                       tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
-               }
-               tg3_link_report(tp);
-       }
+       tg3_test_and_report_link_chg(tp, current_link_up);
        return err;
 }
 
@@ -5355,7 +5402,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
                return;
        }
 
-       if (!netif_carrier_ok(tp->dev) &&
+       if (!tp->link_up &&
            (tp->link_config.autoneg == AUTONEG_ENABLE)) {
                u32 bmcr;
 
@@ -5385,7 +5432,7 @@ static void tg3_serdes_parallel_detect(struct tg3 *tp)
                                tp->phy_flags |= TG3_PHYFLG_PARALLEL_DETECT;
                        }
                }
-       } else if (netif_carrier_ok(tp->dev) &&
+       } else if (tp->link_up &&
                   (tp->link_config.autoneg == AUTONEG_ENABLE) &&
                   (tp->phy_flags & TG3_PHYFLG_PARALLEL_DETECT)) {
                u32 phy2;
@@ -5451,7 +5498,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
                     (32 << TX_LENGTHS_SLOT_TIME_SHIFT));
 
        if (!tg3_flag(tp, 5705_PLUS)) {
-               if (netif_carrier_ok(tp->dev)) {
+               if (tp->link_up) {
                        tw32(HOSTCC_STAT_COAL_TICKS,
                             tp->coal.stats_block_coalesce_usecs);
                } else {
@@ -5461,7 +5508,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
 
        if (tg3_flag(tp, ASPM_WORKAROUND)) {
                val = tr32(PCIE_PWR_MGMT_THRESH);
-               if (!netif_carrier_ok(tp->dev))
+               if (!tp->link_up)
                        val = (val & ~PCIE_PWR_MGMT_L1_THRESH_MSK) |
                              tp->pwrmgmt_thresh;
                else
@@ -5472,6 +5519,190 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
        return err;
 }
 
+/* tp->lock must be held */
+static u64 tg3_refclk_read(struct tg3 *tp)
+{
+       u64 stamp = tr32(TG3_EAV_REF_CLCK_LSB);
+       return stamp | (u64)tr32(TG3_EAV_REF_CLCK_MSB) << 32;
+}
+
+/* tp->lock must be held */
+static void tg3_refclk_write(struct tg3 *tp, u64 newval)
+{
+       tw32(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_STOP);
+       tw32(TG3_EAV_REF_CLCK_LSB, newval & 0xffffffff);
+       tw32(TG3_EAV_REF_CLCK_MSB, newval >> 32);
+       tw32_f(TG3_EAV_REF_CLCK_CTL, TG3_EAV_REF_CLCK_CTL_RESUME);
+}
+
+static inline void tg3_full_lock(struct tg3 *tp, int irq_sync);
+static inline void tg3_full_unlock(struct tg3 *tp);
+static int tg3_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
+{
+       struct tg3 *tp = netdev_priv(dev);
+
+       info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
+                               SOF_TIMESTAMPING_RX_SOFTWARE |
+                               SOF_TIMESTAMPING_SOFTWARE    |
+                               SOF_TIMESTAMPING_TX_HARDWARE |
+                               SOF_TIMESTAMPING_RX_HARDWARE |
+                               SOF_TIMESTAMPING_RAW_HARDWARE;
+
+       if (tp->ptp_clock)
+               info->phc_index = ptp_clock_index(tp->ptp_clock);
+       else
+               info->phc_index = -1;
+
+       info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
+
+       info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
+                          (1 << HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+                          (1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
+       return 0;
+}
+
+static int tg3_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+       struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+       bool neg_adj = false;
+       u32 correction = 0;
+
+       if (ppb < 0) {
+               neg_adj = true;
+               ppb = -ppb;
+       }
+
+       /* Frequency adjustment is performed using hardware with a 24 bit
+        * accumulator and a programmable correction value. On each clk, the
+        * correction value gets added to the accumulator and when it
+        * overflows, the time counter is incremented/decremented.
+        *
+        * So conversion from ppb to correction value is
+        *              ppb * (1 << 24) / 1000000000
+        */
+       correction = div_u64((u64)ppb * (1 << 24), 1000000000ULL) &
+                    TG3_EAV_REF_CLK_CORRECT_MASK;
+
+       tg3_full_lock(tp, 0);
+
+       if (correction)
+               tw32(TG3_EAV_REF_CLK_CORRECT_CTL,
+                    TG3_EAV_REF_CLK_CORRECT_EN |
+                    (neg_adj ? TG3_EAV_REF_CLK_CORRECT_NEG : 0) | correction);
+       else
+               tw32(TG3_EAV_REF_CLK_CORRECT_CTL, 0);
+
+       tg3_full_unlock(tp);
+
+       return 0;
+}
+
+static int tg3_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+       struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+       tg3_full_lock(tp, 0);
+       tp->ptp_adjust += delta;
+       tg3_full_unlock(tp);
+
+       return 0;
+}
+
+static int tg3_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+       u64 ns;
+       u32 remainder;
+       struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+       tg3_full_lock(tp, 0);
+       ns = tg3_refclk_read(tp);
+       ns += tp->ptp_adjust;
+       tg3_full_unlock(tp);
+
+       ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+       ts->tv_nsec = remainder;
+
+       return 0;
+}
+
+static int tg3_ptp_settime(struct ptp_clock_info *ptp,
+                          const struct timespec *ts)
+{
+       u64 ns;
+       struct tg3 *tp = container_of(ptp, struct tg3, ptp_info);
+
+       ns = timespec_to_ns(ts);
+
+       tg3_full_lock(tp, 0);
+       tg3_refclk_write(tp, ns);
+       tp->ptp_adjust = 0;
+       tg3_full_unlock(tp);
+
+       return 0;
+}
+
+static int tg3_ptp_enable(struct ptp_clock_info *ptp,
+                         struct ptp_clock_request *rq, int on)
+{
+       return -EOPNOTSUPP;
+}
+
+static const struct ptp_clock_info tg3_ptp_caps = {
+       .owner          = THIS_MODULE,
+       .name           = "tg3 clock",
+       .max_adj        = 250000000,
+       .n_alarm        = 0,
+       .n_ext_ts       = 0,
+       .n_per_out      = 0,
+       .pps            = 0,
+       .adjfreq        = tg3_ptp_adjfreq,
+       .adjtime        = tg3_ptp_adjtime,
+       .gettime        = tg3_ptp_gettime,
+       .settime        = tg3_ptp_settime,
+       .enable         = tg3_ptp_enable,
+};
+
+static void tg3_hwclock_to_timestamp(struct tg3 *tp, u64 hwclock,
+                                    struct skb_shared_hwtstamps *timestamp)
+{
+       memset(timestamp, 0, sizeof(struct skb_shared_hwtstamps));
+       timestamp->hwtstamp  = ns_to_ktime((hwclock & TG3_TSTAMP_MASK) +
+                                          tp->ptp_adjust);
+}
+
+/* tp->lock must be held */
+static void tg3_ptp_init(struct tg3 *tp)
+{
+       if (!tg3_flag(tp, PTP_CAPABLE))
+               return;
+
+       /* Initialize the hardware clock to the system time. */
+       tg3_refclk_write(tp, ktime_to_ns(ktime_get_real()));
+       tp->ptp_adjust = 0;
+       tp->ptp_info = tg3_ptp_caps;
+}
+
+/* tp->lock must be held */
+static void tg3_ptp_resume(struct tg3 *tp)
+{
+       if (!tg3_flag(tp, PTP_CAPABLE))
+               return;
+
+       tg3_refclk_write(tp, ktime_to_ns(ktime_get_real()) + tp->ptp_adjust);
+       tp->ptp_adjust = 0;
+}
+
+static void tg3_ptp_fini(struct tg3 *tp)
+{
+       if (!tg3_flag(tp, PTP_CAPABLE) || !tp->ptp_clock)
+               return;
+
+       ptp_clock_unregister(tp->ptp_clock);
+       tp->ptp_clock = NULL;
+       tp->ptp_adjust = 0;
+}
+
 static inline int tg3_irq_sync(struct tg3 *tp)
 {
        return tp->irq_sync;
@@ -5652,6 +5883,16 @@ static void tg3_tx(struct tg3_napi *tnapi)
                        return;
                }
 
+               if (tnapi->tx_ring[sw_idx].len_flags & TXD_FLAG_HWTSTAMP) {
+                       struct skb_shared_hwtstamps timestamp;
+                       u64 hwclock = tr32(TG3_TX_TSTAMP_LSB);
+                       hwclock |= (u64)tr32(TG3_TX_TSTAMP_MSB) << 32;
+
+                       tg3_hwclock_to_timestamp(tp, hwclock, &timestamp);
+
+                       skb_tstamp_tx(skb, &timestamp);
+               }
+
                pci_unmap_single(tp->pdev,
                                 dma_unmap_addr(ri, mapping),
                                 skb_headlen(skb),
@@ -5919,6 +6160,7 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                dma_addr_t dma_addr;
                u32 opaque_key, desc_idx, *post_ptr;
                u8 *data;
+               u64 tstamp = 0;
 
                desc_idx = desc->opaque & RXD_OPAQUE_INDEX_MASK;
                opaque_key = desc->opaque & RXD_OPAQUE_RING_MASK;
@@ -5953,6 +6195,14 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
                      ETH_FCS_LEN;
 
+               if ((desc->type_flags & RXD_FLAG_PTPSTAT_MASK) ==
+                    RXD_FLAG_PTPSTAT_PTPV1 ||
+                   (desc->type_flags & RXD_FLAG_PTPSTAT_MASK) ==
+                    RXD_FLAG_PTPSTAT_PTPV2) {
+                       tstamp = tr32(TG3_RX_TSTAMP_LSB);
+                       tstamp |= (u64)tr32(TG3_RX_TSTAMP_MSB) << 32;
+               }
+
                if (len > TG3_RX_COPY_THRESH(tp)) {
                        int skb_size;
                        unsigned int frag_size;
@@ -5996,6 +6246,10 @@ static int tg3_rx(struct tg3_napi *tnapi, int budget)
                }
 
                skb_put(skb, len);
+               if (tstamp)
+                       tg3_hwclock_to_timestamp(tp, tstamp,
+                                                skb_hwtstamps(skb));
+
                if ((tp->dev->features & NETIF_F_RXCSUM) &&
                    (desc->type_flags & RXD_FLAG_TCPUDP_CSUM) &&
                    (((desc->ip_tcp_csum & RXD_TCPCSUM_MASK)
@@ -6477,17 +6731,24 @@ static inline void tg3_netif_stop(struct tg3 *tp)
 {
        tp->dev->trans_start = jiffies; /* prevent tx timeout */
        tg3_napi_disable(tp);
+       netif_carrier_off(tp->dev);
        netif_tx_disable(tp->dev);
 }
 
+/* tp->lock must be held */
 static inline void tg3_netif_start(struct tg3 *tp)
 {
+       tg3_ptp_resume(tp);
+
        /* NOTE: unconditional netif_tx_wake_all_queues is only
         * appropriate so long as all callers are assured to
         * have free tx slots (such as after tg3_init_hw)
         */
        netif_tx_wake_all_queues(tp->dev);
 
+       if (tp->link_up)
+               netif_carrier_on(tp->dev);
+
        tg3_napi_enable(tp);
        tp->napi[0].hw_status->status |= SD_STATUS_UPDATED;
        tg3_enable_ints(tp);
@@ -7046,6 +7307,12 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev)
                vlan = vlan_tx_tag_get(skb);
        }
 
+       if ((unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) &&
+           tg3_flag(tp, TX_TSTAMP_EN)) {
+               skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+               base_flags |= TXD_FLAG_HWTSTAMP;
+       }
+
        len = skb_headlen(skb);
 
        mapping = pci_map_single(tp->pdev, skb->data, len, PCI_DMA_TODEVICE);
@@ -8386,7 +8653,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
                tw32(HOSTCC_RXCOAL_TICK_INT, ec->rx_coalesce_usecs_irq);
                tw32(HOSTCC_TXCOAL_TICK_INT, ec->tx_coalesce_usecs_irq);
 
-               if (!netif_carrier_ok(tp->dev))
+               if (!tp->link_up)
                        val = 0;
 
                tw32(HOSTCC_STAT_COAL_TICKS, val);
@@ -8662,14 +8929,14 @@ static void tg3_rss_check_indir_tbl(struct tg3 *tp)
        if (!tg3_flag(tp, SUPPORT_MSIX))
                return;
 
-       if (tp->irq_cnt <= 2) {
+       if (tp->rxq_cnt == 1) {
                memset(&tp->rss_ind_tbl[0], 0, sizeof(tp->rss_ind_tbl));
                return;
        }
 
        /* Validate table against current IRQ count */
        for (i = 0; i < TG3_RSS_INDIR_TBL_SIZE; i++) {
-               if (tp->rss_ind_tbl[i] >= tp->irq_cnt - 1)
+               if (tp->rss_ind_tbl[i] >= tp->rxq_cnt)
                        break;
        }
 
@@ -8914,9 +9181,15 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
         */
        tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
 
-       tw32(GRC_MODE,
-            tp->grc_mode |
-            (GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP));
+       val = GRC_MODE_IRQ_ON_MAC_ATTN | GRC_MODE_HOST_STACKUP;
+       if (tp->rxptpctl)
+               tw32(TG3_RX_PTP_CTL,
+                    tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK);
+
+       if (tg3_flag(tp, PTP_CAPABLE))
+               val |= GRC_MODE_TIME_SYNC_ENABLE;
+
+       tw32(GRC_MODE, tp->grc_mode | val);
 
        /* Setup the timer prescalar register.  Clock is always 66Mhz. */
        val = tr32(GRC_MISC_CFG);
@@ -9679,7 +9952,7 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp)
 {
        struct tg3_hw_stats *sp = tp->hw_stats;
 
-       if (!netif_carrier_ok(tp->dev))
+       if (!tp->link_up)
                return;
 
        TG3_STAT_ADD32(&sp->tx_octets, MAC_TX_STATS_OCTETS);
@@ -9823,11 +10096,11 @@ static void tg3_timer(unsigned long __opaque)
                        u32 mac_stat = tr32(MAC_STATUS);
                        int need_setup = 0;
 
-                       if (netif_carrier_ok(tp->dev) &&
+                       if (tp->link_up &&
                            (mac_stat & MAC_STATUS_LNKSTATE_CHANGED)) {
                                need_setup = 1;
                        }
-                       if (!netif_carrier_ok(tp->dev) &&
+                       if (!tp->link_up &&
                            (mac_stat & (MAC_STATUS_PCS_SYNCED |
                                         MAC_STATUS_SIGNAL_DET))) {
                                need_setup = 1;
@@ -9890,7 +10163,7 @@ restart_timer:
        add_timer(&tp->timer);
 }
 
-static void __devinit tg3_timer_init(struct tg3 *tp)
+static void tg3_timer_init(struct tg3 *tp)
 {
        if (tg3_flag(tp, TAGGED_STATUS) &&
            GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5717 &&
@@ -10316,7 +10589,8 @@ static void tg3_ints_fini(struct tg3 *tp)
        tg3_flag_clear(tp, ENABLE_TSS);
 }
 
-static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq)
+static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq,
+                    bool init)
 {
        struct net_device *dev = tp->dev;
        int i, err;
@@ -10395,6 +10669,12 @@ static int tg3_start(struct tg3 *tp, bool reset_phy, bool test_irq)
        tg3_flag_set(tp, INIT_COMPLETE);
        tg3_enable_ints(tp);
 
+       if (init)
+               tg3_ptp_init(tp);
+       else
+               tg3_ptp_resume(tp);
+
+
        tg3_full_unlock(tp);
 
        netif_tx_start_all_queues(dev);
@@ -10429,10 +10709,8 @@ static void tg3_stop(struct tg3 *tp)
 {
        int i;
 
-       tg3_napi_disable(tp);
        tg3_reset_task_cancel(tp);
-
-       netif_tx_disable(tp->dev);
+       tg3_netif_stop(tp);
 
        tg3_timer_stop(tp);
 
@@ -10481,7 +10759,7 @@ static int tg3_open(struct net_device *dev)
                }
        }
 
-       netif_carrier_off(tp->dev);
+       tg3_carrier_off(tp);
 
        err = tg3_power_up(tp);
        if (err)
@@ -10494,11 +10772,19 @@ static int tg3_open(struct net_device *dev)
 
        tg3_full_unlock(tp);
 
-       err = tg3_start(tp, true, true);
+       err = tg3_start(tp, true, true, true);
        if (err) {
                tg3_frob_aux_power(tp, false);
                pci_set_power_state(tp->pdev, PCI_D3hot);
        }
+
+       if (tg3_flag(tp, PTP_CAPABLE)) {
+               tp->ptp_clock = ptp_clock_register(&tp->ptp_info,
+                                                  &tp->pdev->dev);
+               if (IS_ERR(tp->ptp_clock))
+                       tp->ptp_clock = NULL;
+       }
+
        return err;
 }
 
@@ -10506,6 +10792,8 @@ static int tg3_close(struct net_device *dev)
 {
        struct tg3 *tp = netdev_priv(dev);
 
+       tg3_ptp_fini(tp);
+
        tg3_stop(tp);
 
        /* Clear stats across close / open calls */
@@ -10514,7 +10802,7 @@ static int tg3_close(struct net_device *dev)
 
        tg3_power_down(tp);
 
-       netif_carrier_off(tp->dev);
+       tg3_carrier_off(tp);
 
        return 0;
 }
@@ -10888,7 +11176,7 @@ static int tg3_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
                        cmd->advertising |= ADVERTISED_Asym_Pause;
                }
        }
-       if (netif_running(dev) && netif_carrier_ok(dev)) {
+       if (netif_running(dev) && tp->link_up) {
                ethtool_cmd_speed_set(cmd, tp->link_config.active_speed);
                cmd->duplex = tp->link_config.active_duplex;
                cmd->lp_advertising = tp->link_config.rmt_adv;
@@ -11406,9 +11694,9 @@ static int tg3_set_channels(struct net_device *dev,
 
        tg3_stop(tp);
 
-       netif_carrier_off(dev);
+       tg3_carrier_off(tp);
 
-       tg3_start(tp, true, false);
+       tg3_start(tp, true, false, false);
 
        return 0;
 }
@@ -11755,7 +12043,7 @@ static int tg3_test_link(struct tg3 *tp)
                max = TG3_COPPER_TIMEOUT_SEC;
 
        for (i = 0; i < max; i++) {
-               if (netif_carrier_ok(tp->dev))
+               if (tp->link_up)
                        return 0;
 
                if (msleep_interruptible(1000))
@@ -12326,19 +12614,19 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
        tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
 
        if (!netif_running(tp->dev)) {
-               data[0] = TG3_LOOPBACK_FAILED;
-               data[1] = TG3_LOOPBACK_FAILED;
+               data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
+               data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                if (do_extlpbk)
-                       data[2] = TG3_LOOPBACK_FAILED;
+                       data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                goto done;
        }
 
        err = tg3_reset_hw(tp, 1);
        if (err) {
-               data[0] = TG3_LOOPBACK_FAILED;
-               data[1] = TG3_LOOPBACK_FAILED;
+               data[TG3_MAC_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
+               data[TG3_PHY_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                if (do_extlpbk)
-                       data[2] = TG3_LOOPBACK_FAILED;
+                       data[TG3_EXT_LOOPB_TEST] = TG3_LOOPBACK_FAILED;
                goto done;
        }
 
@@ -12361,11 +12649,11 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                tg3_mac_loopback(tp, true);
 
                if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-                       data[0] |= TG3_STD_LOOPBACK_FAILED;
+                       data[TG3_MAC_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED;
 
                if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
                    tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-                       data[0] |= TG3_JMB_LOOPBACK_FAILED;
+                       data[TG3_MAC_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED;
 
                tg3_mac_loopback(tp, false);
        }
@@ -12384,13 +12672,13 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                }
 
                if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-                       data[1] |= TG3_STD_LOOPBACK_FAILED;
+                       data[TG3_PHY_LOOPB_TEST] |= TG3_STD_LOOPBACK_FAILED;
                if (tg3_flag(tp, TSO_CAPABLE) &&
                    tg3_run_loopback(tp, ETH_FRAME_LEN, true))
-                       data[1] |= TG3_TSO_LOOPBACK_FAILED;
+                       data[TG3_PHY_LOOPB_TEST] |= TG3_TSO_LOOPBACK_FAILED;
                if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
                    tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-                       data[1] |= TG3_JMB_LOOPBACK_FAILED;
+                       data[TG3_PHY_LOOPB_TEST] |= TG3_JMB_LOOPBACK_FAILED;
 
                if (do_extlpbk) {
                        tg3_phy_lpbk_set(tp, 0, true);
@@ -12402,13 +12690,16 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                        mdelay(40);
 
                        if (tg3_run_loopback(tp, ETH_FRAME_LEN, false))
-                               data[2] |= TG3_STD_LOOPBACK_FAILED;
+                               data[TG3_EXT_LOOPB_TEST] |=
+                                                       TG3_STD_LOOPBACK_FAILED;
                        if (tg3_flag(tp, TSO_CAPABLE) &&
                            tg3_run_loopback(tp, ETH_FRAME_LEN, true))
-                               data[2] |= TG3_TSO_LOOPBACK_FAILED;
+                               data[TG3_EXT_LOOPB_TEST] |=
+                                                       TG3_TSO_LOOPBACK_FAILED;
                        if (tg3_flag(tp, JUMBO_RING_ENABLE) &&
                            tg3_run_loopback(tp, jmb_pkt_sz + ETH_HLEN, false))
-                               data[2] |= TG3_JMB_LOOPBACK_FAILED;
+                               data[TG3_EXT_LOOPB_TEST] |=
+                                                       TG3_JMB_LOOPBACK_FAILED;
                }
 
                /* Re-enable gphy autopowerdown. */
@@ -12416,7 +12707,8 @@ static int tg3_test_loopback(struct tg3 *tp, u64 *data, bool do_extlpbk)
                        tg3_phy_toggle_apd(tp, true);
        }
 
-       err = (data[0] | data[1] | data[2]) ? -EIO : 0;
+       err = (data[TG3_MAC_LOOPB_TEST] | data[TG3_PHY_LOOPB_TEST] |
+              data[TG3_EXT_LOOPB_TEST]) ? -EIO : 0;
 
 done:
        tp->phy_flags |= eee_cap;
@@ -12441,11 +12733,11 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
        if (tg3_test_nvram(tp) != 0) {
                etest->flags |= ETH_TEST_FL_FAILED;
-               data[0] = 1;
+               data[TG3_NVRAM_TEST] = 1;
        }
        if (!doextlpbk && tg3_test_link(tp)) {
                etest->flags |= ETH_TEST_FL_FAILED;
-               data[1] = 1;
+               data[TG3_LINK_TEST] = 1;
        }
        if (etest->flags & ETH_TEST_FL_OFFLINE) {
                int err, err2 = 0, irq_sync = 0;
@@ -12457,7 +12749,6 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
                }
 
                tg3_full_lock(tp, irq_sync);
-
                tg3_halt(tp, RESET_KIND_SUSPEND, 1);
                err = tg3_nvram_lock(tp);
                tg3_halt_cpu(tp, RX_CPU_BASE);
@@ -12471,25 +12762,25 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
                if (tg3_test_registers(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
-                       data[2] = 1;
+                       data[TG3_REGISTER_TEST] = 1;
                }
 
                if (tg3_test_memory(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
-                       data[3] = 1;
+                       data[TG3_MEMORY_TEST] = 1;
                }
 
                if (doextlpbk)
                        etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
 
-               if (tg3_test_loopback(tp, &data[4], doextlpbk))
+               if (tg3_test_loopback(tp, data, doextlpbk))
                        etest->flags |= ETH_TEST_FL_FAILED;
 
                tg3_full_unlock(tp);
 
                if (tg3_test_interrupt(tp) != 0) {
                        etest->flags |= ETH_TEST_FL_FAILED;
-                       data[7] = 1;
+                       data[TG3_INTERRUPT_TEST] = 1;
                }
 
                tg3_full_lock(tp, 0);
@@ -12512,6 +12803,96 @@ static void tg3_self_test(struct net_device *dev, struct ethtool_test *etest,
 
 }
 
+static int tg3_hwtstamp_ioctl(struct net_device *dev,
+                             struct ifreq *ifr, int cmd)
+{
+       struct tg3 *tp = netdev_priv(dev);
+       struct hwtstamp_config stmpconf;
+
+       if (!tg3_flag(tp, PTP_CAPABLE))
+               return -EINVAL;
+
+       if (copy_from_user(&stmpconf, ifr->ifr_data, sizeof(stmpconf)))
+               return -EFAULT;
+
+       if (stmpconf.flags)
+               return -EINVAL;
+
+       switch (stmpconf.tx_type) {
+       case HWTSTAMP_TX_ON:
+               tg3_flag_set(tp, TX_TSTAMP_EN);
+               break;
+       case HWTSTAMP_TX_OFF:
+               tg3_flag_clear(tp, TX_TSTAMP_EN);
+               break;
+       default:
+               return -ERANGE;
+       }
+
+       switch (stmpconf.rx_filter) {
+       case HWTSTAMP_FILTER_NONE:
+               tp->rxptpctl = 0;
+               break;
+       case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+                              TG3_RX_PTP_CTL_ALL_V1_EVENTS;
+               break;
+       case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+                              TG3_RX_PTP_CTL_SYNC_EVNT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V1_EN |
+                              TG3_RX_PTP_CTL_DELAY_REQ;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_EVENT:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+                              TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+                              TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+                              TG3_RX_PTP_CTL_ALL_V2_EVENTS;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_SYNC:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+                              TG3_RX_PTP_CTL_SYNC_EVNT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+                              TG3_RX_PTP_CTL_SYNC_EVNT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+                              TG3_RX_PTP_CTL_SYNC_EVNT;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_EN |
+                              TG3_RX_PTP_CTL_DELAY_REQ;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN |
+                              TG3_RX_PTP_CTL_DELAY_REQ;
+               break;
+       case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+               tp->rxptpctl = TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN |
+                              TG3_RX_PTP_CTL_DELAY_REQ;
+               break;
+       default:
+               return -ERANGE;
+       }
+
+       if (netif_running(dev) && tp->rxptpctl)
+               tw32(TG3_RX_PTP_CTL,
+                    tp->rxptpctl | TG3_RX_PTP_CTL_HWTS_INTERLOCK);
+
+       return copy_to_user(ifr->ifr_data, &stmpconf, sizeof(stmpconf)) ?
+               -EFAULT : 0;
+}
+
 static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        struct mii_ioctl_data *data = if_mii(ifr);
@@ -12562,6 +12943,9 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
                return err;
 
+       case SIOCSHWTSTAMP:
+               return tg3_hwtstamp_ioctl(dev, ifr, cmd);
+
        default:
                /* do nothing */
                break;
@@ -12663,7 +13047,7 @@ static const struct ethtool_ops tg3_ethtool_ops = {
        .set_rxfh_indir         = tg3_set_rxfh_indir,
        .get_channels           = tg3_get_channels,
        .set_channels           = tg3_set_channels,
-       .get_ts_info            = ethtool_op_get_ts_info,
+       .get_ts_info            = tg3_get_ts_info,
 };
 
 static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
@@ -12779,7 +13163,7 @@ static const struct net_device_ops tg3_netdev_ops = {
 #endif
 };
 
-static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
+static void tg3_get_eeprom_size(struct tg3 *tp)
 {
        u32 cursize, val, magic;
 
@@ -12813,7 +13197,7 @@ static void __devinit tg3_get_eeprom_size(struct tg3 *tp)
        tp->nvram_size = cursize;
 }
 
-static void __devinit tg3_get_nvram_size(struct tg3 *tp)
+static void tg3_get_nvram_size(struct tg3 *tp)
 {
        u32 val;
 
@@ -12846,7 +13230,7 @@ static void __devinit tg3_get_nvram_size(struct tg3 *tp)
        tp->nvram_size = TG3_NVRAM_SIZE_512KB;
 }
 
-static void __devinit tg3_get_nvram_info(struct tg3 *tp)
+static void tg3_get_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -12897,7 +13281,7 @@ static void __devinit tg3_get_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
+static void tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
 {
        switch (nvmcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
        case FLASH_5752PAGE_SIZE_256:
@@ -12924,7 +13308,7 @@ static void __devinit tg3_nvram_get_pagesize(struct tg3 *tp, u32 nvmcfg1)
        }
 }
 
-static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
+static void tg3_get_5752_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -12965,7 +13349,7 @@ static void __devinit tg3_get_5752_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
+static void tg3_get_5755_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1, protect = 0;
 
@@ -13021,7 +13405,7 @@ static void __devinit tg3_get_5755_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
+static void tg3_get_5787_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -13059,7 +13443,7 @@ static void __devinit tg3_get_5787_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
+static void tg3_get_5761_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1, protect = 0;
 
@@ -13134,14 +13518,14 @@ static void __devinit tg3_get_5761_nvram_info(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
+static void tg3_get_5906_nvram_info(struct tg3 *tp)
 {
        tp->nvram_jedecnum = JEDEC_ATMEL;
        tg3_flag_set(tp, NVRAM_BUFFERED);
        tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
 }
 
-static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
+static void tg3_get_57780_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -13214,7 +13598,7 @@ static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
 }
 
 
-static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
+static void tg3_get_5717_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1;
 
@@ -13292,7 +13676,7 @@ static void __devinit tg3_get_5717_nvram_info(struct tg3 *tp)
                tg3_flag_set(tp, NO_NVRAM_ADDR_TRANS);
 }
 
-static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
+static void tg3_get_5720_nvram_info(struct tg3 *tp)
 {
        u32 nvcfg1, nvmpinstrp;
 
@@ -13405,7 +13789,7 @@ static void __devinit tg3_get_5720_nvram_info(struct tg3 *tp)
 }
 
 /* Chips other than 5700/5701 use the NVRAM for fetching info. */
-static void __devinit tg3_nvram_init(struct tg3 *tp)
+static void tg3_nvram_init(struct tg3 *tp)
 {
        tw32_f(GRC_EEPROM_ADDR,
             (EEPROM_ADDR_FSM_RESET |
@@ -13475,7 +13859,7 @@ struct subsys_tbl_ent {
        u32 phy_id;
 };
 
-static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = {
+static struct subsys_tbl_ent subsys_id_to_phy_id[] = {
        /* Broadcom boards. */
        { TG3PCI_SUBVENDOR_ID_BROADCOM,
          TG3PCI_SUBDEVICE_ID_BROADCOM_95700A6, TG3_PHY_ID_BCM5401 },
@@ -13539,7 +13923,7 @@ static struct subsys_tbl_ent subsys_id_to_phy_id[] __devinitdata = {
          TG3PCI_SUBDEVICE_ID_IBM_5703SAX2, 0 }
 };
 
-static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
+static struct subsys_tbl_ent *tg3_lookup_by_subsys(struct tg3 *tp)
 {
        int i;
 
@@ -13553,7 +13937,7 @@ static struct subsys_tbl_ent * __devinit tg3_lookup_by_subsys(struct tg3 *tp)
        return NULL;
 }
 
-static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
+static void tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 {
        u32 val;
 
@@ -13753,7 +14137,7 @@ done:
                device_set_wakeup_capable(&tp->pdev->dev, false);
 }
 
-static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
+static int tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
 {
        int i;
        u32 val;
@@ -13776,7 +14160,7 @@ static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
  * configuration is a 32-bit value that straddles the alignment boundary.
  * We do two 32-bit reads and then shift and merge the results.
  */
-static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
+static u32 tg3_read_otp_phycfg(struct tg3 *tp)
 {
        u32 bhalf_otp, thalf_otp;
 
@@ -13802,7 +14186,7 @@ static u32 __devinit tg3_read_otp_phycfg(struct tg3 *tp)
        return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
 }
 
-static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
+static void tg3_phy_init_link_config(struct tg3 *tp)
 {
        u32 adv = ADVERTISED_Autoneg;
 
@@ -13829,7 +14213,7 @@ static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
        tp->old_link = -1;
 }
 
-static int __devinit tg3_phy_probe(struct tg3 *tp)
+static int tg3_phy_probe(struct tg3 *tp)
 {
        u32 hw_phy_id_1, hw_phy_id_2;
        u32 hw_phy_id, hw_phy_id_masked;
@@ -13957,7 +14341,7 @@ skip_phy_reset:
        return err;
 }
 
-static void __devinit tg3_read_vpd(struct tg3 *tp)
+static void tg3_read_vpd(struct tg3 *tp)
 {
        u8 *vpd_data;
        unsigned int block_end, rosize, len;
@@ -14026,7 +14410,8 @@ out_not_found:
 
 out_no_vpd:
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
-               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717)
+               if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C)
                        strcpy(tp->board_part_number, "BCM5717");
                else if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718)
                        strcpy(tp->board_part_number, "BCM5718");
@@ -14077,7 +14462,7 @@ nomatch:
        }
 }
 
-static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
+static int tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
 {
        u32 val;
 
@@ -14090,7 +14475,7 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
        return 1;
 }
 
-static void __devinit tg3_read_bc_ver(struct tg3 *tp)
+static void tg3_read_bc_ver(struct tg3 *tp)
 {
        u32 val, offset, start, ver_offset;
        int i, dst_off;
@@ -14142,7 +14527,7 @@ static void __devinit tg3_read_bc_ver(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_read_hwsb_ver(struct tg3 *tp)
+static void tg3_read_hwsb_ver(struct tg3 *tp)
 {
        u32 val, major, minor;
 
@@ -14158,7 +14543,7 @@ static void __devinit tg3_read_hwsb_ver(struct tg3 *tp)
        snprintf(&tp->fw_ver[0], 32, "sb v%d.%02d", major, minor);
 }
 
-static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
+static void tg3_read_sb_ver(struct tg3 *tp, u32 val)
 {
        u32 offset, major, minor, build;
 
@@ -14213,7 +14598,7 @@ static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
        }
 }
 
-static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp)
+static void tg3_read_mgmtfw_ver(struct tg3 *tp)
 {
        u32 val, offset, start;
        int i, vlen;
@@ -14265,7 +14650,7 @@ static void __devinit tg3_read_mgmtfw_ver(struct tg3 *tp)
        }
 }
 
-static void __devinit tg3_probe_ncsi(struct tg3 *tp)
+static void tg3_probe_ncsi(struct tg3 *tp)
 {
        u32 apedata;
 
@@ -14281,7 +14666,7 @@ static void __devinit tg3_probe_ncsi(struct tg3 *tp)
                tg3_flag_set(tp, APE_HAS_NCSI);
 }
 
-static void __devinit tg3_read_dash_ver(struct tg3 *tp)
+static void tg3_read_dash_ver(struct tg3 *tp)
 {
        int vlen;
        u32 apedata;
@@ -14304,7 +14689,7 @@ static void __devinit tg3_read_dash_ver(struct tg3 *tp)
                 (apedata & APE_FW_VERSION_BLDMSK));
 }
 
-static void __devinit tg3_read_fw_ver(struct tg3 *tp)
+static void tg3_read_fw_ver(struct tg3 *tp)
 {
        u32 val;
        bool vpd_vers = false;
@@ -14357,7 +14742,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
        { },
 };
 
-static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
+static struct pci_dev *tg3_find_peer(struct tg3 *tp)
 {
        struct pci_dev *peer;
        unsigned int func, devnr = tp->pdev->devfn & ~7;
@@ -14385,7 +14770,7 @@ static struct pci_dev * __devinit tg3_find_peer(struct tg3 *tp)
        return peer;
 }
 
-static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
+static void tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
 {
        tp->pci_chip_rev_id = misc_ctrl_reg >> MISC_HOST_CTRL_CHIPREV_SHIFT;
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_USE_PROD_ID_REG) {
@@ -14397,6 +14782,7 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
                tg3_flag_set(tp, CPMU_PRESENT);
 
                if (tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+                   tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C ||
                    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
                    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
                    tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720)
@@ -14424,6 +14810,9 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
        if (tp->pci_chip_rev_id == CHIPREV_ID_5752_A0_HW)
                tp->pci_chip_rev_id = CHIPREV_ID_5752_A0;
 
+       if (tp->pci_chip_rev_id == CHIPREV_ID_5717_C0)
+               tp->pci_chip_rev_id = CHIPREV_ID_5720_A0;
+
        if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
            GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
@@ -14462,7 +14851,29 @@ static void __devinit tg3_detect_asic_rev(struct tg3 *tp, u32 misc_ctrl_reg)
                tg3_flag_set(tp, 5705_PLUS);
 }
 
-static int __devinit tg3_get_invariants(struct tg3 *tp)
+static bool tg3_10_100_only_device(struct tg3 *tp,
+                                  const struct pci_device_id *ent)
+{
+       u32 grc_misc_cfg = tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK;
+
+       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
+           (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
+           (tp->phy_flags & TG3_PHYFLG_IS_FET))
+               return true;
+
+       if (ent->driver_data & TG3_DRV_DATA_FLAG_10_100_ONLY) {
+               if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
+                       if (ent->driver_data & TG3_DRV_DATA_FLAG_5705_10_100)
+                               return true;
+               } else {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+static int tg3_get_invariants(struct tg3 *tp, const struct pci_device_id *ent)
 {
        u32 misc_ctrl_reg;
        u32 pci_state_reg, grc_misc_cfg;
@@ -15141,22 +15552,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
        else
                tp->mac_mode = 0;
 
-       /* these are limited to 10/100 only */
-       if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
-            (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) ||
-           (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-            tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
-            (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901 ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5901_2 ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5705F)) ||
-           (tp->pdev->vendor == PCI_VENDOR_ID_BROADCOM &&
-            (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
-             tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
-           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
-           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57791 ||
-           tp->pdev->device == TG3PCI_DEVICE_TIGON3_57795 ||
-           (tp->phy_flags & TG3_PHYFLG_IS_FET))
+       if (tg3_10_100_only_device(tp, ent))
                tp->phy_flags |= TG3_PHYFLG_10_100_ONLY;
 
        err = tg3_phy_probe(tp);
@@ -15236,7 +15632,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
 }
 
 #ifdef CONFIG_SPARC
-static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
+static int tg3_get_macaddr_sparc(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
        struct pci_dev *pdev = tp->pdev;
@@ -15253,7 +15649,7 @@ static int __devinit tg3_get_macaddr_sparc(struct tg3 *tp)
        return -ENODEV;
 }
 
-static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
+static int tg3_get_default_macaddr_sparc(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
 
@@ -15263,7 +15659,7 @@ static int __devinit tg3_get_default_macaddr_sparc(struct tg3 *tp)
 }
 #endif
 
-static int __devinit tg3_get_device_address(struct tg3 *tp)
+static int tg3_get_device_address(struct tg3 *tp)
 {
        struct net_device *dev = tp->dev;
        u32 hi, lo, mac_offset;
@@ -15342,7 +15738,7 @@ static int __devinit tg3_get_device_address(struct tg3 *tp)
 #define BOUNDARY_SINGLE_CACHELINE      1
 #define BOUNDARY_MULTI_CACHELINE       2
 
-static u32 __devinit tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
+static u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val)
 {
        int cacheline_size;
        u8 byte;
@@ -15483,7 +15879,8 @@ out:
        return val;
 }
 
-static int __devinit tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma, int size, int to_device)
+static int tg3_do_test_dma(struct tg3 *tp, u32 *buf, dma_addr_t buf_dma,
+                          int size, int to_device)
 {
        struct tg3_internal_buffer_desc test_desc;
        u32 sram_dma_descs;
@@ -15570,7 +15967,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = {
        { },
 };
 
-static int __devinit tg3_test_dma(struct tg3 *tp)
+static int tg3_test_dma(struct tg3 *tp)
 {
        dma_addr_t buf_dma;
        u32 *buf, saved_dma_rwctrl;
@@ -15760,7 +16157,7 @@ out_nofree:
        return ret;
 }
 
-static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
+static void tg3_init_bufmgr_config(struct tg3 *tp)
 {
        if (tg3_flag(tp, 57765_PLUS)) {
                tp->bufmgr_config.mbuf_read_dma_low_water =
@@ -15816,7 +16213,7 @@ static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
        tp->bufmgr_config.dma_high_water = DEFAULT_DMA_HIGH_WATER;
 }
 
-static char * __devinit tg3_phy_string(struct tg3 *tp)
+static char *tg3_phy_string(struct tg3 *tp)
 {
        switch (tp->phy_id & TG3_PHY_ID_MASK) {
        case TG3_PHY_ID_BCM5400:        return "5400";
@@ -15847,7 +16244,7 @@ static char * __devinit tg3_phy_string(struct tg3 *tp)
        }
 }
 
-static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
+static char *tg3_bus_string(struct tg3 *tp, char *str)
 {
        if (tg3_flag(tp, PCI_EXPRESS)) {
                strcpy(str, "PCI Express");
@@ -15883,7 +16280,7 @@ static char * __devinit tg3_bus_string(struct tg3 *tp, char *str)
        return str;
 }
 
-static void __devinit tg3_init_coal(struct tg3 *tp)
+static void tg3_init_coal(struct tg3 *tp)
 {
        struct ethtool_coalesce *ec = &tp->coal;
 
@@ -15914,7 +16311,7 @@ static void __devinit tg3_init_coal(struct tg3 *tp)
        }
 }
 
-static int __devinit tg3_init_one(struct pci_dev *pdev,
+static int tg3_init_one(struct pci_dev *pdev,
                                  const struct pci_device_id *ent)
 {
        struct net_device *dev;
@@ -16013,6 +16410,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
            tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S ||
            tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761SE ||
            tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717 ||
+           tp->pdev->device == TG3PCI_DEVICE_TIGON3_5717_C ||
            tp->pdev->device == TG3PCI_DEVICE_TIGON3_5718 ||
            tp->pdev->device == TG3PCI_DEVICE_TIGON3_5719 ||
            tp->pdev->device == TG3PCI_DEVICE_TIGON3_5720) {
@@ -16034,7 +16432,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
        dev->netdev_ops = &tg3_netdev_ops;
        dev->irq = pdev->irq;
 
-       err = tg3_get_invariants(tp);
+       err = tg3_get_invariants(tp, ent);
        if (err) {
                dev_err(&pdev->dev,
                        "Problem fetching invariants of chip, aborting\n");
@@ -16209,6 +16607,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
 
        pci_set_drvdata(pdev, dev);
 
+       if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720)
+               tg3_flag_set(tp, PTP_CAPABLE);
+
        if (tg3_flag(tp, 5717_PLUS)) {
                /* Resume a low-power mode */
                tg3_frob_aux_power(tp, false);
@@ -16293,7 +16695,7 @@ err_out_disable_pdev:
        return err;
 }
 
-static void __devexit tg3_remove_one(struct pci_dev *pdev)
+static void tg3_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -16534,8 +16936,8 @@ static void tg3_io_resume(struct pci_dev *pdev)
        tg3_full_lock(tp, 0);
        tg3_flag_set(tp, INIT_COMPLETE);
        err = tg3_restart_hw(tp, 1);
-       tg3_full_unlock(tp);
        if (err) {
+               tg3_full_unlock(tp);
                netdev_err(netdev, "Cannot restart hardware after reset.\n");
                goto done;
        }
@@ -16546,6 +16948,8 @@ static void tg3_io_resume(struct pci_dev *pdev)
 
        tg3_netif_start(tp);
 
+       tg3_full_unlock(tp);
+
        tg3_phy_start(tp);
 
 done:
@@ -16562,7 +16966,7 @@ static struct pci_driver tg3_driver = {
        .name           = DRV_MODULE_NAME,
        .id_table       = tg3_pci_tbl,
        .probe          = tg3_init_one,
-       .remove         = __devexit_p(tg3_remove_one),
+       .remove         = tg3_remove_one,
        .err_handler    = &tg3_err_handler,
        .driver.pm      = TG3_PM_OPS,
 };
index d9308c32102e998fb22c45f9ee5c21482286072a..d330e81f5793ad47e8f6257d3e08c728719c9651 100644 (file)
 #define  TG3PCI_DEVICE_TIGON3_5761S     0x1688
 #define  TG3PCI_DEVICE_TIGON3_5761SE    0x1689
 #define  TG3PCI_DEVICE_TIGON3_57780     0x1692
+#define  TG3PCI_DEVICE_TIGON3_5787M     0x1693
 #define  TG3PCI_DEVICE_TIGON3_57760     0x1690
 #define  TG3PCI_DEVICE_TIGON3_57790     0x1694
 #define  TG3PCI_DEVICE_TIGON3_57788     0x1691
 #define  TG3PCI_DEVICE_TIGON3_5785_G    0x1699 /* GPHY */
 #define  TG3PCI_DEVICE_TIGON3_5785_F    0x16a0 /* 10/100 only */
 #define  TG3PCI_DEVICE_TIGON3_5717      0x1655
+#define  TG3PCI_DEVICE_TIGON3_5717_C    0x1665
 #define  TG3PCI_DEVICE_TIGON3_5718      0x1656
 #define  TG3PCI_DEVICE_TIGON3_57781     0x16b1
 #define  TG3PCI_DEVICE_TIGON3_57785     0x16b5
 #define TG3PCI_SUBDEVICE_ID_COMPAQ_NC7780_2    0x0099
 #define TG3PCI_SUBVENDOR_ID_IBM                        PCI_VENDOR_ID_IBM
 #define TG3PCI_SUBDEVICE_ID_IBM_5703SAX2       0x0281
+#define TG3PCI_SUBDEVICE_ID_ACER_57780_A       0x0601
+#define TG3PCI_SUBDEVICE_ID_ACER_57780_B       0x0612
+#define TG3PCI_SUBDEVICE_ID_LENOVO_5787M       0x3056
+
 /* 0x30 --> 0x64 unused */
 #define TG3PCI_MSI_DATA                        0x00000064
 /* 0x66 --> 0x68 unused */
 #define  CHIPREV_ID_57780_A0            0x57780000
 #define  CHIPREV_ID_57780_A1            0x57780001
 #define  CHIPREV_ID_5717_A0             0x05717000
+#define  CHIPREV_ID_5717_C0             0x05717200
 #define  CHIPREV_ID_57765_A0            0x57785000
 #define  CHIPREV_ID_5719_A0             0x05719000
 #define  CHIPREV_ID_5720_A0             0x05720000
 #define  SG_DIG_MAC_ACK_STATUS          0x00000004
 #define  SG_DIG_AUTONEG_COMPLETE        0x00000002
 #define  SG_DIG_AUTONEG_ERROR           0x00000001
-/* 0x5b8 --> 0x600 unused */
+#define TG3_TX_TSTAMP_LSB              0x000005c0
+#define TG3_TX_TSTAMP_MSB              0x000005c4
+#define  TG3_TSTAMP_MASK                0x7fffffffffffffff
+/* 0x5c8 --> 0x600 unused */
 #define MAC_TX_MAC_STATE_BASE          0x00000600 /* 16 bytes */
 #define MAC_RX_MAC_STATE_BASE          0x00000610 /* 20 bytes */
 /* 0x624 --> 0x670 unused */
 #define MAC_RSS_HASH_KEY_7             0x0000068c
 #define MAC_RSS_HASH_KEY_8             0x00000690
 #define MAC_RSS_HASH_KEY_9             0x00000694
-/* 0x698 --> 0x800 unused */
+/* 0x698 --> 0x6b0 unused */
+
+#define TG3_RX_TSTAMP_LSB              0x000006b0
+#define TG3_RX_TSTAMP_MSB              0x000006b4
+/* 0x6b8 --> 0x6c8 unused */
+
+#define TG3_RX_PTP_CTL                 0x000006c8
+#define TG3_RX_PTP_CTL_SYNC_EVNT       0x00000001
+#define TG3_RX_PTP_CTL_DELAY_REQ       0x00000002
+#define TG3_RX_PTP_CTL_PDLAY_REQ       0x00000004
+#define TG3_RX_PTP_CTL_PDLAY_RES       0x00000008
+#define TG3_RX_PTP_CTL_ALL_V1_EVENTS   (TG3_RX_PTP_CTL_SYNC_EVNT | \
+                                        TG3_RX_PTP_CTL_DELAY_REQ)
+#define TG3_RX_PTP_CTL_ALL_V2_EVENTS   (TG3_RX_PTP_CTL_SYNC_EVNT | \
+                                        TG3_RX_PTP_CTL_DELAY_REQ | \
+                                        TG3_RX_PTP_CTL_PDLAY_REQ | \
+                                        TG3_RX_PTP_CTL_PDLAY_RES)
+#define TG3_RX_PTP_CTL_FOLLOW_UP       0x00000100
+#define TG3_RX_PTP_CTL_DELAY_RES       0x00000200
+#define TG3_RX_PTP_CTL_PDRES_FLW_UP    0x00000400
+#define TG3_RX_PTP_CTL_ANNOUNCE                0x00000800
+#define TG3_RX_PTP_CTL_SIGNALING       0x00001000
+#define TG3_RX_PTP_CTL_MANAGEMENT      0x00002000
+#define TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN 0x00800000
+#define TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN 0x01000000
+#define TG3_RX_PTP_CTL_RX_PTP_V2_EN    (TG3_RX_PTP_CTL_RX_PTP_V2_L2_EN | \
+                                        TG3_RX_PTP_CTL_RX_PTP_V2_L4_EN)
+#define TG3_RX_PTP_CTL_RX_PTP_V1_EN    0x02000000
+#define TG3_RX_PTP_CTL_HWTS_INTERLOCK  0x04000000
+/* 0x6cc --> 0x800 unused */
 
 #define MAC_TX_STATS_OCTETS            0x00000800
 #define MAC_TX_STATS_RESV1             0x00000804
 #define  GRC_MODE_HOST_STACKUP         0x00010000
 #define  GRC_MODE_HOST_SENDBDS         0x00020000
 #define  GRC_MODE_HTX2B_ENABLE         0x00040000
+#define  GRC_MODE_TIME_SYNC_ENABLE     0x00080000
 #define  GRC_MODE_NO_TX_PHDR_CSUM      0x00100000
 #define  GRC_MODE_NVRAM_WR_ENABLE      0x00200000
 #define  GRC_MODE_PCIE_TL_SEL          0x00000000
 #define GRC_VCPU_EXT_CTRL_DISABLE_WOL   0x20000000
 #define GRC_FASTBOOT_PC                        0x00006894      /* 5752, 5755, 5787 */
 
-/* 0x6c00 --> 0x7000 unused */
+#define TG3_EAV_REF_CLCK_LSB           0x00006900
+#define TG3_EAV_REF_CLCK_MSB           0x00006904
+#define TG3_EAV_REF_CLCK_CTL           0x00006908
+#define  TG3_EAV_REF_CLCK_CTL_STOP      0x00000002
+#define  TG3_EAV_REF_CLCK_CTL_RESUME    0x00000004
+#define TG3_EAV_REF_CLK_CORRECT_CTL    0x00006928
+#define  TG3_EAV_REF_CLK_CORRECT_EN     (1 << 31)
+#define  TG3_EAV_REF_CLK_CORRECT_NEG    (1 << 30)
+
+#define TG3_EAV_REF_CLK_CORRECT_MASK   0xffffff
+/* 0x690c --> 0x7000 unused */
 
 /* NVRAM Control registers */
 #define NVRAM_CMD                      0x00007000
@@ -2432,6 +2482,7 @@ struct tg3_tx_buffer_desc {
 #define TXD_FLAG_IP_FRAG               0x0008
 #define TXD_FLAG_JMB_PKT               0x0008
 #define TXD_FLAG_IP_FRAG_END           0x0010
+#define TXD_FLAG_HWTSTAMP              0x0020
 #define TXD_FLAG_VLAN                  0x0040
 #define TXD_FLAG_COAL_NOW              0x0080
 #define TXD_FLAG_CPU_PRE_DMA           0x0100
@@ -2473,6 +2524,9 @@ struct tg3_rx_buffer_desc {
 #define RXD_FLAG_IP_CSUM               0x1000
 #define RXD_FLAG_TCPUDP_CSUM           0x2000
 #define RXD_FLAG_IS_TCP                        0x4000
+#define RXD_FLAG_PTPSTAT_MASK          0x0210
+#define RXD_FLAG_PTPSTAT_PTPV1         0x0010
+#define RXD_FLAG_PTPSTAT_PTPV2         0x0200
 
        u32                             ip_tcp_csum;
 #define RXD_IPCSUM_MASK                0xffff0000
@@ -2963,9 +3017,11 @@ enum TG3_FLAGS {
        TG3_FLAG_USE_JUMBO_BDFLAG,
        TG3_FLAG_L1PLLPD_EN,
        TG3_FLAG_APE_HAS_NCSI,
+       TG3_FLAG_TX_TSTAMP_EN,
        TG3_FLAG_4K_FIFO_LIMIT,
        TG3_FLAG_5719_RDMA_BUG,
        TG3_FLAG_RESET_TASK_PENDING,
+       TG3_FLAG_PTP_CAPABLE,
        TG3_FLAG_5705_PLUS,
        TG3_FLAG_IS_5788,
        TG3_FLAG_5750_PLUS,
@@ -3034,6 +3090,10 @@ struct tg3 {
        u32                             coal_now;
        u32                             msg_enable;
 
+       struct ptp_clock_info           ptp_info;
+       struct ptp_clock                *ptp_clock;
+       s64                             ptp_adjust;
+
        /* begin "tx thread" cacheline section */
        void                            (*write32_tx_mbox) (struct tg3 *, u32,
                                                            u32);
@@ -3101,6 +3161,7 @@ struct tg3 {
        u32                             dma_rwctrl;
        u32                             coalesce_mode;
        u32                             pwrmgmt_thresh;
+       u32                             rxptpctl;
 
        /* PCI block */
        u32                             pci_chip_rev_id;
@@ -3262,6 +3323,7 @@ struct tg3 {
 #if IS_ENABLED(CONFIG_HWMON)
        struct device                   *hwmon_dev;
 #endif
+       bool                            link_up;
 };
 
 #endif /* !(_T3_H) */
index 959c58ef972abffa33ce9c24638bffbbc366e720..3227fdde521b09323f6e4ba58188198052aeb70e 100644 (file)
@@ -2273,7 +2273,6 @@ bfa_ioc_get_type(struct bfa_ioc *ioc)
 static void
 bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
 {
-       memset(serial_num, 0, BFA_ADAPTER_SERIAL_NUM_LEN);
        memcpy(serial_num,
                        (void *)ioc->attr->brcd_serialnum,
                        BFA_ADAPTER_SERIAL_NUM_LEN);
@@ -2282,7 +2281,6 @@ bfa_ioc_get_adapter_serial_num(struct bfa_ioc *ioc, char *serial_num)
 static void
 bfa_ioc_get_adapter_fw_ver(struct bfa_ioc *ioc, char *fw_ver)
 {
-       memset(fw_ver, 0, BFA_VERSION_LEN);
        memcpy(fw_ver, ioc->attr->fw_version, BFA_VERSION_LEN);
 }
 
@@ -2304,7 +2302,6 @@ bfa_ioc_get_pci_chip_rev(struct bfa_ioc *ioc, char *chip_rev)
 static void
 bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
 {
-       memset(optrom_ver, 0, BFA_VERSION_LEN);
        memcpy(optrom_ver, ioc->attr->optrom_version,
                      BFA_VERSION_LEN);
 }
@@ -2312,7 +2309,6 @@ bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
 static void
 bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
 {
-       memset(manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN);
        memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
 }
 
index ce1eac529470de89cdbc2107a649affbfedb3761..76b2af64adc226b5af141c0c7802c02e647783f4 100644 (file)
@@ -3226,7 +3226,7 @@ bnad_pci_uninit(struct pci_dev *pdev)
        pci_disable_device(pdev);
 }
 
-static int __devinit
+static int
 bnad_pci_probe(struct pci_dev *pdev,
                const struct pci_device_id *pcidev_id)
 {
@@ -3426,7 +3426,7 @@ unlock_mutex:
        return err;
 }
 
-static void __devexit
+static void
 bnad_pci_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3490,7 +3490,7 @@ static struct pci_driver bnad_pci_driver = {
        .name = BNAD_NAME,
        .id_table = bnad_pci_id_table,
        .probe = bnad_pci_probe,
-       .remove = __devexit_p(bnad_pci_remove),
+       .remove = bnad_pci_remove,
 };
 
 static int __init
index db931916da08c8ddfd26b9068a94b7dddd1bfb46..ceb0de0cf62c6e4f2dffcc0c650f256dd8adbbf1 100644 (file)
@@ -2,13 +2,10 @@
 # Atmel device configuration
 #
 
-config HAVE_NET_MACB
-       bool
-
 config NET_CADENCE
        bool "Cadence devices"
+       depends on HAS_IOMEM
        default y
-       depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y.
          Make sure you know the name of your card. Read the Ethernet-HOWTO,
@@ -25,16 +22,14 @@ if NET_CADENCE
 
 config ARM_AT91_ETHER
        tristate "AT91RM9200 Ethernet support"
-       depends on ARM && ARCH_AT91RM9200
        select NET_CORE
-       select MII
+       select MACB
        ---help---
          If you wish to compile a kernel for the AT91RM9200 and enable
          ethernet support, then you should always answer Y to this.
 
 config MACB
        tristate "Cadence MACB/GEM support"
-       depends on HAVE_NET_MACB
        select PHYLIB
        ---help---
          The Cadence MACB ethernet interface is found on many Atmel AT32 and
index 4e980a7886fb58758fa84071b2494f56364da1f2..3becdb2deb46c8dbfb3faa4e2916e1cdf41bc6d3 100644 (file)
@@ -6,11 +6,6 @@
  * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
  * Initial version by Rick Bronson 01/11/2003
  *
- * Intel LXT971A PHY support by Christopher Bahns & David Knickerbocker
- *   (Polaroid Corporation)
- *
- * Realtek RTL8201(B)L PHY support by Roman Avramenko <roman@imsystems.ru>
- *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
@@ -20,7 +15,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
-#include <linux/mii.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/clk.h>
 #include <linux/gfp.h>
 #include <linux/phy.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_net.h>
+#include <linux/pinctrl/consumer.h>
 
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/mach-types.h>
-
-#include <mach/at91rm9200_emac.h>
-#include <asm/gpio.h>
-#include <mach/board.h>
-
-#include "at91_ether.h"
-
-#define DRV_NAME       "at91_ether"
-#define DRV_VERSION    "1.0"
-
-#define LINK_POLL_INTERVAL     (HZ)
-
-/* ..................................................................... */
-
-/*
- * Read from a EMAC register.
- */
-static inline unsigned long at91_emac_read(struct at91_private *lp, unsigned int reg)
-{
-       return __raw_readl(lp->emac_base + reg);
-}
-
-/*
- * Write to a EMAC register.
- */
-static inline void at91_emac_write(struct at91_private *lp, unsigned int reg, unsigned long value)
-{
-       __raw_writel(value, lp->emac_base + reg);
-}
-
-/* ........................... PHY INTERFACE ........................... */
-
-/*
- * Enable the MDIO bit in MAC control register
- * When not called from an interrupt-handler, access to the PHY must be
- *  protected by a spinlock.
- */
-static void enable_mdi(struct at91_private *lp)
-{
-       unsigned long ctl;
-
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_MPE);        /* enable management port */
-}
-
-/*
- * Disable the MDIO bit in the MAC control register
- */
-static void disable_mdi(struct at91_private *lp)
-{
-       unsigned long ctl;
-
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_MPE);       /* disable management port */
-}
-
-/*
- * Wait until the PHY operation is complete.
- */
-static inline void at91_phy_wait(struct at91_private *lp)
-{
-       unsigned long timeout = jiffies + 2;
-
-       while (!(at91_emac_read(lp, AT91_EMAC_SR) & AT91_EMAC_SR_IDLE)) {
-               if (time_after(jiffies, timeout)) {
-                       printk("at91_ether: MIO timeout\n");
-                       break;
-               }
-               cpu_relax();
-       }
-}
-
-/*
- * Write value to the a PHY register
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void write_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int value)
-{
-       at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_W
-               | ((phy_addr & 0x1f) << 23) | (address << 18) | (value & AT91_EMAC_DATA));
-
-       /* Wait until IDLE bit in Network Status register is cleared */
-       at91_phy_wait(lp);
-}
-
-/*
- * Read value stored in a PHY register.
- * Note: MDI interface is assumed to already have been enabled.
- */
-static void read_phy(struct at91_private *lp, unsigned char phy_addr, unsigned char address, unsigned int *value)
-{
-       at91_emac_write(lp, AT91_EMAC_MAN, AT91_EMAC_MAN_802_3 | AT91_EMAC_RW_R
-               | ((phy_addr & 0x1f) << 23) | (address << 18));
-
-       /* Wait until IDLE bit in Network Status register is cleared */
-       at91_phy_wait(lp);
-
-       *value = at91_emac_read(lp, AT91_EMAC_MAN) & AT91_EMAC_DATA;
-}
-
-/* ........................... PHY MANAGEMENT .......................... */
-
-/*
- * Access the PHY to determine the current link speed and mode, and update the
- * MAC accordingly.
- * If no link or auto-negotiation is busy, then no changes are made.
- */
-static void update_linkspeed(struct net_device *dev, int silent)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int bmsr, bmcr, lpa, mac_cfg;
-       unsigned int speed, duplex;
-
-       if (!mii_link_ok(&lp->mii)) {           /* no link */
-               netif_carrier_off(dev);
-               if (!silent)
-                       printk(KERN_INFO "%s: Link down.\n", dev->name);
-               return;
-       }
-
-       /* Link up, or auto-negotiation still in progress */
-       read_phy(lp, lp->phy_address, MII_BMSR, &bmsr);
-       read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
-       if (bmcr & BMCR_ANENABLE) {                             /* AutoNegotiation is enabled */
-               if (!(bmsr & BMSR_ANEGCOMPLETE))
-                       return;                 /* Do nothing - another interrupt generated when negotiation complete */
-
-               read_phy(lp, lp->phy_address, MII_LPA, &lpa);
-               if ((lpa & LPA_100FULL) || (lpa & LPA_100HALF)) speed = SPEED_100;
-               else speed = SPEED_10;
-               if ((lpa & LPA_100FULL) || (lpa & LPA_10FULL)) duplex = DUPLEX_FULL;
-               else duplex = DUPLEX_HALF;
-       } else {
-               speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
-               duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
-       }
-
-       /* Update the MAC */
-       mac_cfg = at91_emac_read(lp, AT91_EMAC_CFG) & ~(AT91_EMAC_SPD | AT91_EMAC_FD);
-       if (speed == SPEED_100) {
-               if (duplex == DUPLEX_FULL)              /* 100 Full Duplex */
-                       mac_cfg |= AT91_EMAC_SPD | AT91_EMAC_FD;
-               else                                    /* 100 Half Duplex */
-                       mac_cfg |= AT91_EMAC_SPD;
-       } else {
-               if (duplex == DUPLEX_FULL)              /* 10 Full Duplex */
-                       mac_cfg |= AT91_EMAC_FD;
-               else {}                                 /* 10 Half Duplex */
-       }
-       at91_emac_write(lp, AT91_EMAC_CFG, mac_cfg);
-
-       if (!silent)
-               printk(KERN_INFO "%s: Link now %i-%s\n", dev->name, speed, (duplex == DUPLEX_FULL) ? "FullDuplex" : "HalfDuplex");
-       netif_carrier_on(dev);
-}
-
-/*
- * Handle interrupts from the PHY
- */
-static irqreturn_t at91ether_phy_interrupt(int irq, void *dev_id)
-{
-       struct net_device *dev = (struct net_device *) dev_id;
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int phy;
-
-       /*
-        * This hander is triggered on both edges, but the PHY chips expect
-        * level-triggering.  We therefore have to check if the PHY actually has
-        * an IRQ pending.
-        */
-       enable_mdi(lp);
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-               read_phy(lp, lp->phy_address, MII_DSINTR_REG, &phy);    /* ack interrupt in Davicom PHY */
-               if (!(phy & (1 << 0)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {
-               read_phy(lp, lp->phy_address, MII_ISINTS_REG, &phy);    /* ack interrupt in Intel PHY */
-               if (!(phy & (1 << 2)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {
-               read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &phy);   /* ack interrupt in Broadcom PHY */
-               if (!(phy & (1 << 0)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {
-               read_phy(lp, lp->phy_address, MII_TPISTATUS, &phy);             /* ack interrupt in Micrel PHY */
-               if (!(phy & ((1 << 2) | 1)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_T78Q21x3_ID) {                                     /* ack interrupt in Teridian PHY */
-               read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &phy);
-               if (!(phy & ((1 << 2) | 1)))
-                       goto done;
-       }
-       else if (lp->phy_type == MII_DP83848_ID) {
-               read_phy(lp, lp->phy_address, MII_DPPHYSTS_REG, &phy);  /* ack interrupt in DP83848 PHY */
-               if (!(phy & (1 << 7)))
-                       goto done;
-       }
-
-       update_linkspeed(dev, 0);
-
-done:
-       disable_mdi(lp);
-
-       return IRQ_HANDLED;
-}
-
-/*
- * Initialize and enable the PHY interrupt for link-state changes
- */
-static void enable_phyirq(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int dsintr, irq_number;
-       int status;
-
-       if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
-               /*
-                * PHY doesn't have an IRQ pin (RTL8201, DP83847, AC101L),
-                * or board does not have it connected.
-                */
-               mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-               return;
-       }
-
-       irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
-       status = request_irq(irq_number, at91ether_phy_interrupt, 0, dev->name, dev);
-       if (status) {
-               printk(KERN_ERR "at91_ether: PHY IRQ %d request failed - status %d!\n", irq_number, status);
-               return;
-       }
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {      /* for Davicom PHY */
-               read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
-               dsintr = dsintr & ~0xf00;               /* clear bits 8..11 */
-               write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {      /* for Intel PHY */
-               read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
-               dsintr = dsintr | 0xf2;                 /* set bits 1, 4..7 */
-               write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {      /* for Broadcom PHY */
-               dsintr = (1 << 15) | ( 1 << 14);
-               write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {       /* for Micrel PHY */
-               dsintr = (1 << 10) | ( 1 << 8);
-               write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
-       }
-       else if (lp->phy_type == MII_T78Q21x3_ID) {     /* for Teridian PHY */
-               read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-               dsintr = dsintr | 0x500;                /* set bits 8, 10 */
-               write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_DP83848_ID) {      /* National Semiconductor DP83848 PHY */
-               read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
-               dsintr = dsintr | 0x3c;                 /* set bits 2..5 */
-               write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
-               read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
-               dsintr = dsintr | 0x3;                  /* set bits 0,1 */
-               write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
-       }
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-}
-
-/*
- * Disable the PHY interrupt
- */
-static void disable_phyirq(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int dsintr;
-       unsigned int irq_number;
-
-       if (!gpio_is_valid(lp->board_data.phy_irq_pin)) {
-               del_timer_sync(&lp->check_timer);
-               return;
-       }
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {      /* for Davicom PHY */
-               read_phy(lp, lp->phy_address, MII_DSINTR_REG, &dsintr);
-               dsintr = dsintr | 0xf00;                        /* set bits 8..11 */
-               write_phy(lp, lp->phy_address, MII_DSINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_LXT971A_ID) {      /* for Intel PHY */
-               read_phy(lp, lp->phy_address, MII_ISINTE_REG, &dsintr);
-               dsintr = dsintr & ~0xf2;                        /* clear bits 1, 4..7 */
-               write_phy(lp, lp->phy_address, MII_ISINTE_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_BCM5221_ID) {      /* for Broadcom PHY */
-               read_phy(lp, lp->phy_address, MII_BCMINTR_REG, &dsintr);
-               dsintr = ~(1 << 14);
-               write_phy(lp, lp->phy_address, MII_BCMINTR_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_KS8721_ID) {       /* for Micrel PHY */
-               read_phy(lp, lp->phy_address, MII_TPISTATUS, &dsintr);
-               dsintr = ~((1 << 10) | (1 << 8));
-               write_phy(lp, lp->phy_address, MII_TPISTATUS, dsintr);
-       }
-       else if (lp->phy_type == MII_T78Q21x3_ID) {     /* for Teridian PHY */
-               read_phy(lp, lp->phy_address, MII_T78Q21INT_REG, &dsintr);
-               dsintr = dsintr & ~0x500;                       /* clear bits 8, 10 */
-               write_phy(lp, lp->phy_address, MII_T78Q21INT_REG, dsintr);
-       }
-       else if (lp->phy_type == MII_DP83848_ID) {      /* National Semiconductor DP83848 PHY */
-               read_phy(lp, lp->phy_address, MII_DPMICR_REG, &dsintr);
-               dsintr = dsintr & ~0x3;                         /* clear bits 0, 1 */
-               write_phy(lp, lp->phy_address, MII_DPMICR_REG, dsintr);
-               read_phy(lp, lp->phy_address, MII_DPMISR_REG, &dsintr);
-               dsintr = dsintr & ~0x3c;                        /* clear bits 2..5 */
-               write_phy(lp, lp->phy_address, MII_DPMISR_REG, dsintr);
-       }
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       irq_number = gpio_to_irq(lp->board_data.phy_irq_pin);
-       free_irq(irq_number, dev);                      /* Free interrupt handler */
-}
-
-/*
- * Perform a software reset of the PHY.
- */
-#if 0
-static void reset_phy(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int bmcr;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       /* Perform PHY reset */
-       write_phy(lp, lp->phy_address, MII_BMCR, BMCR_RESET);
-
-       /* Wait until PHY reset is complete */
-       do {
-               read_phy(lp, lp->phy_address, MII_BMCR, &bmcr);
-       } while (!(bmcr & BMCR_RESET));
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-}
-#endif
-
-static void at91ether_check_link(unsigned long dev_id)
-{
-       struct net_device *dev = (struct net_device *) dev_id;
-       struct at91_private *lp = netdev_priv(dev);
-
-       enable_mdi(lp);
-       update_linkspeed(dev, 1);
-       disable_mdi(lp);
-
-       mod_timer(&lp->check_timer, jiffies + LINK_POLL_INTERVAL);
-}
-
-/*
- * Perform any PHY-specific initialization.
- */
-static void __init initialize_phy(struct at91_private *lp)
-{
-       unsigned int val;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID)) {
-               read_phy(lp, lp->phy_address, MII_DSCR_REG, &val);
-               if ((val & (1 << 10)) == 0)                     /* DSCR bit 10 is 0 -- fiber mode */
-                       lp->phy_media = PORT_FIBRE;
-       } else if (machine_is_csb337()) {
-               /* mix link activity status into LED2 link state */
-               write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x0d22);
-       } else if (machine_is_ecbat91())
-               write_phy(lp, lp->phy_address, MII_LEDCTRL_REG, 0x156A);
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-}
-
-/* ......................... ADDRESS MANAGEMENT ........................ */
-
-/*
- * NOTE: Your bootloader must always set the MAC address correctly before
- * booting into Linux.
- *
- * - It must always set the MAC address after reset, even if it doesn't
- *   happen to access the Ethernet while it's booting.  Some versions of
- *   U-Boot on the AT91RM9200-DK do not do this.
- *
- * - Likewise it must store the addresses in the correct byte order.
- *   MicroMonitor (uMon) on the CSB337 does this incorrectly (and
- *   continues to do so, for bug-compatibility).
- */
-
-static short __init unpack_mac_address(struct net_device *dev, unsigned int hi, unsigned int lo)
-{
-       char addr[6];
-
-       if (machine_is_csb337()) {
-               addr[5] = (lo & 0xff);                  /* The CSB337 bootloader stores the MAC the wrong-way around */
-               addr[4] = (lo & 0xff00) >> 8;
-               addr[3] = (lo & 0xff0000) >> 16;
-               addr[2] = (lo & 0xff000000) >> 24;
-               addr[1] = (hi & 0xff);
-               addr[0] = (hi & 0xff00) >> 8;
-       }
-       else {
-               addr[0] = (lo & 0xff);
-               addr[1] = (lo & 0xff00) >> 8;
-               addr[2] = (lo & 0xff0000) >> 16;
-               addr[3] = (lo & 0xff000000) >> 24;
-               addr[4] = (hi & 0xff);
-               addr[5] = (hi & 0xff00) >> 8;
-       }
-
-       if (is_valid_ether_addr(addr)) {
-               memcpy(dev->dev_addr, &addr, 6);
-               return 1;
-       }
-       return 0;
-}
-
-/*
- * Set the ethernet MAC address in dev->dev_addr
- */
-static void __init get_mac_address(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-
-       /* Check Specific-Address 1 */
-       if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA1H), at91_emac_read(lp, AT91_EMAC_SA1L)))
-               return;
-       /* Check Specific-Address 2 */
-       if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA2H), at91_emac_read(lp, AT91_EMAC_SA2L)))
-               return;
-       /* Check Specific-Address 3 */
-       if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA3H), at91_emac_read(lp, AT91_EMAC_SA3L)))
-               return;
-       /* Check Specific-Address 4 */
-       if (unpack_mac_address(dev, at91_emac_read(lp, AT91_EMAC_SA4H), at91_emac_read(lp, AT91_EMAC_SA4L)))
-               return;
-
-       printk(KERN_ERR "at91_ether: Your bootloader did not configure a MAC address.\n");
-}
-
-/*
- * Program the hardware MAC address from dev->dev_addr.
- */
-static void update_mac_address(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-
-       at91_emac_write(lp, AT91_EMAC_SA1L, (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]));
-       at91_emac_write(lp, AT91_EMAC_SA1H, (dev->dev_addr[5] << 8) | (dev->dev_addr[4]));
-
-       at91_emac_write(lp, AT91_EMAC_SA2L, 0);
-       at91_emac_write(lp, AT91_EMAC_SA2H, 0);
-}
-
-/*
- * Store the new hardware address in dev->dev_addr, and update the MAC.
- */
-static int set_mac_address(struct net_device *dev, void* addr)
-{
-       struct sockaddr *address = addr;
-
-       if (!is_valid_ether_addr(address->sa_data))
-               return -EADDRNOTAVAIL;
-
-       memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
-       update_mac_address(dev);
-
-       printk("%s: Setting MAC address to %pM\n", dev->name,
-              dev->dev_addr);
+#include "macb.h"
 
-       return 0;
-}
-
-static int inline hash_bit_value(int bitnr, __u8 *addr)
-{
-       if (addr[bitnr / 8] & (1 << (bitnr % 8)))
-               return 1;
-       return 0;
-}
+/* 1518 rounded up */
+#define MAX_RBUFF_SZ   0x600
+/* max number of receive buffers */
+#define MAX_RX_DESCR   9
 
-/*
- * The hash address register is 64 bits long and takes up two locations in the memory map.
- * The least significant bits are stored in EMAC_HSL and the most significant
- * bits in EMAC_HSH.
- *
- * The unicast hash enable and the multicast hash enable bits in the network configuration
- *  register enable the reception of hash matched frames. The destination address is
- *  reduced to a 6 bit index into the 64 bit hash register using the following hash function.
- * The hash function is an exclusive or of every sixth bit of the destination address.
- *   hash_index[5] = da[5] ^ da[11] ^ da[17] ^ da[23] ^ da[29] ^ da[35] ^ da[41] ^ da[47]
- *   hash_index[4] = da[4] ^ da[10] ^ da[16] ^ da[22] ^ da[28] ^ da[34] ^ da[40] ^ da[46]
- *   hash_index[3] = da[3] ^ da[09] ^ da[15] ^ da[21] ^ da[27] ^ da[33] ^ da[39] ^ da[45]
- *   hash_index[2] = da[2] ^ da[08] ^ da[14] ^ da[20] ^ da[26] ^ da[32] ^ da[38] ^ da[44]
- *   hash_index[1] = da[1] ^ da[07] ^ da[13] ^ da[19] ^ da[25] ^ da[31] ^ da[37] ^ da[43]
- *   hash_index[0] = da[0] ^ da[06] ^ da[12] ^ da[18] ^ da[24] ^ da[30] ^ da[36] ^ da[42]
- * da[0] represents the least significant bit of the first byte received, that is, the multicast/
- *  unicast indicator, and da[47] represents the most significant bit of the last byte
- *  received.
- * If the hash index points to a bit that is set in the hash register then the frame will be
- *  matched according to whether the frame is multicast or unicast.
- * A multicast match will be signalled if the multicast hash enable bit is set, da[0] is 1 and
- *  the hash index points to a bit set in the hash register.
- * A unicast match will be signalled if the unicast hash enable bit is set, da[0] is 0 and the
- *  hash index points to a bit set in the hash register.
- * To receive all multicast frames, the hash register should be set with all ones and the
- *  multicast hash enable bit should be set in the network configuration register.
- */
-
-/*
- * Return the hash index value for the specified address.
- */
-static int hash_get_index(__u8 *addr)
-{
-       int i, j, bitval;
-       int hash_index = 0;
-
-       for (j = 0; j < 6; j++) {
-               for (i = 0, bitval = 0; i < 8; i++)
-                       bitval ^= hash_bit_value(i*6 + j, addr);
-
-               hash_index |= (bitval << j);
-       }
-
-       return hash_index;
-}
-
-/*
- * Add multicast addresses to the internal multicast-hash table.
- */
-static void at91ether_sethashtable(struct net_device *dev)
+/* Initialize and start the Receiver and Transmit subsystems */
+static int at91ether_start(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
-       struct netdev_hw_addr *ha;
-       unsigned long mc_filter[2];
-       unsigned int bitnr;
-
-       mc_filter[0] = mc_filter[1] = 0;
-
-       netdev_for_each_mc_addr(ha, dev) {
-               bitnr = hash_get_index(ha->addr);
-               mc_filter[bitnr >> 5] |= 1 << (bitnr & 31);
-       }
-
-       at91_emac_write(lp, AT91_EMAC_HSL, mc_filter[0]);
-       at91_emac_write(lp, AT91_EMAC_HSH, mc_filter[1]);
-}
+       struct macb *lp = netdev_priv(dev);
+       dma_addr_t addr;
+       u32 ctl;
+       int i;
 
-/*
- * Enable/Disable promiscuous and multicast modes.
- */
-static void at91ether_set_multicast_list(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned long cfg;
-
-       cfg = at91_emac_read(lp, AT91_EMAC_CFG);
-
-       if (dev->flags & IFF_PROMISC)                   /* Enable promiscuous mode */
-               cfg |= AT91_EMAC_CAF;
-       else if (dev->flags & (~IFF_PROMISC))           /* Disable promiscuous mode */
-               cfg &= ~AT91_EMAC_CAF;
-
-       if (dev->flags & IFF_ALLMULTI) {                /* Enable all multicast mode */
-               at91_emac_write(lp, AT91_EMAC_HSH, -1);
-               at91_emac_write(lp, AT91_EMAC_HSL, -1);
-               cfg |= AT91_EMAC_MTI;
-       } else if (!netdev_mc_empty(dev)) { /* Enable specific multicasts */
-               at91ether_sethashtable(dev);
-               cfg |= AT91_EMAC_MTI;
-       } else if (dev->flags & (~IFF_ALLMULTI)) {      /* Disable all multicast mode */
-               at91_emac_write(lp, AT91_EMAC_HSH, 0);
-               at91_emac_write(lp, AT91_EMAC_HSL, 0);
-               cfg &= ~AT91_EMAC_MTI;
+       lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev,
+                                       MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+                                       &lp->rx_ring_dma, GFP_KERNEL);
+       if (!lp->rx_ring) {
+               netdev_err(dev, "unable to alloc rx ring DMA buffer\n");
+               return -ENOMEM;
        }
 
-       at91_emac_write(lp, AT91_EMAC_CFG, cfg);
-}
-
-/* ......................... ETHTOOL SUPPORT ........................... */
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned int value;
-
-       read_phy(lp, phy_id, location, &value);
-       return value;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
-       struct at91_private *lp = netdev_priv(dev);
-
-       write_phy(lp, phy_id, location, value);
-}
-
-static int at91ether_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int ret;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
+       lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev,
+                                       MAX_RX_DESCR * MAX_RBUFF_SZ,
+                                       &lp->rx_buffers_dma, GFP_KERNEL);
+       if (!lp->rx_buffers) {
+               netdev_err(dev, "unable to alloc rx data DMA buffer\n");
 
-       ret = mii_ethtool_gset(&lp->mii, cmd);
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       if (lp->phy_media == PORT_FIBRE) {              /* override media type since mii.c doesn't know */
-               cmd->supported = SUPPORTED_FIBRE;
-               cmd->port = PORT_FIBRE;
+               dma_free_coherent(&lp->pdev->dev,
+                                       MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+                                       lp->rx_ring, lp->rx_ring_dma);
+               lp->rx_ring = NULL;
+               return -ENOMEM;
        }
 
-       return ret;
-}
-
-static int at91ether_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int ret;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       ret = mii_ethtool_sset(&lp->mii, cmd);
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       return ret;
-}
-
-static int at91ether_nwayreset(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int ret;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-
-       ret = mii_nway_restart(&lp->mii);
-
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       return ret;
-}
-
-static void at91ether_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
-}
-
-static const struct ethtool_ops at91ether_ethtool_ops = {
-       .get_settings   = at91ether_get_settings,
-       .set_settings   = at91ether_set_settings,
-       .get_drvinfo    = at91ether_get_drvinfo,
-       .nway_reset     = at91ether_nwayreset,
-       .get_link       = ethtool_op_get_link,
-};
-
-static int at91ether_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int res;
-
-       if (!netif_running(dev))
-               return -EINVAL;
-
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-       res = generic_mii_ioctl(&lp->mii, if_mii(rq), cmd, NULL);
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       return res;
-}
-
-/* ................................ MAC ................................ */
-
-/*
- * Initialize and start the Receiver and Transmit subsystems
- */
-static void at91ether_start(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       struct recv_desc_bufs *dlist, *dlist_phys;
-       int i;
-       unsigned long ctl;
-
-       dlist = lp->dlist;
-       dlist_phys = lp->dlist_phys;
-
+       addr = lp->rx_buffers_dma;
        for (i = 0; i < MAX_RX_DESCR; i++) {
-               dlist->descriptors[i].addr = (unsigned int) &dlist_phys->recv_buf[i][0];
-               dlist->descriptors[i].size = 0;
+               lp->rx_ring[i].addr = addr;
+               lp->rx_ring[i].ctrl = 0;
+               addr += MAX_RBUFF_SZ;
        }
 
        /* Set the Wrap bit on the last descriptor */
-       dlist->descriptors[i-1].addr |= EMAC_DESC_WRAP;
+       lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP);
 
        /* Reset buffer index */
-       lp->rxBuffIndex = 0;
+       lp->rx_tail = 0;
 
        /* Program address of descriptor list in Rx Buffer Queue register */
-       at91_emac_write(lp, AT91_EMAC_RBQP, (unsigned long) dlist_phys);
+       macb_writel(lp, RBQP, lp->rx_ring_dma);
 
        /* Enable Receive and Transmit */
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE | AT91_EMAC_TE);
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE));
+
+       return 0;
 }
 
-/*
- * Open the ethernet interface
- */
+/* Open the ethernet interface */
 static int at91ether_open(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned long ctl;
-
-       if (!is_valid_ether_addr(dev->dev_addr))
-               return -EADDRNOTAVAIL;
-
-       clk_enable(lp->ether_clk);              /* Re-enable Peripheral clock */
+       struct macb *lp = netdev_priv(dev);
+       u32 ctl;
+       int ret;
 
        /* Clear internal statistics */
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_CSR);
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT));
 
-       /* Update the MAC address (incase user has changed it) */
-       update_mac_address(dev);
+       macb_set_hwaddr(lp);
 
-       /* Enable PHY interrupt */
-       enable_phyirq(dev);
+       ret = at91ether_start(dev);
+       if (ret)
+               return ret;
 
        /* Enable MAC interrupts */
-       at91_emac_write(lp, AT91_EMAC_IER, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-                               | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
-                               | AT91_EMAC_ROVR | AT91_EMAC_ABT);
-
-       /* Determine current link speed */
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-       update_linkspeed(dev, 0);
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-
-       at91ether_start(dev);
+       macb_writel(lp, IER, MACB_BIT(RCOMP)    |
+                            MACB_BIT(RXUBR)    |
+                            MACB_BIT(ISR_TUND) |
+                            MACB_BIT(ISR_RLE)  |
+                            MACB_BIT(TCOMP)    |
+                            MACB_BIT(ISR_ROVR) |
+                            MACB_BIT(HRESP));
+
+       /* schedule a link state check */
+       phy_start(lp->phy_dev);
+
        netif_start_queue(dev);
+
        return 0;
 }
 
-/*
- * Close the interface
- */
+/* Close the interface */
 static int at91ether_close(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned long ctl;
+       struct macb *lp = netdev_priv(dev);
+       u32 ctl;
 
        /* Disable Receiver and Transmitter */
-       ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-       at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~(AT91_EMAC_TE | AT91_EMAC_RE));
-
-       /* Disable PHY interrupt */
-       disable_phyirq(dev);
+       ctl = macb_readl(lp, NCR);
+       macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE)));
 
        /* Disable MAC interrupts */
-       at91_emac_write(lp, AT91_EMAC_IDR, AT91_EMAC_RCOM | AT91_EMAC_RBNA
-                               | AT91_EMAC_TUND | AT91_EMAC_RTRY | AT91_EMAC_TCOM
-                               | AT91_EMAC_ROVR | AT91_EMAC_ABT);
+       macb_writel(lp, IDR, MACB_BIT(RCOMP)    |
+                            MACB_BIT(RXUBR)    |
+                            MACB_BIT(ISR_TUND) |
+                            MACB_BIT(ISR_RLE)  |
+                            MACB_BIT(TCOMP)    |
+                            MACB_BIT(ISR_ROVR) |
+                            MACB_BIT(HRESP));
 
        netif_stop_queue(dev);
 
-       clk_disable(lp->ether_clk);             /* Disable Peripheral clock */
+       dma_free_coherent(&lp->pdev->dev,
+                               MAX_RX_DESCR * sizeof(struct macb_dma_desc),
+                               lp->rx_ring, lp->rx_ring_dma);
+       lp->rx_ring = NULL;
+
+       dma_free_coherent(&lp->pdev->dev,
+                               MAX_RX_DESCR * MAX_RBUFF_SZ,
+                               lp->rx_buffers, lp->rx_buffers_dma);
+       lp->rx_buffers = NULL;
 
        return 0;
 }
 
-/*
- * Transmit packet.
- */
+/* Transmit packet */
 static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
 
-       if (at91_emac_read(lp, AT91_EMAC_TSR) & AT91_EMAC_TSR_BNQ) {
+       if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) {
                netif_stop_queue(dev);
 
                /* Store packet information (to free when Tx completed) */
                lp->skb = skb;
                lp->skb_length = skb->len;
-               lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, DMA_TO_DEVICE);
-               dev->stats.tx_bytes += skb->len;
+               lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len,
+                                                       DMA_TO_DEVICE);
 
                /* Set address of the data in the Transmit Address register */
-               at91_emac_write(lp, AT91_EMAC_TAR, lp->skb_physaddr);
+               macb_writel(lp, TAR, lp->skb_physaddr);
                /* Set length of the packet in the Transmit Control register */
-               at91_emac_write(lp, AT91_EMAC_TCR, skb->len);
+               macb_writel(lp, TCR, skb->len);
 
        } else {
-               printk(KERN_ERR "at91_ether.c: at91ether_start_xmit() called, but device is busy!\n");
-               return NETDEV_TX_BUSY;  /* if we return anything but zero, dev.c:1055 calls kfree_skb(skb)
-                               on this skb, he also reports -ENETDOWN and printk's, so either
-                               we free and return(0) or don't free and return 1 */
+               netdev_err(dev, "%s called, but device is busy!\n", __func__);
+               return NETDEV_TX_BUSY;
        }
 
        return NETDEV_TX_OK;
 }
 
-/*
- * Update the current statistics from the internal statistics registers.
- */
-static struct net_device_stats *at91ether_stats(struct net_device *dev)
-{
-       struct at91_private *lp = netdev_priv(dev);
-       int ale, lenerr, seqe, lcol, ecol;
-
-       if (netif_running(dev)) {
-               dev->stats.rx_packets += at91_emac_read(lp, AT91_EMAC_OK);      /* Good frames received */
-               ale = at91_emac_read(lp, AT91_EMAC_ALE);
-               dev->stats.rx_frame_errors += ale;                              /* Alignment errors */
-               lenerr = at91_emac_read(lp, AT91_EMAC_ELR) + at91_emac_read(lp, AT91_EMAC_USF);
-               dev->stats.rx_length_errors += lenerr;                          /* Excessive Length or Undersize Frame error */
-               seqe = at91_emac_read(lp, AT91_EMAC_SEQE);
-               dev->stats.rx_crc_errors += seqe;                               /* CRC error */
-               dev->stats.rx_fifo_errors += at91_emac_read(lp, AT91_EMAC_DRFC);/* Receive buffer not available */
-               dev->stats.rx_errors += (ale + lenerr + seqe
-                       + at91_emac_read(lp, AT91_EMAC_CDE) + at91_emac_read(lp, AT91_EMAC_RJB));
-
-               dev->stats.tx_packets += at91_emac_read(lp, AT91_EMAC_FRA);     /* Frames successfully transmitted */
-               dev->stats.tx_fifo_errors += at91_emac_read(lp, AT91_EMAC_TUE); /* Transmit FIFO underruns */
-               dev->stats.tx_carrier_errors += at91_emac_read(lp, AT91_EMAC_CSE);      /* Carrier Sense errors */
-               dev->stats.tx_heartbeat_errors += at91_emac_read(lp, AT91_EMAC_SQEE);/* Heartbeat error */
-
-               lcol = at91_emac_read(lp, AT91_EMAC_LCOL);
-               ecol = at91_emac_read(lp, AT91_EMAC_ECOL);
-               dev->stats.tx_window_errors += lcol;                    /* Late collisions */
-               dev->stats.tx_aborted_errors += ecol;                   /* 16 collisions */
-
-               dev->stats.collisions += (at91_emac_read(lp, AT91_EMAC_SCOL) + at91_emac_read(lp, AT91_EMAC_MCOL) + lcol + ecol);
-       }
-       return &dev->stats;
-}
-
-/*
- * Extract received frame from buffer descriptors and sent to upper layers.
+/* Extract received frame from buffer descriptors and sent to upper layers.
  * (Called from interrupt context)
  */
 static void at91ether_rx(struct net_device *dev)
 {
-       struct at91_private *lp = netdev_priv(dev);
-       struct recv_desc_bufs *dlist;
+       struct macb *lp = netdev_priv(dev);
        unsigned char *p_recv;
        struct sk_buff *skb;
        unsigned int pktlen;
 
-       dlist = lp->dlist;
-       while (dlist->descriptors[lp->rxBuffIndex].addr & EMAC_DESC_DONE) {
-               p_recv = dlist->recv_buf[lp->rxBuffIndex];
-               pktlen = dlist->descriptors[lp->rxBuffIndex].size & 0x7ff;      /* Length of frame including FCS */
+       while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) {
+               p_recv = lp->rx_buffers + lp->rx_tail * MAX_RBUFF_SZ;
+               pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl);
                skb = netdev_alloc_skb(dev, pktlen + 2);
-               if (skb != NULL) {
+               if (skb) {
                        skb_reserve(skb, 2);
                        memcpy(skb_put(skb, pktlen), p_recv, pktlen);
 
                        skb->protocol = eth_type_trans(skb, dev);
-                       dev->stats.rx_bytes += pktlen;
+                       lp->stats.rx_packets++;
+                       lp->stats.rx_bytes += pktlen;
                        netif_rx(skb);
+               } else {
+                       lp->stats.rx_dropped++;
+                       netdev_notice(dev, "Memory squeeze, dropping packet.\n");
                }
-               else {
-                       dev->stats.rx_dropped += 1;
-                       printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", dev->name);
-               }
 
-               if (dlist->descriptors[lp->rxBuffIndex].size & EMAC_MULTICAST)
-                       dev->stats.multicast++;
+               if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH))
+                       lp->stats.multicast++;
+
+               /* reset ownership bit */
+               lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED);
 
-               dlist->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE;    /* reset ownership bit */
-               if (lp->rxBuffIndex == MAX_RX_DESCR-1)                          /* wrap after last buffer */
-                       lp->rxBuffIndex = 0;
+               /* wrap after last buffer */
+               if (lp->rx_tail == MAX_RX_DESCR - 1)
+                       lp->rx_tail = 0;
                else
-                       lp->rxBuffIndex++;
+                       lp->rx_tail++;
        }
 }
 
-/*
- * MAC interrupt handler
- */
+/* MAC interrupt handler */
 static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
 {
-       struct net_device *dev = (struct net_device *) dev_id;
-       struct at91_private *lp = netdev_priv(dev);
-       unsigned long intstatus, ctl;
+       struct net_device *dev = dev_id;
+       struct macb *lp = netdev_priv(dev);
+       u32 intstatus, ctl;
 
        /* MAC Interrupt Status register indicates what interrupts are pending.
-          It is automatically cleared once read. */
-       intstatus = at91_emac_read(lp, AT91_EMAC_ISR);
+        * It is automatically cleared once read.
+        */
+       intstatus = macb_readl(lp, ISR);
 
-       if (intstatus & AT91_EMAC_RCOM)         /* Receive complete */
+       /* Receive complete */
+       if (intstatus & MACB_BIT(RCOMP))
                at91ether_rx(dev);
 
-       if (intstatus & AT91_EMAC_TCOM) {       /* Transmit complete */
-               /* The TCOM bit is set even if the transmission failed. */
-               if (intstatus & (AT91_EMAC_TUND | AT91_EMAC_RTRY))
-                       dev->stats.tx_errors += 1;
+       /* Transmit complete */
+       if (intstatus & MACB_BIT(TCOMP)) {
+               /* The TCOM bit is set even if the transmission failed */
+               if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE)))
+                       lp->stats.tx_errors++;
 
                if (lp->skb) {
                        dev_kfree_skb_irq(lp->skb);
                        lp->skb = NULL;
                        dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE);
+                       lp->stats.tx_packets++;
+                       lp->stats.tx_bytes += lp->skb_length;
                }
                netif_wake_queue(dev);
        }
 
-       /* Work-around for Errata #11 */
-       if (intstatus & AT91_EMAC_RBNA) {
-               ctl = at91_emac_read(lp, AT91_EMAC_CTL);
-               at91_emac_write(lp, AT91_EMAC_CTL, ctl & ~AT91_EMAC_RE);
-               at91_emac_write(lp, AT91_EMAC_CTL, ctl | AT91_EMAC_RE);
+       /* Work-around for EMAC Errata section 41.3.1 */
+       if (intstatus & MACB_BIT(RXUBR)) {
+               ctl = macb_readl(lp, NCR);
+               macb_writel(lp, NCR, ctl & ~MACB_BIT(RE));
+               macb_writel(lp, NCR, ctl | MACB_BIT(RE));
        }
 
-       if (intstatus & AT91_EMAC_ROVR)
-               printk("%s: ROVR error\n", dev->name);
+       if (intstatus & MACB_BIT(ISR_ROVR))
+               netdev_err(dev, "ROVR error\n");
 
        return IRQ_HANDLED;
 }
@@ -1000,10 +286,10 @@ static const struct net_device_ops at91ether_netdev_ops = {
        .ndo_open               = at91ether_open,
        .ndo_stop               = at91ether_close,
        .ndo_start_xmit         = at91ether_start_xmit,
-       .ndo_get_stats          = at91ether_stats,
-       .ndo_set_rx_mode        = at91ether_set_multicast_list,
-       .ndo_set_mac_address    = set_mac_address,
-       .ndo_do_ioctl           = at91ether_ioctl,
+       .ndo_get_stats          = macb_get_stats,
+       .ndo_set_rx_mode        = macb_set_rx_mode,
+       .ndo_set_mac_address    = eth_mac_addr,
+       .ndo_do_ioctl           = macb_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1011,237 +297,195 @@ static const struct net_device_ops at91ether_netdev_ops = {
 #endif
 };
 
-/*
- * Detect the PHY type, and its address.
- */
-static int __init at91ether_phy_detect(struct at91_private *lp)
+#if defined(CONFIG_OF)
+static const struct of_device_id at91ether_dt_ids[] = {
+       { .compatible = "cdns,at91rm9200-emac" },
+       { .compatible = "cdns,emac" },
+       { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, at91ether_dt_ids);
+
+static int at91ether_get_phy_mode_dt(struct platform_device *pdev)
 {
-       unsigned int phyid1, phyid2;
-       unsigned long phy_id;
-       unsigned short phy_address = 0;
-
-       while (phy_address < PHY_MAX_ADDR) {
-               /* Read the PHY ID registers */
-               enable_mdi(lp);
-               read_phy(lp, phy_address, MII_PHYSID1, &phyid1);
-               read_phy(lp, phy_address, MII_PHYSID2, &phyid2);
-               disable_mdi(lp);
-
-               phy_id = (phyid1 << 16) | (phyid2 & 0xfff0);
-               switch (phy_id) {
-                       case MII_DM9161_ID:             /* Davicom 9161: PHY_ID1 = 0x181, PHY_ID2 = B881 */
-                       case MII_DM9161A_ID:            /* Davicom 9161A: PHY_ID1 = 0x181, PHY_ID2 = B8A0 */
-                       case MII_LXT971A_ID:            /* Intel LXT971A: PHY_ID1 = 0x13, PHY_ID2 = 78E0 */
-                       case MII_RTL8201_ID:            /* Realtek RTL8201: PHY_ID1 = 0, PHY_ID2 = 0x8201 */
-                       case MII_BCM5221_ID:            /* Broadcom BCM5221: PHY_ID1 = 0x40, PHY_ID2 = 0x61e0 */
-                       case MII_DP83847_ID:            /* National Semiconductor DP83847:  */
-                       case MII_DP83848_ID:            /* National Semiconductor DP83848:  */
-                       case MII_AC101L_ID:             /* Altima AC101L: PHY_ID1 = 0x22, PHY_ID2 = 0x5520 */
-                       case MII_KS8721_ID:             /* Micrel KS8721: PHY_ID1 = 0x22, PHY_ID2 = 0x1610 */
-                       case MII_T78Q21x3_ID:           /* Teridian 78Q21x3: PHY_ID1 = 0x0E, PHY_ID2 = 7237 */
-                       case MII_LAN83C185_ID:          /* SMSC LAN83C185: PHY_ID1 = 0x0007, PHY_ID2 = 0xC0A1 */
-                               /* store detected values */
-                               lp->phy_type = phy_id;          /* Type of PHY connected */
-                               lp->phy_address = phy_address;  /* MDI address of PHY */
-                               return 1;
-               }
+       struct device_node *np = pdev->dev.of_node;
 
-               phy_address++;
-       }
+       if (np)
+               return of_get_phy_mode(np);
 
-       return 0;               /* not detected */
+       return -ENODEV;
 }
 
+static int at91ether_get_hwaddr_dt(struct macb *bp)
+{
+       struct device_node *np = bp->pdev->dev.of_node;
 
-/*
- * Detect MAC & PHY and perform ethernet interface initialization
- */
+       if (np) {
+               const char *mac = of_get_mac_address(np);
+               if (mac) {
+                       memcpy(bp->dev->dev_addr, mac, ETH_ALEN);
+                       return 0;
+               }
+       }
+
+       return -ENODEV;
+}
+#else
+static int at91ether_get_phy_mode_dt(struct platform_device *pdev)
+{
+       return -ENODEV;
+}
+static int at91ether_get_hwaddr_dt(struct macb *bp)
+{
+       return -ENODEV;
+}
+#endif
+
+/* Detect MAC & PHY and perform ethernet interface initialization */
 static int __init at91ether_probe(struct platform_device *pdev)
 {
        struct macb_platform_data *board_data = pdev->dev.platform_data;
        struct resource *regs;
        struct net_device *dev;
-       struct at91_private *lp;
+       struct phy_device *phydev;
+       struct pinctrl *pinctrl;
+       struct macb *lp;
        int res;
+       u32 reg;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs)
                return -ENOENT;
 
-       dev = alloc_etherdev(sizeof(struct at91_private));
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl)) {
+               res = PTR_ERR(pinctrl);
+               if (res == -EPROBE_DEFER)
+                       return res;
+
+               dev_warn(&pdev->dev, "No pinctrl provided\n");
+       }
+
+       dev = alloc_etherdev(sizeof(struct macb));
        if (!dev)
                return -ENOMEM;
 
        lp = netdev_priv(dev);
-       lp->board_data = *board_data;
+       lp->pdev = pdev;
+       lp->dev = dev;
        spin_lock_init(&lp->lock);
 
-       dev->base_addr = regs->start;           /* physical base address */
-       lp->emac_base = ioremap(regs->start, regs->end - regs->start + 1);
-       if (!lp->emac_base) {
+       /* physical base address */
+       dev->base_addr = regs->start;
+       lp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs));
+       if (!lp->regs) {
                res = -ENOMEM;
                goto err_free_dev;
        }
 
        /* Clock */
-       lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
-       if (IS_ERR(lp->ether_clk)) {
-               res = PTR_ERR(lp->ether_clk);
-               goto err_ioumap;
+       lp->pclk = devm_clk_get(&pdev->dev, "ether_clk");
+       if (IS_ERR(lp->pclk)) {
+               res = PTR_ERR(lp->pclk);
+               goto err_free_dev;
        }
-       clk_enable(lp->ether_clk);
+       clk_enable(lp->pclk);
 
        /* Install the interrupt handler */
        dev->irq = platform_get_irq(pdev, 0);
-       if (request_irq(dev->irq, at91ether_interrupt, 0, dev->name, dev)) {
-               res = -EBUSY;
+       res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev);
+       if (res)
                goto err_disable_clock;
-       }
-
-       /* Allocate memory for DMA Receive descriptors */
-       lp->dlist = (struct recv_desc_bufs *) dma_alloc_coherent(NULL, sizeof(struct recv_desc_bufs), (dma_addr_t *) &lp->dlist_phys, GFP_KERNEL);
-       if (lp->dlist == NULL) {
-               res = -ENOMEM;
-               goto err_free_irq;
-       }
 
        ether_setup(dev);
        dev->netdev_ops = &at91ether_netdev_ops;
-       dev->ethtool_ops = &at91ether_ethtool_ops;
+       dev->ethtool_ops = &macb_ethtool_ops;
        platform_set_drvdata(pdev, dev);
        SET_NETDEV_DEV(dev, &pdev->dev);
 
-       get_mac_address(dev);           /* Get ethernet address and store it in dev->dev_addr */
-       update_mac_address(dev);        /* Program ethernet address into MAC */
-
-       at91_emac_write(lp, AT91_EMAC_CTL, 0);
+       res = at91ether_get_hwaddr_dt(lp);
+       if (res < 0)
+               macb_get_hwaddr(lp);
 
-       if (board_data->is_rmii)
-               at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG | AT91_EMAC_RMII);
-       else
-               at91_emac_write(lp, AT91_EMAC_CFG, AT91_EMAC_CLK_DIV32 | AT91_EMAC_BIG);
-
-       /* Detect PHY */
-       if (!at91ether_phy_detect(lp)) {
-               printk(KERN_ERR "at91_ether: Could not detect ethernet PHY\n");
-               res = -ENODEV;
-               goto err_free_dmamem;
+       res = at91ether_get_phy_mode_dt(pdev);
+       if (res < 0) {
+               if (board_data && board_data->is_rmii)
+                       lp->phy_interface = PHY_INTERFACE_MODE_RMII;
+               else
+                       lp->phy_interface = PHY_INTERFACE_MODE_MII;
+       } else {
+               lp->phy_interface = res;
        }
 
-       initialize_phy(lp);
+       macb_writel(lp, NCR, 0);
+
+       reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG);
+       if (lp->phy_interface == PHY_INTERFACE_MODE_RMII)
+               reg |= MACB_BIT(RM9200_RMII);
 
-       lp->mii.dev = dev;              /* Support for ethtool */
-       lp->mii.mdio_read = mdio_read;
-       lp->mii.mdio_write = mdio_write;
-       lp->mii.phy_id = lp->phy_address;
-       lp->mii.phy_id_mask = 0x1f;
-       lp->mii.reg_num_mask = 0x1f;
+       macb_writel(lp, NCFGR, reg);
 
        /* Register the network interface */
        res = register_netdev(dev);
        if (res)
-               goto err_free_dmamem;
-
-       /* Determine current link speed */
-       spin_lock_irq(&lp->lock);
-       enable_mdi(lp);
-       update_linkspeed(dev, 0);
-       disable_mdi(lp);
-       spin_unlock_irq(&lp->lock);
-       netif_carrier_off(dev);         /* will be enabled in open() */
-
-       /* If board has no PHY IRQ, use a timer to poll the PHY */
-       if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-               gpio_request(board_data->phy_irq_pin, "ethernet_phy");
-       } else {
-               /* If board has no PHY IRQ, use a timer to poll the PHY */
-               init_timer(&lp->check_timer);
-               lp->check_timer.data = (unsigned long)dev;
-               lp->check_timer.function = at91ether_check_link;
-       }
+               goto err_disable_clock;
+
+       if (macb_mii_init(lp) != 0)
+               goto err_out_unregister_netdev;
+
+       /* will be enabled in open() */
+       netif_carrier_off(dev);
+
+       phydev = lp->phy_dev;
+       netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+                               phydev->drv->name, dev_name(&phydev->dev),
+                               phydev->irq);
 
        /* Display ethernet banner */
-       printk(KERN_INFO "%s: AT91 ethernet at 0x%08x int=%d %s%s (%pM)\n",
-              dev->name, (uint) dev->base_addr, dev->irq,
-              at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_SPD ? "100-" : "10-",
-              at91_emac_read(lp, AT91_EMAC_CFG) & AT91_EMAC_FD ? "FullDuplex" : "HalfDuplex",
-              dev->dev_addr);
-       if ((lp->phy_type == MII_DM9161_ID) || (lp->phy_type == MII_DM9161A_ID))
-               printk(KERN_INFO "%s: Davicom 9161 PHY %s\n", dev->name, (lp->phy_media == PORT_FIBRE) ? "(Fiber)" : "(Copper)");
-       else if (lp->phy_type == MII_LXT971A_ID)
-               printk(KERN_INFO "%s: Intel LXT971A PHY\n", dev->name);
-       else if (lp->phy_type == MII_RTL8201_ID)
-               printk(KERN_INFO "%s: Realtek RTL8201(B)L PHY\n", dev->name);
-       else if (lp->phy_type == MII_BCM5221_ID)
-               printk(KERN_INFO "%s: Broadcom BCM5221 PHY\n", dev->name);
-       else if (lp->phy_type == MII_DP83847_ID)
-               printk(KERN_INFO "%s: National Semiconductor DP83847 PHY\n", dev->name);
-       else if (lp->phy_type == MII_DP83848_ID)
-               printk(KERN_INFO "%s: National Semiconductor DP83848 PHY\n", dev->name);
-       else if (lp->phy_type == MII_AC101L_ID)
-               printk(KERN_INFO "%s: Altima AC101L PHY\n", dev->name);
-       else if (lp->phy_type == MII_KS8721_ID)
-               printk(KERN_INFO "%s: Micrel KS8721 PHY\n", dev->name);
-       else if (lp->phy_type == MII_T78Q21x3_ID)
-               printk(KERN_INFO "%s: Teridian 78Q21x3 PHY\n", dev->name);
-       else if (lp->phy_type == MII_LAN83C185_ID)
-               printk(KERN_INFO "%s: SMSC LAN83C185 PHY\n", dev->name);
-
-       clk_disable(lp->ether_clk);                                     /* Disable Peripheral clock */
+       netdev_info(dev, "AT91 ethernet at 0x%08lx int=%d (%pM)\n",
+                               dev->base_addr, dev->irq, dev->dev_addr);
 
        return 0;
 
-
-err_free_dmamem:
-       platform_set_drvdata(pdev, NULL);
-       dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-err_free_irq:
-       free_irq(dev->irq, dev);
+err_out_unregister_netdev:
+       unregister_netdev(dev);
 err_disable_clock:
-       clk_disable(lp->ether_clk);
-       clk_put(lp->ether_clk);
-err_ioumap:
-       iounmap(lp->emac_base);
+       clk_disable(lp->pclk);
 err_free_dev:
        free_netdev(dev);
        return res;
 }
 
-static int __devexit at91ether_remove(struct platform_device *pdev)
+static int at91ether_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
-       struct at91_private *lp = netdev_priv(dev);
+       struct macb *lp = netdev_priv(dev);
 
-       if (gpio_is_valid(lp->board_data.phy_irq_pin))
-               gpio_free(lp->board_data.phy_irq_pin);
+       if (lp->phy_dev)
+               phy_disconnect(lp->phy_dev);
 
+       mdiobus_unregister(lp->mii_bus);
+       kfree(lp->mii_bus->irq);
+       mdiobus_free(lp->mii_bus);
        unregister_netdev(dev);
-       free_irq(dev->irq, dev);
-       dma_free_coherent(NULL, sizeof(struct recv_desc_bufs), lp->dlist, (dma_addr_t)lp->dlist_phys);
-       clk_put(lp->ether_clk);
-
-       platform_set_drvdata(pdev, NULL);
+       clk_disable(lp->pclk);
        free_netdev(dev);
+       platform_set_drvdata(pdev, NULL);
+
        return 0;
 }
 
 #ifdef CONFIG_PM
-
 static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 {
        struct net_device *net_dev = platform_get_drvdata(pdev);
-       struct at91_private *lp = netdev_priv(net_dev);
+       struct macb *lp = netdev_priv(net_dev);
 
        if (netif_running(net_dev)) {
-               if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-                       int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
-                       disable_irq(phy_irq);
-               }
-
                netif_stop_queue(net_dev);
                netif_device_detach(net_dev);
 
-               clk_disable(lp->ether_clk);
+               clk_disable(lp->pclk);
        }
        return 0;
 }
@@ -1249,34 +493,29 @@ static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg)
 static int at91ether_resume(struct platform_device *pdev)
 {
        struct net_device *net_dev = platform_get_drvdata(pdev);
-       struct at91_private *lp = netdev_priv(net_dev);
+       struct macb *lp = netdev_priv(net_dev);
 
        if (netif_running(net_dev)) {
-               clk_enable(lp->ether_clk);
+               clk_enable(lp->pclk);
 
                netif_device_attach(net_dev);
                netif_start_queue(net_dev);
-
-               if (gpio_is_valid(lp->board_data.phy_irq_pin)) {
-                       int phy_irq = gpio_to_irq(lp->board_data.phy_irq_pin);
-                       enable_irq(phy_irq);
-               }
        }
        return 0;
 }
-
 #else
 #define at91ether_suspend      NULL
 #define at91ether_resume       NULL
 #endif
 
 static struct platform_driver at91ether_driver = {
-       .remove         = __devexit_p(at91ether_remove),
+       .remove         = at91ether_remove,
        .suspend        = at91ether_suspend,
        .resume         = at91ether_resume,
        .driver         = {
-               .name   = DRV_NAME,
+               .name   = "at91_ether",
                .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(at91ether_dt_ids),
        },
 };
 
@@ -1296,4 +535,4 @@ module_exit(at91ether_exit)
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver");
 MODULE_AUTHOR("Andrew Victor");
-MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS("platform:at91_ether");
diff --git a/drivers/net/ethernet/cadence/at91_ether.h b/drivers/net/ethernet/cadence/at91_ether.h
deleted file mode 100644 (file)
index 0ef6328..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Ethernet driver for the Atmel AT91RM9200 (Thunder)
- *
- *  Copyright (C) SAN People (Pty) Ltd
- *
- * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc.
- * Initial version by Rick Bronson.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef AT91_ETHERNET
-#define AT91_ETHERNET
-
-
-/* Davicom 9161 PHY */
-#define MII_DM9161_ID          0x0181b880
-#define MII_DM9161A_ID         0x0181b8a0
-#define MII_DSCR_REG           16
-#define MII_DSCSR_REG          17
-#define MII_DSINTR_REG         21
-
-/* Intel LXT971A PHY */
-#define MII_LXT971A_ID         0x001378E0
-#define MII_ISINTE_REG         18
-#define MII_ISINTS_REG         19
-#define MII_LEDCTRL_REG                20
-
-/* Realtek RTL8201 PHY */
-#define MII_RTL8201_ID         0x00008200
-
-/* Broadcom BCM5221 PHY */
-#define MII_BCM5221_ID         0x004061e0
-#define MII_BCMINTR_REG                26
-
-/* National Semiconductor DP83847 */
-#define MII_DP83847_ID         0x20005c30
-
-/* National Semiconductor DP83848 */
-#define MII_DP83848_ID         0x20005c90
-#define MII_DPPHYSTS_REG       16
-#define MII_DPMICR_REG         17
-#define MII_DPMISR_REG         18
-
-/* Altima AC101L PHY */
-#define MII_AC101L_ID          0x00225520
-
-/* Micrel KS8721 PHY */
-#define MII_KS8721_ID          0x00221610
-
-/* Teridian 78Q2123/78Q2133 */
-#define MII_T78Q21x3_ID                0x000e7230
-#define MII_T78Q21INT_REG      17
-
-/* SMSC LAN83C185 */
-#define MII_LAN83C185_ID       0x0007C0A0
-
-/* ........................................................................ */
-
-#define MAX_RBUFF_SZ   0x600           /* 1518 rounded up */
-#define MAX_RX_DESCR   9               /* max number of receive buffers */
-
-#define EMAC_DESC_DONE 0x00000001      /* bit for if DMA is done */
-#define EMAC_DESC_WRAP 0x00000002      /* bit for wrap */
-
-#define EMAC_BROADCAST 0x80000000      /* broadcast address */
-#define EMAC_MULTICAST 0x40000000      /* multicast address */
-#define EMAC_UNICAST   0x20000000      /* unicast address */
-
-struct rbf_t
-{
-       unsigned int addr;
-       unsigned long size;
-};
-
-struct recv_desc_bufs
-{
-       struct rbf_t descriptors[MAX_RX_DESCR];         /* must be on sizeof (rbf_t) boundary */
-       char recv_buf[MAX_RX_DESCR][MAX_RBUFF_SZ];      /* must be on long boundary */
-};
-
-struct at91_private
-{
-       struct mii_if_info mii;                 /* ethtool support */
-       struct macb_platform_data board_data;   /* board-specific
-                                                * configuration (shared with
-                                                * macb for common data */
-       void __iomem *emac_base;                /* base register address */
-       struct clk *ether_clk;                  /* clock */
-
-       /* PHY */
-       unsigned long phy_type;                 /* type of PHY (PHY_ID) */
-       spinlock_t lock;                        /* lock for MDI interface */
-       short phy_media;                        /* media interface type */
-       unsigned short phy_address;             /* 5-bit MDI address of PHY (0..31) */
-       struct timer_list check_timer;          /* Poll link status */
-
-       /* Transmit */
-       struct sk_buff *skb;                    /* holds skb until xmit interrupt completes */
-       dma_addr_t skb_physaddr;                /* phys addr from pci_map_single */
-       int skb_length;                         /* saved skb length for pci_unmap_single */
-
-       /* Receive */
-       int rxBuffIndex;                        /* index into receive descriptor list */
-       struct recv_desc_bufs *dlist;           /* descriptor list address */
-       struct recv_desc_bufs *dlist_phys;      /* descriptor list physical address */
-};
-
-#endif
index 033064b7b576ad9199702d0a515331dda141fe41..a9b0830fb39d90b3227fe14741c8a4a3f09dc2d6 100644 (file)
 #include <linux/moduleparam.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/circ_buf.h>
 #include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_net.h>
+#include <linux/pinctrl/consumer.h>
 
 #include "macb.h"
 
 #define RX_BUFFER_SIZE         128
-#define RX_RING_SIZE           512
-#define RX_RING_BYTES          (sizeof(struct dma_desc) * RX_RING_SIZE)
+#define RX_RING_SIZE           512 /* must be power of 2 */
+#define RX_RING_BYTES          (sizeof(struct macb_dma_desc) * RX_RING_SIZE)
 
-/* Make the IP header word-aligned (the ethernet header is 14 bytes) */
-#define RX_OFFSET              2
+#define TX_RING_SIZE           128 /* must be power of 2 */
+#define TX_RING_BYTES          (sizeof(struct macb_dma_desc) * TX_RING_SIZE)
 
-#define TX_RING_SIZE           128
-#define DEF_TX_RING_PENDING    (TX_RING_SIZE - 1)
-#define TX_RING_BYTES          (sizeof(struct dma_desc) * TX_RING_SIZE)
+/* level of occupied TX descriptors under which we wake up TX process */
+#define MACB_TX_WAKEUP_THRESH  (3 * TX_RING_SIZE / 4)
 
-#define TX_RING_GAP(bp)                                                \
-       (TX_RING_SIZE - (bp)->tx_pending)
-#define TX_BUFFS_AVAIL(bp)                                     \
-       (((bp)->tx_tail <= (bp)->tx_head) ?                     \
-        (bp)->tx_tail + (bp)->tx_pending - (bp)->tx_head :     \
-        (bp)->tx_tail - (bp)->tx_head - TX_RING_GAP(bp))
-#define NEXT_TX(n)             (((n) + 1) & (TX_RING_SIZE - 1))
+#define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(RXUBR)      \
+                                | MACB_BIT(ISR_ROVR))
+#define MACB_TX_ERR_FLAGS      (MACB_BIT(ISR_TUND)                     \
+                                       | MACB_BIT(ISR_RLE)             \
+                                       | MACB_BIT(TXERR))
+#define MACB_TX_INT_FLAGS      (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP))
 
-#define NEXT_RX(n)             (((n) + 1) & (RX_RING_SIZE - 1))
+/*
+ * Graceful stop timeouts in us. We should allow up to
+ * 1 frame time (10 Mbits/s, full-duplex, ignoring collisions)
+ */
+#define MACB_HALT_TIMEOUT      1230
 
-/* minimum number of free TX descriptors before waking up TX process */
-#define MACB_TX_WAKEUP_THRESH  (TX_RING_SIZE / 4)
+/* Ring buffer accessors */
+static unsigned int macb_tx_ring_wrap(unsigned int index)
+{
+       return index & (TX_RING_SIZE - 1);
+}
 
-#define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(RXUBR)      \
-                                | MACB_BIT(ISR_ROVR))
+static struct macb_dma_desc *macb_tx_desc(struct macb *bp, unsigned int index)
+{
+       return &bp->tx_ring[macb_tx_ring_wrap(index)];
+}
 
-static void __macb_set_hwaddr(struct macb *bp)
+static struct macb_tx_skb *macb_tx_skb(struct macb *bp, unsigned int index)
+{
+       return &bp->tx_skb[macb_tx_ring_wrap(index)];
+}
+
+static dma_addr_t macb_tx_dma(struct macb *bp, unsigned int index)
+{
+       dma_addr_t offset;
+
+       offset = macb_tx_ring_wrap(index) * sizeof(struct macb_dma_desc);
+
+       return bp->tx_ring_dma + offset;
+}
+
+static unsigned int macb_rx_ring_wrap(unsigned int index)
+{
+       return index & (RX_RING_SIZE - 1);
+}
+
+static struct macb_dma_desc *macb_rx_desc(struct macb *bp, unsigned int index)
+{
+       return &bp->rx_ring[macb_rx_ring_wrap(index)];
+}
+
+static void *macb_rx_buffer(struct macb *bp, unsigned int index)
+{
+       return bp->rx_buffers + RX_BUFFER_SIZE * macb_rx_ring_wrap(index);
+}
+
+void macb_set_hwaddr(struct macb *bp)
 {
        u32 bottom;
        u16 top;
@@ -65,31 +104,58 @@ static void __macb_set_hwaddr(struct macb *bp)
        macb_or_gem_writel(bp, SA1B, bottom);
        top = cpu_to_le16(*((u16 *)(bp->dev->dev_addr + 4)));
        macb_or_gem_writel(bp, SA1T, top);
+
+       /* Clear unused address register sets */
+       macb_or_gem_writel(bp, SA2B, 0);
+       macb_or_gem_writel(bp, SA2T, 0);
+       macb_or_gem_writel(bp, SA3B, 0);
+       macb_or_gem_writel(bp, SA3T, 0);
+       macb_or_gem_writel(bp, SA4B, 0);
+       macb_or_gem_writel(bp, SA4T, 0);
 }
+EXPORT_SYMBOL_GPL(macb_set_hwaddr);
 
-static void __init macb_get_hwaddr(struct macb *bp)
+void macb_get_hwaddr(struct macb *bp)
 {
+       struct macb_platform_data *pdata;
        u32 bottom;
        u16 top;
        u8 addr[6];
+       int i;
 
-       bottom = macb_or_gem_readl(bp, SA1B);
-       top = macb_or_gem_readl(bp, SA1T);
+       pdata = bp->pdev->dev.platform_data;
 
-       addr[0] = bottom & 0xff;
-       addr[1] = (bottom >> 8) & 0xff;
-       addr[2] = (bottom >> 16) & 0xff;
-       addr[3] = (bottom >> 24) & 0xff;
-       addr[4] = top & 0xff;
-       addr[5] = (top >> 8) & 0xff;
+       /* Check all 4 address register for vaild address */
+       for (i = 0; i < 4; i++) {
+               bottom = macb_or_gem_readl(bp, SA1B + i * 8);
+               top = macb_or_gem_readl(bp, SA1T + i * 8);
+
+               if (pdata && pdata->rev_eth_addr) {
+                       addr[5] = bottom & 0xff;
+                       addr[4] = (bottom >> 8) & 0xff;
+                       addr[3] = (bottom >> 16) & 0xff;
+                       addr[2] = (bottom >> 24) & 0xff;
+                       addr[1] = top & 0xff;
+                       addr[0] = (top & 0xff00) >> 8;
+               } else {
+                       addr[0] = bottom & 0xff;
+                       addr[1] = (bottom >> 8) & 0xff;
+                       addr[2] = (bottom >> 16) & 0xff;
+                       addr[3] = (bottom >> 24) & 0xff;
+                       addr[4] = top & 0xff;
+                       addr[5] = (top >> 8) & 0xff;
+               }
 
-       if (is_valid_ether_addr(addr)) {
-               memcpy(bp->dev->dev_addr, addr, sizeof(addr));
-       } else {
-               netdev_info(bp->dev, "invalid hw address, using random\n");
-               eth_hw_addr_random(bp->dev);
+               if (is_valid_ether_addr(addr)) {
+                       memcpy(bp->dev->dev_addr, addr, sizeof(addr));
+                       return;
+               }
        }
+
+       netdev_info(bp->dev, "invalid hw address, using random\n");
+       eth_hw_addr_random(bp->dev);
 }
+EXPORT_SYMBOL_GPL(macb_get_hwaddr);
 
 static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
 {
@@ -152,13 +218,17 @@ static void macb_handle_link_change(struct net_device *dev)
 
                        reg = macb_readl(bp, NCFGR);
                        reg &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
+                       if (macb_is_gem(bp))
+                               reg &= ~GEM_BIT(GBE);
 
                        if (phydev->duplex)
                                reg |= MACB_BIT(FD);
                        if (phydev->speed == SPEED_100)
                                reg |= MACB_BIT(SPD);
+                       if (phydev->speed == SPEED_1000)
+                               reg |= GEM_BIT(GBE);
 
-                       macb_writel(bp, NCFGR, reg);
+                       macb_or_gem_writel(bp, NCFGR, reg);
 
                        bp->speed = phydev->speed;
                        bp->duplex = phydev->duplex;
@@ -196,7 +266,9 @@ static void macb_handle_link_change(struct net_device *dev)
 static int macb_mii_probe(struct net_device *dev)
 {
        struct macb *bp = netdev_priv(dev);
+       struct macb_platform_data *pdata;
        struct phy_device *phydev;
+       int phy_irq;
        int ret;
 
        phydev = phy_find_first(bp->mii_bus);
@@ -205,7 +277,14 @@ static int macb_mii_probe(struct net_device *dev)
                return -1;
        }
 
-       /* TODO : add pin_irq */
+       pdata = dev_get_platdata(&bp->pdev->dev);
+       if (pdata && gpio_is_valid(pdata->phy_irq_pin)) {
+               ret = devm_gpio_request(&bp->pdev->dev, pdata->phy_irq_pin, "phy int");
+               if (!ret) {
+                       phy_irq = gpio_to_irq(pdata->phy_irq_pin);
+                       phydev->irq = (phy_irq < 0) ? PHY_POLL : phy_irq;
+               }
+       }
 
        /* attach the mac to the phy */
        ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0,
@@ -216,7 +295,10 @@ static int macb_mii_probe(struct net_device *dev)
        }
 
        /* mask with MAC supported features */
-       phydev->supported &= PHY_BASIC_FEATURES;
+       if (macb_is_gem(bp))
+               phydev->supported &= PHY_GBIT_FEATURES;
+       else
+               phydev->supported &= PHY_BASIC_FEATURES;
 
        phydev->advertising = phydev->supported;
 
@@ -228,7 +310,7 @@ static int macb_mii_probe(struct net_device *dev)
        return 0;
 }
 
-static int macb_mii_init(struct macb *bp)
+int macb_mii_init(struct macb *bp)
 {
        struct macb_platform_data *pdata;
        int err = -ENXIO, i;
@@ -284,6 +366,7 @@ err_out_free_mdiobus:
 err_out:
        return err;
 }
+EXPORT_SYMBOL_GPL(macb_mii_init);
 
 static void macb_update_stats(struct macb *bp)
 {
@@ -297,93 +380,148 @@ static void macb_update_stats(struct macb *bp)
                *p += __raw_readl(reg);
 }
 
-static void macb_tx(struct macb *bp)
+static int macb_halt_tx(struct macb *bp)
 {
-       unsigned int tail;
-       unsigned int head;
-       u32 status;
+       unsigned long   halt_time, timeout;
+       u32             status;
 
-       status = macb_readl(bp, TSR);
-       macb_writel(bp, TSR, status);
+       macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(THALT));
 
-       netdev_dbg(bp->dev, "macb_tx status = %02lx\n", (unsigned long)status);
+       timeout = jiffies + usecs_to_jiffies(MACB_HALT_TIMEOUT);
+       do {
+               halt_time = jiffies;
+               status = macb_readl(bp, TSR);
+               if (!(status & MACB_BIT(TGO)))
+                       return 0;
 
-       if (status & (MACB_BIT(UND) | MACB_BIT(TSR_RLE))) {
-               int i;
-               netdev_err(bp->dev, "TX %s, resetting buffers\n",
-                          status & MACB_BIT(UND) ?
-                          "underrun" : "retry limit exceeded");
+               usleep_range(10, 250);
+       } while (time_before(halt_time, timeout));
 
-               /* Transfer ongoing, disable transmitter, to avoid confusion */
-               if (status & MACB_BIT(TGO))
-                       macb_writel(bp, NCR, macb_readl(bp, NCR) & ~MACB_BIT(TE));
+       return -ETIMEDOUT;
+}
 
-               head = bp->tx_head;
+static void macb_tx_error_task(struct work_struct *work)
+{
+       struct macb     *bp = container_of(work, struct macb, tx_error_task);
+       struct macb_tx_skb      *tx_skb;
+       struct sk_buff          *skb;
+       unsigned int            tail;
 
-               /*Mark all the buffer as used to avoid sending a lost buffer*/
-               for (i = 0; i < TX_RING_SIZE; i++)
-                       bp->tx_ring[i].ctrl = MACB_BIT(TX_USED);
+       netdev_vdbg(bp->dev, "macb_tx_error_task: t = %u, h = %u\n",
+                   bp->tx_tail, bp->tx_head);
 
-               /* Add wrap bit */
-               bp->tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
+       /* Make sure nobody is trying to queue up new packets */
+       netif_stop_queue(bp->dev);
 
-               /* free transmit buffer in upper layer*/
-               for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
-                       struct ring_info *rp = &bp->tx_skb[tail];
-                       struct sk_buff *skb = rp->skb;
+       /*
+        * Stop transmission now
+        * (in case we have just queued new packets)
+        */
+       if (macb_halt_tx(bp))
+               /* Just complain for now, reinitializing TX path can be good */
+               netdev_err(bp->dev, "BUG: halt tx timed out\n");
 
-                       BUG_ON(skb == NULL);
+       /* No need for the lock here as nobody will interrupt us anymore */
 
-                       rmb();
+       /*
+        * Treat frames in TX queue including the ones that caused the error.
+        * Free transmit buffers in upper layer.
+        */
+       for (tail = bp->tx_tail; tail != bp->tx_head; tail++) {
+               struct macb_dma_desc    *desc;
+               u32                     ctrl;
+
+               desc = macb_tx_desc(bp, tail);
+               ctrl = desc->ctrl;
+               tx_skb = macb_tx_skb(bp, tail);
+               skb = tx_skb->skb;
+
+               if (ctrl & MACB_BIT(TX_USED)) {
+                       netdev_vdbg(bp->dev, "txerr skb %u (data %p) TX complete\n",
+                                   macb_tx_ring_wrap(tail), skb->data);
+                       bp->stats.tx_packets++;
+                       bp->stats.tx_bytes += skb->len;
+               } else {
+                       /*
+                        * "Buffers exhausted mid-frame" errors may only happen
+                        * if the driver is buggy, so complain loudly about those.
+                        * Statistics are updated by hardware.
+                        */
+                       if (ctrl & MACB_BIT(TX_BUF_EXHAUSTED))
+                               netdev_err(bp->dev,
+                                          "BUG: TX buffers exhausted mid-frame\n");
 
-                       dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
-                                                        DMA_TO_DEVICE);
-                       rp->skb = NULL;
-                       dev_kfree_skb_irq(skb);
+                       desc->ctrl = ctrl | MACB_BIT(TX_USED);
                }
 
-               bp->tx_head = bp->tx_tail = 0;
-
-               /* Enable the transmitter again */
-               if (status & MACB_BIT(TGO))
-                       macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TE));
+               dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
+                                DMA_TO_DEVICE);
+               tx_skb->skb = NULL;
+               dev_kfree_skb(skb);
        }
 
-       if (!(status & MACB_BIT(COMP)))
-               /*
-                * This may happen when a buffer becomes complete
-                * between reading the ISR and scanning the
-                * descriptors.  Nothing to worry about.
-                */
-               return;
+       /* Make descriptor updates visible to hardware */
+       wmb();
+
+       /* Reinitialize the TX desc queue */
+       macb_writel(bp, TBQP, bp->tx_ring_dma);
+       /* Make TX ring reflect state of hardware */
+       bp->tx_head = bp->tx_tail = 0;
+
+       /* Now we are ready to start transmission again */
+       netif_wake_queue(bp->dev);
+
+       /* Housework before enabling TX IRQ */
+       macb_writel(bp, TSR, macb_readl(bp, TSR));
+       macb_writel(bp, IER, MACB_TX_INT_FLAGS);
+}
+
+static void macb_tx_interrupt(struct macb *bp)
+{
+       unsigned int tail;
+       unsigned int head;
+       u32 status;
+
+       status = macb_readl(bp, TSR);
+       macb_writel(bp, TSR, status);
+
+       netdev_vdbg(bp->dev, "macb_tx_interrupt status = 0x%03lx\n",
+               (unsigned long)status);
 
        head = bp->tx_head;
-       for (tail = bp->tx_tail; tail != head; tail = NEXT_TX(tail)) {
-               struct ring_info *rp = &bp->tx_skb[tail];
-               struct sk_buff *skb = rp->skb;
-               u32 bufstat;
+       for (tail = bp->tx_tail; tail != head; tail++) {
+               struct macb_tx_skb      *tx_skb;
+               struct sk_buff          *skb;
+               struct macb_dma_desc    *desc;
+               u32                     ctrl;
 
-               BUG_ON(skb == NULL);
+               desc = macb_tx_desc(bp, tail);
 
+               /* Make hw descriptor updates visible to CPU */
                rmb();
-               bufstat = bp->tx_ring[tail].ctrl;
 
-               if (!(bufstat & MACB_BIT(TX_USED)))
+               ctrl = desc->ctrl;
+
+               if (!(ctrl & MACB_BIT(TX_USED)))
                        break;
 
-               netdev_dbg(bp->dev, "skb %u (data %p) TX complete\n",
-                          tail, skb->data);
-               dma_unmap_single(&bp->pdev->dev, rp->mapping, skb->len,
+               tx_skb = macb_tx_skb(bp, tail);
+               skb = tx_skb->skb;
+
+               netdev_vdbg(bp->dev, "skb %u (data %p) TX complete\n",
+                       macb_tx_ring_wrap(tail), skb->data);
+               dma_unmap_single(&bp->pdev->dev, tx_skb->mapping, skb->len,
                                 DMA_TO_DEVICE);
                bp->stats.tx_packets++;
                bp->stats.tx_bytes += skb->len;
-               rp->skb = NULL;
+               tx_skb->skb = NULL;
                dev_kfree_skb_irq(skb);
        }
 
        bp->tx_tail = tail;
-       if (netif_queue_stopped(bp->dev) &&
-           TX_BUFFS_AVAIL(bp) > MACB_TX_WAKEUP_THRESH)
+       if (netif_queue_stopped(bp->dev)
+                       && CIRC_CNT(bp->tx_head, bp->tx_tail,
+                                   TX_RING_SIZE) <= MACB_TX_WAKEUP_THRESH)
                netif_wake_queue(bp->dev);
 }
 
@@ -392,31 +530,48 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
 {
        unsigned int len;
        unsigned int frag;
-       unsigned int offset = 0;
+       unsigned int offset;
        struct sk_buff *skb;
+       struct macb_dma_desc *desc;
 
-       len = MACB_BFEXT(RX_FRMLEN, bp->rx_ring[last_frag].ctrl);
+       desc = macb_rx_desc(bp, last_frag);
+       len = MACB_BFEXT(RX_FRMLEN, desc->ctrl);
 
-       netdev_dbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
-                  first_frag, last_frag, len);
+       netdev_vdbg(bp->dev, "macb_rx_frame frags %u - %u (len %u)\n",
+               macb_rx_ring_wrap(first_frag),
+               macb_rx_ring_wrap(last_frag), len);
 
-       skb = netdev_alloc_skb(bp->dev, len + RX_OFFSET);
+       /*
+        * The ethernet header starts NET_IP_ALIGN bytes into the
+        * first buffer. Since the header is 14 bytes, this makes the
+        * payload word-aligned.
+        *
+        * Instead of calling skb_reserve(NET_IP_ALIGN), we just copy
+        * the two padding bytes into the skb so that we avoid hitting
+        * the slowpath in memcpy(), and pull them off afterwards.
+        */
+       skb = netdev_alloc_skb(bp->dev, len + NET_IP_ALIGN);
        if (!skb) {
                bp->stats.rx_dropped++;
-               for (frag = first_frag; ; frag = NEXT_RX(frag)) {
-                       bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+               for (frag = first_frag; ; frag++) {
+                       desc = macb_rx_desc(bp, frag);
+                       desc->addr &= ~MACB_BIT(RX_USED);
                        if (frag == last_frag)
                                break;
                }
+
+               /* Make descriptor updates visible to hardware */
                wmb();
+
                return 1;
        }
 
-       skb_reserve(skb, RX_OFFSET);
+       offset = 0;
+       len += NET_IP_ALIGN;
        skb_checksum_none_assert(skb);
        skb_put(skb, len);
 
-       for (frag = first_frag; ; frag = NEXT_RX(frag)) {
+       for (frag = first_frag; ; frag++) {
                unsigned int frag_len = RX_BUFFER_SIZE;
 
                if (offset + frag_len > len) {
@@ -424,22 +579,24 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
                        frag_len = len - offset;
                }
                skb_copy_to_linear_data_offset(skb, offset,
-                                              (bp->rx_buffers +
-                                               (RX_BUFFER_SIZE * frag)),
-                                              frag_len);
+                               macb_rx_buffer(bp, frag), frag_len);
                offset += RX_BUFFER_SIZE;
-               bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
-               wmb();
+               desc = macb_rx_desc(bp, frag);
+               desc->addr &= ~MACB_BIT(RX_USED);
 
                if (frag == last_frag)
                        break;
        }
 
+       /* Make descriptor updates visible to hardware */
+       wmb();
+
+       __skb_pull(skb, NET_IP_ALIGN);
        skb->protocol = eth_type_trans(skb, bp->dev);
 
        bp->stats.rx_packets++;
-       bp->stats.rx_bytes += len;
-       netdev_dbg(bp->dev, "received skb of length %u, csum: %08x\n",
+       bp->stats.rx_bytes += skb->len;
+       netdev_vdbg(bp->dev, "received skb of length %u, csum: %08x\n",
                   skb->len, skb->csum);
        netif_receive_skb(skb);
 
@@ -452,8 +609,12 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
 {
        unsigned int frag;
 
-       for (frag = begin; frag != end; frag = NEXT_RX(frag))
-               bp->rx_ring[frag].addr &= ~MACB_BIT(RX_USED);
+       for (frag = begin; frag != end; frag++) {
+               struct macb_dma_desc *desc = macb_rx_desc(bp, frag);
+               desc->addr &= ~MACB_BIT(RX_USED);
+       }
+
+       /* Make descriptor updates visible to hardware */
        wmb();
 
        /*
@@ -466,15 +627,18 @@ static void discard_partial_frame(struct macb *bp, unsigned int begin,
 static int macb_rx(struct macb *bp, int budget)
 {
        int received = 0;
-       unsigned int tail = bp->rx_tail;
+       unsigned int tail;
        int first_frag = -1;
 
-       for (; budget > 0; tail = NEXT_RX(tail)) {
+       for (tail = bp->rx_tail; budget > 0; tail++) {
+               struct macb_dma_desc *desc = macb_rx_desc(bp, tail);
                u32 addr, ctrl;
 
+               /* Make hw descriptor updates visible to CPU */
                rmb();
-               addr = bp->rx_ring[tail].addr;
-               ctrl = bp->rx_ring[tail].ctrl;
+
+               addr = desc->addr;
+               ctrl = desc->ctrl;
 
                if (!(addr & MACB_BIT(RX_USED)))
                        break;
@@ -517,7 +681,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
 
        work_done = 0;
 
-       netdev_dbg(bp->dev, "poll: status = %08lx, budget = %d\n",
+       netdev_vdbg(bp->dev, "poll: status = %08lx, budget = %d\n",
                   (unsigned long)status, budget);
 
        work_done = macb_rx(bp, budget);
@@ -552,10 +716,12 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
        while (status) {
                /* close possible race with dev_close */
                if (unlikely(!netif_running(dev))) {
-                       macb_writel(bp, IDR, ~0UL);
+                       macb_writel(bp, IDR, -1);
                        break;
                }
 
+               netdev_vdbg(bp->dev, "isr = 0x%08lx\n", (unsigned long)status);
+
                if (status & MACB_RX_INT_FLAGS) {
                        /*
                         * There's no point taking any more interrupts
@@ -567,14 +733,19 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                        macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
 
                        if (napi_schedule_prep(&bp->napi)) {
-                               netdev_dbg(bp->dev, "scheduling RX softirq\n");
+                               netdev_vdbg(bp->dev, "scheduling RX softirq\n");
                                __napi_schedule(&bp->napi);
                        }
                }
 
-               if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND) |
-                           MACB_BIT(ISR_RLE)))
-                       macb_tx(bp);
+               if (unlikely(status & (MACB_TX_ERR_FLAGS))) {
+                       macb_writel(bp, IDR, MACB_TX_INT_FLAGS);
+                       schedule_work(&bp->tx_error_task);
+                       break;
+               }
+
+               if (status & MACB_BIT(TCOMP))
+                       macb_tx_interrupt(bp);
 
                /*
                 * Link change detection isn't possible with RMII, so we'll
@@ -626,11 +797,13 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct macb *bp = netdev_priv(dev);
        dma_addr_t mapping;
        unsigned int len, entry;
+       struct macb_dma_desc *desc;
+       struct macb_tx_skb *tx_skb;
        u32 ctrl;
        unsigned long flags;
 
-#ifdef DEBUG
-       netdev_dbg(bp->dev,
+#if defined(DEBUG) && defined(VERBOSE_DEBUG)
+       netdev_vdbg(bp->dev,
                   "start_xmit: len %u head %p data %p tail %p end %p\n",
                   skb->len, skb->head, skb->data,
                   skb_tail_pointer(skb), skb_end_pointer(skb));
@@ -642,7 +815,7 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        spin_lock_irqsave(&bp->lock, flags);
 
        /* This is a hard error, log it. */
-       if (TX_BUFFS_AVAIL(bp) < 1) {
+       if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1) {
                netif_stop_queue(dev);
                spin_unlock_irqrestore(&bp->lock, flags);
                netdev_err(bp->dev, "BUG! Tx Ring full when queue awake!\n");
@@ -651,13 +824,16 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       entry = bp->tx_head;
-       netdev_dbg(bp->dev, "Allocated ring entry %u\n", entry);
+       entry = macb_tx_ring_wrap(bp->tx_head);
+       bp->tx_head++;
+       netdev_vdbg(bp->dev, "Allocated ring entry %u\n", entry);
        mapping = dma_map_single(&bp->pdev->dev, skb->data,
                                 len, DMA_TO_DEVICE);
-       bp->tx_skb[entry].skb = skb;
-       bp->tx_skb[entry].mapping = mapping;
-       netdev_dbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
+
+       tx_skb = &bp->tx_skb[entry];
+       tx_skb->skb = skb;
+       tx_skb->mapping = mapping;
+       netdev_vdbg(bp->dev, "Mapped skb data %p to DMA addr %08lx\n",
                   skb->data, (unsigned long)mapping);
 
        ctrl = MACB_BF(TX_FRMLEN, len);
@@ -665,18 +841,18 @@ static int macb_start_xmit(struct sk_buff *skb, struct net_device *dev)
        if (entry == (TX_RING_SIZE - 1))
                ctrl |= MACB_BIT(TX_WRAP);
 
-       bp->tx_ring[entry].addr = mapping;
-       bp->tx_ring[entry].ctrl = ctrl;
-       wmb();
+       desc = &bp->tx_ring[entry];
+       desc->addr = mapping;
+       desc->ctrl = ctrl;
 
-       entry = NEXT_TX(entry);
-       bp->tx_head = entry;
+       /* Make newly initialized descriptor visible to hardware */
+       wmb();
 
        skb_tx_timestamp(skb);
 
        macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
 
-       if (TX_BUFFS_AVAIL(bp) < 1)
+       if (CIRC_SPACE(bp->tx_head, bp->tx_tail, TX_RING_SIZE) < 1)
                netif_stop_queue(dev);
 
        spin_unlock_irqrestore(&bp->lock, flags);
@@ -712,7 +888,7 @@ static int macb_alloc_consistent(struct macb *bp)
 {
        int size;
 
-       size = TX_RING_SIZE * sizeof(struct ring_info);
+       size = TX_RING_SIZE * sizeof(struct macb_tx_skb);
        bp->tx_skb = kmalloc(size, GFP_KERNEL);
        if (!bp->tx_skb)
                goto out_err;
@@ -775,9 +951,6 @@ static void macb_init_rings(struct macb *bp)
 
 static void macb_reset_hw(struct macb *bp)
 {
-       /* Make sure we have the write buffer for ourselves */
-       wmb();
-
        /*
         * Disable RX and TX (XXX: Should we halt the transmission
         * more gracefully?)
@@ -788,11 +961,11 @@ static void macb_reset_hw(struct macb *bp)
        macb_writel(bp, NCR, MACB_BIT(CLRSTAT));
 
        /* Clear all status flags */
-       macb_writel(bp, TSR, ~0UL);
-       macb_writel(bp, RSR, ~0UL);
+       macb_writel(bp, TSR, -1);
+       macb_writel(bp, RSR, -1);
 
        /* Disable all interrupts */
-       macb_writel(bp, IDR, ~0UL);
+       macb_writel(bp, IDR, -1);
        macb_readl(bp, ISR);
 }
 
@@ -860,8 +1033,12 @@ static u32 macb_dbw(struct macb *bp)
 }
 
 /*
- * Configure the receive DMA engine to use the correct receive buffer size.
- * This is a configurable parameter for GEM.
+ * Configure the receive DMA engine
+ * - use the correct receive buffer size
+ * - set the possibility to use INCR16 bursts
+ *   (if not supported by FIFO, it will fallback to default)
+ * - set both rx/tx packet buffers to full memory size
+ * These are configurable parameters for GEM.
  */
 static void macb_configure_dma(struct macb *bp)
 {
@@ -870,6 +1047,8 @@ static void macb_configure_dma(struct macb *bp)
        if (macb_is_gem(bp)) {
                dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
                dmacfg |= GEM_BF(RXBS, RX_BUFFER_SIZE / 64);
+               dmacfg |= GEM_BF(FBLDO, 16);
+               dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
                gem_writel(bp, DMACFG, dmacfg);
        }
 }
@@ -879,9 +1058,10 @@ static void macb_init_hw(struct macb *bp)
        u32 config;
 
        macb_reset_hw(bp);
-       __macb_set_hwaddr(bp);
+       macb_set_hwaddr(bp);
 
        config = macb_mdc_clk_div(bp);
+       config |= MACB_BF(RBOF, NET_IP_ALIGN);  /* Make eth data aligned */
        config |= MACB_BIT(PAE);                /* PAuse Enable */
        config |= MACB_BIT(DRFCS);              /* Discard Rx FCS */
        config |= MACB_BIT(BIG);                /* Receive oversized frames */
@@ -891,6 +1071,8 @@ static void macb_init_hw(struct macb *bp)
                config |= MACB_BIT(NBC);        /* No BroadCast */
        config |= macb_dbw(bp);
        macb_writel(bp, NCFGR, config);
+       bp->speed = SPEED_10;
+       bp->duplex = DUPLEX_HALF;
 
        macb_configure_dma(bp);
 
@@ -902,13 +1084,8 @@ static void macb_init_hw(struct macb *bp)
        macb_writel(bp, NCR, MACB_BIT(RE) | MACB_BIT(TE) | MACB_BIT(MPE));
 
        /* Enable interrupts */
-       macb_writel(bp, IER, (MACB_BIT(RCOMP)
-                             | MACB_BIT(RXUBR)
-                             | MACB_BIT(ISR_TUND)
-                             | MACB_BIT(ISR_RLE)
-                             | MACB_BIT(TXERR)
-                             | MACB_BIT(TCOMP)
-                             | MACB_BIT(ISR_ROVR)
+       macb_writel(bp, IER, (MACB_RX_INT_FLAGS
+                             | MACB_TX_INT_FLAGS
                              | MACB_BIT(HRESP)));
 
 }
@@ -996,7 +1173,7 @@ static void macb_sethashtable(struct net_device *dev)
 /*
  * Enable/Disable promiscuous and multicast modes.
  */
-static void macb_set_rx_mode(struct net_device *dev)
+void macb_set_rx_mode(struct net_device *dev)
 {
        unsigned long cfg;
        struct macb *bp = netdev_priv(dev);
@@ -1028,6 +1205,7 @@ static void macb_set_rx_mode(struct net_device *dev)
 
        macb_writel(bp, NCFGR, cfg);
 }
+EXPORT_SYMBOL_GPL(macb_set_rx_mode);
 
 static int macb_open(struct net_device *dev)
 {
@@ -1043,9 +1221,6 @@ static int macb_open(struct net_device *dev)
        if (!bp->phy_dev)
                return -EAGAIN;
 
-       if (!is_valid_ether_addr(dev->dev_addr))
-               return -EADDRNOTAVAIL;
-
        err = macb_alloc_consistent(bp);
        if (err) {
                netdev_err(dev, "Unable to allocate DMA memory (error %d)\n",
@@ -1135,7 +1310,7 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
        return nstat;
 }
 
-static struct net_device_stats *macb_get_stats(struct net_device *dev)
+struct net_device_stats *macb_get_stats(struct net_device *dev)
 {
        struct macb *bp = netdev_priv(dev);
        struct net_device_stats *nstat = &bp->stats;
@@ -1181,6 +1356,7 @@ static struct net_device_stats *macb_get_stats(struct net_device *dev)
 
        return nstat;
 }
+EXPORT_SYMBOL_GPL(macb_get_stats);
 
 static int macb_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
@@ -1204,25 +1380,55 @@ static int macb_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
        return phy_ethtool_sset(phydev, cmd);
 }
 
-static void macb_get_drvinfo(struct net_device *dev,
-                            struct ethtool_drvinfo *info)
+static int macb_get_regs_len(struct net_device *netdev)
+{
+       return MACB_GREGS_NBR * sizeof(u32);
+}
+
+static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs,
+                         void *p)
 {
        struct macb *bp = netdev_priv(dev);
+       unsigned int tail, head;
+       u32 *regs_buff = p;
+
+       regs->version = (macb_readl(bp, MID) & ((1 << MACB_REV_SIZE) - 1))
+                       | MACB_GREGS_VERSION;
+
+       tail = macb_tx_ring_wrap(bp->tx_tail);
+       head = macb_tx_ring_wrap(bp->tx_head);
+
+       regs_buff[0]  = macb_readl(bp, NCR);
+       regs_buff[1]  = macb_or_gem_readl(bp, NCFGR);
+       regs_buff[2]  = macb_readl(bp, NSR);
+       regs_buff[3]  = macb_readl(bp, TSR);
+       regs_buff[4]  = macb_readl(bp, RBQP);
+       regs_buff[5]  = macb_readl(bp, TBQP);
+       regs_buff[6]  = macb_readl(bp, RSR);
+       regs_buff[7]  = macb_readl(bp, IMR);
 
-       strcpy(info->driver, bp->pdev->dev.driver->name);
-       strcpy(info->version, "$Revision: 1.14 $");
-       strcpy(info->bus_info, dev_name(&bp->pdev->dev));
+       regs_buff[8]  = tail;
+       regs_buff[9]  = head;
+       regs_buff[10] = macb_tx_dma(bp, tail);
+       regs_buff[11] = macb_tx_dma(bp, head);
+
+       if (macb_is_gem(bp)) {
+               regs_buff[12] = gem_readl(bp, USRIO);
+               regs_buff[13] = gem_readl(bp, DMACFG);
+       }
 }
 
-static const struct ethtool_ops macb_ethtool_ops = {
+const struct ethtool_ops macb_ethtool_ops = {
        .get_settings           = macb_get_settings,
        .set_settings           = macb_set_settings,
-       .get_drvinfo            = macb_get_drvinfo,
+       .get_regs_len           = macb_get_regs_len,
+       .get_regs               = macb_get_regs,
        .get_link               = ethtool_op_get_link,
        .get_ts_info            = ethtool_op_get_ts_info,
 };
+EXPORT_SYMBOL_GPL(macb_ethtool_ops);
 
-static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
        struct macb *bp = netdev_priv(dev);
        struct phy_device *phydev = bp->phy_dev;
@@ -1235,6 +1441,7 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
        return phy_mii_ioctl(phydev, rq, cmd);
 }
+EXPORT_SYMBOL_GPL(macb_ioctl);
 
 static const struct net_device_ops macb_netdev_ops = {
        .ndo_open               = macb_open,
@@ -1263,7 +1470,7 @@ static const struct of_device_id macb_dt_ids[] = {
 
 MODULE_DEVICE_TABLE(of, macb_dt_ids);
 
-static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
+static int macb_get_phy_mode_dt(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
 
@@ -1273,7 +1480,7 @@ static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
        return -ENODEV;
 }
 
-static int __devinit macb_get_hwaddr_dt(struct macb *bp)
+static int macb_get_hwaddr_dt(struct macb *bp)
 {
        struct device_node *np = bp->pdev->dev.of_node;
        if (np) {
@@ -1287,11 +1494,11 @@ static int __devinit macb_get_hwaddr_dt(struct macb *bp)
        return -ENODEV;
 }
 #else
-static int __devinit macb_get_phy_mode_dt(struct platform_device *pdev)
+static int macb_get_phy_mode_dt(struct platform_device *pdev)
 {
        return -ENODEV;
 }
-static int __devinit macb_get_hwaddr_dt(struct macb *bp)
+static int macb_get_hwaddr_dt(struct macb *bp)
 {
        return -ENODEV;
 }
@@ -1306,6 +1513,7 @@ static int __init macb_probe(struct platform_device *pdev)
        struct phy_device *phydev;
        u32 config;
        int err = -ENXIO;
+       struct pinctrl *pinctrl;
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!regs) {
@@ -1313,6 +1521,15 @@ static int __init macb_probe(struct platform_device *pdev)
                goto err_out;
        }
 
+       pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+       if (IS_ERR(pinctrl)) {
+               err = PTR_ERR(pinctrl);
+               if (err == -EPROBE_DEFER)
+                       goto err_out;
+
+               dev_warn(&pdev->dev, "No pinctrl provided\n");
+       }
+
        err = -ENOMEM;
        dev = alloc_etherdev(sizeof(*bp));
        if (!dev)
@@ -1328,6 +1545,7 @@ static int __init macb_probe(struct platform_device *pdev)
        bp->dev = dev;
 
        spin_lock_init(&bp->lock);
+       INIT_WORK(&bp->tx_error_task, macb_tx_error_task);
 
        bp->pclk = clk_get(&pdev->dev, "pclk");
        if (IS_ERR(bp->pclk)) {
@@ -1384,7 +1602,9 @@ static int __init macb_probe(struct platform_device *pdev)
                bp->phy_interface = err;
        }
 
-       if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
+       if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
+               macb_or_gem_writel(bp, USRIO, GEM_BIT(RGMII));
+       else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII)
 #if defined(CONFIG_ARCH_AT91)
                macb_or_gem_writel(bp, USRIO, (MACB_BIT(RMII) |
                                               MACB_BIT(CLKEN)));
@@ -1398,8 +1618,6 @@ static int __init macb_probe(struct platform_device *pdev)
                macb_or_gem_writel(bp, USRIO, MACB_BIT(MII));
 #endif
 
-       bp->tx_pending = DEF_TX_RING_PENDING;
-
        err = register_netdev(dev);
        if (err) {
                dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
index 335e288f53140159e2f1956a716713b69c03933a..570908b935784204e6b85d7f44a81c5a499db409 100644 (file)
 #ifndef _MACB_H
 #define _MACB_H
 
+#define MACB_GREGS_NBR 16
+#define MACB_GREGS_VERSION 1
+
 /* MACB register offsets */
 #define MACB_NCR                               0x0000
 #define MACB_NCFGR                             0x0004
 #define MACB_NSR                               0x0008
+#define MACB_TAR                               0x000c /* AT91RM9200 only */
+#define MACB_TCR                               0x0010 /* AT91RM9200 only */
 #define MACB_TSR                               0x0014
 #define MACB_RBQP                              0x0018
 #define MACB_TBQP                              0x001c
 #define GEM_HRT                                        0x0084
 #define GEM_SA1B                               0x0088
 #define GEM_SA1T                               0x008C
+#define GEM_SA2B                               0x0090
+#define GEM_SA2T                               0x0094
+#define GEM_SA3B                               0x0098
+#define GEM_SA3T                               0x009C
+#define GEM_SA4B                               0x00A0
+#define GEM_SA4T                               0x00A4
 #define GEM_OTX                                        0x0100
 #define GEM_DCFG1                              0x0280
 #define GEM_DCFG2                              0x0284
 #define MACB_RTY_SIZE                          1
 #define MACB_PAE_OFFSET                                13
 #define MACB_PAE_SIZE                          1
+#define MACB_RM9200_RMII_OFFSET                        13 /* AT91RM9200 only */
+#define MACB_RM9200_RMII_SIZE                  1  /* AT91RM9200 only */
 #define MACB_RBOF_OFFSET                       14
 #define MACB_RBOF_SIZE                         2
 #define MACB_RLCE_OFFSET                       16
 #define MACB_IRXFCS_SIZE                       1
 
 /* GEM specific NCFGR bitfields. */
+#define GEM_GBE_OFFSET                         10
+#define GEM_GBE_SIZE                           1
 #define GEM_CLK_OFFSET                         18
 #define GEM_CLK_SIZE                           3
 #define GEM_DBW_OFFSET                         21
 #define GEM_DBW128                             2
 
 /* Bitfields in DMACFG. */
+#define GEM_FBLDO_OFFSET                       0
+#define GEM_FBLDO_SIZE                         5
+#define GEM_RXBMS_OFFSET                       8
+#define GEM_RXBMS_SIZE                         2
+#define GEM_TXPBMS_OFFSET                      10
+#define GEM_TXPBMS_SIZE                                1
+#define GEM_TXCOEN_OFFSET                      11
+#define GEM_TXCOEN_SIZE                                1
 #define GEM_RXBS_OFFSET                                16
 #define GEM_RXBS_SIZE                          8
+#define GEM_DDRP_OFFSET                                24
+#define GEM_DDRP_SIZE                          1
+
 
 /* Bitfields in NSR */
 #define MACB_NSR_LINK_OFFSET                   0
 #define MACB_TGO_SIZE                          1
 #define MACB_BEX_OFFSET                                4
 #define MACB_BEX_SIZE                          1
+#define MACB_RM9200_BNQ_OFFSET                 4 /* AT91RM9200 only */
+#define MACB_RM9200_BNQ_SIZE                   1 /* AT91RM9200 only */
 #define MACB_COMP_OFFSET                       5
 #define MACB_COMP_SIZE                         1
 #define MACB_UND_OFFSET                                6
 /* Bitfields in USRIO (AT91) */
 #define MACB_RMII_OFFSET                       0
 #define MACB_RMII_SIZE                         1
+#define GEM_RGMII_OFFSET                       0       /* GEM gigabit mode */
+#define GEM_RGMII_SIZE                         1
 #define MACB_CLKEN_OFFSET                      1
 #define MACB_CLKEN_SIZE                                1
 
                __v; \
        })
 
-struct dma_desc {
+/**
+ * struct macb_dma_desc - Hardware DMA descriptor
+ * @addr: DMA address of data buffer
+ * @ctrl: Control and status bits
+ */
+struct macb_dma_desc {
        u32     addr;
        u32     ctrl;
 };
@@ -417,7 +452,12 @@ struct dma_desc {
 #define MACB_TX_USED_OFFSET                    31
 #define MACB_TX_USED_SIZE                      1
 
-struct ring_info {
+/**
+ * struct macb_tx_skb - data about an skb which is being transmitted
+ * @skb: skb currently being transmitted
+ * @mapping: DMA address of the skb's data buffer
+ */
+struct macb_tx_skb {
        struct sk_buff          *skb;
        dma_addr_t              mapping;
 };
@@ -502,12 +542,12 @@ struct macb {
        void __iomem            *regs;
 
        unsigned int            rx_tail;
-       struct dma_desc         *rx_ring;
+       struct macb_dma_desc    *rx_ring;
        void                    *rx_buffers;
 
        unsigned int            tx_head, tx_tail;
-       struct dma_desc         *tx_ring;
-       struct ring_info        *tx_skb;
+       struct macb_dma_desc    *tx_ring;
+       struct macb_tx_skb      *tx_skb;
 
        spinlock_t              lock;
        struct platform_device  *pdev;
@@ -515,6 +555,7 @@ struct macb {
        struct clk              *hclk;
        struct net_device       *dev;
        struct napi_struct      napi;
+       struct work_struct      tx_error_task;
        struct net_device_stats stats;
        union {
                struct macb_stats       macb;
@@ -525,8 +566,6 @@ struct macb {
        dma_addr_t              tx_ring_dma;
        dma_addr_t              rx_buffers_dma;
 
-       unsigned int            rx_pending, tx_pending;
-
        struct mii_bus          *mii_bus;
        struct phy_device       *phy_dev;
        unsigned int            link;
@@ -534,8 +573,22 @@ struct macb {
        unsigned int            duplex;
 
        phy_interface_t         phy_interface;
+
+       /* AT91RM9200 transmit */
+       struct sk_buff *skb;                    /* holds skb until xmit interrupt completes */
+       dma_addr_t skb_physaddr;                /* phys addr from pci_map_single */
+       int skb_length;                         /* saved skb length for pci_unmap_single */
 };
 
+extern const struct ethtool_ops macb_ethtool_ops;
+
+int macb_mii_init(struct macb *bp);
+int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+struct net_device_stats *macb_get_stats(struct net_device *dev);
+void macb_set_rx_mode(struct net_device *dev);
+void macb_set_hwaddr(struct macb *bp);
+void macb_get_hwaddr(struct macb *bp);
+
 static inline bool macb_is_gem(struct macb *bp)
 {
        return MACB_BFEXT(IDNUM, macb_readl(bp, MID)) == 0x2;
index 16814b34d4b66ae8a39414a14e2bec0a72f89029..b407043ce9b0df3c1286fb3c0051f012cfa5e5b0 100644 (file)
 #define DMA_CONTROL_ST         0x00002000      /* Start/Stop Transmission */
 #define DMA_CONTROL_SR         0x00000002      /* Start/Stop Receive */
 #define DMA_CONTROL_DFF                0x01000000      /* Disable flush of rx frames */
+#define DMA_CONTROL_OSF                0x00000004      /* Operate on 2nd tx frame */
 
 /* DMA Normal interrupt */
 #define DMA_INTR_ENA_NIE       0x00010000      /* Normal Summary */
 #define DMA_INTR_ENA_TIE       0x00000001      /* Transmit Interrupt */
 
 #define DMA_INTR_NORMAL                (DMA_INTR_ENA_NIE | DMA_INTR_ENA_RIE | \
-                                DMA_INTR_ENA_TUE)
+                                DMA_INTR_ENA_TUE | DMA_INTR_ENA_TIE)
 
 #define DMA_INTR_ABNORMAL      (DMA_INTR_ENA_AIE | DMA_INTR_ENA_FBE | \
                                 DMA_INTR_ENA_RWE | DMA_INTR_ENA_RSE | \
@@ -373,6 +374,7 @@ struct xgmac_priv {
        struct sk_buff **tx_skbuff;
        unsigned int tx_head;
        unsigned int tx_tail;
+       int tx_irq_cnt;
 
        void __iomem *base;
        unsigned int dma_buf_sz;
@@ -663,6 +665,7 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
 {
        struct xgmac_dma_desc *p;
        dma_addr_t paddr;
+       int bufsz = priv->dev->mtu + ETH_HLEN + ETH_FCS_LEN;
 
        while (dma_ring_space(priv->rx_head, priv->rx_tail, DMA_RX_RING_SZ) > 1) {
                int entry = priv->rx_head;
@@ -671,13 +674,13 @@ static void xgmac_rx_refill(struct xgmac_priv *priv)
                p = priv->dma_rx + entry;
 
                if (priv->rx_skbuff[entry] == NULL) {
-                       skb = netdev_alloc_skb(priv->dev, priv->dma_buf_sz);
+                       skb = netdev_alloc_skb_ip_align(priv->dev, bufsz);
                        if (unlikely(skb == NULL))
                                break;
 
                        priv->rx_skbuff[entry] = skb;
                        paddr = dma_map_single(priv->device, skb->data,
-                                              priv->dma_buf_sz, DMA_FROM_DEVICE);
+                                              bufsz, DMA_FROM_DEVICE);
                        desc_set_buf_addr(p, paddr, priv->dma_buf_sz);
                }
 
@@ -701,10 +704,10 @@ static int xgmac_dma_desc_rings_init(struct net_device *dev)
        unsigned int bfsize;
 
        /* Set the Buffer size according to the MTU;
-        * indeed, in case of jumbo we need to bump-up the buffer sizes.
+        * The total buffer size including any IP offset must be a multiple
+        * of 8 bytes.
         */
-       bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN + 64,
-                      64);
+       bfsize = ALIGN(dev->mtu + ETH_HLEN + ETH_FCS_LEN + NET_IP_ALIGN, 8);
 
        netdev_dbg(priv->dev, "mtu [%d] bfsize [%d]\n", dev->mtu, bfsize);
 
@@ -845,9 +848,6 @@ static void xgmac_free_dma_desc_rings(struct xgmac_priv *priv)
 static void xgmac_tx_complete(struct xgmac_priv *priv)
 {
        int i;
-       void __iomem *ioaddr = priv->base;
-
-       writel(DMA_STATUS_TU | DMA_STATUS_NIS, ioaddr + XGMAC_DMA_STATUS);
 
        while (dma_ring_cnt(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ)) {
                unsigned int entry = priv->tx_tail;
@@ -888,7 +888,7 @@ static void xgmac_tx_complete(struct xgmac_priv *priv)
        }
 
        if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) >
-           TX_THRESH)
+           MAX_SKB_FRAGS)
                netif_wake_queue(priv->dev);
 }
 
@@ -965,8 +965,7 @@ static int xgmac_hw_init(struct net_device *dev)
                ctrl |= XGMAC_CONTROL_IPC;
        writel(ctrl, ioaddr + XGMAC_CONTROL);
 
-       value = DMA_CONTROL_DFF;
-       writel(value, ioaddr + XGMAC_DMA_CONTROL);
+       writel(DMA_CONTROL_OSF, ioaddr + XGMAC_DMA_CONTROL);
 
        /* Set the HW DMA mode and the COE */
        writel(XGMAC_OMR_TSF | XGMAC_OMR_RFD | XGMAC_OMR_RFA |
@@ -1060,19 +1059,15 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
        struct xgmac_priv *priv = netdev_priv(dev);
        unsigned int entry;
        int i;
+       u32 irq_flag;
        int nfrags = skb_shinfo(skb)->nr_frags;
        struct xgmac_dma_desc *desc, *first;
        unsigned int desc_flags;
        unsigned int len;
        dma_addr_t paddr;
 
-       if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
-           (nfrags + 1)) {
-               writel(DMA_INTR_DEFAULT_MASK | DMA_INTR_ENA_TIE,
-                       priv->base + XGMAC_DMA_INTR_ENA);
-               netif_stop_queue(dev);
-               return NETDEV_TX_BUSY;
-       }
+       priv->tx_irq_cnt = (priv->tx_irq_cnt + 1) & (DMA_TX_RING_SZ/4 - 1);
+       irq_flag = priv->tx_irq_cnt ? 0 : TXDESC_INTERRUPT;
 
        desc_flags = (skb->ip_summed == CHECKSUM_PARTIAL) ?
                TXDESC_CSUM_ALL : 0;
@@ -1113,9 +1108,9 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Interrupt on completition only for the latest segment */
        if (desc != first)
                desc_set_tx_owner(desc, desc_flags |
-                       TXDESC_LAST_SEG | TXDESC_INTERRUPT);
+                       TXDESC_LAST_SEG | irq_flag);
        else
-               desc_flags |= TXDESC_LAST_SEG | TXDESC_INTERRUPT;
+               desc_flags |= TXDESC_LAST_SEG | irq_flag;
 
        /* Set owner on first desc last to avoid race condition */
        wmb();
@@ -1124,6 +1119,9 @@ static netdev_tx_t xgmac_xmit(struct sk_buff *skb, struct net_device *dev)
        priv->tx_head = dma_ring_incr(entry, DMA_TX_RING_SZ);
 
        writel(1, priv->base + XGMAC_DMA_TX_POLL);
+       if (dma_ring_space(priv->tx_head, priv->tx_tail, DMA_TX_RING_SZ) <
+           MAX_SKB_FRAGS)
+               netif_stop_queue(dev);
 
        return NETDEV_TX_OK;
 }
@@ -1139,9 +1137,6 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
                struct sk_buff *skb;
                int frame_len;
 
-               writel(DMA_STATUS_RI | DMA_STATUS_NIS,
-                      priv->base + XGMAC_DMA_STATUS);
-
                entry = priv->rx_tail;
                p = priv->dma_rx + entry;
                if (desc_get_owner(p))
@@ -1180,8 +1175,6 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
 
        xgmac_rx_refill(priv);
 
-       writel(1, priv->base + XGMAC_DMA_RX_POLL);
-
        return count;
 }
 
@@ -1205,7 +1198,7 @@ static int xgmac_poll(struct napi_struct *napi, int budget)
 
        if (work_done < budget) {
                napi_complete(napi);
-               writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
+               __raw_writel(DMA_INTR_DEFAULT_MASK, priv->base + XGMAC_DMA_INTR_ENA);
        }
        return work_done;
 }
@@ -1350,7 +1343,7 @@ static irqreturn_t xgmac_pmt_interrupt(int irq, void *dev_id)
        struct xgmac_priv *priv = netdev_priv(dev);
        void __iomem *ioaddr = priv->base;
 
-       intr_status = readl(ioaddr + XGMAC_INT_STAT);
+       intr_status = __raw_readl(ioaddr + XGMAC_INT_STAT);
        if (intr_status & XGMAC_INT_STAT_PMT) {
                netdev_dbg(priv->dev, "received Magic frame\n");
                /* clear the PMT bits 5 and 6 by reading the PMT */
@@ -1368,9 +1361,9 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
        struct xgmac_extra_stats *x = &priv->xstats;
 
        /* read the status register (CSR5) */
-       intr_status = readl(priv->base + XGMAC_DMA_STATUS);
-       intr_status &= readl(priv->base + XGMAC_DMA_INTR_ENA);
-       writel(intr_status, priv->base + XGMAC_DMA_STATUS);
+       intr_status = __raw_readl(priv->base + XGMAC_DMA_STATUS);
+       intr_status &= __raw_readl(priv->base + XGMAC_DMA_INTR_ENA);
+       __raw_writel(intr_status, priv->base + XGMAC_DMA_STATUS);
 
        /* It displays the DMA process states (CSR5 register) */
        /* ABNORMAL interrupts */
@@ -1405,8 +1398,8 @@ static irqreturn_t xgmac_interrupt(int irq, void *dev_id)
        }
 
        /* TX/RX NORMAL interrupts */
-       if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU)) {
-               writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
+       if (intr_status & (DMA_STATUS_RI | DMA_STATUS_TU | DMA_STATUS_TI)) {
+               __raw_writel(DMA_INTR_ABNORMAL, priv->base + XGMAC_DMA_INTR_ENA);
                napi_schedule(&priv->napi);
        }
 
index 2de50f95798f266213b9c9a150145929f509fc16..d40c994a4f6a2c807965e44eaf81f2be0053fb50 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_CHELSIO
        bool "Chelsio devices"
        default y
-       depends on PCI || INET
+       depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 1d17c92f2dda175547ec107a599fa8f42b37ce5d..c8fdeaae56c0a70bbb28e147979738f5533e2fdb 100644 (file)
@@ -974,8 +974,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
 #endif
 };
 
-static int __devinit init_one(struct pci_dev *pdev,
-                             const struct pci_device_id *ent)
+static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int version_printed;
 
@@ -1332,7 +1331,7 @@ static inline void t1_sw_reset(struct pci_dev *pdev)
        pci_write_config_dword(pdev, A_PCICFG_PM_CSR, 0);
 }
 
-static void __devexit remove_one(struct pci_dev *pdev)
+static void remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct adapter *adapter = dev->ml_priv;
@@ -1361,7 +1360,7 @@ static struct pci_driver driver = {
        .name     = DRV_NAME,
        .id_table = t1_pci_tbl,
        .probe    = init_one,
-       .remove   = __devexit_p(remove_one),
+       .remove   = remove_one,
 };
 
 static int __init t1_init_module(void)
index 47a84359d4e44b65fa6536553215f714a2df47a5..d84872e8817131233c9f949615ec9b0492d1ebe8 100644 (file)
@@ -367,18 +367,6 @@ void t1_sched_set_drain_bits_per_us(struct sge *sge, unsigned int port,
 
 #endif  /*  0  */
 
-
-/*
- * get_clock() implements a ns clock (see ktime_get)
- */
-static inline ktime_t get_clock(void)
-{
-       struct timespec ts;
-
-       ktime_get_ts(&ts);
-       return timespec_to_ktime(ts);
-}
-
 /*
  * tx_sched_init() allocates resources and does basic initialization.
  */
@@ -411,7 +399,7 @@ static int tx_sched_init(struct sge *sge)
 static inline int sched_update_avail(struct sge *sge)
 {
        struct sched *s = sge->tx_sched;
-       ktime_t now = get_clock();
+       ktime_t now = ktime_get();
        unsigned int i;
        long long delta_time_ns;
 
@@ -2071,8 +2059,7 @@ static void espibug_workaround(unsigned long data)
 /*
  * Creates a t1_sge structure and returns suggested resource parameters.
  */
-struct sge * __devinit t1_sge_create(struct adapter *adapter,
-                                    struct sge_params *p)
+struct sge *t1_sge_create(struct adapter *adapter, struct sge_params *p)
 {
        struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL);
        int i;
index 8a43c7e1970190fcc95daf581e4f1cee9363f55e..e0a03a31e7c487489006aa57594d86cfb73e27b0 100644 (file)
@@ -892,8 +892,8 @@ static void power_sequence_xpak(adapter_t* adapter)
        }
 }
 
-int __devinit t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
-                              struct adapter_params *p)
+int t1_get_board_rev(adapter_t *adapter, const struct board_info *bi,
+                    struct adapter_params *p)
 {
        p->chip_version = bi->chip_term;
        p->is_asic = (p->chip_version != CHBT_TERM_FPGA);
@@ -992,7 +992,7 @@ out_err:
 /*
  * Determine a card's PCI mode.
  */
-static void __devinit get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
+static void get_pci_mode(adapter_t *adapter, struct chelsio_pci_params *p)
 {
        static const unsigned short speed_map[] = { 33, 66, 100, 133 };
        u32 pci_mode;
@@ -1028,8 +1028,8 @@ void t1_free_sw_modules(adapter_t *adapter)
                t1_espi_destroy(adapter->espi);
 }
 
-static void __devinit init_link_config(struct link_config *lc,
-                                      const struct board_info *bi)
+static void init_link_config(struct link_config *lc,
+                            const struct board_info *bi)
 {
        lc->supported = bi->caps;
        lc->requested_speed = lc->speed = SPEED_INVALID;
@@ -1049,8 +1049,7 @@ static void __devinit init_link_config(struct link_config *lc,
  * Allocate and initialize the data structures that hold the SW state of
  * the Terminator HW modules.
  */
-int __devinit t1_init_sw_modules(adapter_t *adapter,
-                                const struct board_info *bi)
+int t1_init_sw_modules(adapter_t *adapter, const struct board_info *bi)
 {
        unsigned int i;
 
index 8bed4a59e65f2a51a071c98cd94b7eb6e046a6e9..b146acabf982005db2ed2128540f8d99810f3d87 100644 (file)
@@ -55,7 +55,7 @@ void t1_tp_destroy(struct petp *tp)
        kfree(tp);
 }
 
-struct petp *__devinit t1_tp_create(adapter_t * adapter, struct tp_params *p)
+struct petp *t1_tp_create(adapter_t *adapter, struct tp_params *p)
 {
        struct petp *tp = kzalloc(sizeof(*tp), GFP_KERNEL);
 
index df01b63432415800e418b2df97e8462c85cbcfb8..8c82248ce41624156b2e429b6b716fae013e00bc 100644 (file)
 #include <linux/mdio.h>
 #include "version.h"
 
-#define CH_ERR(adap, fmt, ...)   dev_err(&adap->pdev->dev, fmt, ## __VA_ARGS__)
-#define CH_WARN(adap, fmt, ...)  dev_warn(&adap->pdev->dev, fmt, ## __VA_ARGS__)
-#define CH_ALERT(adap, fmt, ...) \
-       dev_printk(KERN_ALERT, &adap->pdev->dev, fmt, ## __VA_ARGS__)
+#define CH_ERR(adap, fmt, ...)   dev_err(&adap->pdev->dev, fmt, ##__VA_ARGS__)
+#define CH_WARN(adap, fmt, ...)  dev_warn(&adap->pdev->dev, fmt, ##__VA_ARGS__)
+#define CH_ALERT(adap, fmt, ...) dev_alert(&adap->pdev->dev, fmt, ##__VA_ARGS__)
 
 /*
  * More powerful macro that selectively prints messages based on msg_enable.
index 9c9f3260344a346175c149824c249cd3ebf72be1..f15ee326d5c19414563b30abbb66ba780fd59b00 100644 (file)
@@ -3078,7 +3078,7 @@ static void set_nqsets(struct adapter *adap)
        }
 }
 
-static int __devinit cxgb_enable_msix(struct adapter *adap)
+static int cxgb_enable_msix(struct adapter *adap)
 {
        struct msix_entry entries[SGE_QSETS + 1];
        int vectors;
@@ -3108,8 +3108,7 @@ static int __devinit cxgb_enable_msix(struct adapter *adap)
        return err;
 }
 
-static void __devinit print_port_info(struct adapter *adap,
-                                     const struct adapter_info *ai)
+static void print_port_info(struct adapter *adap, const struct adapter_info *ai)
 {
        static const char *pci_variant[] = {
                "PCI", "PCI-X", "PCI-X ECC", "PCI-X 266", "PCI Express"
@@ -3165,7 +3164,7 @@ static const struct net_device_ops cxgb_netdev_ops = {
 #endif
 };
 
-static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev)
+static void cxgb3_init_iscsi_mac(struct net_device *dev)
 {
        struct port_info *pi = netdev_priv(dev);
 
@@ -3176,8 +3175,7 @@ static void __devinit cxgb3_init_iscsi_mac(struct net_device *dev)
 #define TSO_FLAGS (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN)
 #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
                        NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
-static int __devinit init_one(struct pci_dev *pdev,
-                             const struct pci_device_id *ent)
+static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int version_printed;
 
@@ -3381,7 +3379,7 @@ out:
        return err;
 }
 
-static void __devexit remove_one(struct pci_dev *pdev)
+static void remove_one(struct pci_dev *pdev)
 {
        struct adapter *adapter = pci_get_drvdata(pdev);
 
@@ -3425,7 +3423,7 @@ static struct pci_driver driver = {
        .name = DRV_NAME,
        .id_table = cxgb3_pci_tbl,
        .probe = init_one,
-       .remove = __devexit_p(remove_one),
+       .remove = remove_one,
        .err_handler = &t3_err_handler,
 };
 
index 2dbbcbb450d30470b76e024835bdc00916af0d54..942dace361d229e061545c51340f9fb37d194dd7 100644 (file)
@@ -1382,7 +1382,7 @@ static inline int adap2type(struct adapter *adapter)
        return type;
 }
 
-void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
+void cxgb3_adapter_ofld(struct adapter *adapter)
 {
        struct t3cdev *tdev = &adapter->tdev;
 
@@ -1396,7 +1396,7 @@ void __devinit cxgb3_adapter_ofld(struct adapter *adapter)
        register_tdev(tdev);
 }
 
-void __devexit cxgb3_adapter_unofld(struct adapter *adapter)
+void cxgb3_adapter_unofld(struct adapter *adapter)
 {
        struct t3cdev *tdev = &adapter->tdev;
 
index a4da893ac1e15cfd02a2d071503afaa21838e51c..378988b5709a2262b98c0a790072be38b837cdf3 100644 (file)
@@ -251,6 +251,8 @@ struct adapter_params {
        unsigned char rev;                /* chip revision */
        unsigned char offload;
 
+       unsigned char bypass;
+
        unsigned int ofldq_wr_cred;
 };
 
@@ -642,6 +644,23 @@ extern int dbfifo_int_thresh;
 #define for_each_port(adapter, iter) \
        for (iter = 0; iter < (adapter)->params.nports; ++iter)
 
+static inline int is_bypass(struct adapter *adap)
+{
+       return adap->params.bypass;
+}
+
+static inline int is_bypass_device(int device)
+{
+       /* this should be set based upon device capabilities */
+       switch (device) {
+       case 0x440b:
+       case 0x440c:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
 static inline unsigned int core_ticks_per_usec(const struct adapter *adap)
 {
        return adap->params.vpd.cclk / 1000;
index 604f4f87f550c879a087fd128892d97450aa2d19..130dd9d5b493d6600a0e68194a1a4919a414151b 100644 (file)
@@ -2148,8 +2148,8 @@ static const struct file_operations mem_debugfs_fops = {
        .llseek  = default_llseek,
 };
 
-static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
-                                     unsigned int idx, unsigned int size_mb)
+static void add_debugfs_mem(struct adapter *adap, const char *name,
+                           unsigned int idx, unsigned int size_mb)
 {
        struct dentry *de;
 
@@ -2159,7 +2159,7 @@ static void __devinit add_debugfs_mem(struct adapter *adap, const char *name,
                de->d_inode->i_size = size_mb << 20;
 }
 
-static int __devinit setup_debugfs(struct adapter *adap)
+static int setup_debugfs(struct adapter *adap)
 {
        int i;
 
@@ -3415,16 +3415,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)
                         "mismatch: [fini] csum=%#x, computed csum=%#x\n",
                         finicsum, cfcsum);
 
-       /*
-        * If we're a pure NIC driver then disable all offloading facilities.
-        * This will allow the firmware to optimize aspects of the hardware
-        * configuration which will result in improved performance.
-        */
-       caps_cmd.ofldcaps = 0;
-       caps_cmd.iscsicaps = 0;
-       caps_cmd.rdmacaps = 0;
-       caps_cmd.fcoecaps = 0;
-
        /*
         * And now tell the firmware to use the configuration we just loaded.
         */
@@ -3513,18 +3503,6 @@ static int adap_init0_no_config(struct adapter *adapter, int reset)
        if (ret < 0)
                goto bye;
 
-#ifndef CONFIG_CHELSIO_T4_OFFLOAD
-       /*
-        * If we're a pure NIC driver then disable all offloading facilities.
-        * This will allow the firmware to optimize aspects of the hardware
-        * configuration which will result in improved performance.
-        */
-       caps_cmd.ofldcaps = 0;
-       caps_cmd.iscsicaps = 0;
-       caps_cmd.rdmacaps = 0;
-       caps_cmd.fcoecaps = 0;
-#endif
-
        if (caps_cmd.niccaps & htons(FW_CAPS_CONFIG_NIC_VM)) {
                if (!vf_acls)
                        caps_cmd.niccaps ^= htons(FW_CAPS_CONFIG_NIC_VM);
@@ -3745,6 +3723,7 @@ static int adap_init0(struct adapter *adap)
        u32 v, port_vec;
        enum dev_state state;
        u32 params[7], val[7];
+       struct fw_caps_config_cmd caps_cmd;
        int reset = 1, j;
 
        /*
@@ -3898,6 +3877,9 @@ static int adap_init0(struct adapter *adap)
                        goto bye;
        }
 
+       if (is_bypass_device(adap->pdev->device))
+               adap->params.bypass = 1;
+
        /*
         * Grab some of our basic fundamental operating parameters.
         */
@@ -3940,13 +3922,12 @@ static int adap_init0(struct adapter *adap)
                adap->tids.aftid_end = val[1];
        }
 
-#ifdef CONFIG_CHELSIO_T4_OFFLOAD
        /*
         * Get device capabilities so we can determine what resources we need
         * to manage.
         */
        memset(&caps_cmd, 0, sizeof(caps_cmd));
-       caps_cmd.op_to_write = htonl(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
+       caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
                                     FW_CMD_REQUEST | FW_CMD_READ);
        caps_cmd.retval_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd),
@@ -3991,15 +3972,6 @@ static int adap_init0(struct adapter *adap)
                adap->vres.ddp.size = val[4] - val[3] + 1;
                adap->params.ofldq_wr_cred = val[5];
 
-               params[0] = FW_PARAM_PFVF(ETHOFLD_START);
-               params[1] = FW_PARAM_PFVF(ETHOFLD_END);
-               ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 2,
-                                     params, val);
-               if ((val[0] != val[1]) && (ret >= 0)) {
-                       adap->tids.uotid_base = val[0];
-                       adap->tids.nuotids = val[1] - val[0] + 1;
-               }
-
                adap->params.offload = 1;
        }
        if (caps_cmd.rdmacaps) {
@@ -4048,7 +4020,6 @@ static int adap_init0(struct adapter *adap)
        }
 #undef FW_PARAM_PFVF
 #undef FW_PARAM_DEV
-#endif /* CONFIG_CHELSIO_T4_OFFLOAD */
 
        /*
         * These are finalized by FW initialization, load their values now.
@@ -4202,7 +4173,7 @@ static inline void init_rspq(struct sge_rspq *q, u8 timer_idx, u8 pkt_cnt_idx,
  * of ports we found and the number of available CPUs.  Most settings can be
  * modified by the admin prior to actual use.
  */
-static void __devinit cfg_queues(struct adapter *adap)
+static void cfg_queues(struct adapter *adap)
 {
        struct sge *s = &adap->sge;
        int i, q10g = 0, n10g = 0, qidx = 0;
@@ -4286,7 +4257,7 @@ static void __devinit cfg_queues(struct adapter *adap)
  * Reduce the number of Ethernet queues across all ports to at most n.
  * n provides at least one queue per port.
  */
-static void __devinit reduce_ethqs(struct adapter *adap, int n)
+static void reduce_ethqs(struct adapter *adap, int n)
 {
        int i;
        struct port_info *pi;
@@ -4313,7 +4284,7 @@ static void __devinit reduce_ethqs(struct adapter *adap, int n)
 /* 2 MSI-X vectors needed for the FW queue and non-data interrupts */
 #define EXTRA_VECS 2
 
-static int __devinit enable_msix(struct adapter *adap)
+static int enable_msix(struct adapter *adap)
 {
        int ofld_need = 0;
        int i, err, want, need;
@@ -4362,7 +4333,7 @@ static int __devinit enable_msix(struct adapter *adap)
 
 #undef EXTRA_VECS
 
-static int __devinit init_rss(struct adapter *adap)
+static int init_rss(struct adapter *adap)
 {
        unsigned int i, j;
 
@@ -4378,7 +4349,7 @@ static int __devinit init_rss(struct adapter *adap)
        return 0;
 }
 
-static void __devinit print_port_info(const struct net_device *dev)
+static void print_port_info(const struct net_device *dev)
 {
        static const char *base[] = {
                "R XFI", "R XAUI", "T SGMII", "T XFI", "T XAUI", "KX4", "CX4",
@@ -4415,7 +4386,7 @@ static void __devinit print_port_info(const struct net_device *dev)
                    adap->params.vpd.sn, adap->params.vpd.ec);
 }
 
-static void __devinit enable_pcie_relaxed_ordering(struct pci_dev *dev)
+static void enable_pcie_relaxed_ordering(struct pci_dev *dev)
 {
        pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_RELAX_EN);
 }
@@ -4448,8 +4419,7 @@ static void free_some_resources(struct adapter *adapter)
 #define VLAN_FEAT (NETIF_F_SG | NETIF_F_IP_CSUM | TSO_FLAGS | \
                   NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA)
 
-static int __devinit init_one(struct pci_dev *pdev,
-                             const struct pci_device_id *ent)
+static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int func, i, err;
        struct port_info *pi;
@@ -4669,7 +4639,7 @@ sriov:
        return err;
 }
 
-static void __devexit remove_one(struct pci_dev *pdev)
+static void remove_one(struct pci_dev *pdev)
 {
        struct adapter *adapter = pci_get_drvdata(pdev);
 
@@ -4709,7 +4679,7 @@ static struct pci_driver cxgb4_driver = {
        .name     = KBUILD_MODNAME,
        .id_table = cxgb4_pci_tbl,
        .probe    = init_one,
-       .remove   = __devexit_p(remove_one),
+       .remove   = remove_one,
        .err_handler = &cxgb4_eeh,
 };
 
index 1b899fea1a91427bac31b171cd799fad2fc384f0..39bec73ff87c5879a9b1f6ca9ad1425d4d78c9b2 100644 (file)
@@ -102,6 +102,9 @@ struct tid_info {
        unsigned int ftid_base;
        unsigned int aftid_base;
        unsigned int aftid_end;
+       /* Server filter region */
+       unsigned int sftid_base;
+       unsigned int nsftids;
 
        spinlock_t atid_lock ____cacheline_aligned_in_smp;
        union aopen_entry *afree;
index 32eec15fe4c2cd8425f89661231797e96007c5b1..45f2bea2e929b098ce2fa90be9987406c66c8d05 100644 (file)
@@ -2003,7 +2003,7 @@ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
  *
  *     Initialize the congestion control parameters.
  */
-static void __devinit init_cong_ctrl(unsigned short *a, unsigned short *b)
+static void init_cong_ctrl(unsigned short *a, unsigned short *b)
 {
        a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = a[6] = a[7] = a[8] = 1;
        a[9] = 2;
@@ -2519,6 +2519,7 @@ int t4_fw_bye(struct adapter *adap, unsigned int mbox)
 {
        struct fw_bye_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, BYE, WRITE);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
@@ -2535,6 +2536,7 @@ int t4_early_init(struct adapter *adap, unsigned int mbox)
 {
        struct fw_initialize_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, INITIALIZE, WRITE);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
@@ -2551,6 +2553,7 @@ int t4_fw_reset(struct adapter *adap, unsigned int mbox, int reset)
 {
        struct fw_reset_cmd c;
 
+       memset(&c, 0, sizeof(c));
        INIT_CMD(c, RESET, WRITE);
        c.val = htonl(reset);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
@@ -2828,7 +2831,7 @@ int t4_fixup_host_params(struct adapter *adap, unsigned int page_size,
                     HOSTPAGESIZEPF7(sge_hps));
 
        t4_set_reg_field(adap, SGE_CONTROL,
-                        INGPADBOUNDARY(INGPADBOUNDARY_MASK) |
+                        INGPADBOUNDARY_MASK |
                         EGRSTATUSPAGESIZE_MASK,
                         INGPADBOUNDARY(fl_align_log - 5) |
                         EGRSTATUSPAGESIZE(stat_len != 64));
@@ -3278,6 +3281,7 @@ int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid,
 {
        struct fw_vi_enable_cmd c;
 
+       memset(&c, 0, sizeof(c));
        c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
                             FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
        c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
@@ -3436,8 +3440,7 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
        return 0;
 }
 
-static void __devinit get_pci_mode(struct adapter *adapter,
-                                  struct pci_params *p)
+static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
 {
        u16 val;
 
@@ -3456,8 +3459,7 @@ static void __devinit get_pci_mode(struct adapter *adapter,
  *     Initializes the SW state maintained for each link, including the link's
  *     capabilities and default speed/flow-control/autonegotiation settings.
  */
-static void __devinit init_link_config(struct link_config *lc,
-                                      unsigned int caps)
+static void init_link_config(struct link_config *lc, unsigned int caps)
 {
        lc->supported = caps;
        lc->requested_speed = 0;
@@ -3481,7 +3483,7 @@ int t4_wait_dev_ready(struct adapter *adap)
        return t4_read_reg(adap, PL_WHOAMI) != 0xffffffff ? 0 : -EIO;
 }
 
-static int __devinit get_flash_params(struct adapter *adap)
+static int get_flash_params(struct adapter *adap)
 {
        int ret;
        u32 info;
@@ -3517,7 +3519,7 @@ static int __devinit get_flash_params(struct adapter *adap)
  *     values for some adapter tunables, take PHYs out of reset, and
  *     initialize the MDIO interface.
  */
-int __devinit t4_prep_adapter(struct adapter *adapter)
+int t4_prep_adapter(struct adapter *adapter)
 {
        int ret;
 
@@ -3545,7 +3547,7 @@ int __devinit t4_prep_adapter(struct adapter *adapter)
        return 0;
 }
 
-int __devinit t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
+int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
 {
        u8 addr[6];
        int ret, i, j = 0;
index 9dad56101e23fbcca6a0360c2d223ae531d4afb3..0188df705719d8d601c6d4dd4685f1f762c023f6 100644 (file)
@@ -2023,7 +2023,7 @@ static struct cxgb4vf_debugfs_entry debugfs_files[] = {
  * Set up out /sys/kernel/debug/cxgb4vf sub-nodes.  We assume that the
  * directory (debugfs_root) has already been set up.
  */
-static int __devinit setup_debugfs(struct adapter *adapter)
+static int setup_debugfs(struct adapter *adapter)
 {
        int i;
 
@@ -2064,7 +2064,7 @@ static void cleanup_debugfs(struct adapter *adapter)
  * adapter parameters we're going to be using and initialize basic adapter
  * hardware support.
  */
-static int __devinit adap_init0(struct adapter *adapter)
+static int adap_init0(struct adapter *adapter)
 {
        struct vf_resources *vfres = &adapter->params.vfres;
        struct sge_params *sge_params = &adapter->params.sge;
@@ -2266,7 +2266,7 @@ static inline void init_rspq(struct sge_rspq *rspq, u8 timer_idx,
  * be modified by the admin via ethtool and cxgbtool prior to the adapter
  * being brought up for the first time.
  */
-static void __devinit cfg_queues(struct adapter *adapter)
+static void cfg_queues(struct adapter *adapter)
 {
        struct sge *s = &adapter->sge;
        int q10g, n10g, qidx, pidx, qs;
@@ -2361,7 +2361,7 @@ static void __devinit cfg_queues(struct adapter *adapter)
  * Reduce the number of Ethernet queues across all ports to at most n.
  * n provides at least one queue per port.
  */
-static void __devinit reduce_ethqs(struct adapter *adapter, int n)
+static void reduce_ethqs(struct adapter *adapter, int n)
 {
        int i;
        struct port_info *pi;
@@ -2400,7 +2400,7 @@ static void __devinit reduce_ethqs(struct adapter *adapter, int n)
  * for our "extras".  Note that this process may lower the maximum number of
  * allowed Queue Sets ...
  */
-static int __devinit enable_msix(struct adapter *adapter)
+static int enable_msix(struct adapter *adapter)
 {
        int i, err, want, need;
        struct msix_entry entries[MSIX_ENTRIES];
@@ -2462,8 +2462,8 @@ static const struct net_device_ops cxgb4vf_netdev_ops     = {
  * state needed to manage the device.  This routine is called "init_one" in
  * the PF Driver ...
  */
-static int __devinit cxgb4vf_pci_probe(struct pci_dev *pdev,
-                                      const struct pci_device_id *ent)
+static int cxgb4vf_pci_probe(struct pci_dev *pdev,
+                            const struct pci_device_id *ent)
 {
        static int version_printed;
 
@@ -2769,7 +2769,7 @@ err_disable_device:
  * "probe" routine and quiesce the device (disable interrupts, etc.).  (Note
  * that this is called "remove_one" in the PF Driver.)
  */
-static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
+static void cxgb4vf_pci_remove(struct pci_dev *pdev)
 {
        struct adapter *adapter = pci_get_drvdata(pdev);
 
@@ -2835,7 +2835,7 @@ static void __devexit cxgb4vf_pci_remove(struct pci_dev *pdev)
  * "Shutdown" quiesce the device, stopping Ingress Packet and Interrupt
  * delivery.
  */
-static void __devexit cxgb4vf_pci_shutdown(struct pci_dev *pdev)
+static void cxgb4vf_pci_shutdown(struct pci_dev *pdev)
 {
        struct adapter *adapter;
        int pidx;
@@ -2905,8 +2905,8 @@ static struct pci_driver cxgb4vf_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = cxgb4vf_pci_tbl,
        .probe          = cxgb4vf_pci_probe,
-       .remove         = __devexit_p(cxgb4vf_pci_remove),
-       .shutdown       = __devexit_p(cxgb4vf_pci_shutdown),
+       .remove         = cxgb4vf_pci_remove,
+       .shutdown       = cxgb4vf_pci_shutdown,
 };
 
 /*
index a65c80aed1f2a214d99e520a2125755e2c16ecec..283f9d0d37fd4e4b689e698f965036ba6cda40e2 100644 (file)
@@ -232,8 +232,8 @@ static inline int t4vf_wr_mbox_ns(struct adapter *adapter, const void *cmd,
        return t4vf_wr_mbox_core(adapter, cmd, size, rpl, false);
 }
 
-int __devinit t4vf_wait_dev_ready(struct adapter *);
-int __devinit t4vf_port_init(struct adapter *, int);
+int t4vf_wait_dev_ready(struct adapter *);
+int t4vf_port_init(struct adapter *, int);
 
 int t4vf_fw_reset(struct adapter *);
 int t4vf_query_params(struct adapter *, unsigned int, const u32 *, u32 *);
index fe3fd3dad6f712a91c5af9b314f6bad8a44a36a7..7127c7b9efdeb59474554b70c71b52754a26bc24 100644 (file)
@@ -46,7 +46,7 @@
  * returning a value other than all 1's).  Return an error if it doesn't
  * become ready ...
  */
-int __devinit t4vf_wait_dev_ready(struct adapter *adapter)
+int t4vf_wait_dev_ready(struct adapter *adapter)
 {
        const u32 whoami = T4VF_PL_BASE_ADDR + PL_VF_WHOAMI;
        const u32 notready1 = 0xffffffff;
@@ -253,8 +253,7 @@ static int hash_mac_addr(const u8 *addr)
  *     Initializes the SW state maintained for each link, including the link's
  *     capabilities and default speed/flow-control/autonegotiation settings.
  */
-static void __devinit init_link_config(struct link_config *lc,
-                                      unsigned int caps)
+static void init_link_config(struct link_config *lc, unsigned int caps)
 {
        lc->supported = caps;
        lc->requested_speed = 0;
@@ -275,7 +274,7 @@ static void __devinit init_link_config(struct link_config *lc,
  *     @adapter: the adapter
  *     @pidx: the adapter port index
  */
-int __devinit t4vf_port_init(struct adapter *adapter, int pidx)
+int t4vf_port_init(struct adapter *adapter, int pidx)
 {
        struct port_info *pi = adap2pinfo(adapter, pidx);
        struct fw_vi_cmd vi_cmd, vi_rpl;
index 94606f7ee13ae2e969c9c91fccce118d908f6b02..1c7b884e337147a32e588b83750e4ce767f87d4f 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_CISCO
        bool "Cisco devices"
        default y
-       depends on PCI && INET
+       depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 9cc706a6cffdfefd8b967fae3da9e0d052802a15..b63f8d8a42612940d7cd403493327b0b7d98ff2d 100644 (file)
@@ -4,6 +4,6 @@
 
 config ENIC
        tristate "Cisco VIC Ethernet NIC Support"
-       depends on PCI && INET
+       depends on PCI
        ---help---
          This enables the support for the Cisco VIC Ethernet card.
index ad1468b3ab914442575f3fce1e35754da3221789..64866ff1aea0d9894f2a296ebed80324e5638f15 100644 (file)
@@ -2275,8 +2275,7 @@ static void enic_iounmap(struct enic *enic)
                        iounmap(enic->bar[i].vaddr);
 }
 
-static int __devinit enic_probe(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct device *dev = &pdev->dev;
        struct net_device *netdev;
@@ -2552,7 +2551,7 @@ err_out_free_netdev:
        return err;
 }
 
-static void __devexit enic_remove(struct pci_dev *pdev)
+static void enic_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
 
@@ -2584,7 +2583,7 @@ static struct pci_driver enic_driver = {
        .name = DRV_NAME,
        .id_table = enic_id_table,
        .probe = enic_probe,
-       .remove = __devexit_p(enic_remove),
+       .remove = enic_remove,
 };
 
 static int __init enic_init_module(void)
index 36499d5edd95b002e8fa59e91512f322ef1f4fca..c73472c369cd6e7334e42baf3d61f15952ece55a 100644 (file)
@@ -193,35 +193,35 @@ iow(board_info_t * db, int reg, int value)
 
 static void dm9000_outblk_8bit(void __iomem *reg, void *data, int count)
 {
-       writesb(reg, data, count);
+       iowrite8_rep(reg, data, count);
 }
 
 static void dm9000_outblk_16bit(void __iomem *reg, void *data, int count)
 {
-       writesw(reg, data, (count+1) >> 1);
+       iowrite16_rep(reg, data, (count+1) >> 1);
 }
 
 static void dm9000_outblk_32bit(void __iomem *reg, void *data, int count)
 {
-       writesl(reg, data, (count+3) >> 2);
+       iowrite32_rep(reg, data, (count+3) >> 2);
 }
 
 /* input block from chip to memory */
 
 static void dm9000_inblk_8bit(void __iomem *reg, void *data, int count)
 {
-       readsb(reg, data, count);
+       ioread8_rep(reg, data, count);
 }
 
 
 static void dm9000_inblk_16bit(void __iomem *reg, void *data, int count)
 {
-       readsw(reg, data, (count+1) >> 1);
+       ioread16_rep(reg, data, (count+1) >> 1);
 }
 
 static void dm9000_inblk_32bit(void __iomem *reg, void *data, int count)
 {
-       readsl(reg, data, (count+3) >> 2);
+       ioread32_rep(reg, data, (count+3) >> 2);
 }
 
 /* dump block from chip to null */
@@ -1359,7 +1359,7 @@ static const struct net_device_ops dm9000_netdev_ops = {
 /*
  * Search DM9000 board, allocate space and register it
  */
-static int __devinit
+static int
 dm9000_probe(struct platform_device *pdev)
 {
        struct dm9000_plat_data *pdata = pdev->dev.platform_data;
@@ -1661,7 +1661,7 @@ static const struct dev_pm_ops dm9000_drv_pm_ops = {
        .resume         = dm9000_drv_resume,
 };
 
-static int __devexit
+static int
 dm9000_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
@@ -1683,7 +1683,7 @@ static struct platform_driver dm9000_driver = {
                .pm      = &dm9000_drv_pm_ops,
        },
        .probe   = dm9000_probe,
-       .remove  = __devexit_p(dm9000_drv_remove),
+       .remove  = dm9000_drv_remove,
 };
 
 static int __init
index 17ae8c61968017aa6aa6a7477ac062f8dba79669..9f992b95eddc1b13209082890f13d1d9a8248964 100644 (file)
@@ -1910,9 +1910,8 @@ static struct net_device *ewrk3_devs[MAX_NUM_EWRK3S];
 static int ndevs;
 static int io[MAX_NUM_EWRK3S+1] = { 0x300, 0, };
 
-/* '21' below should really be 'MAX_NUM_EWRK3S' */
 module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_array(irq, byte, NULL, 0);
 MODULE_PARM_DESC(io, "EtherWORKS 3 I/O base address(es)");
 MODULE_PARM_DESC(irq, "EtherWORKS 3 IRQ number(s)");
 
index 77335853ac364bcedbadcec6449ddac45b71359b..eaab73cf27caffbbabb2904c47be6fc7941f5303 100644 (file)
@@ -1700,7 +1700,7 @@ static const struct ethtool_ops de_ethtool_ops = {
        .get_regs               = de_get_regs,
 };
 
-static void __devinit de21040_get_mac_address (struct de_private *de)
+static void de21040_get_mac_address(struct de_private *de)
 {
        unsigned i;
 
@@ -1721,7 +1721,7 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
        }
 }
 
-static void __devinit de21040_get_media_info(struct de_private *de)
+static void de21040_get_media_info(struct de_private *de)
 {
        unsigned int i;
 
@@ -1748,7 +1748,8 @@ static void __devinit de21040_get_media_info(struct de_private *de)
 }
 
 /* Note: this routine returns extra data bits for size detection. */
-static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, int addr_len)
+static unsigned tulip_read_eeprom(void __iomem *regs, int location,
+                                 int addr_len)
 {
        int i;
        unsigned retval = 0;
@@ -1783,7 +1784,7 @@ static unsigned __devinit tulip_read_eeprom(void __iomem *regs, int location, in
        return retval;
 }
 
-static void __devinit de21041_get_srom_info (struct de_private *de)
+static void de21041_get_srom_info(struct de_private *de)
 {
        unsigned i, sa_offset = 0, ofs;
        u8 ee_data[DE_EEPROM_SIZE + 6] = {};
@@ -1961,8 +1962,7 @@ static const struct net_device_ops de_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit de_init_one (struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int de_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct de_private *de;
@@ -2099,7 +2099,7 @@ err_out_free:
        return rc;
 }
 
-static void __devexit de_remove_one (struct pci_dev *pdev)
+static void de_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct de_private *de = netdev_priv(dev);
@@ -2184,7 +2184,7 @@ static struct pci_driver de_driver = {
        .name           = DRV_NAME,
        .id_table       = de_pci_tbl,
        .probe          = de_init_one,
-       .remove         = __devexit_p(de_remove_one),
+       .remove         = de_remove_one,
 #ifdef CONFIG_PM
        .suspend        = de_suspend,
        .resume         = de_resume,
index f879e922484685aa8523dff90dcec75703631758..4c830030fb06ca23056f67a6aebe815a79d57841 100644 (file)
 
 #include "de4x5.h"
 
-static const char version[] __devinitconst =
+static const char version[] =
        KERN_INFO "de4x5.c:V0.546 2001/02/22 davies@maniac.ultranet.com\n";
 
 #define c_char const char
@@ -1092,7 +1092,7 @@ static const struct net_device_ops de4x5_netdev_ops = {
 };
 
 
-static int __devinit
+static int
 de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
 {
     char name[DE4X5_NAME_LENGTH + 1];
@@ -2077,7 +2077,7 @@ static int __init de4x5_eisa_probe (struct device *gendev)
        return status;
 }
 
-static int __devexit de4x5_eisa_remove (struct device *device)
+static int de4x5_eisa_remove(struct device *device)
 {
        struct net_device *dev;
        u_long iobase;
@@ -2104,7 +2104,7 @@ static struct eisa_driver de4x5_eisa_driver = {
         .driver   = {
                 .name    = "de4x5",
                 .probe   = de4x5_eisa_probe,
-                .remove  = __devexit_p (de4x5_eisa_remove),
+               .remove  = de4x5_eisa_remove,
         }
 };
 MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
@@ -2118,7 +2118,7 @@ MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids);
 ** DECchips, we can find the base SROM irrespective of the BIOS scan direction.
 ** For single port cards this is a time waster...
 */
-static void __devinit
+static void
 srom_search(struct net_device *dev, struct pci_dev *pdev)
 {
     u_char pb;
@@ -2192,8 +2192,8 @@ srom_search(struct net_device *dev, struct pci_dev *pdev)
 ** kernels use the V0.535[n] drivers.
 */
 
-static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int de4x5_pci_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        u_char pb, pbus = 0, dev_num, dnum = 0, timer;
        u_short vendor, status;
@@ -2314,7 +2314,7 @@ static int __devinit de4x5_pci_probe (struct pci_dev *pdev,
        return error;
 }
 
-static void __devexit de4x5_pci_remove (struct pci_dev *pdev)
+static void de4x5_pci_remove(struct pci_dev *pdev)
 {
        struct net_device *dev;
        u_long iobase;
@@ -2344,7 +2344,7 @@ static struct pci_driver de4x5_pci_driver = {
         .name           = "de4x5",
         .id_table       = de4x5_pci_tbl,
         .probe          = de4x5_pci_probe,
-       .remove         = __devexit_p (de4x5_pci_remove),
+       .remove         = de4x5_pci_remove,
 };
 
 #endif
index d23755ea9bc79c68b793af65c824dfd6477ddb78..83139307861cd720edfd78d71d7abbe6b2265ff5 100644 (file)
@@ -291,8 +291,8 @@ enum dmfe_CR6_bits {
 };
 
 /* Global variable declaration ----------------------------- */
-static int __devinitdata printed_version;
-static const char version[] __devinitconst =
+static int printed_version;
+static const char version[] =
        "Davicom DM9xxx net driver, version " DRV_VERSION " (" DRV_RELDATE ")";
 
 static int dmfe_debug;
@@ -367,8 +367,7 @@ static const struct net_device_ops netdev_ops = {
  *     Search DM910X board ,allocate space and register it
  */
 
-static int __devinit dmfe_init_one (struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int dmfe_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct dmfe_board_info *db;     /* board information structure */
        struct net_device *dev;
@@ -531,7 +530,7 @@ err_out_free:
 }
 
 
-static void __devexit dmfe_remove_one (struct pci_dev *pdev)
+static void dmfe_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct dmfe_board_info *db = netdev_priv(dev);
@@ -2187,7 +2186,7 @@ static struct pci_driver dmfe_driver = {
        .name           = "dmfe",
        .id_table       = dmfe_pci_tbl,
        .probe          = dmfe_init_one,
-       .remove         = __devexit_p(dmfe_remove_one),
+       .remove         = dmfe_remove_one,
        .suspend        = dmfe_suspend,
        .resume         = dmfe_resume
 };
index 44f7e8e82d85dbbdc9b67031b708e41bb9e8cb9e..df5a892fb49cb52a5b3623bf44cf4fc3ab261828 100644 (file)
@@ -26,7 +26,7 @@
    */
 
 /* Known cards that have old-style EEPROMs. */
-static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
+static struct eeprom_fixup eeprom_fixups[] = {
   {"Asante", 0, 0, 0x94, {0x1e00, 0x0000, 0x0800, 0x0100, 0x018c,
                          0x0000, 0x0000, 0xe078, 0x0001, 0x0050, 0x0018 }},
   {"SMC9332DST", 0, 0, 0xC0, { 0x1e00, 0x0000, 0x0800, 0x041f,
@@ -79,7 +79,7 @@ static struct eeprom_fixup eeprom_fixups[] __devinitdata = {
   {NULL}};
 
 
-static const char *const block_name[] __devinitconst = {
+static const char *const block_name[] = {
        "21140 non-MII",
        "21140 MII PHY",
        "21142 Serial PHY",
@@ -102,7 +102,7 @@ static const char *const block_name[] __devinitconst = {
  * #ifdef __hppa__ should completely optimize this function away for
  * non-parisc hardware.
  */
-static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
+static void tulip_build_fake_mediatable(struct tulip_private *tp)
 {
 #ifdef CONFIG_GSC
        if (tp->flags & NEEDS_FAKE_MEDIA_TABLE) {
@@ -140,7 +140,7 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp)
 #endif
 }
 
-void __devinit tulip_parse_eeprom(struct net_device *dev)
+void tulip_parse_eeprom(struct net_device *dev)
 {
        /*
          dev is not registered at this point, so logging messages can't
@@ -339,7 +339,7 @@ subsequent_board:
 #define EE_READ_CMD            (6)
 
 /* Note: this routine returns extra data bits for size detection. */
-int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
+int tulip_read_eeprom(struct net_device *dev, int location, int addr_len)
 {
        int i;
        unsigned retval = 0;
index ae937c6749e7847facb80b06553c356dd32c627d..93a4afaa09f125ca92ec6f2de037de82215db8c3 100644 (file)
@@ -447,7 +447,7 @@ int tulip_check_duplex(struct net_device *dev)
        return 0;
 }
 
-void __devinit tulip_find_mii (struct net_device *dev, int board_idx)
+void tulip_find_mii(struct net_device *dev, int board_idx)
 {
        struct tulip_private *tp = netdev_priv(dev);
        int phyn, phy_idx = 0;
index 885700a199785a6b840b5cf4bddb9494d8f5bc67..1e9443d9fb5732fffa352683de3a019679c7f6b8 100644 (file)
@@ -37,7 +37,7 @@
 #include <asm/prom.h>
 #endif
 
-static char version[] __devinitdata =
+static char version[] =
        "Linux Tulip driver version " DRV_VERSION " (" DRV_RELDATE ")\n";
 
 /* A few user-configurable values. */
@@ -1191,8 +1191,7 @@ static void set_rx_mode(struct net_device *dev)
 }
 
 #ifdef CONFIG_TULIP_MWI
-static void __devinit tulip_mwi_config (struct pci_dev *pdev,
-                                       struct net_device *dev)
+static void tulip_mwi_config(struct pci_dev *pdev, struct net_device *dev)
 {
        struct tulip_private *tp = netdev_priv(dev);
        u8 cache;
@@ -1301,8 +1300,7 @@ DEFINE_PCI_DEVICE_TABLE(early_486_chipsets) = {
        { },
 };
 
-static int __devinit tulip_init_one (struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int tulip_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct tulip_private *tp;
        /* See note below on the multiport cards. */
@@ -1927,7 +1925,7 @@ static int tulip_resume(struct pci_dev *pdev)
 #endif /* CONFIG_PM */
 
 
-static void __devexit tulip_remove_one (struct pci_dev *pdev)
+static void tulip_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata (pdev);
        struct tulip_private *tp;
@@ -1974,7 +1972,7 @@ static struct pci_driver tulip_driver = {
        .name           = DRV_NAME,
        .id_table       = tulip_pci_tbl,
        .probe          = tulip_init_one,
-       .remove         = __devexit_p(tulip_remove_one),
+       .remove         = tulip_remove_one,
 #ifdef CONFIG_PM
        .suspend        = tulip_suspend,
        .resume         = tulip_resume,
index 75d45f8a37dc170db51678919acbc27cc9cd2ac5..93845afe1cea105f21751c4bea54100405799b42 100644 (file)
@@ -204,8 +204,8 @@ enum uli526x_CR6_bits {
 };
 
 /* Global variable declaration ----------------------------- */
-static int __devinitdata printed_version;
-static const char version[] __devinitconst =
+static int printed_version;
+static const char version[] =
        "ULi M5261/M5263 net driver, version " DRV_VERSION " (" DRV_RELDATE ")";
 
 static int uli526x_debug;
@@ -281,8 +281,8 @@ static const struct net_device_ops netdev_ops = {
  *     Search ULI526X board, allocate space and register it
  */
 
-static int __devinit uli526x_init_one (struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int uli526x_init_one(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        struct uli526x_board_info *db;  /* board information structure */
        struct net_device *dev;
@@ -436,7 +436,7 @@ err_out_free:
 }
 
 
-static void __devexit uli526x_remove_one (struct pci_dev *pdev)
+static void uli526x_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct uli526x_board_info *db = netdev_priv(dev);
@@ -1788,7 +1788,7 @@ static struct pci_driver uli526x_driver = {
        .name           = "uli526x",
        .id_table       = uli526x_pci_tbl,
        .probe          = uli526x_init_one,
-       .remove         = __devexit_p(uli526x_remove_one),
+       .remove         = uli526x_remove_one,
        .suspend        = uli526x_suspend,
        .resume         = uli526x_resume,
 };
index 7c1ec4d7920bf607e43cd50c5c5624adcc86b08b..c7b04ecf5b497ea26f969ce52eeaffccfc0ee5ef 100644 (file)
@@ -236,7 +236,7 @@ struct pci_id_info {
         int drv_flags;         /* Driver use, intended as capability flags. */
 };
 
-static const struct pci_id_info pci_id_tbl[] __devinitconst = {
+static const struct pci_id_info pci_id_tbl[] = {
        {                               /* Sometime a Level-One switch card. */
          "Winbond W89c840",    CanHaveMII | HasBrokenTx | FDXOnNoMII},
        { "Winbond W89c840",    CanHaveMII | HasBrokenTx},
@@ -358,8 +358,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit w840_probe1 (struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int w840_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct netdev_private *np;
@@ -1532,7 +1531,7 @@ static int netdev_close(struct net_device *dev)
        return 0;
 }
 
-static void __devexit w840_remove1 (struct pci_dev *pdev)
+static void w840_remove1(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -1647,7 +1646,7 @@ static struct pci_driver w840_driver = {
        .name           = DRV_NAME,
        .id_table       = w840_pci_tbl,
        .probe          = w840_probe1,
-       .remove         = __devexit_p(w840_remove1),
+       .remove         = w840_remove1,
 #ifdef CONFIG_PM
        .suspend        = w840_suspend,
        .resume         = w840_resume,
index 138bf83bc98e346c66b2c90ff691512e49f539a8..88feced9a6293432e3dd5316a8ec48ab284ca3e7 100644 (file)
@@ -148,7 +148,7 @@ static struct pci_driver xircom_ops = {
        .name           = "xircom_cb",
        .id_table       = xircom_pci_table,
        .probe          = xircom_probe,
-       .remove         = __devexit_p(xircom_remove),
+       .remove         = xircom_remove,
 };
 
 
@@ -190,7 +190,7 @@ static const struct net_device_ops netdev_ops = {
          first two packets that get send, and pump hates that.
 
  */
-static int __devinit xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+static int xircom_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct device *d = &pdev->dev;
        struct net_device *dev = NULL;
@@ -312,7 +312,7 @@ err_disable:
  Interrupts and such are already stopped in the "ifconfig ethX down"
  code.
  */
-static void __devexit xircom_remove(struct pci_dev *pdev)
+static void xircom_remove(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct xircom_private *card = netdev_priv(dev);
index a059f0c27e28f19251a282b36f35b1254e90b273..1d342d37915cd1d45b8c00088079e6aef2b273fc 100644 (file)
@@ -23,7 +23,7 @@
 #define dr16(reg)      ioread16(ioaddr + (reg))
 #define dr8(reg)       ioread8(ioaddr + (reg))
 
-static char version[] __devinitdata =
+static char version[] =
       KERN_INFO DRV_NAME " " DRV_VERSION " " DRV_RELDATE "\n";
 #define MAX_UNITS 8
 static int mtu[MAX_UNITS];
@@ -110,7 +110,7 @@ static const struct net_device_ops netdev_ops = {
        .ndo_change_mtu         = change_mtu,
 };
 
-static int __devinit
+static int
 rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
@@ -1727,7 +1727,7 @@ rio_close (struct net_device *dev)
        return 0;
 }
 
-static void __devexit
+static void
 rio_remove1 (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata (pdev);
@@ -1755,24 +1755,10 @@ static struct pci_driver rio_driver = {
        .name           = "dl2k",
        .id_table       = rio_pci_tbl,
        .probe          = rio_probe1,
-       .remove         = __devexit_p(rio_remove1),
+       .remove         = rio_remove1,
 };
 
-static int __init
-rio_init (void)
-{
-       return pci_register_driver(&rio_driver);
-}
-
-static void __exit
-rio_exit (void)
-{
-       pci_unregister_driver (&rio_driver);
-}
-
-module_init (rio_init);
-module_exit (rio_exit);
-
+module_pci_driver(rio_driver);
 /*
 
 Compile command:
index 3b83588e51f6ad41ac112b06d9f219c33eb957d2..28fc11b2f1ea9235ce8c9fdb3ac8abbb35b72bac 100644 (file)
@@ -102,7 +102,7 @@ static char *media[MAX_UNITS];
 #include <linux/mii.h>
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
        KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE
        " Written by Donald Becker\n";
 
@@ -218,7 +218,7 @@ enum {
 struct pci_id_info {
         const char *name;
 };
-static const struct pci_id_info pci_id_tbl[] __devinitconst = {
+static const struct pci_id_info pci_id_tbl[] = {
        {"D-Link DFE-550TX FAST Ethernet Adapter"},
        {"D-Link DFE-550FX 100Mbps Fiber-optics Adapter"},
        {"D-Link DFE-580TX 4 port Server Adapter"},
@@ -259,6 +259,7 @@ enum alta_offsets {
        EECtrl = 0x36,
        FlashAddr = 0x40,
        FlashData = 0x44,
+       WakeEvent = 0x45,
        TxStatus = 0x46,
        TxFrameId = 0x47,
        DownCounter = 0x18,
@@ -333,6 +334,14 @@ enum mac_ctrl1_bits {
        RxEnable=0x0800, RxDisable=0x1000, RxEnabled=0x2000,
 };
 
+/* Bits in WakeEvent register. */
+enum wake_event_bits {
+       WakePktEnable = 0x01,
+       MagicPktEnable = 0x02,
+       LinkEventEnable = 0x04,
+       WolEnable = 0x80,
+};
+
 /* The Rx and Tx buffer descriptors. */
 /* Note that using only 32 bit fields simplifies conversion to big-endian
    architectures. */
@@ -392,6 +401,7 @@ struct netdev_private {
        unsigned int default_port:4;            /* Last dev->if_port value. */
        unsigned int an_enable:1;
        unsigned int speed;
+       unsigned int wol_enabled:1;                     /* Wake on LAN enabled */
        struct tasklet_struct rx_tasklet;
        struct tasklet_struct tx_tasklet;
        int budget;
@@ -472,8 +482,8 @@ static const struct net_device_ops netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit sundance_probe1 (struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int sundance_probe1(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct netdev_private *np;
@@ -701,7 +711,7 @@ static int change_mtu(struct net_device *dev, int new_mtu)
 
 #define eeprom_delay(ee_addr)  ioread32(ee_addr)
 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
-static int __devinit eeprom_read(void __iomem *ioaddr, int location)
+static int eeprom_read(void __iomem *ioaddr, int location)
 {
        int boguscnt = 10000;           /* Typical 1900 ticks. */
        iowrite16(0x0200 | (location & 0xff), ioaddr + EECtrl);
@@ -829,7 +839,7 @@ static int netdev_open(struct net_device *dev)
        unsigned long flags;
        int i;
 
-       /* Do we need to reset the chip??? */
+       sundance_reset(dev, 0x00ff << 16);
 
        i = request_irq(irq, intr_handler, IRQF_SHARED, dev->name, dev);
        if (i)
@@ -877,6 +887,10 @@ static int netdev_open(struct net_device *dev)
 
        iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
 
+       /* Disable Wol */
+       iowrite8(ioread8(ioaddr + WakeEvent) | 0x00, ioaddr + WakeEvent);
+       np->wol_enabled = 0;
+
        if (netif_msg_ifup(np))
                printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x "
                           "MAC Control %x, %4.4x %4.4x.\n",
@@ -1715,6 +1729,60 @@ static void get_ethtool_stats(struct net_device *dev,
        data[i++] = np->xstats.rx_mcasts;
 }
 
+#ifdef CONFIG_PM
+
+static void sundance_get_wol(struct net_device *dev,
+               struct ethtool_wolinfo *wol)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
+       u8 wol_bits;
+
+       wol->wolopts = 0;
+
+       wol->supported = (WAKE_PHY | WAKE_MAGIC);
+       if (!np->wol_enabled)
+               return;
+
+       wol_bits = ioread8(ioaddr + WakeEvent);
+       if (wol_bits & MagicPktEnable)
+               wol->wolopts |= WAKE_MAGIC;
+       if (wol_bits & LinkEventEnable)
+               wol->wolopts |= WAKE_PHY;
+}
+
+static int sundance_set_wol(struct net_device *dev,
+       struct ethtool_wolinfo *wol)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
+       u8 wol_bits;
+
+       if (!device_can_wakeup(&np->pci_dev->dev))
+               return -EOPNOTSUPP;
+
+       np->wol_enabled = !!(wol->wolopts);
+       wol_bits = ioread8(ioaddr + WakeEvent);
+       wol_bits &= ~(WakePktEnable | MagicPktEnable |
+                       LinkEventEnable | WolEnable);
+
+       if (np->wol_enabled) {
+               if (wol->wolopts & WAKE_MAGIC)
+                       wol_bits |= (MagicPktEnable | WolEnable);
+               if (wol->wolopts & WAKE_PHY)
+                       wol_bits |= (LinkEventEnable | WolEnable);
+       }
+       iowrite8(wol_bits, ioaddr + WakeEvent);
+
+       device_set_wakeup_enable(&np->pci_dev->dev, np->wol_enabled);
+
+       return 0;
+}
+#else
+#define sundance_get_wol NULL
+#define sundance_set_wol NULL
+#endif /* CONFIG_PM */
+
 static const struct ethtool_ops ethtool_ops = {
        .begin = check_if_running,
        .get_drvinfo = get_drvinfo,
@@ -1722,6 +1790,8 @@ static const struct ethtool_ops ethtool_ops = {
        .set_settings = set_settings,
        .nway_reset = nway_reset,
        .get_link = get_link,
+       .get_wol = sundance_get_wol,
+       .set_wol = sundance_set_wol,
        .get_msglevel = get_msglevel,
        .set_msglevel = set_msglevel,
        .get_strings = get_strings,
@@ -1844,7 +1914,7 @@ static int netdev_close(struct net_device *dev)
        return 0;
 }
 
-static void __devexit sundance_remove1 (struct pci_dev *pdev)
+static void sundance_remove1(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -1867,6 +1937,8 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev)
 static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
        struct net_device *dev = pci_get_drvdata(pci_dev);
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
 
        if (!netif_running(dev))
                return 0;
@@ -1875,6 +1947,12 @@ static int sundance_suspend(struct pci_dev *pci_dev, pm_message_t state)
        netif_device_detach(dev);
 
        pci_save_state(pci_dev);
+       if (np->wol_enabled) {
+               iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode);
+               iowrite16(RxEnable, ioaddr + MACCtrl1);
+       }
+       pci_enable_wake(pci_dev, pci_choose_state(pci_dev, state),
+                       np->wol_enabled);
        pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state));
 
        return 0;
@@ -1890,6 +1968,7 @@ static int sundance_resume(struct pci_dev *pci_dev)
 
        pci_set_power_state(pci_dev, PCI_D0);
        pci_restore_state(pci_dev);
+       pci_enable_wake(pci_dev, PCI_D0, 0);
 
        err = netdev_open(dev);
        if (err) {
@@ -1910,7 +1989,7 @@ static struct pci_driver sundance_driver = {
        .name           = DRV_NAME,
        .id_table       = sundance_pci_tbl,
        .probe          = sundance_probe1,
-       .remove         = __devexit_p(sundance_remove1),
+       .remove         = sundance_remove1,
 #ifdef CONFIG_PM
        .suspend        = sundance_suspend,
        .resume         = sundance_resume,
index 290b26f868c9f7d358c125822dd67bc412d85b16..2c177b329c8bd4ccd1bad6ffef72deab6b3dc8a1 100644 (file)
@@ -72,7 +72,7 @@ static void __dnet_set_hwaddr(struct dnet *bp)
        dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp);
 }
 
-static void __devinit dnet_get_hwaddr(struct dnet *bp)
+static void dnet_get_hwaddr(struct dnet *bp)
 {
        u16 tmp;
        u8 addr[6];
@@ -664,9 +664,6 @@ static int dnet_open(struct net_device *dev)
        if (!bp->phy_dev)
                return -EAGAIN;
 
-       if (!is_valid_ether_addr(dev->dev_addr))
-               return -EADDRNOTAVAIL;
-
        napi_enable(&bp->napi);
        dnet_init_hw(bp);
 
@@ -829,7 +826,7 @@ static const struct net_device_ops dnet_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
 };
 
-static int __devinit dnet_probe(struct platform_device *pdev)
+static int dnet_probe(struct platform_device *pdev)
 {
        struct resource *res;
        struct net_device *dev;
@@ -945,7 +942,7 @@ err_out:
        return err;
 }
 
-static int __devexit dnet_remove(struct platform_device *pdev)
+static int dnet_remove(struct platform_device *pdev)
 {
 
        struct net_device *dev;
@@ -971,7 +968,7 @@ static int __devexit dnet_remove(struct platform_device *pdev)
 
 static struct platform_driver dnet_driver = {
        .probe          = dnet_probe,
-       .remove         = __devexit_p(dnet_remove),
+       .remove         = dnet_remove,
        .driver         = {
                .name           = "dnet",
        },
index 7a28a643394414a40eb3d3493eb7ffcea188f7cc..1b8d638c6cb18963f7d06dc57a5355bc8e93272a 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_EMULEX
        bool "Emulex devices"
        default y
-       depends on PCI && INET
+       depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 804db04a2bd0431d970b39bd8e7381507d78d799..231129dd1764e70e1c0b8d9c7195685859d2ea42 100644 (file)
@@ -1,6 +1,6 @@
 config BE2NET
        tristate "ServerEngines' 10Gbps NIC - BladeEngine"
-       depends on PCI && INET
+       depends on PCI
        ---help---
          This driver implements the NIC functionality for ServerEngines'
          10Gbps network adapter - BladeEngine.
index cf4c05bdf5fe71262abf8fd4ac10e11e0cb0240a..abf26c7c1d1911c2f46a5684dc102f4181eba843 100644 (file)
@@ -34,7 +34,7 @@
 #include "be_hw.h"
 #include "be_roce.h"
 
-#define DRV_VER                        "4.4.31.0u"
+#define DRV_VER                        "4.4.161.0u"
 #define DRV_NAME               "be2net"
 #define BE_NAME                        "ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME               "ServerEngines BladeEngine3 10Gbps NIC"
@@ -53,6 +53,7 @@
 #define OC_DEVICE_ID3          0xe220  /* Device id for Lancer cards */
 #define OC_DEVICE_ID4           0xe228   /* Device id for VF in Lancer */
 #define OC_DEVICE_ID5          0x720   /* Device Id for Skyhawk cards */
+#define OC_DEVICE_ID6          0x728   /* Device id for VF in SkyHawk */
 #define OC_SUBSYS_DEVICE_ID1   0xE602
 #define OC_SUBSYS_DEVICE_ID2   0xE642
 #define OC_SUBSYS_DEVICE_ID3   0xE612
@@ -71,6 +72,7 @@ static inline char *nic_name(struct pci_dev *pdev)
        case BE_DEVICE_ID2:
                return BE3_NAME;
        case OC_DEVICE_ID5:
+       case OC_DEVICE_ID6:
                return OC_NAME_SH;
        default:
                return BE_NAME;
@@ -346,7 +348,6 @@ struct be_adapter {
        struct pci_dev *pdev;
        struct net_device *netdev;
 
-       u8 __iomem *csr;
        u8 __iomem *db;         /* Door Bell */
 
        struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
@@ -374,11 +375,8 @@ struct be_adapter {
        struct be_rx_obj rx_obj[MAX_RX_QS];
        u32 big_page_size;      /* Compounded page size shared by rx wrbs */
 
-       u8 eq_next_idx;
        struct be_drv_stats drv_stats;
-
        u16 vlans_added;
-       u16 max_vlans;  /* Number of vlans supported */
        u8 vlan_tag[VLAN_N_VID];
        u8 vlan_prio_bmap;      /* Available Priority BitMap */
        u16 recommended_prio;   /* Recommended Priority */
@@ -391,6 +389,7 @@ struct be_adapter {
 
        struct delayed_work func_recovery_work;
        u32 flags;
+       u32 cmd_privileges;
        /* Ethtool knobs and info */
        char fw_ver[FW_VER_LEN];
        int if_handle;          /* Used to configure filtering */
@@ -408,10 +407,8 @@ struct be_adapter {
        u32 rx_fc;              /* Rx flow control */
        u32 tx_fc;              /* Tx flow control */
        bool stats_cmd_sent;
-       u8 generation;          /* BladeEngine ASIC generation */
        u32 if_type;
        struct {
-               u8 __iomem *base;       /* Door Bell */
                u32 size;
                u32 total_size;
                u64 io_addr;
@@ -434,10 +431,18 @@ struct be_adapter {
        struct phy_info phy;
        u8 wol_cap;
        bool wol;
-       u32 max_pmac_cnt;       /* Max secondary UC MACs programmable */
        u32 uc_macs;            /* Count of secondary UC MAC programmed */
        u32 msg_enable;
        int be_get_temp_freq;
+       u16 max_mcast_mac;
+       u16 max_tx_queues;
+       u16 max_rss_queues;
+       u16 max_rx_queues;
+       u16 max_pmac_cnt;
+       u16 max_vlans;
+       u16 max_event_queues;
+       u32 if_cap_flags;
+       u8 pf_number;
 };
 
 #define be_physfn(adapter)             (!adapter->virtfn)
@@ -448,21 +453,25 @@ struct be_adapter {
        for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \
                i++, vf_cfg++)
 
-/* BladeEngine Generation numbers */
-#define BE_GEN2 2
-#define BE_GEN3 3
-
 #define ON                             1
 #define OFF                            0
-#define lancer_chip(adapter)   ((adapter->pdev->device == OC_DEVICE_ID3) || \
-                                (adapter->pdev->device == OC_DEVICE_ID4))
 
-#define skyhawk_chip(adapter)  (adapter->pdev->device == OC_DEVICE_ID5)
+#define lancer_chip(adapter)   (adapter->pdev->device == OC_DEVICE_ID3 || \
+                                adapter->pdev->device == OC_DEVICE_ID4)
+
+#define skyhawk_chip(adapter)  (adapter->pdev->device == OC_DEVICE_ID5 || \
+                                adapter->pdev->device == OC_DEVICE_ID6)
+
+#define BE3_chip(adapter)      (adapter->pdev->device == BE_DEVICE_ID2 || \
+                                adapter->pdev->device == OC_DEVICE_ID2)
 
+#define BE2_chip(adapter)      (adapter->pdev->device == BE_DEVICE_ID1 || \
+                                adapter->pdev->device == OC_DEVICE_ID1)
 
-#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \
-                               adapter->sli_family == SKYHAWK_SLI_FAMILY) && \
-                               (adapter->function_mode & RDMA_ENABLED))
+#define BEx_chip(adapter)      (BE3_chip(adapter) || BE2_chip(adapter))
+
+#define be_roce_supported(adapter)     (skyhawk_chip(adapter) && \
+                                       (adapter->function_mode & RDMA_ENABLED))
 
 extern const struct ethtool_ops be_ethtool_ops;
 
@@ -637,12 +646,6 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter)
        }
 }
 
-static inline bool be_type_2_3(struct be_adapter *adapter)
-{
-       return (adapter->if_type == SLI_INTF_TYPE_2 ||
-               adapter->if_type == SLI_INTF_TYPE_3) ? true : false;
-}
-
 extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
                u16 num_popped);
 extern void be_link_status_update(struct be_adapter *adapter, u8 link_status);
index af60bb26e33023ac523b672f76e68dcbdd172f92..f2875aa4766170a100b7a21aeffac60e1b9c8d57 100644 (file)
 #include "be.h"
 #include "be_cmds.h"
 
+static struct be_cmd_priv_map cmd_priv_map[] = {
+       {
+               OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
+               CMD_SUBSYSTEM_ETH,
+               BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       },
+       {
+               OPCODE_COMMON_GET_FLOW_CONTROL,
+               CMD_SUBSYSTEM_COMMON,
+               BE_PRIV_LNKQUERY | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       },
+       {
+               OPCODE_COMMON_SET_FLOW_CONTROL,
+               CMD_SUBSYSTEM_COMMON,
+               BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       },
+       {
+               OPCODE_ETH_GET_PPORT_STATS,
+               CMD_SUBSYSTEM_ETH,
+               BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       },
+       {
+               OPCODE_COMMON_GET_PHY_DETAILS,
+               CMD_SUBSYSTEM_COMMON,
+               BE_PRIV_LNKMGMT | BE_PRIV_VHADM |
+               BE_PRIV_DEVCFG | BE_PRIV_DEVSEC
+       }
+};
+
+static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode,
+                          u8 subsystem)
+{
+       int i;
+       int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map);
+       u32 cmd_privileges = adapter->cmd_privileges;
+
+       for (i = 0; i < num_entries; i++)
+               if (opcode == cmd_priv_map[i].opcode &&
+                   subsystem == cmd_priv_map[i].subsystem)
+                       if (!(cmd_privileges & cmd_priv_map[i].priv_mask))
+                               return false;
+
+       return true;
+}
+
 static inline void *embedded_payload(struct be_mcc_wrb *wrb)
 {
        return wrb->payload.embedded_payload;
@@ -419,14 +468,13 @@ static int be_mbox_notify_wait(struct be_adapter *adapter)
 static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
 {
        u32 sem;
+       u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH :
+                                         SLIPORT_SEMAPHORE_OFFSET_BE;
 
-       if (lancer_chip(adapter))
-               sem  = ioread32(adapter->db + MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET);
-       else
-               sem  = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET);
+       pci_read_config_dword(adapter->pdev, reg, &sem);
+       *stage = sem & POST_STAGE_MASK;
 
-       *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK;
-       if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK)
+       if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK)
                return -1;
        else
                return 0;
@@ -452,10 +500,33 @@ int lancer_wait_ready(struct be_adapter *adapter)
        return status;
 }
 
+static bool lancer_provisioning_error(struct be_adapter *adapter)
+{
+       u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0;
+       sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+       if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
+               sliport_err1 = ioread32(adapter->db +
+                                       SLIPORT_ERROR1_OFFSET);
+               sliport_err2 = ioread32(adapter->db +
+                                       SLIPORT_ERROR2_OFFSET);
+
+               if (sliport_err1 == SLIPORT_ERROR_NO_RESOURCE1 &&
+                   sliport_err2 == SLIPORT_ERROR_NO_RESOURCE2)
+                       return true;
+       }
+       return false;
+}
+
 int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
 {
        int status;
        u32 sliport_status, err, reset_needed;
+       bool resource_error;
+
+       resource_error = lancer_provisioning_error(adapter);
+       if (resource_error)
+               return -1;
+
        status = lancer_wait_ready(adapter);
        if (!status) {
                sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
@@ -477,6 +548,14 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
                        status = -1;
                }
        }
+       /* Stop error recovery if error is not recoverable.
+        * No resource error is temporary errors and will go away
+        * when PF provisions resources.
+        */
+       resource_error = lancer_provisioning_error(adapter);
+       if (status == -1 && !resource_error)
+               adapter->eeh_error = true;
+
        return status;
 }
 
@@ -601,6 +680,9 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
        struct be_queue_info *mccq = &adapter->mcc_obj.q;
        struct be_mcc_wrb *wrb;
 
+       if (!mccq->created)
+               return NULL;
+
        if (atomic_read(&mccq->used) >= mccq->len) {
                dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n");
                return NULL;
@@ -1155,8 +1237,7 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
        req->id = cpu_to_le16(q->id);
 
        status = be_mbox_notify_wait(adapter);
-       if (!status)
-               q->created = false;
+       q->created = false;
 
        mutex_unlock(&adapter->mbox_lock);
        return status;
@@ -1183,8 +1264,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q)
        req->id = cpu_to_le16(q->id);
 
        status = be_mcc_notify_wait(adapter);
-       if (!status)
-               q->created = false;
+       q->created = false;
 
 err:
        spin_unlock_bh(&adapter->mcc_lock);
@@ -1281,7 +1361,8 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)
        be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH,
                OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, nonemb_cmd);
 
-       if (adapter->generation == BE_GEN3)
+       /* version 1 of the cmd is not supported only by BE2 */
+       if (!BE2_chip(adapter))
                hdr->version = 1;
 
        be_mcc_notify(adapter);
@@ -1301,6 +1382,10 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter,
        struct lancer_cmd_req_pport_stats *req;
        int status = 0;
 
+       if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS,
+                           CMD_SUBSYSTEM_ETH))
+               return -EPERM;
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -1367,7 +1452,8 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed,
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
                OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL);
 
-       if (adapter->generation == BE_GEN3 || lancer_chip(adapter))
+       /* version 1 of the cmd is not supported only by BE2 */
+       if (!BE2_chip(adapter))
                req->hdr.version = 1;
 
        req->hdr.domain = dom;
@@ -1658,9 +1744,9 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value)
                /* Reset mcast promisc mode if already set by setting mask
                 * and not setting flags field
                 */
-               if (!lancer_chip(adapter) || be_physfn(adapter))
-                       req->if_flags_mask |=
-                               cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS);
+               req->if_flags_mask |=
+                       cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS &
+                                   adapter->if_cap_flags);
 
                req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev));
                netdev_for_each_mc_addr(ha, adapter->netdev)
@@ -1680,6 +1766,10 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc)
        struct be_cmd_req_set_flow_control *req;
        int status;
 
+       if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL,
+                           CMD_SUBSYSTEM_COMMON))
+               return -EPERM;
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -1709,6 +1799,10 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc)
        struct be_cmd_req_get_flow_control *req;
        int status;
 
+       if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL,
+                           CMD_SUBSYSTEM_COMMON))
+               return -EPERM;
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -2067,7 +2161,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
                         int offset)
 {
        struct be_mcc_wrb *wrb;
-       struct be_cmd_write_flashrom *req;
+       struct be_cmd_read_flash_crc *req;
        int status;
 
        spin_lock_bh(&adapter->mcc_lock);
@@ -2080,7 +2174,8 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
        req = embedded_payload(wrb);
 
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-               OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL);
+                              OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
+                              wrb, NULL);
 
        req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
        req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
@@ -2089,7 +2184,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
 
        status = be_mcc_notify_wait(adapter);
        if (!status)
-               memcpy(flashed_crc, req->params.data_buf, 4);
+               memcpy(flashed_crc, req->crc, 4);
 
 err:
        spin_unlock_bh(&adapter->mcc_lock);
@@ -2275,6 +2370,10 @@ int be_cmd_get_phy_info(struct be_adapter *adapter)
        struct be_dma_mem cmd;
        int status;
 
+       if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS,
+                           CMD_SUBSYSTEM_COMMON))
+               return -EPERM;
+
        spin_lock_bh(&adapter->mcc_lock);
 
        wrb = wrb_from_mccq(adapter);
@@ -2434,6 +2533,42 @@ err:
        return status;
 }
 
+/* Get privilege(s) for a function */
+int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege,
+                            u32 domain)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_fn_privileges *req;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req),
+                              wrb, NULL);
+
+       req->hdr.domain = domain;
+
+       status = be_mcc_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_get_fn_privileges *resp =
+                                               embedded_payload(wrb);
+               *privilege = le32_to_cpu(resp->privilege_mask);
+       }
+
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
 /* Uses synchronous MCCQ */
 int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
                             bool *pmac_id_active, u32 *pmac_id, u8 domain)
@@ -2651,6 +2786,10 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
        int payload_len = sizeof(*req);
        struct be_dma_mem cmd;
 
+       if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG,
+                           CMD_SUBSYSTEM_ETH))
+               return -EPERM;
+
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
        cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
@@ -2792,6 +2931,240 @@ err:
        return status;
 }
 
+static struct be_nic_resource_desc *be_get_nic_desc(u8 *buf, u32 desc_count,
+                                                   u32 max_buf_size)
+{
+       struct be_nic_resource_desc *desc = (struct be_nic_resource_desc *)buf;
+       int i;
+
+       for (i = 0; i < desc_count; i++) {
+               desc->desc_len = RESOURCE_DESC_SIZE;
+               if (((void *)desc + desc->desc_len) >
+                   (void *)(buf + max_buf_size)) {
+                       desc = NULL;
+                       break;
+               }
+
+               if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_ID)
+                       break;
+
+               desc = (void *)desc + desc->desc_len;
+       }
+
+       if (!desc || i == MAX_RESOURCE_DESC)
+               return NULL;
+
+       return desc;
+}
+
+/* Uses Mbox */
+int be_cmd_get_func_config(struct be_adapter *adapter)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_func_config *req;
+       int status;
+       struct be_dma_mem cmd;
+
+       memset(&cmd, 0, sizeof(struct be_dma_mem));
+       cmd.size = sizeof(struct be_cmd_resp_get_func_config);
+       cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+                                     &cmd.dma);
+       if (!cmd.va) {
+               dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+               return -ENOMEM;
+       }
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
+
+       wrb = wrb_from_mbox(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = cmd.va;
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_GET_FUNC_CONFIG,
+                              cmd.size, wrb, &cmd);
+
+       status = be_mbox_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_get_func_config *resp = cmd.va;
+               u32 desc_count = le32_to_cpu(resp->desc_count);
+               struct be_nic_resource_desc *desc;
+
+               desc = be_get_nic_desc(resp->func_param, desc_count,
+                                      sizeof(resp->func_param));
+               if (!desc) {
+                       status = -EINVAL;
+                       goto err;
+               }
+
+               adapter->pf_number = desc->pf_num;
+               adapter->max_pmac_cnt = le16_to_cpu(desc->unicast_mac_count);
+               adapter->max_vlans = le16_to_cpu(desc->vlan_count);
+               adapter->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count);
+               adapter->max_tx_queues = le16_to_cpu(desc->txq_count);
+               adapter->max_rss_queues = le16_to_cpu(desc->rssq_count);
+               adapter->max_rx_queues = le16_to_cpu(desc->rq_count);
+
+               adapter->max_event_queues = le16_to_cpu(desc->eq_count);
+               adapter->if_cap_flags = le32_to_cpu(desc->cap_flags);
+       }
+err:
+       mutex_unlock(&adapter->mbox_lock);
+       pci_free_consistent(adapter->pdev, cmd.size,
+                           cmd.va, cmd.dma);
+       return status;
+}
+
+ /* Uses sync mcc */
+int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+                             u8 domain)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_get_profile_config *req;
+       int status;
+       struct be_dma_mem cmd;
+
+       memset(&cmd, 0, sizeof(struct be_dma_mem));
+       cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
+       cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size,
+                                     &cmd.dma);
+       if (!cmd.va) {
+               dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
+               return -ENOMEM;
+       }
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = cmd.va;
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_GET_PROFILE_CONFIG,
+                              cmd.size, wrb, &cmd);
+
+       req->type = ACTIVE_PROFILE_TYPE;
+       req->hdr.domain = domain;
+
+       status = be_mcc_notify_wait(adapter);
+       if (!status) {
+               struct be_cmd_resp_get_profile_config *resp = cmd.va;
+               u32 desc_count = le32_to_cpu(resp->desc_count);
+               struct be_nic_resource_desc *desc;
+
+               desc = be_get_nic_desc(resp->func_param, desc_count,
+                                      sizeof(resp->func_param));
+
+               if (!desc) {
+                       status = -EINVAL;
+                       goto err;
+               }
+               *cap_flags = le32_to_cpu(desc->cap_flags);
+       }
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       pci_free_consistent(adapter->pdev, cmd.size,
+                           cmd.va, cmd.dma);
+       return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
+                             u8 domain)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_req_set_profile_config *req;
+       int status;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req),
+                              wrb, NULL);
+
+       req->hdr.domain = domain;
+       req->desc_count = cpu_to_le32(1);
+
+       req->nic_desc.desc_type = NIC_RESOURCE_DESC_TYPE_ID;
+       req->nic_desc.desc_len = RESOURCE_DESC_SIZE;
+       req->nic_desc.flags = (1 << QUN) | (1 << IMM) | (1 << NOSV);
+       req->nic_desc.pf_num = adapter->pf_number;
+       req->nic_desc.vf_num = domain;
+
+       /* Mark fields invalid */
+       req->nic_desc.unicast_mac_count = 0xFFFF;
+       req->nic_desc.mcc_count = 0xFFFF;
+       req->nic_desc.vlan_count = 0xFFFF;
+       req->nic_desc.mcast_mac_count = 0xFFFF;
+       req->nic_desc.txq_count = 0xFFFF;
+       req->nic_desc.rq_count = 0xFFFF;
+       req->nic_desc.rssq_count = 0xFFFF;
+       req->nic_desc.lro_count = 0xFFFF;
+       req->nic_desc.cq_count = 0xFFFF;
+       req->nic_desc.toe_conn_count = 0xFFFF;
+       req->nic_desc.eq_count = 0xFFFF;
+       req->nic_desc.link_param = 0xFF;
+       req->nic_desc.bw_min = 0xFFFFFFFF;
+       req->nic_desc.acpi_params = 0xFF;
+       req->nic_desc.wol_param = 0x0F;
+
+       /* Change BW */
+       req->nic_desc.bw_min = cpu_to_le32(bps);
+       req->nic_desc.bw_max = cpu_to_le32(bps);
+       status = be_mcc_notify_wait(adapter);
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
+/* Uses sync mcc */
+int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
+{
+       struct be_mcc_wrb *wrb;
+       struct be_cmd_enable_disable_vf *req;
+       int status;
+
+       if (!lancer_chip(adapter))
+               return 0;
+
+       spin_lock_bh(&adapter->mcc_lock);
+
+       wrb = wrb_from_mccq(adapter);
+       if (!wrb) {
+               status = -EBUSY;
+               goto err;
+       }
+
+       req = embedded_payload(wrb);
+
+       be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+                              OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req),
+                              wrb, NULL);
+
+       req->hdr.domain = domain;
+       req->enable = 1;
+       status = be_mcc_notify_wait(adapter);
+err:
+       spin_unlock_bh(&adapter->mcc_lock);
+       return status;
+}
+
 int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
                        int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
 {
index 0936e21e3cff3d6cdf3767dbf1d0e708744f9b26..d6552e19ffee386c369a13ae651634e9da2e1b62 100644 (file)
@@ -196,9 +196,14 @@ struct be_mcc_mailbox {
 #define OPCODE_COMMON_GET_MAC_LIST                     147
 #define OPCODE_COMMON_SET_MAC_LIST                     148
 #define OPCODE_COMMON_GET_HSW_CONFIG                   152
+#define OPCODE_COMMON_GET_FUNC_CONFIG                  160
+#define OPCODE_COMMON_GET_PROFILE_CONFIG               164
+#define OPCODE_COMMON_SET_PROFILE_CONFIG               165
 #define OPCODE_COMMON_SET_HSW_CONFIG                   153
+#define OPCODE_COMMON_GET_FN_PRIVILEGES                        170
 #define OPCODE_COMMON_READ_OBJECT                      171
 #define OPCODE_COMMON_WRITE_OBJECT                     172
+#define OPCODE_COMMON_ENABLE_DISABLE_VF                        196
 
 #define OPCODE_ETH_RSS_CONFIG                          1
 #define OPCODE_ETH_ACPI_CONFIG                         2
@@ -1151,14 +1156,22 @@ struct flashrom_params {
        u32 op_type;
        u32 data_buf_size;
        u32 offset;
-       u8 data_buf[4];
 };
 
 struct be_cmd_write_flashrom {
        struct be_cmd_req_hdr hdr;
        struct flashrom_params params;
-};
+       u8 data_buf[32768];
+       u8 rsvd[4];
+} __packed;
 
+/* cmd to read flash crc */
+struct be_cmd_read_flash_crc {
+       struct be_cmd_req_hdr hdr;
+       struct flashrom_params params;
+       u8 crc[4];
+       u8 rsvd[4];
+};
 /**************** Lancer Firmware Flash ************/
 struct amap_lancer_write_obj_context {
        u8 write_length[24];
@@ -1429,6 +1442,41 @@ struct be_cmd_resp_set_func_cap {
        u8 rsvd[212];
 };
 
+/*********************** Function Privileges ***********************/
+enum {
+       BE_PRIV_DEFAULT = 0x1,
+       BE_PRIV_LNKQUERY = 0x2,
+       BE_PRIV_LNKSTATS = 0x4,
+       BE_PRIV_LNKMGMT = 0x8,
+       BE_PRIV_LNKDIAG = 0x10,
+       BE_PRIV_UTILQUERY = 0x20,
+       BE_PRIV_FILTMGMT = 0x40,
+       BE_PRIV_IFACEMGMT = 0x80,
+       BE_PRIV_VHADM = 0x100,
+       BE_PRIV_DEVCFG = 0x200,
+       BE_PRIV_DEVSEC = 0x400
+};
+#define MAX_PRIVILEGES         (BE_PRIV_VHADM | BE_PRIV_DEVCFG | \
+                                BE_PRIV_DEVSEC)
+#define MIN_PRIVILEGES         BE_PRIV_DEFAULT
+
+struct be_cmd_priv_map {
+       u8 opcode;
+       u8 subsystem;
+       u32 priv_mask;
+};
+
+struct be_cmd_req_get_fn_privileges {
+       struct be_cmd_req_hdr hdr;
+       u32 rsvd;
+};
+
+struct be_cmd_resp_get_fn_privileges {
+       struct be_cmd_resp_hdr hdr;
+       u32 privilege_mask;
+};
+
+
 /******************** GET/SET_MACLIST  **************************/
 #define BE_MAX_MAC                     64
 struct be_cmd_req_get_mac_list {
@@ -1608,33 +1656,6 @@ struct be_cmd_resp_get_stats_v1 {
        struct be_hw_stats_v1 hw_stats;
 };
 
-static inline void *hw_stats_from_cmd(struct be_adapter *adapter)
-{
-       if (adapter->generation == BE_GEN3) {
-               struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va;
-
-               return &cmd->hw_stats;
-       } else {
-               struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va;
-
-               return &cmd->hw_stats;
-       }
-}
-
-static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter)
-{
-       if (adapter->generation == BE_GEN3) {
-               struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
-
-               return &hw_stats->erx;
-       } else {
-               struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
-
-               return &hw_stats->erx;
-       }
-}
-
-
 /************** get fat capabilites *******************/
 #define MAX_MODULES 27
 #define MAX_MODES 4
@@ -1684,6 +1705,96 @@ struct be_cmd_req_set_ext_fat_caps {
        struct be_fat_conf_params set_params;
 };
 
+#define RESOURCE_DESC_SIZE                     72
+#define NIC_RESOURCE_DESC_TYPE_ID              0x41
+#define MAX_RESOURCE_DESC                      4
+
+/* QOS unit number */
+#define QUN                                    4
+/* Immediate */
+#define IMM                                    6
+/* No save */
+#define NOSV                                   7
+
+struct be_nic_resource_desc {
+       u8 desc_type;
+       u8 desc_len;
+       u8 rsvd1;
+       u8 flags;
+       u8 vf_num;
+       u8 rsvd2;
+       u8 pf_num;
+       u8 rsvd3;
+       u16 unicast_mac_count;
+       u8 rsvd4[6];
+       u16 mcc_count;
+       u16 vlan_count;
+       u16 mcast_mac_count;
+       u16 txq_count;
+       u16 rq_count;
+       u16 rssq_count;
+       u16 lro_count;
+       u16 cq_count;
+       u16 toe_conn_count;
+       u16 eq_count;
+       u32 rsvd5;
+       u32 cap_flags;
+       u8 link_param;
+       u8 rsvd6[3];
+       u32 bw_min;
+       u32 bw_max;
+       u8 acpi_params;
+       u8 wol_param;
+       u16 rsvd7;
+       u32 rsvd8[3];
+};
+
+struct be_cmd_req_get_func_config {
+       struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_resp_get_func_config {
+       struct be_cmd_req_hdr hdr;
+       u32 desc_count;
+       u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE];
+};
+
+#define ACTIVE_PROFILE_TYPE                    0x2
+struct be_cmd_req_get_profile_config {
+       struct be_cmd_req_hdr hdr;
+       u8 rsvd;
+       u8 type;
+       u16 rsvd1;
+};
+
+struct be_cmd_resp_get_profile_config {
+       struct be_cmd_req_hdr hdr;
+       u32 desc_count;
+       u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE];
+};
+
+struct be_cmd_req_set_profile_config {
+       struct be_cmd_req_hdr hdr;
+       u32 rsvd;
+       u32 desc_count;
+       struct be_nic_resource_desc nic_desc;
+};
+
+struct be_cmd_resp_set_profile_config {
+       struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_enable_disable_vf {
+       struct be_cmd_req_hdr hdr;
+       u8 enable;
+       u8 rsvd[3];
+};
+
+static inline bool check_privilege(struct be_adapter *adapter, u32 flags)
+{
+       return flags & adapter->cmd_privileges ? true : false;
+}
+
 extern int be_pci_fnum_get(struct be_adapter *adapter);
 extern int be_fw_wait_ready(struct be_adapter *adapter);
 extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
@@ -1780,6 +1891,8 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
 extern int be_cmd_req_native_mode(struct be_adapter *adapter);
 extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size);
 extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf);
+extern int be_cmd_get_fn_privileges(struct be_adapter *adapter,
+                                   u32 *privilege, u32 domain);
 extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
                                    bool *pmac_id_active, u32 *pmac_id,
                                    u8 domain);
@@ -1798,4 +1911,10 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter,
 extern int lancer_wait_ready(struct be_adapter *adapter);
 extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter);
 extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name);
+extern int be_cmd_get_func_config(struct be_adapter *adapter);
+extern int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags,
+                                    u8 domain);
 
+extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps,
+                                    u8 domain);
+extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain);
index 8e6fb0ba6aa9631132686566859a8228c0c1fb86..00454a10f88d6111f5bfb30987703c04d807e8ba 100644 (file)
@@ -261,6 +261,9 @@ be_get_reg_len(struct net_device *netdev)
        struct be_adapter *adapter = netdev_priv(netdev);
        u32 log_size = 0;
 
+       if (!check_privilege(adapter, MAX_PRIVILEGES))
+               return 0;
+
        if (be_physfn(adapter)) {
                if (lancer_chip(adapter))
                        log_size = lancer_cmd_get_file_len(adapter,
@@ -525,6 +528,10 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
        u8 link_status;
        u16 link_speed = 0;
        int status;
+       u32 auto_speeds;
+       u32 fixed_speeds;
+       u32 dac_cable_len;
+       u16 interface_type;
 
        if (adapter->phy.link_speed < 0) {
                status = be_cmd_link_status_query(adapter, &link_speed,
@@ -534,39 +541,46 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
                ethtool_cmd_speed_set(ecmd, link_speed);
 
                status = be_cmd_get_phy_info(adapter);
-               if (status)
-                       return status;
-
-               ecmd->supported =
-                       convert_to_et_setting(adapter->phy.interface_type,
-                                       adapter->phy.auto_speeds_supported |
-                                       adapter->phy.fixed_speeds_supported);
-               ecmd->advertising =
-                       convert_to_et_setting(adapter->phy.interface_type,
-                                       adapter->phy.auto_speeds_supported);
-
-               ecmd->port = be_get_port_type(adapter->phy.interface_type,
-                                             adapter->phy.dac_cable_len);
-
-               if (adapter->phy.auto_speeds_supported) {
-                       ecmd->supported |= SUPPORTED_Autoneg;
-                       ecmd->autoneg = AUTONEG_ENABLE;
-                       ecmd->advertising |= ADVERTISED_Autoneg;
-               }
+               if (!status) {
+                       interface_type = adapter->phy.interface_type;
+                       auto_speeds = adapter->phy.auto_speeds_supported;
+                       fixed_speeds = adapter->phy.fixed_speeds_supported;
+                       dac_cable_len = adapter->phy.dac_cable_len;
+
+                       ecmd->supported =
+                               convert_to_et_setting(interface_type,
+                                                     auto_speeds |
+                                                     fixed_speeds);
+                       ecmd->advertising =
+                               convert_to_et_setting(interface_type,
+                                                     auto_speeds);
+
+                       ecmd->port = be_get_port_type(interface_type,
+                                                     dac_cable_len);
+
+                       if (adapter->phy.auto_speeds_supported) {
+                               ecmd->supported |= SUPPORTED_Autoneg;
+                               ecmd->autoneg = AUTONEG_ENABLE;
+                               ecmd->advertising |= ADVERTISED_Autoneg;
+                       }
 
-               if (be_pause_supported(adapter)) {
                        ecmd->supported |= SUPPORTED_Pause;
-                       ecmd->advertising |= ADVERTISED_Pause;
-               }
-
-               switch (adapter->phy.interface_type) {
-               case PHY_TYPE_KR_10GB:
-               case PHY_TYPE_KX4_10GB:
-                       ecmd->transceiver = XCVR_INTERNAL;
-                       break;
-               default:
-                       ecmd->transceiver = XCVR_EXTERNAL;
-                       break;
+                       if (be_pause_supported(adapter))
+                               ecmd->advertising |= ADVERTISED_Pause;
+
+                       switch (adapter->phy.interface_type) {
+                       case PHY_TYPE_KR_10GB:
+                       case PHY_TYPE_KX4_10GB:
+                               ecmd->transceiver = XCVR_INTERNAL;
+                               break;
+                       default:
+                               ecmd->transceiver = XCVR_EXTERNAL;
+                               break;
+                       }
+               } else {
+                       ecmd->port = PORT_OTHER;
+                       ecmd->autoneg = AUTONEG_DISABLE;
+                       ecmd->transceiver = XCVR_DUMMY1;
                }
 
                /* Save for future use */
@@ -787,6 +801,10 @@ static int
 be_get_eeprom_len(struct net_device *netdev)
 {
        struct be_adapter *adapter = netdev_priv(netdev);
+
+       if (!check_privilege(adapter, MAX_PRIVILEGES))
+               return 0;
+
        if (lancer_chip(adapter)) {
                if (be_physfn(adapter))
                        return lancer_cmd_get_file_len(adapter,
index b755f7061dce56edf88e486662c7d0c0b100a2a8..541d4530d5bfadb2d038b3aa4e233a069cf9c94a 100644 (file)
 
 #define MPU_EP_CONTROL                 0
 
-/********** MPU semphore ******************/
-#define MPU_EP_SEMAPHORE_OFFSET                0xac
-#define MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET       0x400
-#define EP_SEMAPHORE_POST_STAGE_MASK           0x0000FFFF
-#define EP_SEMAPHORE_POST_ERR_MASK             0x1
-#define EP_SEMAPHORE_POST_ERR_SHIFT            31
+/********** MPU semphore: used for SH & BE  *************/
+#define SLIPORT_SEMAPHORE_OFFSET_BE            0x7c
+#define SLIPORT_SEMAPHORE_OFFSET_SH            0x94
+#define POST_STAGE_MASK                                0x0000FFFF
+#define POST_ERR_MASK                          0x1
+#define POST_ERR_SHIFT                         31
 
 /* MPU semphore POST stage values */
 #define POST_STAGE_AWAITING_HOST_RDY   0x1 /* FW awaiting goahead from host */
@@ -59,6 +59,9 @@
 #define PHYSDEV_CONTROL_FW_RESET_MASK  0x00000002
 #define PHYSDEV_CONTROL_INP_MASK       0x40000000
 
+#define SLIPORT_ERROR_NO_RESOURCE1     0x2
+#define SLIPORT_ERROR_NO_RESOURCE2     0x9
+
 /********* Memory BAR register ************/
 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET     0xfc
 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
 #define SLI_INTF_TYPE_2                2
 #define SLI_INTF_TYPE_3                3
 
-/* SLI family */
-#define BE_SLI_FAMILY          0x0
-#define LANCER_A0_SLI_FAMILY   0xA
-#define SKYHAWK_SLI_FAMILY      0x2
-
 /********* ISR0 Register offset **********/
 #define CEV_ISR0_OFFSET                        0xC18
 #define CEV_ISR_SIZE                           4
index d1b6cc5876393cc598a5d473fab158bb13477bdd..f95612b907aea3a8341752f3e02f3446b432007e 100644 (file)
@@ -44,6 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = {
        { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)},
        { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)},
        { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)},
+       { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID6)},
        { 0 }
 };
 MODULE_DEVICE_TABLE(pci, be_dev_ids);
@@ -237,23 +238,46 @@ static int be_mac_addr_set(struct net_device *netdev, void *p)
        int status = 0;
        u8 current_mac[ETH_ALEN];
        u32 pmac_id = adapter->pmac_id[0];
+       bool active_mac = true;
 
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       status = be_cmd_mac_addr_query(adapter, current_mac, false,
-                                      adapter->if_handle, 0);
+       /* For BE VF, MAC address is already activated by PF.
+        * Hence only operation left is updating netdev->devaddr.
+        * Update it if user is passing the same MAC which was used
+        * during configuring VF MAC from PF(Hypervisor).
+        */
+       if (!lancer_chip(adapter) && !be_physfn(adapter)) {
+               status = be_cmd_mac_addr_query(adapter, current_mac,
+                                              false, adapter->if_handle, 0);
+               if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN))
+                       goto done;
+               else
+                       goto err;
+       }
+
+       if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN))
+               goto done;
+
+       /* For Lancer check if any MAC is active.
+        * If active, get its mac id.
+        */
+       if (lancer_chip(adapter) && !be_physfn(adapter))
+               be_cmd_get_mac_from_list(adapter, current_mac, &active_mac,
+                                        &pmac_id, 0);
+
+       status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
+                                adapter->if_handle,
+                                &adapter->pmac_id[0], 0);
+
        if (status)
                goto err;
 
-       if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) {
-               status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
-                               adapter->if_handle, &adapter->pmac_id[0], 0);
-               if (status)
-                       goto err;
-
-               be_cmd_pmac_del(adapter, adapter->if_handle, pmac_id, 0);
-       }
+       if (active_mac)
+               be_cmd_pmac_del(adapter, adapter->if_handle,
+                               pmac_id, 0);
+done:
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
        return 0;
 err:
@@ -261,7 +285,35 @@ err:
        return status;
 }
 
-static void populate_be2_stats(struct be_adapter *adapter)
+/* BE2 supports only v0 cmd */
+static void *hw_stats_from_cmd(struct be_adapter *adapter)
+{
+       if (BE2_chip(adapter)) {
+               struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va;
+
+               return &cmd->hw_stats;
+       } else  {
+               struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va;
+
+               return &cmd->hw_stats;
+       }
+}
+
+/* BE2 supports only v0 cmd */
+static void *be_erx_stats_from_cmd(struct be_adapter *adapter)
+{
+       if (BE2_chip(adapter)) {
+               struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
+
+               return &hw_stats->erx;
+       } else {
+               struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
+
+               return &hw_stats->erx;
+       }
+}
+
+static void populate_be_v0_stats(struct be_adapter *adapter)
 {
        struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter);
        struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
@@ -310,7 +362,7 @@ static void populate_be2_stats(struct be_adapter *adapter)
        adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops;
 }
 
-static void populate_be3_stats(struct be_adapter *adapter)
+static void populate_be_v1_stats(struct be_adapter *adapter)
 {
        struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter);
        struct be_pmem_stats *pmem_sts = &hw_stats->pmem;
@@ -412,28 +464,25 @@ void be_parse_stats(struct be_adapter *adapter)
        struct be_rx_obj *rxo;
        int i;
 
-       if (adapter->generation == BE_GEN3) {
-               if (lancer_chip(adapter))
-                       populate_lancer_stats(adapter);
-                else
-                       populate_be3_stats(adapter);
+       if (lancer_chip(adapter)) {
+               populate_lancer_stats(adapter);
        } else {
-               populate_be2_stats(adapter);
-       }
-
-       if (lancer_chip(adapter))
-               goto done;
+               if (BE2_chip(adapter))
+                       populate_be_v0_stats(adapter);
+               else
+                       /* for BE3 and Skyhawk */
+                       populate_be_v1_stats(adapter);
 
-       /* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */
-       for_all_rx_queues(adapter, rxo, i) {
-               /* below erx HW counter can actually wrap around after
-                * 65535. Driver accumulates a 32-bit value
-                */
-               accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
-                               (u16)erx->rx_drops_no_fragments[rxo->q.id]);
+               /* as erx_v1 is longer than v0, ok to use v1 for v0 access */
+               for_all_rx_queues(adapter, rxo, i) {
+                       /* below erx HW counter can actually wrap around after
+                        * 65535. Driver accumulates a 32-bit value
+                        */
+                       accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags,
+                                            (u16)erx->rx_drops_no_fragments \
+                                            [rxo->q.id]);
+               }
        }
-done:
-       return;
 }
 
 static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev,
@@ -597,16 +646,6 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr,
                        hdr, skb_shinfo(skb)->gso_size);
                if (skb_is_gso_v6(skb) && !lancer_chip(adapter))
                        AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1);
-               if (lancer_chip(adapter) && adapter->sli_family  ==
-                                                       LANCER_A0_SLI_FAMILY) {
-                       AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1);
-                       if (is_tcp_pkt(skb))
-                               AMAP_SET_BITS(struct amap_eth_hdr_wrb,
-                                                               tcpcs, hdr, 1);
-                       else if (is_udp_pkt(skb))
-                               AMAP_SET_BITS(struct amap_eth_hdr_wrb,
-                                                               udpcs, hdr, 1);
-               }
        } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
                if (is_tcp_pkt(skb))
                        AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1);
@@ -856,11 +895,15 @@ static int be_vlan_add_vid(struct net_device *netdev, u16 vid)
        struct be_adapter *adapter = netdev_priv(netdev);
        int status = 0;
 
-       if (!be_physfn(adapter)) {
+       if (!lancer_chip(adapter) && !be_physfn(adapter)) {
                status = -EINVAL;
                goto ret;
        }
 
+       /* Packets with VID 0 are always received by Lancer by default */
+       if (lancer_chip(adapter) && vid == 0)
+               goto ret;
+
        adapter->vlan_tag[vid] = 1;
        if (adapter->vlans_added <= (adapter->max_vlans + 1))
                status = be_vid_config(adapter);
@@ -878,11 +921,15 @@ static int be_vlan_rem_vid(struct net_device *netdev, u16 vid)
        struct be_adapter *adapter = netdev_priv(netdev);
        int status = 0;
 
-       if (!be_physfn(adapter)) {
+       if (!lancer_chip(adapter) && !be_physfn(adapter)) {
                status = -EINVAL;
                goto ret;
        }
 
+       /* Packets with VID 0 are always received by Lancer by default */
+       if (lancer_chip(adapter) && vid == 0)
+               goto ret;
+
        adapter->vlan_tag[vid] = 0;
        if (adapter->vlans_added <= adapter->max_vlans)
                status = be_vid_config(adapter);
@@ -917,7 +964,7 @@ static void be_set_rx_mode(struct net_device *netdev)
 
        /* Enable multicast promisc if num configured exceeds what we support */
        if (netdev->flags & IFF_ALLMULTI ||
-                       netdev_mc_count(netdev) > BE_MAX_MC) {
+           netdev_mc_count(netdev) > adapter->max_mcast_mac) {
                be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
                goto done;
        }
@@ -962,6 +1009,9 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
        struct be_adapter *adapter = netdev_priv(netdev);
        struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf];
        int status;
+       bool active_mac = false;
+       u32 pmac_id;
+       u8 old_mac[ETH_ALEN];
 
        if (!sriov_enabled(adapter))
                return -EPERM;
@@ -970,6 +1020,12 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
                return -EINVAL;
 
        if (lancer_chip(adapter)) {
+               status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac,
+                                                 &pmac_id, vf + 1);
+               if (!status && active_mac)
+                       be_cmd_pmac_del(adapter, vf_cfg->if_handle,
+                                       pmac_id, vf + 1);
+
                status = be_cmd_set_mac_list(adapter,  mac, 1, vf + 1);
        } else {
                status = be_cmd_pmac_del(adapter, vf_cfg->if_handle,
@@ -1062,7 +1118,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev,
                return -EINVAL;
        }
 
-       status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
+       if (lancer_chip(adapter))
+               status = be_cmd_set_profile_config(adapter, rate / 10, vf + 1);
+       else
+               status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
 
        if (status)
                dev_err(&adapter->pdev->dev,
@@ -1616,24 +1675,6 @@ static inline int events_get(struct be_eq_obj *eqo)
        return num;
 }
 
-static int event_handle(struct be_eq_obj *eqo)
-{
-       bool rearm = false;
-       int num = events_get(eqo);
-
-       /* Deal with any spurious interrupts that come without events */
-       if (!num)
-               rearm = true;
-
-       if (num || msix_enabled(eqo->adapter))
-               be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num);
-
-       if (num)
-               napi_schedule(&eqo->napi);
-
-       return num;
-}
-
 /* Leaves the EQ is disarmed state */
 static void be_eq_clean(struct be_eq_obj *eqo)
 {
@@ -1837,12 +1878,13 @@ static void be_tx_queues_destroy(struct be_adapter *adapter)
 
 static int be_num_txqs_want(struct be_adapter *adapter)
 {
-       if (sriov_want(adapter) || be_is_mc(adapter) ||
-           lancer_chip(adapter) || !be_physfn(adapter) ||
-           adapter->generation == BE_GEN2)
+       if ((!lancer_chip(adapter) && sriov_want(adapter)) ||
+           be_is_mc(adapter) ||
+           (!lancer_chip(adapter) && !be_physfn(adapter)) ||
+           BE2_chip(adapter))
                return 1;
        else
-               return MAX_TX_QS;
+               return adapter->max_tx_queues;
 }
 
 static int be_tx_cqs_create(struct be_adapter *adapter)
@@ -1954,22 +1996,31 @@ static int be_rx_cqs_create(struct be_adapter *adapter)
 
 static irqreturn_t be_intx(int irq, void *dev)
 {
-       struct be_adapter *adapter = dev;
-       int num_evts;
+       struct be_eq_obj *eqo = dev;
+       struct be_adapter *adapter = eqo->adapter;
+       int num_evts = 0;
 
-       /* With INTx only one EQ is used */
-       num_evts = event_handle(&adapter->eq_obj[0]);
-       if (num_evts)
-               return IRQ_HANDLED;
-       else
-               return IRQ_NONE;
+       /* On Lancer, clear-intr bit of the EQ DB does not work.
+        * INTx is de-asserted only on notifying num evts.
+        */
+       if (lancer_chip(adapter))
+               num_evts = events_get(eqo);
+
+       /* The EQ-notify may not de-assert INTx rightaway, causing
+        * the ISR to be invoked again. So, return HANDLED even when
+        * num_evts is zero.
+        */
+       be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
+       napi_schedule(&eqo->napi);
+       return IRQ_HANDLED;
 }
 
 static irqreturn_t be_msix(int irq, void *dev)
 {
        struct be_eq_obj *eqo = dev;
 
-       event_handle(eqo);
+       be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0);
+       napi_schedule(&eqo->napi);
        return IRQ_HANDLED;
 }
 
@@ -2065,9 +2116,11 @@ int be_poll(struct napi_struct *napi, int budget)
 {
        struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi);
        struct be_adapter *adapter = eqo->adapter;
-       int max_work = 0, work, i;
+       int max_work = 0, work, i, num_evts;
        bool tx_done;
 
+       num_evts = events_get(eqo);
+
        /* Process all TXQs serviced by this EQ */
        for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) {
                tx_done = be_process_tx(adapter, &adapter->tx_obj[i],
@@ -2090,10 +2143,10 @@ int be_poll(struct napi_struct *napi, int budget)
 
        if (max_work < budget) {
                napi_complete(napi);
-               be_eq_notify(adapter, eqo->q.id, true, false, 0);
+               be_eq_notify(adapter, eqo->q.id, true, false, num_evts);
        } else {
                /* As we'll continue in polling mode, count and clear events */
-               be_eq_notify(adapter, eqo->q.id, false, false, events_get(eqo));
+               be_eq_notify(adapter, eqo->q.id, false, false, num_evts);
        }
        return max_work;
 }
@@ -2177,9 +2230,11 @@ static void be_msix_disable(struct be_adapter *adapter)
 static uint be_num_rss_want(struct be_adapter *adapter)
 {
        u32 num = 0;
+
        if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) &&
-            !sriov_want(adapter) && be_physfn(adapter)) {
-               num = (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+           (lancer_chip(adapter) ||
+            (!sriov_want(adapter) && be_physfn(adapter)))) {
+               num = adapter->max_rss_queues;
                num = min_t(u32, num, (u32)netif_get_num_default_rss_queues());
        }
        return num;
@@ -2277,10 +2332,10 @@ static int be_irq_register(struct be_adapter *adapter)
                        return status;
        }
 
-       /* INTx */
+       /* INTx: only the first EQ is used */
        netdev->irq = adapter->pdev->irq;
        status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name,
-                       adapter);
+                            &adapter->eq_obj[0]);
        if (status) {
                dev_err(&adapter->pdev->dev,
                        "INTx request IRQ failed - err %d\n", status);
@@ -2302,7 +2357,7 @@ static void be_irq_unregister(struct be_adapter *adapter)
 
        /* INTx */
        if (!msix_enabled(adapter)) {
-               free_irq(netdev->irq, adapter);
+               free_irq(netdev->irq, &adapter->eq_obj[0]);
                goto done;
        }
 
@@ -2579,10 +2634,30 @@ static int be_clear(struct be_adapter *adapter)
        be_tx_queues_destroy(adapter);
        be_evt_queues_destroy(adapter);
 
+       kfree(adapter->pmac_id);
+       adapter->pmac_id = NULL;
+
        be_msix_disable(adapter);
        return 0;
 }
 
+static void be_get_vf_if_cap_flags(struct be_adapter *adapter,
+                                  u32 *cap_flags, u8 domain)
+{
+       bool profile_present = false;
+       int status;
+
+       if (lancer_chip(adapter)) {
+               status = be_cmd_get_profile_config(adapter, cap_flags, domain);
+               if (!status)
+                       profile_present = true;
+       }
+
+       if (!profile_present)
+               *cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+                            BE_IF_FLAGS_MULTICAST;
+}
+
 static int be_vf_setup_init(struct be_adapter *adapter)
 {
        struct be_vf_cfg *vf_cfg;
@@ -2634,9 +2709,13 @@ static int be_vf_setup(struct be_adapter *adapter)
        if (status)
                goto err;
 
-       cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
-                               BE_IF_FLAGS_MULTICAST;
        for_all_vfs(adapter, vf_cfg, vf) {
+               be_get_vf_if_cap_flags(adapter, &cap_flags, vf + 1);
+
+               en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
+                                       BE_IF_FLAGS_BROADCAST |
+                                       BE_IF_FLAGS_MULTICAST);
+
                status = be_cmd_if_create(adapter, cap_flags, en_flags,
                                          &vf_cfg->if_handle, vf + 1);
                if (status)
@@ -2661,6 +2740,8 @@ static int be_vf_setup(struct be_adapter *adapter)
                if (status)
                        goto err;
                vf_cfg->def_vid = def_vlan;
+
+               be_cmd_enable_vf(adapter, vf + 1);
        }
        return 0;
 err:
@@ -2674,7 +2755,10 @@ static void be_setup_init(struct be_adapter *adapter)
        adapter->if_handle = -1;
        adapter->be3_native = false;
        adapter->promiscuous = false;
-       adapter->eq_next_idx = 0;
+       if (be_physfn(adapter))
+               adapter->cmd_privileges = MAX_PRIVILEGES;
+       else
+               adapter->cmd_privileges = MIN_PRIVILEGES;
 }
 
 static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
@@ -2712,12 +2796,93 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle,
        return status;
 }
 
+static void be_get_resources(struct be_adapter *adapter)
+{
+       int status;
+       bool profile_present = false;
+
+       if (lancer_chip(adapter)) {
+               status = be_cmd_get_func_config(adapter);
+
+               if (!status)
+                       profile_present = true;
+       }
+
+       if (profile_present) {
+               /* Sanity fixes for Lancer */
+               adapter->max_pmac_cnt = min_t(u16, adapter->max_pmac_cnt,
+                                             BE_UC_PMAC_COUNT);
+               adapter->max_vlans = min_t(u16, adapter->max_vlans,
+                                          BE_NUM_VLANS_SUPPORTED);
+               adapter->max_mcast_mac = min_t(u16, adapter->max_mcast_mac,
+                                              BE_MAX_MC);
+               adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues,
+                                              MAX_TX_QS);
+               adapter->max_rss_queues = min_t(u16, adapter->max_rss_queues,
+                                               BE3_MAX_RSS_QS);
+               adapter->max_event_queues = min_t(u16,
+                                                 adapter->max_event_queues,
+                                                 BE3_MAX_RSS_QS);
+
+               if (adapter->max_rss_queues &&
+                   adapter->max_rss_queues == adapter->max_rx_queues)
+                       adapter->max_rss_queues -= 1;
+
+               if (adapter->max_event_queues < adapter->max_rss_queues)
+                       adapter->max_rss_queues = adapter->max_event_queues;
+
+       } else {
+               if (be_physfn(adapter))
+                       adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
+               else
+                       adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
+
+               if (adapter->function_mode & FLEX10_MODE)
+                       adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
+               else
+                       adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
+
+               adapter->max_mcast_mac = BE_MAX_MC;
+               adapter->max_tx_queues = MAX_TX_QS;
+               adapter->max_rss_queues = (adapter->be3_native) ?
+                                          BE3_MAX_RSS_QS : BE2_MAX_RSS_QS;
+               adapter->max_event_queues = BE3_MAX_RSS_QS;
+
+               adapter->if_cap_flags = BE_IF_FLAGS_UNTAGGED |
+                                       BE_IF_FLAGS_BROADCAST |
+                                       BE_IF_FLAGS_MULTICAST |
+                                       BE_IF_FLAGS_PASS_L3L4_ERRORS |
+                                       BE_IF_FLAGS_MCAST_PROMISCUOUS |
+                                       BE_IF_FLAGS_VLAN_PROMISCUOUS |
+                                       BE_IF_FLAGS_PROMISCUOUS;
+
+               if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
+                       adapter->if_cap_flags |= BE_IF_FLAGS_RSS;
+       }
+}
+
 /* Routine to query per function resource limits */
 static int be_get_config(struct be_adapter *adapter)
 {
-       int pos;
+       int pos, status;
        u16 dev_num_vfs;
 
+       status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
+                                    &adapter->function_mode,
+                                    &adapter->function_caps);
+       if (status)
+               goto err;
+
+       be_get_resources(adapter);
+
+       /* primary mac needs 1 pmac entry */
+       adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
+                                  sizeof(u32), GFP_KERNEL);
+       if (!adapter->pmac_id) {
+               status = -ENOMEM;
+               goto err;
+       }
+
        pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV);
        if (pos) {
                pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF,
@@ -2726,13 +2891,14 @@ static int be_get_config(struct be_adapter *adapter)
                        dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS);
                adapter->dev_num_vfs = dev_num_vfs;
        }
-       return 0;
+err:
+       return status;
 }
 
 static int be_setup(struct be_adapter *adapter)
 {
        struct device *dev = &adapter->pdev->dev;
-       u32 cap_flags, en_flags;
+       u32 en_flags;
        u32 tx_fc, rx_fc;
        int status;
        u8 mac[ETH_ALEN];
@@ -2740,9 +2906,12 @@ static int be_setup(struct be_adapter *adapter)
 
        be_setup_init(adapter);
 
-       be_get_config(adapter);
+       if (!lancer_chip(adapter))
+               be_cmd_req_native_mode(adapter);
 
-       be_cmd_req_native_mode(adapter);
+       status = be_get_config(adapter);
+       if (status)
+               goto err;
 
        be_msix_enable(adapter);
 
@@ -2762,24 +2931,22 @@ static int be_setup(struct be_adapter *adapter)
        if (status)
                goto err;
 
+       be_cmd_get_fn_privileges(adapter, &adapter->cmd_privileges, 0);
+       /* In UMC mode FW does not return right privileges.
+        * Override with correct privilege equivalent to PF.
+        */
+       if (be_is_mc(adapter))
+               adapter->cmd_privileges = MAX_PRIVILEGES;
+
        en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
                        BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS;
-       cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS |
-                       BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS;
 
-       if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) {
-               cap_flags |= BE_IF_FLAGS_RSS;
+       if (adapter->function_caps & BE_FUNCTION_CAPS_RSS)
                en_flags |= BE_IF_FLAGS_RSS;
-       }
 
-       if (lancer_chip(adapter) && !be_physfn(adapter)) {
-               en_flags = BE_IF_FLAGS_UNTAGGED |
-                           BE_IF_FLAGS_BROADCAST |
-                           BE_IF_FLAGS_MULTICAST;
-               cap_flags = en_flags;
-       }
+       en_flags = en_flags & adapter->if_cap_flags;
 
-       status = be_cmd_if_create(adapter, cap_flags, en_flags,
+       status = be_cmd_if_create(adapter, adapter->if_cap_flags, en_flags,
                                  &adapter->if_handle, 0);
        if (status != 0)
                goto err;
@@ -2827,8 +2994,8 @@ static int be_setup(struct be_adapter *adapter)
                        dev_warn(dev, "device doesn't support SRIOV\n");
        }
 
-       be_cmd_get_phy_info(adapter);
-       if (be_pause_supported(adapter))
+       status = be_cmd_get_phy_info(adapter);
+       if (!status && be_pause_supported(adapter))
                adapter->phy.fc_autoneg = 1;
 
        schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
@@ -2846,8 +3013,10 @@ static void be_netpoll(struct net_device *netdev)
        struct be_eq_obj *eqo;
        int i;
 
-       for_all_evt_queues(adapter, eqo, i)
-               event_handle(eqo);
+       for_all_evt_queues(adapter, eqo, i) {
+               be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0);
+               napi_schedule(&eqo->napi);
+       }
 
        return;
 }
@@ -2895,7 +3064,7 @@ static bool is_comp_in_ufi(struct be_adapter *adapter,
        int i = 0, img_type = 0;
        struct flash_section_info_g2 *fsec_g2 = NULL;
 
-       if (adapter->generation != BE_GEN3)
+       if (BE2_chip(adapter))
                fsec_g2 = (struct flash_section_info_g2 *)fsec;
 
        for (i = 0; i < MAX_FLASH_COMP; i++) {
@@ -2928,7 +3097,49 @@ struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
        return NULL;
 }
 
-static int be_flash_data(struct be_adapter *adapter,
+static int be_flash(struct be_adapter *adapter, const u8 *img,
+               struct be_dma_mem *flash_cmd, int optype, int img_size)
+{
+       u32 total_bytes = 0, flash_op, num_bytes = 0;
+       int status = 0;
+       struct be_cmd_write_flashrom *req = flash_cmd->va;
+
+       total_bytes = img_size;
+       while (total_bytes) {
+               num_bytes = min_t(u32, 32*1024, total_bytes);
+
+               total_bytes -= num_bytes;
+
+               if (!total_bytes) {
+                       if (optype == OPTYPE_PHY_FW)
+                               flash_op = FLASHROM_OPER_PHY_FLASH;
+                       else
+                               flash_op = FLASHROM_OPER_FLASH;
+               } else {
+                       if (optype == OPTYPE_PHY_FW)
+                               flash_op = FLASHROM_OPER_PHY_SAVE;
+                       else
+                               flash_op = FLASHROM_OPER_SAVE;
+               }
+
+               memcpy(req->data_buf, img, num_bytes);
+               img += num_bytes;
+               status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
+                                               flash_op, num_bytes);
+               if (status) {
+                       if (status == ILLEGAL_IOCTL_REQ &&
+                           optype == OPTYPE_PHY_FW)
+                               break;
+                       dev_err(&adapter->pdev->dev,
+                               "cmd to write to flash rom failed.\n");
+                       return status;
+               }
+       }
+       return 0;
+}
+
+/* For BE2 and BE3 */
+static int be_flash_BEx(struct be_adapter *adapter,
                         const struct firmware *fw,
                         struct be_dma_mem *flash_cmd,
                         int num_of_images)
@@ -2936,12 +3147,9 @@ static int be_flash_data(struct be_adapter *adapter,
 {
        int status = 0, i, filehdr_size = 0;
        int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
-       u32 total_bytes = 0, flash_op;
-       int num_bytes;
        const u8 *p = fw->data;
-       struct be_cmd_write_flashrom *req = flash_cmd->va;
        const struct flash_comp *pflashcomp;
-       int num_comp, hdr_size;
+       int num_comp, redboot;
        struct flash_section_info *fsec = NULL;
 
        struct flash_comp gen3_flash_types[] = {
@@ -2986,7 +3194,7 @@ static int be_flash_data(struct be_adapter *adapter,
                         FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE}
        };
 
-       if (adapter->generation == BE_GEN3) {
+       if (BE3_chip(adapter)) {
                pflashcomp = gen3_flash_types;
                filehdr_size = sizeof(struct flash_file_hdr_g3);
                num_comp = ARRAY_SIZE(gen3_flash_types);
@@ -2995,6 +3203,7 @@ static int be_flash_data(struct be_adapter *adapter,
                filehdr_size = sizeof(struct flash_file_hdr_g2);
                num_comp = ARRAY_SIZE(gen2_flash_types);
        }
+
        /* Get flash section info*/
        fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
        if (!fsec) {
@@ -3010,70 +3219,105 @@ static int be_flash_data(struct be_adapter *adapter,
                    memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0)
                        continue;
 
-               if (pflashcomp[i].optype == OPTYPE_PHY_FW) {
-                       if (!phy_flashing_required(adapter))
+               if (pflashcomp[i].optype == OPTYPE_PHY_FW  &&
+                   !phy_flashing_required(adapter))
                                continue;
-               }
-
-               hdr_size = filehdr_size +
-                          (num_of_images * sizeof(struct image_hdr));
 
-               if ((pflashcomp[i].optype == OPTYPE_REDBOOT) &&
-                   (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset,
-                                      pflashcomp[i].size, hdr_size)))
-                       continue;
+               if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
+                       redboot = be_flash_redboot(adapter, fw->data,
+                               pflashcomp[i].offset, pflashcomp[i].size,
+                               filehdr_size + img_hdrs_size);
+                       if (!redboot)
+                               continue;
+               }
 
-               /* Flash the component */
                p = fw->data;
                p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
                if (p + pflashcomp[i].size > fw->data + fw->size)
                        return -1;
-               total_bytes = pflashcomp[i].size;
-               while (total_bytes) {
-                       if (total_bytes > 32*1024)
-                               num_bytes = 32*1024;
-                       else
-                               num_bytes = total_bytes;
-                       total_bytes -= num_bytes;
-                       if (!total_bytes) {
-                               if (pflashcomp[i].optype == OPTYPE_PHY_FW)
-                                       flash_op = FLASHROM_OPER_PHY_FLASH;
-                               else
-                                       flash_op = FLASHROM_OPER_FLASH;
-                       } else {
-                               if (pflashcomp[i].optype == OPTYPE_PHY_FW)
-                                       flash_op = FLASHROM_OPER_PHY_SAVE;
-                               else
-                                       flash_op = FLASHROM_OPER_SAVE;
-                       }
-                       memcpy(req->params.data_buf, p, num_bytes);
-                       p += num_bytes;
-                       status = be_cmd_write_flashrom(adapter, flash_cmd,
-                               pflashcomp[i].optype, flash_op, num_bytes);
-                       if (status) {
-                               if ((status == ILLEGAL_IOCTL_REQ) &&
-                                       (pflashcomp[i].optype ==
-                                               OPTYPE_PHY_FW))
-                                       break;
-                               dev_err(&adapter->pdev->dev,
-                                       "cmd to write to flash rom failed.\n");
-                               return -1;
-                       }
+
+               status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
+                                       pflashcomp[i].size);
+               if (status) {
+                       dev_err(&adapter->pdev->dev,
+                               "Flashing section type %d failed.\n",
+                               pflashcomp[i].img_type);
+                       return status;
                }
        }
        return 0;
 }
 
-static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr)
+static int be_flash_skyhawk(struct be_adapter *adapter,
+               const struct firmware *fw,
+               struct be_dma_mem *flash_cmd, int num_of_images)
 {
-       if (fhdr == NULL)
-               return 0;
-       if (fhdr->build[0] == '3')
-               return BE_GEN3;
-       else if (fhdr->build[0] == '2')
-               return BE_GEN2;
-       else
-               return 0;
+       int status = 0, i, filehdr_size = 0;
+       int img_offset, img_size, img_optype, redboot;
+       int img_hdrs_size = num_of_images * sizeof(struct image_hdr);
+       const u8 *p = fw->data;
+       struct flash_section_info *fsec = NULL;
+
+       filehdr_size = sizeof(struct flash_file_hdr_g3);
+       fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
+       if (!fsec) {
+               dev_err(&adapter->pdev->dev,
+                       "Invalid Cookie. UFI corrupted ?\n");
+               return -1;
+       }
+
+       for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
+               img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
+               img_size   = le32_to_cpu(fsec->fsec_entry[i].pad_size);
+
+               switch (le32_to_cpu(fsec->fsec_entry[i].type)) {
+               case IMAGE_FIRMWARE_iSCSI:
+                       img_optype = OPTYPE_ISCSI_ACTIVE;
+                       break;
+               case IMAGE_BOOT_CODE:
+                       img_optype = OPTYPE_REDBOOT;
+                       break;
+               case IMAGE_OPTION_ROM_ISCSI:
+                       img_optype = OPTYPE_BIOS;
+                       break;
+               case IMAGE_OPTION_ROM_PXE:
+                       img_optype = OPTYPE_PXE_BIOS;
+                       break;
+               case IMAGE_OPTION_ROM_FCoE:
+                       img_optype = OPTYPE_FCOE_BIOS;
+                       break;
+               case IMAGE_FIRMWARE_BACKUP_iSCSI:
+                       img_optype = OPTYPE_ISCSI_BACKUP;
+                       break;
+               case IMAGE_NCSI:
+                       img_optype = OPTYPE_NCSI_FW;
+                       break;
+               default:
+                       continue;
+               }
+
+               if (img_optype == OPTYPE_REDBOOT) {
+                       redboot = be_flash_redboot(adapter, fw->data,
+                                       img_offset, img_size,
+                                       filehdr_size + img_hdrs_size);
+                       if (!redboot)
+                               continue;
+               }
+
+               p = fw->data;
+               p += filehdr_size + img_offset + img_hdrs_size;
+               if (p + img_size > fw->data + fw->size)
+                       return -1;
+
+               status = be_flash(adapter, p, flash_cmd, img_optype, img_size);
+               if (status) {
+                       dev_err(&adapter->pdev->dev,
+                               "Flashing section type %d failed.\n",
+                               fsec->fsec_entry[i].type);
+                       return status;
+               }
+       }
+       return 0;
 }
 
 static int lancer_wait_idle(struct be_adapter *adapter)
@@ -3207,6 +3451,28 @@ lancer_fw_exit:
        return status;
 }
 
+#define UFI_TYPE2              2
+#define UFI_TYPE3              3
+#define UFI_TYPE4              4
+static int be_get_ufi_type(struct be_adapter *adapter,
+                          struct flash_file_hdr_g2 *fhdr)
+{
+       if (fhdr == NULL)
+               goto be_get_ufi_exit;
+
+       if (skyhawk_chip(adapter) && fhdr->build[0] == '4')
+               return UFI_TYPE4;
+       else if (BE3_chip(adapter) && fhdr->build[0] == '3')
+               return UFI_TYPE3;
+       else if (BE2_chip(adapter) && fhdr->build[0] == '2')
+               return UFI_TYPE2;
+
+be_get_ufi_exit:
+       dev_err(&adapter->pdev->dev,
+               "UFI and Interface are not compatible for flashing\n");
+       return -1;
+}
+
 static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
 {
        struct flash_file_hdr_g2 *fhdr;
@@ -3214,12 +3480,9 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
        struct image_hdr *img_hdr_ptr = NULL;
        struct be_dma_mem flash_cmd;
        const u8 *p;
-       int status = 0, i = 0, num_imgs = 0;
-
-       p = fw->data;
-       fhdr = (struct flash_file_hdr_g2 *) p;
+       int status = 0, i = 0, num_imgs = 0, ufi_type = 0;
 
-       flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
+       flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
        flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
                                          &flash_cmd.dma, GFP_KERNEL);
        if (!flash_cmd.va) {
@@ -3229,27 +3492,32 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw)
                goto be_fw_exit;
        }
 
-       if ((adapter->generation == BE_GEN3) &&
-                       (get_ufigen_type(fhdr) == BE_GEN3)) {
-               fhdr3 = (struct flash_file_hdr_g3 *) fw->data;
-               num_imgs = le32_to_cpu(fhdr3->num_imgs);
-               for (i = 0; i < num_imgs; i++) {
-                       img_hdr_ptr = (struct image_hdr *) (fw->data +
-                                       (sizeof(struct flash_file_hdr_g3) +
-                                        i * sizeof(struct image_hdr)));
-                       if (le32_to_cpu(img_hdr_ptr->imageid) == 1)
-                               status = be_flash_data(adapter, fw, &flash_cmd,
-                                                       num_imgs);
+       p = fw->data;
+       fhdr = (struct flash_file_hdr_g2 *)p;
+
+       ufi_type = be_get_ufi_type(adapter, fhdr);
+
+       fhdr3 = (struct flash_file_hdr_g3 *)fw->data;
+       num_imgs = le32_to_cpu(fhdr3->num_imgs);
+       for (i = 0; i < num_imgs; i++) {
+               img_hdr_ptr = (struct image_hdr *)(fw->data +
+                               (sizeof(struct flash_file_hdr_g3) +
+                                i * sizeof(struct image_hdr)));
+               if (le32_to_cpu(img_hdr_ptr->imageid) == 1) {
+                       if (ufi_type == UFI_TYPE4)
+                               status = be_flash_skyhawk(adapter, fw,
+                                                       &flash_cmd, num_imgs);
+                       else if (ufi_type == UFI_TYPE3)
+                               status = be_flash_BEx(adapter, fw, &flash_cmd,
+                                                     num_imgs);
                }
-       } else if ((adapter->generation == BE_GEN2) &&
-                       (get_ufigen_type(fhdr) == BE_GEN2)) {
-               status = be_flash_data(adapter, fw, &flash_cmd, 0);
-       } else {
-               dev_err(&adapter->pdev->dev,
-                       "UFI and Interface are not compatible for flashing\n");
-               status = -1;
        }
 
+       if (ufi_type == UFI_TYPE2)
+               status = be_flash_BEx(adapter, fw, &flash_cmd, 0);
+       else if (ufi_type == -1)
+               status = -1;
+
        dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
                          flash_cmd.dma);
        if (status) {
@@ -3344,80 +3612,47 @@ static void be_netdev_init(struct net_device *netdev)
 
 static void be_unmap_pci_bars(struct be_adapter *adapter)
 {
-       if (adapter->csr)
-               iounmap(adapter->csr);
        if (adapter->db)
-               iounmap(adapter->db);
-       if (adapter->roce_db.base)
-               pci_iounmap(adapter->pdev, adapter->roce_db.base);
+               pci_iounmap(adapter->pdev, adapter->db);
 }
 
-static int lancer_roce_map_pci_bars(struct be_adapter *adapter)
+static int db_bar(struct be_adapter *adapter)
 {
-       struct pci_dev *pdev = adapter->pdev;
-       u8 __iomem *addr;
-
-       addr = pci_iomap(pdev, 2, 0);
-       if (addr == NULL)
-               return -ENOMEM;
+       if (lancer_chip(adapter) || !be_physfn(adapter))
+               return 0;
+       else
+               return 4;
+}
 
-       adapter->roce_db.base = addr;
-       adapter->roce_db.io_addr = pci_resource_start(pdev, 2);
-       adapter->roce_db.size = 8192;
-       adapter->roce_db.total_size = pci_resource_len(pdev, 2);
+static int be_roce_map_pci_bars(struct be_adapter *adapter)
+{
+       if (skyhawk_chip(adapter)) {
+               adapter->roce_db.size = 4096;
+               adapter->roce_db.io_addr = pci_resource_start(adapter->pdev,
+                                                             db_bar(adapter));
+               adapter->roce_db.total_size = pci_resource_len(adapter->pdev,
+                                                              db_bar(adapter));
+       }
        return 0;
 }
 
 static int be_map_pci_bars(struct be_adapter *adapter)
 {
        u8 __iomem *addr;
-       int db_reg;
+       u32 sli_intf;
 
-       if (lancer_chip(adapter)) {
-               if (be_type_2_3(adapter)) {
-                       addr = ioremap_nocache(
-                                       pci_resource_start(adapter->pdev, 0),
-                                       pci_resource_len(adapter->pdev, 0));
-                       if (addr == NULL)
-                               return -ENOMEM;
-                       adapter->db = addr;
-               }
-               if (adapter->if_type == SLI_INTF_TYPE_3) {
-                       if (lancer_roce_map_pci_bars(adapter))
-                               goto pci_map_err;
-               }
-               return 0;
-       }
-
-       if (be_physfn(adapter)) {
-               addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2),
-                               pci_resource_len(adapter->pdev, 2));
-               if (addr == NULL)
-                       return -ENOMEM;
-               adapter->csr = addr;
-       }
+       pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+       adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
+                               SLI_INTF_IF_TYPE_SHIFT;
 
-       if (adapter->generation == BE_GEN2) {
-               db_reg = 4;
-       } else {
-               if (be_physfn(adapter))
-                       db_reg = 4;
-               else
-                       db_reg = 0;
-       }
-       addr = ioremap_nocache(pci_resource_start(adapter->pdev, db_reg),
-                               pci_resource_len(adapter->pdev, db_reg));
+       addr = pci_iomap(adapter->pdev, db_bar(adapter), 0);
        if (addr == NULL)
                goto pci_map_err;
        adapter->db = addr;
-       if (adapter->sli_family == SKYHAWK_SLI_FAMILY) {
-               adapter->roce_db.size = 4096;
-               adapter->roce_db.io_addr =
-                               pci_resource_start(adapter->pdev, db_reg);
-               adapter->roce_db.total_size =
-                               pci_resource_len(adapter->pdev, db_reg);
-       }
+
+       be_roce_map_pci_bars(adapter);
        return 0;
+
 pci_map_err:
        be_unmap_pci_bars(adapter);
        return -ENOMEM;
@@ -3437,7 +3672,6 @@ static void be_ctrl_cleanup(struct be_adapter *adapter)
        if (mem->va)
                dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
                                  mem->dma);
-       kfree(adapter->pmac_id);
 }
 
 static int be_ctrl_init(struct be_adapter *adapter)
@@ -3445,8 +3679,14 @@ static int be_ctrl_init(struct be_adapter *adapter)
        struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced;
        struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem;
        struct be_dma_mem *rx_filter = &adapter->rx_filter;
+       u32 sli_intf;
        int status;
 
+       pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
+       adapter->sli_family = (sli_intf & SLI_INTF_FAMILY_MASK) >>
+                                SLI_INTF_FAMILY_SHIFT;
+       adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
+
        status = be_map_pci_bars(adapter);
        if (status)
                goto done;
@@ -3473,13 +3713,6 @@ static int be_ctrl_init(struct be_adapter *adapter)
                goto free_mbox;
        }
        memset(rx_filter->va, 0, rx_filter->size);
-
-       /* primary mac needs 1 pmac entry */
-       adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1,
-                                  sizeof(*adapter->pmac_id), GFP_KERNEL);
-       if (!adapter->pmac_id)
-               return -ENOMEM;
-
        mutex_init(&adapter->mbox_lock);
        spin_lock_init(&adapter->mcc_lock);
        spin_lock_init(&adapter->mcc_cq_lock);
@@ -3512,14 +3745,14 @@ static int be_stats_init(struct be_adapter *adapter)
 {
        struct be_dma_mem *cmd = &adapter->stats_cmd;
 
-       if (adapter->generation == BE_GEN2) {
+       if (lancer_chip(adapter))
+               cmd->size = sizeof(struct lancer_cmd_req_pport_stats);
+       else if (BE2_chip(adapter))
                cmd->size = sizeof(struct be_cmd_req_get_stats_v0);
-       } else {
-               if (lancer_chip(adapter))
-                       cmd->size = sizeof(struct lancer_cmd_req_pport_stats);
-               else
-                       cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
-       }
+       else
+               /* BE3 and Skyhawk */
+               cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
+
        cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
                                     GFP_KERNEL);
        if (cmd->va == NULL)
@@ -3528,7 +3761,7 @@ static int be_stats_init(struct be_adapter *adapter)
        return 0;
 }
 
-static void __devexit be_remove(struct pci_dev *pdev)
+static void be_remove(struct pci_dev *pdev)
 {
        struct be_adapter *adapter = pci_get_drvdata(pdev);
 
@@ -3573,6 +3806,9 @@ u32 be_get_fw_log_level(struct be_adapter *adapter)
        u32 level = 0;
        int j;
 
+       if (lancer_chip(adapter))
+               return 0;
+
        memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
        extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
        extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size,
@@ -3598,26 +3834,12 @@ u32 be_get_fw_log_level(struct be_adapter *adapter)
 err:
        return level;
 }
+
 static int be_get_initial_config(struct be_adapter *adapter)
 {
        int status;
        u32 level;
 
-       status = be_cmd_query_fw_cfg(adapter, &adapter->port_num,
-                       &adapter->function_mode, &adapter->function_caps);
-       if (status)
-               return status;
-
-       if (adapter->function_mode & FLEX10_MODE)
-               adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8;
-       else
-               adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
-
-       if (be_physfn(adapter))
-               adapter->max_pmac_cnt = BE_UC_PMAC_COUNT;
-       else
-               adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT;
-
        status = be_cmd_get_cntl_attributes(adapter);
        if (status)
                return status;
@@ -3642,55 +3864,6 @@ static int be_get_initial_config(struct be_adapter *adapter)
        return 0;
 }
 
-static int be_dev_type_check(struct be_adapter *adapter)
-{
-       struct pci_dev *pdev = adapter->pdev;
-       u32 sli_intf = 0, if_type;
-
-       switch (pdev->device) {
-       case BE_DEVICE_ID1:
-       case OC_DEVICE_ID1:
-               adapter->generation = BE_GEN2;
-               break;
-       case BE_DEVICE_ID2:
-       case OC_DEVICE_ID2:
-               adapter->generation = BE_GEN3;
-               break;
-       case OC_DEVICE_ID3:
-       case OC_DEVICE_ID4:
-               pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
-               adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
-                                               SLI_INTF_IF_TYPE_SHIFT;
-               if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
-                                               SLI_INTF_IF_TYPE_SHIFT;
-               if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) ||
-                       !be_type_2_3(adapter)) {
-                       dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
-                       return -EINVAL;
-               }
-               adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
-                                        SLI_INTF_FAMILY_SHIFT);
-               adapter->generation = BE_GEN3;
-               break;
-       case OC_DEVICE_ID5:
-               pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf);
-               if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) {
-                       dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n");
-                       return -EINVAL;
-               }
-               adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >>
-                                        SLI_INTF_FAMILY_SHIFT);
-               adapter->generation = BE_GEN3;
-               break;
-       default:
-               adapter->generation = 0;
-       }
-
-       pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf);
-       adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0;
-       return 0;
-}
-
 static int lancer_recover_func(struct be_adapter *adapter)
 {
        int status;
@@ -3721,8 +3894,9 @@ static int lancer_recover_func(struct be_adapter *adapter)
                "Adapter SLIPORT recovery succeeded\n");
        return 0;
 err:
-       dev_err(&adapter->pdev->dev,
-               "Adapter SLIPORT recovery failed\n");
+       if (adapter->eeh_error)
+               dev_err(&adapter->pdev->dev,
+                       "Adapter SLIPORT recovery failed\n");
 
        return status;
 }
@@ -3820,8 +3994,7 @@ static inline char *func_name(struct be_adapter *adapter)
        return be_physfn(adapter) ? "PF" : "VF";
 }
 
-static int __devinit be_probe(struct pci_dev *pdev,
-                       const struct pci_device_id *pdev_id)
+static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id)
 {
        int status = 0;
        struct be_adapter *adapter;
@@ -3845,11 +4018,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
        adapter = netdev_priv(netdev);
        adapter->pdev = pdev;
        pci_set_drvdata(pdev, adapter);
-
-       status = be_dev_type_check(adapter);
-       if (status)
-               goto free_netdev;
-
        adapter->netdev = netdev;
        SET_NETDEV_DEV(netdev, &pdev->dev);
 
@@ -4023,9 +4191,6 @@ static void be_shutdown(struct pci_dev *pdev)
 
        netif_device_detach(adapter->netdev);
 
-       if (adapter->wol)
-               be_setup_wol(adapter, true);
-
        be_cmd_reset_function(adapter);
 
        pci_disable_device(pdev);
@@ -4061,9 +4226,13 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev,
 
        /* The error could cause the FW to trigger a flash debug dump.
         * Resetting the card while flash dump is in progress
-        * can cause it not to recover; wait for it to finish
+        * can cause it not to recover; wait for it to finish.
+        * Wait only for first function as it is needed only once per
+        * adapter.
         */
-       ssleep(30);
+       if (pdev->devfn == 0)
+               ssleep(30);
+
        return PCI_ERS_RESULT_NEED_RESET;
 }
 
index deecc44b36177aff72f65f1a258d5b7391827a6e..55d32aa0a093afa74de8c26661468a97b31d5cc7 100644 (file)
@@ -47,10 +47,7 @@ static void _be_roce_dev_add(struct be_adapter *adapter)
                dev_info.dpp_unmapped_len = 0;
        }
        dev_info.pdev = adapter->pdev;
-       if (adapter->sli_family == SKYHAWK_SLI_FAMILY)
-               dev_info.db = adapter->db;
-       else
-               dev_info.db = adapter->roce_db.base;
+       dev_info.db = adapter->db;
        dev_info.unmapped_db = adapter->roce_db.io_addr;
        dev_info.db_page_size = adapter->roce_db.size;
        dev_info.db_total_size = adapter->roce_db.total_size;
index 94b7bfcdb24e4a2fb3d9639a9f053c6186bfef87..8db1c06008de16107ba5475580a696f04a5d745a 100644 (file)
@@ -665,7 +665,7 @@ static void ethoc_mdio_poll(struct net_device *dev)
 {
 }
 
-static int __devinit ethoc_mdio_probe(struct net_device *dev)
+static int ethoc_mdio_probe(struct net_device *dev)
 {
        struct ethoc *priv = netdev_priv(dev);
        struct phy_device *phy;
@@ -905,7 +905,7 @@ static const struct net_device_ops ethoc_netdev_ops = {
  * ethoc_probe - initialize OpenCores ethernet MAC
  * pdev:       platform device
  */
-static int __devinit ethoc_probe(struct platform_device *pdev)
+static int ethoc_probe(struct platform_device *pdev)
 {
        struct net_device *netdev = NULL;
        struct resource *res = NULL;
@@ -1143,7 +1143,7 @@ out:
  * ethoc_remove - shutdown OpenCores ethernet MAC
  * @pdev:      platform device
  */
-static int __devexit ethoc_remove(struct platform_device *pdev)
+static int ethoc_remove(struct platform_device *pdev)
 {
        struct net_device *netdev = platform_get_drvdata(pdev);
        struct ethoc *priv = netdev_priv(netdev);
@@ -1190,7 +1190,7 @@ MODULE_DEVICE_TABLE(of, ethoc_match);
 
 static struct platform_driver ethoc_driver = {
        .probe   = ethoc_probe,
-       .remove  = __devexit_p(ethoc_remove),
+       .remove  = ethoc_remove,
        .suspend = ethoc_suspend,
        .resume  = ethoc_resume,
        .driver  = {
index 0e4a0ac86aa8f1a9ad2d760cb066974abd678c79..c706b7a9397ed6f13dedfee142f99ae50a98ff98 100644 (file)
@@ -92,7 +92,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
 #include <asm/byteorder.h>
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
        KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
 
 
@@ -150,7 +150,7 @@ struct chip_info {
        int flags;
 };
 
-static const struct chip_info skel_netdrv_tbl[] __devinitconst = {
+static const struct chip_info skel_netdrv_tbl[] = {
        { "100/10M Ethernet PCI Adapter",       HAS_MII_XCVR },
        { "100/10M Ethernet PCI Adapter",       HAS_CHIP_XCVR },
        { "1000/100/10M Ethernet PCI Adapter",  HAS_MII_XCVR },
@@ -477,8 +477,8 @@ static const struct net_device_ops netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit fealnx_init_one(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int fealnx_init_one(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct netdev_private *np;
        int i, option, err, irq;
@@ -684,7 +684,7 @@ err_out_res:
 }
 
 
-static void __devexit fealnx_remove_one(struct pci_dev *pdev)
+static void fealnx_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -1950,7 +1950,7 @@ static struct pci_driver fealnx_driver = {
        .name           = "fealnx",
        .id_table       = fealnx_pci_tbl,
        .probe          = fealnx_init_one,
-       .remove         = __devexit_p(fealnx_remove_one),
+       .remove         = fealnx_remove_one,
 };
 
 static int __init fealnx_init(void)
index feff51664dcf76974cc62a58be978bbbe83f0cf7..5ba6e1cbd346723f069074016ce06b2bb82a223c 100644 (file)
@@ -92,4 +92,13 @@ config GIANFAR
          This driver supports the Gigabit TSEC on the MPC83xx, MPC85xx,
          and MPC86xx family of chips, and the FEC on the 8540.
 
+config FEC_PTP
+       bool "PTP Hardware Clock (PHC)"
+       depends on FEC && ARCH_MXC
+       select PTP_1588_CLOCK
+       default y if SOC_IMX6Q
+       --help---
+         Say Y here if you want to use PTP Hardware Clock (PHC) in the
+         driver.  Only the basic clock operations have been implemented.
+
 endif # NET_VENDOR_FREESCALE
index 3d1839afff6574ac96a9f4f2c7955739a8574567..d4d19b3d00aed69b8d905307f16b53e717926dcc 100644 (file)
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_FEC) += fec.o
+obj-$(CONFIG_FEC_PTP) += fec_ptp.o
 obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx.o
 ifeq ($(CONFIG_FEC_MPC52xx_MDIO),y)
        obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx_phy.o
index fffd20528b5da8e0864eeddcccbf4f034a9ba9d2..0704bcab178ab64a036e6cec7e44167622c7271c 100644 (file)
@@ -140,21 +140,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #endif
 #endif /* CONFIG_M5272 */
 
-/* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it it best
- * to keep them that size.
- * We don't need to allocate pages for the transmitter.  We just use
- * the skbuffer directly.
- */
-#define FEC_ENET_RX_PAGES      8
-#define FEC_ENET_RX_FRSIZE     2048
-#define FEC_ENET_RX_FRPPG      (PAGE_SIZE / FEC_ENET_RX_FRSIZE)
-#define RX_RING_SIZE           (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
-#define FEC_ENET_TX_FRSIZE     2048
-#define FEC_ENET_TX_FRPPG      (PAGE_SIZE / FEC_ENET_TX_FRSIZE)
-#define TX_RING_SIZE           16      /* Must be power of two */
-#define TX_RING_MOD_MASK       15      /*   for this to work */
-
 #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE)
 #error "FEC: descriptor ring size constants too large"
 #endif
@@ -179,9 +164,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #define PKT_MINBUF_SIZE                64
 #define PKT_MAXBLR_SIZE                1520
 
-/* This device has up to three irqs on some platforms */
-#define FEC_IRQ_NUM            3
-
 /*
  * The 5270/5271/5280/5282/532x RX control register also contains maximum frame
  * size bits. Other FEC hardware does not, so we need to take that into
@@ -194,61 +176,6 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #define        OPT_FRAME_SIZE  0
 #endif
 
-/* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
- * tx_bd_base always point to the base of the buffer descriptors.  The
- * cur_rx and cur_tx point to the currently available buffer.
- * The dirty_tx tracks the current buffer that is being sent by the
- * controller.  The cur_tx and dirty_tx are equal under both completely
- * empty and completely full conditions.  The empty/ready indicator in
- * the buffer descriptor determines the actual condition.
- */
-struct fec_enet_private {
-       /* Hardware registers of the FEC device */
-       void __iomem *hwp;
-
-       struct net_device *netdev;
-
-       struct clk *clk_ipg;
-       struct clk *clk_ahb;
-
-       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
-       unsigned char *tx_bounce[TX_RING_SIZE];
-       struct  sk_buff* tx_skbuff[TX_RING_SIZE];
-       struct  sk_buff* rx_skbuff[RX_RING_SIZE];
-       ushort  skb_cur;
-       ushort  skb_dirty;
-
-       /* CPM dual port RAM relative addresses */
-       dma_addr_t      bd_dma;
-       /* Address of Rx and Tx buffers */
-       struct bufdesc  *rx_bd_base;
-       struct bufdesc  *tx_bd_base;
-       /* The next free ring entry */
-       struct bufdesc  *cur_rx, *cur_tx;
-       /* The ring entries to be free()ed */
-       struct bufdesc  *dirty_tx;
-
-       uint    tx_full;
-       /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
-       spinlock_t hw_lock;
-
-       struct  platform_device *pdev;
-
-       int     opened;
-       int     dev_id;
-
-       /* Phylib and MDIO interface */
-       struct  mii_bus *mii_bus;
-       struct  phy_device *phy_dev;
-       int     mii_timeout;
-       uint    phy_speed;
-       phy_interface_t phy_interface;
-       int     link;
-       int     full_duplex;
-       struct  completion mdio_done;
-       int     irq[FEC_IRQ_NUM];
-};
-
 /* FEC MII MMFR bits definition */
 #define FEC_MMFR_ST            (1 << 30)
 #define FEC_MMFR_OP_READ       (2 << 28)
@@ -353,6 +280,17 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                        | BD_ENET_TX_LAST | BD_ENET_TX_TC);
        bdp->cbd_sc = status;
 
+#ifdef CONFIG_FEC_PTP
+       bdp->cbd_bdu = 0;
+       if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP &&
+                       fep->hwts_tx_en)) {
+                       bdp->cbd_esc = (BD_ENET_TX_TS | BD_ENET_TX_INT);
+                       skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+       } else {
+
+               bdp->cbd_esc = BD_ENET_TX_INT;
+       }
+#endif
        /* Trigger transmission start */
        writel(0, fep->hwp + FEC_X_DES_ACTIVE);
 
@@ -510,10 +448,17 @@ fec_restart(struct net_device *ndev, int duplex)
                writel(1 << 8, fep->hwp + FEC_X_WMRK);
        }
 
+#ifdef CONFIG_FEC_PTP
+       ecntl |= (1 << 4);
+#endif
+
        /* And last, enable the transmit and receive processing */
        writel(ecntl, fep->hwp + FEC_ECNTRL);
        writel(0, fep->hwp + FEC_R_DES_ACTIVE);
 
+#ifdef CONFIG_FEC_PTP
+       fec_ptp_start_cyclecounter(ndev);
+#endif
        /* Enable interrupts we wish to service */
        writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
 }
@@ -599,6 +544,19 @@ fec_enet_tx(struct net_device *ndev)
                        ndev->stats.tx_packets++;
                }
 
+#ifdef CONFIG_FEC_PTP
+               if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
+                       struct skb_shared_hwtstamps shhwtstamps;
+                       unsigned long flags;
+
+                       memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+                       spin_lock_irqsave(&fep->tmreg_lock, flags);
+                       shhwtstamps.hwtstamp = ns_to_ktime(
+                               timecounter_cyc2time(&fep->tc, bdp->ts));
+                       spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+                       skb_tstamp_tx(skb, &shhwtstamps);
+               }
+#endif
                if (status & BD_ENET_TX_READY)
                        printk("HEY! Enet xmit interrupt and TX_READY.\n");
 
@@ -725,6 +683,21 @@ fec_enet_rx(struct net_device *ndev)
                        skb_put(skb, pkt_len - 4);      /* Make room */
                        skb_copy_to_linear_data(skb, data, pkt_len - 4);
                        skb->protocol = eth_type_trans(skb, ndev);
+#ifdef CONFIG_FEC_PTP
+                       /* Get receive timestamp from the skb */
+                       if (fep->hwts_rx_en) {
+                               struct skb_shared_hwtstamps *shhwtstamps =
+                                                           skb_hwtstamps(skb);
+                               unsigned long flags;
+
+                               memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+
+                               spin_lock_irqsave(&fep->tmreg_lock, flags);
+                               shhwtstamps->hwtstamp = ns_to_ktime(
+                                   timecounter_cyc2time(&fep->tc, bdp->ts));
+                               spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+                       }
+#endif
                        if (!skb_defer_rx_timestamp(skb))
                                netif_rx(skb);
                }
@@ -739,6 +712,12 @@ rx_processing_done:
                status |= BD_ENET_RX_EMPTY;
                bdp->cbd_sc = status;
 
+#ifdef CONFIG_FEC_PTP
+               bdp->cbd_esc = BD_ENET_RX_INT;
+               bdp->cbd_prot = 0;
+               bdp->cbd_bdu = 0;
+#endif
+
                /* Update BD pointer to next entry */
                if (status & BD_ENET_RX_WRAP)
                        bdp = fep->rx_bd_base;
@@ -1178,6 +1157,10 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
        if (!phydev)
                return -ENODEV;
 
+#ifdef CONFIG_FEC_PTP
+       if (cmd == SIOCSHWTSTAMP)
+               return fec_ptp_ioctl(ndev, rq, cmd);
+#endif
        return phy_mii_ioctl(phydev, rq, cmd);
 }
 
@@ -1224,6 +1207,9 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
                bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
                                FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
                bdp->cbd_sc = BD_ENET_RX_EMPTY;
+#ifdef CONFIG_FEC_PTP
+               bdp->cbd_esc = BD_ENET_RX_INT;
+#endif
                bdp++;
        }
 
@@ -1237,6 +1223,10 @@ static int fec_enet_alloc_buffers(struct net_device *ndev)
 
                bdp->cbd_sc = 0;
                bdp->cbd_bufaddr = 0;
+
+#ifdef CONFIG_FEC_PTP
+               bdp->cbd_esc = BD_ENET_RX_INT;
+#endif
                bdp++;
        }
 
@@ -1494,7 +1484,7 @@ static int fec_enet_init(struct net_device *ndev)
 }
 
 #ifdef CONFIG_OF
-static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
+static int fec_get_phy_mode_dt(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
 
@@ -1504,7 +1494,7 @@ static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
        return -ENODEV;
 }
 
-static void __devinit fec_reset_phy(struct platform_device *pdev)
+static void fec_reset_phy(struct platform_device *pdev)
 {
        int err, phy_reset;
        int msec = 1;
@@ -1543,7 +1533,7 @@ static inline void fec_reset_phy(struct platform_device *pdev)
 }
 #endif /* CONFIG_OF */
 
-static int __devinit
+static int
 fec_probe(struct platform_device *pdev)
 {
        struct fec_enet_private *fep;
@@ -1638,9 +1628,19 @@ fec_probe(struct platform_device *pdev)
                goto failed_clk;
        }
 
+#ifdef CONFIG_FEC_PTP
+       fep->clk_ptp = devm_clk_get(&pdev->dev, "ptp");
+       if (IS_ERR(fep->clk_ptp)) {
+               ret = PTR_ERR(fep->clk_ptp);
+               goto failed_clk;
+       }
+#endif
+
        clk_prepare_enable(fep->clk_ahb);
        clk_prepare_enable(fep->clk_ipg);
-
+#ifdef CONFIG_FEC_PTP
+       clk_prepare_enable(fep->clk_ptp);
+#endif
        reg_phy = devm_regulator_get(&pdev->dev, "phy");
        if (!IS_ERR(reg_phy)) {
                ret = regulator_enable(reg_phy);
@@ -1668,6 +1668,10 @@ fec_probe(struct platform_device *pdev)
        if (ret)
                goto failed_register;
 
+#ifdef CONFIG_FEC_PTP
+       fec_ptp_init(ndev, pdev);
+#endif
+
        return 0;
 
 failed_register:
@@ -1677,6 +1681,9 @@ failed_init:
 failed_regulator:
        clk_disable_unprepare(fep->clk_ahb);
        clk_disable_unprepare(fep->clk_ipg);
+#ifdef CONFIG_FEC_PTP
+       clk_disable_unprepare(fep->clk_ptp);
+#endif
 failed_pin:
 failed_clk:
        for (i = 0; i < FEC_IRQ_NUM; i++) {
@@ -1694,7 +1701,7 @@ failed_alloc_etherdev:
        return ret;
 }
 
-static int __devexit
+static int
 fec_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
@@ -1709,6 +1716,12 @@ fec_drv_remove(struct platform_device *pdev)
                if (irq > 0)
                        free_irq(irq, ndev);
        }
+#ifdef CONFIG_FEC_PTP
+       del_timer_sync(&fep->time_keep);
+       clk_disable_unprepare(fep->clk_ptp);
+       if (fep->ptp_clock)
+               ptp_clock_unregister(fep->ptp_clock);
+#endif
        clk_disable_unprepare(fep->clk_ahb);
        clk_disable_unprepare(fep->clk_ipg);
        iounmap(fep->hwp);
@@ -1777,7 +1790,7 @@ static struct platform_driver fec_driver = {
        },
        .id_table = fec_devtype,
        .probe  = fec_probe,
-       .remove = __devexit_p(fec_drv_remove),
+       .remove = fec_drv_remove,
 };
 
 module_platform_driver(fec_driver);
index 8408c627b1953a230c1f25d24b05217b0718d19f..c5a3bc1475c7f58381b3ad654501a5a116821651 100644 (file)
 #define        FEC_H
 /****************************************************************************/
 
+#ifdef CONFIG_FEC_PTP
+#include <linux/clocksource.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+#endif
+
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
     defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
     defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
@@ -88,6 +94,13 @@ struct bufdesc {
        unsigned short cbd_datlen;      /* Data length */
        unsigned short cbd_sc;  /* Control and status info */
        unsigned long cbd_bufaddr;      /* Buffer address */
+#ifdef CONFIG_FEC_PTP
+       unsigned long cbd_esc;
+       unsigned long cbd_prot;
+       unsigned long cbd_bdu;
+       unsigned long ts;
+       unsigned short res0[4];
+#endif
 };
 #else
 struct bufdesc {
@@ -147,6 +160,112 @@ struct bufdesc {
 #define BD_ENET_TX_CSL          ((ushort)0x0001)
 #define BD_ENET_TX_STATS        ((ushort)0x03ff)        /* All status bits */
 
+/*enhanced buffer desciptor control/status used by Ethernet transmit*/
+#define BD_ENET_TX_INT          0x40000000
+#define BD_ENET_TX_TS           0x20000000
+
+
+/* This device has up to three irqs on some platforms */
+#define FEC_IRQ_NUM            3
+
+/* The number of Tx and Rx buffers.  These are allocated from the page
+ * pool.  The code may assume these are power of two, so it it best
+ * to keep them that size.
+ * We don't need to allocate pages for the transmitter.  We just use
+ * the skbuffer directly.
+ */
+
+#define FEC_ENET_RX_PAGES      8
+#define FEC_ENET_RX_FRSIZE     2048
+#define FEC_ENET_RX_FRPPG      (PAGE_SIZE / FEC_ENET_RX_FRSIZE)
+#define RX_RING_SIZE           (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
+#define FEC_ENET_TX_FRSIZE     2048
+#define FEC_ENET_TX_FRPPG      (PAGE_SIZE / FEC_ENET_TX_FRSIZE)
+#define TX_RING_SIZE           16      /* Must be power of two */
+#define TX_RING_MOD_MASK       15      /*   for this to work */
+
+#define BD_ENET_RX_INT          0x00800000
+#define BD_ENET_RX_PTP          ((ushort)0x0400)
+
+/* The FEC buffer descriptors track the ring buffers.  The rx_bd_base and
+ * tx_bd_base always point to the base of the buffer descriptors.  The
+ * cur_rx and cur_tx point to the currently available buffer.
+ * The dirty_tx tracks the current buffer that is being sent by the
+ * controller.  The cur_tx and dirty_tx are equal under both completely
+ * empty and completely full conditions.  The empty/ready indicator in
+ * the buffer descriptor determines the actual condition.
+ */
+struct fec_enet_private {
+       /* Hardware registers of the FEC device */
+       void __iomem *hwp;
+
+       struct net_device *netdev;
+
+       struct clk *clk_ipg;
+       struct clk *clk_ahb;
+#ifdef CONFIG_FEC_PTP
+       struct clk *clk_ptp;
+#endif
+
+       /* The saved address of a sent-in-place packet/buffer, for skfree(). */
+       unsigned char *tx_bounce[TX_RING_SIZE];
+       struct  sk_buff *tx_skbuff[TX_RING_SIZE];
+       struct  sk_buff *rx_skbuff[RX_RING_SIZE];
+       ushort  skb_cur;
+       ushort  skb_dirty;
+
+       /* CPM dual port RAM relative addresses */
+       dma_addr_t      bd_dma;
+       /* Address of Rx and Tx buffers */
+       struct bufdesc  *rx_bd_base;
+       struct bufdesc  *tx_bd_base;
+       /* The next free ring entry */
+       struct bufdesc  *cur_rx, *cur_tx;
+       /* The ring entries to be free()ed */
+       struct bufdesc  *dirty_tx;
+
+       uint    tx_full;
+       /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
+       spinlock_t hw_lock;
+
+       struct  platform_device *pdev;
+
+       int     opened;
+       int     dev_id;
+
+       /* Phylib and MDIO interface */
+       struct  mii_bus *mii_bus;
+       struct  phy_device *phy_dev;
+       int     mii_timeout;
+       uint    phy_speed;
+       phy_interface_t phy_interface;
+       int     link;
+       int     full_duplex;
+       struct  completion mdio_done;
+       int     irq[FEC_IRQ_NUM];
+
+#ifdef CONFIG_FEC_PTP
+       struct ptp_clock *ptp_clock;
+       struct ptp_clock_info ptp_caps;
+       unsigned long last_overflow_check;
+       spinlock_t tmreg_lock;
+       struct cyclecounter cc;
+       struct timecounter tc;
+       int rx_hwtstamp_filter;
+       u32 base_incval;
+       u32 cycle_speed;
+       int hwts_rx_en;
+       int hwts_tx_en;
+       struct timer_list time_keep;
+#endif
+
+};
+
+#ifdef CONFIG_FEC_PTP
+void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev);
+void fec_ptp_start_cyclecounter(struct net_device *ndev);
+int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd);
+#endif
 
 /****************************************************************************/
 #endif /* FEC_H */
index 2933d08b036edc437b0e026ed55404fa34c8b4fb..817d081d2cd8e8b9d2fdddfc4a69edb3dc6d7b32 100644 (file)
@@ -845,7 +845,7 @@ static const struct net_device_ops mpc52xx_fec_netdev_ops = {
 /* OF Driver                                                                */
 /* ======================================================================== */
 
-static int __devinit mpc52xx_fec_probe(struct platform_device *op)
+static int mpc52xx_fec_probe(struct platform_device *op)
 {
        int rv;
        struct net_device *ndev;
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
new file mode 100644 (file)
index 0000000..c40526c
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Fast Ethernet Controller (ENET) PTP driver for MX6x.
+ *
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/phy.h>
+#include <linux/fec.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_net.h>
+
+#include "fec.h"
+
+/* FEC 1588 register bits */
+#define FEC_T_CTRL_SLAVE                0x00002000
+#define FEC_T_CTRL_CAPTURE              0x00000800
+#define FEC_T_CTRL_RESTART              0x00000200
+#define FEC_T_CTRL_PERIOD_RST           0x00000030
+#define FEC_T_CTRL_PERIOD_EN           0x00000010
+#define FEC_T_CTRL_ENABLE               0x00000001
+
+#define FEC_T_INC_MASK                  0x0000007f
+#define FEC_T_INC_OFFSET                0
+#define FEC_T_INC_CORR_MASK             0x00007f00
+#define FEC_T_INC_CORR_OFFSET           8
+
+#define FEC_ATIME_CTRL         0x400
+#define FEC_ATIME              0x404
+#define FEC_ATIME_EVT_OFFSET   0x408
+#define FEC_ATIME_EVT_PERIOD   0x40c
+#define FEC_ATIME_CORR         0x410
+#define FEC_ATIME_INC          0x414
+#define FEC_TS_TIMESTAMP       0x418
+
+#define FEC_CC_MULT    (1 << 31)
+/**
+ * fec_ptp_read - read raw cycle counter (to be used by time counter)
+ * @cc: the cyclecounter structure
+ *
+ * this function reads the cyclecounter registers and is called by the
+ * cyclecounter structure used to construct a ns counter from the
+ * arbitrary fixed point registers
+ */
+static cycle_t fec_ptp_read(const struct cyclecounter *cc)
+{
+       struct fec_enet_private *fep =
+               container_of(cc, struct fec_enet_private, cc);
+       u32 tempval;
+
+       tempval = readl(fep->hwp + FEC_ATIME_CTRL);
+       tempval |= FEC_T_CTRL_CAPTURE;
+       writel(tempval, fep->hwp + FEC_ATIME_CTRL);
+
+       return readl(fep->hwp + FEC_ATIME);
+}
+
+/**
+ * fec_ptp_start_cyclecounter - create the cycle counter from hw
+ * @ndev: network device
+ *
+ * this function initializes the timecounter and cyclecounter
+ * structures for use in generated a ns counter from the arbitrary
+ * fixed point cycles registers in the hardware.
+ */
+void fec_ptp_start_cyclecounter(struct net_device *ndev)
+{
+       struct fec_enet_private *fep = netdev_priv(ndev);
+       unsigned long flags;
+       int inc;
+
+       inc = 1000000000 / clk_get_rate(fep->clk_ptp);
+
+       /* grab the ptp lock */
+       spin_lock_irqsave(&fep->tmreg_lock, flags);
+
+       /* 1ns counter */
+       writel(inc << FEC_T_INC_OFFSET, fep->hwp + FEC_ATIME_INC);
+
+       /* use free running count */
+       writel(0, fep->hwp + FEC_ATIME_EVT_PERIOD);
+
+       writel(FEC_T_CTRL_ENABLE, fep->hwp + FEC_ATIME_CTRL);
+
+       memset(&fep->cc, 0, sizeof(fep->cc));
+       fep->cc.read = fec_ptp_read;
+       fep->cc.mask = CLOCKSOURCE_MASK(32);
+       fep->cc.shift = 31;
+       fep->cc.mult = FEC_CC_MULT;
+
+       /* reset the ns time counter */
+       timecounter_init(&fep->tc, &fep->cc, ktime_to_ns(ktime_get_real()));
+
+       spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+}
+
+/**
+ * fec_ptp_adjfreq - adjust ptp cycle frequency
+ * @ptp: the ptp clock structure
+ * @ppb: parts per billion adjustment from base
+ *
+ * Adjust the frequency of the ptp cycle counter by the
+ * indicated ppb from the base frequency.
+ *
+ * Because ENET hardware frequency adjust is complex,
+ * using software method to do that.
+ */
+static int fec_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+       u64 diff;
+       unsigned long flags;
+       int neg_adj = 0;
+       u32 mult = FEC_CC_MULT;
+
+       struct fec_enet_private *fep =
+           container_of(ptp, struct fec_enet_private, ptp_caps);
+
+       if (ppb < 0) {
+               ppb = -ppb;
+               neg_adj = 1;
+       }
+
+       diff = mult;
+       diff *= ppb;
+       diff = div_u64(diff, 1000000000ULL);
+
+       spin_lock_irqsave(&fep->tmreg_lock, flags);
+       /*
+        * dummy read to set cycle_last in tc to now.
+        * So use adjusted mult to calculate when next call
+        * timercounter_read.
+        */
+       timecounter_read(&fep->tc);
+
+       fep->cc.mult = neg_adj ? mult - diff : mult + diff;
+
+       spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+       return 0;
+}
+
+/**
+ * fec_ptp_adjtime
+ * @ptp: the ptp clock structure
+ * @delta: offset to adjust the cycle counter by
+ *
+ * adjust the timer by resetting the timecounter structure.
+ */
+static int fec_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+       struct fec_enet_private *fep =
+           container_of(ptp, struct fec_enet_private, ptp_caps);
+       unsigned long flags;
+       u64 now;
+
+       spin_lock_irqsave(&fep->tmreg_lock, flags);
+
+       now = timecounter_read(&fep->tc);
+       now += delta;
+
+       /* reset the timecounter */
+       timecounter_init(&fep->tc, &fep->cc, now);
+
+       spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+       return 0;
+}
+
+/**
+ * fec_ptp_gettime
+ * @ptp: the ptp clock structure
+ * @ts: timespec structure to hold the current time value
+ *
+ * read the timecounter and return the correct value on ns,
+ * after converting it into a struct timespec.
+ */
+static int fec_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+       struct fec_enet_private *adapter =
+           container_of(ptp, struct fec_enet_private, ptp_caps);
+       u64 ns;
+       u32 remainder;
+       unsigned long flags;
+
+       spin_lock_irqsave(&adapter->tmreg_lock, flags);
+       ns = timecounter_read(&adapter->tc);
+       spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+       ts->tv_sec = div_u64_rem(ns, 1000000000ULL, &remainder);
+       ts->tv_nsec = remainder;
+
+       return 0;
+}
+
+/**
+ * fec_ptp_settime
+ * @ptp: the ptp clock structure
+ * @ts: the timespec containing the new time for the cycle counter
+ *
+ * reset the timecounter to use a new base value instead of the kernel
+ * wall timer value.
+ */
+static int fec_ptp_settime(struct ptp_clock_info *ptp,
+                          const struct timespec *ts)
+{
+       struct fec_enet_private *fep =
+           container_of(ptp, struct fec_enet_private, ptp_caps);
+
+       u64 ns;
+       unsigned long flags;
+
+       ns = ts->tv_sec * 1000000000ULL;
+       ns += ts->tv_nsec;
+
+       spin_lock_irqsave(&fep->tmreg_lock, flags);
+       timecounter_init(&fep->tc, &fep->cc, ns);
+       spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+       return 0;
+}
+
+/**
+ * fec_ptp_enable
+ * @ptp: the ptp clock structure
+ * @rq: the requested feature to change
+ * @on: whether to enable or disable the feature
+ *
+ */
+static int fec_ptp_enable(struct ptp_clock_info *ptp,
+                         struct ptp_clock_request *rq, int on)
+{
+       return -EOPNOTSUPP;
+}
+
+/**
+ * fec_ptp_hwtstamp_ioctl - control hardware time stamping
+ * @ndev: pointer to net_device
+ * @ifreq: ioctl data
+ * @cmd: particular ioctl requested
+ */
+int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
+{
+       struct fec_enet_private *fep = netdev_priv(ndev);
+
+       struct hwtstamp_config config;
+
+       if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
+               return -EFAULT;
+
+       /* reserved for future extensions */
+       if (config.flags)
+               return -EINVAL;
+
+       switch (config.tx_type) {
+       case HWTSTAMP_TX_OFF:
+               fep->hwts_tx_en = 0;
+               break;
+       case HWTSTAMP_TX_ON:
+               fep->hwts_tx_en = 1;
+               break;
+       default:
+               return -ERANGE;
+       }
+
+       switch (config.rx_filter) {
+       case HWTSTAMP_FILTER_NONE:
+               if (fep->hwts_rx_en)
+                       fep->hwts_rx_en = 0;
+               config.rx_filter = HWTSTAMP_FILTER_NONE;
+               break;
+
+       default:
+               /*
+                * register RXMTRL must be set in order to do V1 packets,
+                * therefore it is not possible to time stamp both V1 Sync and
+                * Delay_Req messages and hardware does not support
+                * timestamping all packets => return error
+                */
+               fep->hwts_rx_en = 1;
+               config.rx_filter = HWTSTAMP_FILTER_ALL;
+               break;
+       }
+
+       return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
+           -EFAULT : 0;
+}
+
+/**
+ * fec_time_keep - call timecounter_read every second to avoid timer overrun
+ *                 because ENET just support 32bit counter, will timeout in 4s
+ */
+static void fec_time_keep(unsigned long _data)
+{
+       struct fec_enet_private *fep = (struct fec_enet_private *)_data;
+       u64 ns;
+       unsigned long flags;
+
+       spin_lock_irqsave(&fep->tmreg_lock, flags);
+       ns = timecounter_read(&fep->tc);
+       spin_unlock_irqrestore(&fep->tmreg_lock, flags);
+
+       mod_timer(&fep->time_keep, jiffies + HZ);
+}
+
+/**
+ * fec_ptp_init
+ * @ndev: The FEC network adapter
+ *
+ * This function performs the required steps for enabling ptp
+ * support. If ptp support has already been loaded it simply calls the
+ * cyclecounter init routine and exits.
+ */
+
+void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev)
+{
+       struct fec_enet_private *fep = netdev_priv(ndev);
+
+       fep->ptp_caps.owner = THIS_MODULE;
+       snprintf(fep->ptp_caps.name, 16, "fec ptp");
+
+       fep->ptp_caps.max_adj = 250000000;
+       fep->ptp_caps.n_alarm = 0;
+       fep->ptp_caps.n_ext_ts = 0;
+       fep->ptp_caps.n_per_out = 0;
+       fep->ptp_caps.pps = 0;
+       fep->ptp_caps.adjfreq = fec_ptp_adjfreq;
+       fep->ptp_caps.adjtime = fec_ptp_adjtime;
+       fep->ptp_caps.gettime = fec_ptp_gettime;
+       fep->ptp_caps.settime = fec_ptp_settime;
+       fep->ptp_caps.enable = fec_ptp_enable;
+
+       spin_lock_init(&fep->tmreg_lock);
+
+       fec_ptp_start_cyclecounter(ndev);
+
+       init_timer(&fep->time_keep);
+       fep->time_keep.data = (unsigned long)fep;
+       fep->time_keep.function = fec_time_keep;
+       fep->time_keep.expires = jiffies + HZ;
+       add_timer(&fep->time_keep);
+
+       fep->ptp_clock = ptp_clock_register(&fep->ptp_caps, &pdev->dev);
+       if (IS_ERR(fep->ptp_clock)) {
+               fep->ptp_clock = NULL;
+               pr_err("ptp_clock_register failed\n");
+       } else {
+               pr_info("registered PHC device on %s\n", ndev->name);
+       }
+}
index 2b7633f766d98a0d79138fc317303579c71ddae6..e9879c5af7ba05dcea3364fb3db9c13d028998eb 100644 (file)
@@ -1004,7 +1004,7 @@ static const struct net_device_ops fs_enet_netdev_ops = {
 };
 
 static struct of_device_id fs_enet_match[];
-static int __devinit fs_enet_probe(struct platform_device *ofdev)
+static int fs_enet_probe(struct platform_device *ofdev)
 {
        const struct of_device_id *match;
        struct net_device *ndev;
index 151453309401694360f311ccb09e0caea8480b01..2bafbd37c247ab52802e64b531ac2e7ccc5e148a 100644 (file)
@@ -108,8 +108,7 @@ static struct mdiobb_ops bb_ops = {
        .get_mdio_data = mdio_read,
 };
 
-static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
-                                         struct device_node *np)
+static int fs_mii_bitbang_init(struct mii_bus *bus, struct device_node *np)
 {
        struct resource res;
        const u32 *data;
@@ -150,7 +149,7 @@ static int __devinit fs_mii_bitbang_init(struct mii_bus *bus,
        return 0;
 }
 
-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
+static int fs_enet_mdio_probe(struct platform_device *ofdev)
 {
        struct mii_bus *new_bus;
        struct bb_info *bitbang;
index cdf702a594858146fd4f04ab02966d941edeeea5..18e8ef203736bf2154967599a102fd454e7cc05a 100644 (file)
@@ -102,7 +102,7 @@ static int fs_enet_fec_mii_reset(struct mii_bus *bus)
 }
 
 static struct of_device_id fs_enet_mdio_fec_match[];
-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
+static int fs_enet_mdio_probe(struct platform_device *ofdev)
 {
        const struct of_device_id *match;
        struct resource res;
index 1d03dcdd5e5686bb6e76cb71069607a44d8d4eb2..bffb2edd68584633aa8b5248fc27faf0990a05d5 100644 (file)
@@ -210,7 +210,7 @@ static int gfar_init_bds(struct net_device *ndev)
                                skb = gfar_new_skb(ndev);
                                if (!skb) {
                                        netdev_err(ndev, "Can't allocate RX buffers\n");
-                                       goto err_rxalloc_fail;
+                                       return -ENOMEM;
                                }
                                rx_queue->rx_skbuff[j] = skb;
 
@@ -223,10 +223,6 @@ static int gfar_init_bds(struct net_device *ndev)
        }
 
        return 0;
-
-err_rxalloc_fail:
-       free_skb_resources(priv);
-       return -ENOMEM;
 }
 
 static int gfar_alloc_skb_resources(struct net_device *ndev)
@@ -1353,10 +1349,17 @@ static int gfar_restore(struct device *dev)
        struct gfar_private *priv = dev_get_drvdata(dev);
        struct net_device *ndev = priv->ndev;
 
-       if (!netif_running(ndev))
+       if (!netif_running(ndev)) {
+               netif_device_attach(ndev);
+
                return 0;
+       }
+
+       if (gfar_init_bds(ndev)) {
+               free_skb_resources(priv);
+               return -ENOMEM;
+       }
 
-       gfar_init_bds(ndev);
        init_registers(ndev);
        gfar_set_mac_address(ndev);
        gfar_init_mac(ndev);
@@ -1709,6 +1712,7 @@ static void free_skb_tx_queue(struct gfar_priv_tx_q *tx_queue)
                tx_queue->tx_skbuff[i] = NULL;
        }
        kfree(tx_queue->tx_skbuff);
+       tx_queue->tx_skbuff = NULL;
 }
 
 static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
@@ -1732,6 +1736,7 @@ static void free_skb_rx_queue(struct gfar_priv_rx_q *rx_queue)
                rxbdp++;
        }
        kfree(rx_queue->rx_skbuff);
+       rx_queue->rx_skbuff = NULL;
 }
 
 /* If there are any tx skbs or rx skbs still around, free them.
index b9db0e0405636780bf02bc598b12e79ea5f71074..2e5daee0438a55891072595400d643bd8ad1340b 100644 (file)
@@ -478,7 +478,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
                pr_err("no resource\n");
                goto no_resource;
        }
-       if (request_resource(&ioport_resource, etsects->rsrc)) {
+       if (request_resource(&iomem_resource, etsects->rsrc)) {
                pr_err("resource busy\n");
                goto no_resource;
        }
index 1afb5ea2a984e2bc91aad9983bd14a0a32ae1e15..418068b941b1cadea61271ba5cc52aff01aefc10 100644 (file)
@@ -189,7 +189,7 @@ static int xgmac_mdio_reset(struct mii_bus *bus)
        return ret;
 }
 
-static int __devinit xgmac_mdio_probe(struct platform_device *pdev)
+static int xgmac_mdio_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct mii_bus *bus;
@@ -240,7 +240,7 @@ err_ioremap:
        return ret;
 }
 
-static int __devexit xgmac_mdio_remove(struct platform_device *pdev)
+static int xgmac_mdio_remove(struct platform_device *pdev)
 {
        struct mii_bus *bus = dev_get_drvdata(&pdev->dev);
 
index 3f4391bede815f4b2f97d0557d4af4d5848f57c8..e3c7c697fc45c2e1c5670cdc6a04b6d93083a40c 100644 (file)
@@ -308,7 +308,7 @@ static void wait(void)
  * Read board id and convert to string.
  * Effectively same code as decode_eisa_sig
  */
-static __devinit const char *hp100_read_id(int ioaddr)
+static const char *hp100_read_id(int ioaddr)
 {
        int i;
        static char str[HP100_SIG_LEN];
@@ -447,8 +447,8 @@ static const struct net_device_ops hp100_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit hp100_probe1(struct net_device *dev, int ioaddr,
-                                 u_char bus, struct pci_dev *pci_dev)
+static int hp100_probe1(struct net_device *dev, int ioaddr, u_char bus,
+                       struct pci_dev *pci_dev)
 {
        int i;
        int err = -ENODEV;
@@ -2866,7 +2866,7 @@ static int __init hp100_eisa_probe (struct device *gendev)
        return err;
 }
 
-static int __devexit hp100_eisa_remove (struct device *gendev)
+static int hp100_eisa_remove(struct device *gendev)
 {
        struct net_device *dev = dev_get_drvdata(gendev);
        cleanup_dev(dev);
@@ -2878,14 +2878,14 @@ static struct eisa_driver hp100_eisa_driver = {
         .driver   = {
                 .name    = "hp100",
                 .probe   = hp100_eisa_probe,
-                .remove  = __devexit_p (hp100_eisa_remove),
+               .remove  = hp100_eisa_remove,
         }
 };
 #endif
 
 #ifdef CONFIG_PCI
-static int __devinit hp100_pci_probe (struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int hp100_pci_probe(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        struct net_device *dev;
        int ioaddr;
@@ -2937,7 +2937,7 @@ static int __devinit hp100_pci_probe (struct pci_dev *pdev,
        return err;
 }
 
-static void __devexit hp100_pci_remove (struct pci_dev *pdev)
+static void hp100_pci_remove(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -2950,7 +2950,7 @@ static struct pci_driver hp100_pci_driver = {
        .name           = "hp100",
        .id_table       = hp100_pci_tbl,
        .probe          = hp100_pci_probe,
-       .remove         = __devexit_p(hp100_pci_remove),
+       .remove         = hp100_pci_remove,
 };
 #endif
 
index 067db3f13e918ddc7ac896ab0212e20921fd8d31..5d353c66006829ef08a3ffdef537c825d367f58b 100644 (file)
@@ -72,7 +72,7 @@ static void ether1_timeout(struct net_device *dev);
 
 /* ------------------------------------------------------------------------- */
 
-static char version[] __devinitdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
+static char version[] = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
 
 #define BUS_16 16
 #define BUS_8  8
@@ -250,7 +250,7 @@ ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsig
        } while (thislen);
 }
 
-static int __devinit
+static int
 ether1_ramtest(struct net_device *dev, unsigned char byte)
 {
        unsigned char *buffer = kmalloc (BUFFER_SIZE, GFP_KERNEL);
@@ -304,7 +304,7 @@ ether1_reset (struct net_device *dev)
        return BUS_16;
 }
 
-static int __devinit
+static int
 ether1_init_2(struct net_device *dev)
 {
        int i;
@@ -638,12 +638,6 @@ ether1_txalloc (struct net_device *dev, int size)
 static int
 ether1_open (struct net_device *dev)
 {
-       if (!is_valid_ether_addr(dev->dev_addr)) {
-               printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-                       dev->name);
-               return -EINVAL;
-       }
-
        if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
                return -EAGAIN;
 
@@ -972,7 +966,7 @@ ether1_setmulticastlist (struct net_device *dev)
 
 /* ------------------------------------------------------------------------- */
 
-static void __devinit ether1_banner(void)
+static void ether1_banner(void)
 {
        static unsigned int version_printed = 0;
 
@@ -991,7 +985,7 @@ static const struct net_device_ops ether1_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __devinit
+static int
 ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        struct net_device *dev;
@@ -1052,7 +1046,7 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit ether1_remove(struct expansion_card *ec)
+static void ether1_remove(struct expansion_card *ec)
 {
        struct net_device *dev = ecard_get_drvdata(ec);
 
@@ -1070,7 +1064,7 @@ static const struct ecard_id ether1_ids[] = {
 
 static struct ecard_driver ether1_driver = {
        .probe          = ether1_probe,
-       .remove         = __devexit_p(ether1_remove),
+       .remove         = ether1_remove,
        .id_table       = ether1_ids,
        .drv = {
                .name   = "ether1",
index 6eba352c52e0809127d7e02ffea24e413ca82a47..f42f1b707733269bdef7dde20b7956d8cc74a54f 100644 (file)
@@ -150,7 +150,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
 
 #define LAN_PROM_ADDR  0xF0810000
 
-static int __devinit
+static int
 lan_init_chip(struct parisc_device *dev)
 {
        struct  net_device *netdevice;
@@ -195,7 +195,7 @@ lan_init_chip(struct parisc_device *dev)
        return retval;
 }
 
-static int __devexit lan_remove_chip (struct parisc_device *pdev)
+static int lan_remove_chip(struct parisc_device *pdev)
 {
        struct net_device *dev = parisc_get_drvdata(pdev);
        struct i596_private *lp = netdev_priv(dev);
@@ -219,10 +219,10 @@ static struct parisc_driver lan_driver = {
        .name           = "lasi_82596",
        .id_table       = lan_tbl,
        .probe          = lan_init_chip,
-       .remove         = __devexit_p(lan_remove_chip),
+       .remove         = lan_remove_chip,
 };
 
-static int __devinit lasi_82596_init(void)
+static int lasi_82596_init(void)
 {
        printk(KERN_INFO LASI_82596_DRIVER_VERSION "\n");
        return register_parisc_driver(&lan_driver);
index 3efbd8dbb63dd27b268167b9ad9538a455ef86c8..f045ea4dc5144e60be6fd25b730e8fabc65f2871 100644 (file)
@@ -1048,7 +1048,7 @@ static const struct net_device_ops i596_netdev_ops = {
 #endif
 };
 
-static int __devinit i82596_probe(struct net_device *dev)
+static int i82596_probe(struct net_device *dev)
 {
        int i;
        struct i596_private *lp = netdev_priv(dev);
index 6b2a888174732e613ec5094153fd68f29505d749..4ceae9a30274baf86f57482274625abfd75ce9ef 100644 (file)
@@ -75,7 +75,7 @@ static void mpu_port(struct net_device *dev, int c, dma_addr_t x)
 }
 
 
-static int __devinit sni_82596_probe(struct platform_device *dev)
+static int sni_82596_probe(struct platform_device *dev)
 {
        struct  net_device *netdevice;
        struct i596_private *lp;
@@ -147,7 +147,7 @@ probe_failed_free_mpu:
        return retval;
 }
 
-static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
+static int sni_82596_driver_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct i596_private *lp = netdev_priv(dev);
@@ -163,14 +163,14 @@ static int __devexit sni_82596_driver_remove(struct platform_device *pdev)
 
 static struct platform_driver sni_82596_driver = {
        .probe  = sni_82596_probe,
-       .remove = __devexit_p(sni_82596_driver_remove),
+       .remove = sni_82596_driver_remove,
        .driver = {
                .name   = sni_82596_string,
                .owner  = THIS_MODULE,
        },
 };
 
-static int __devinit sni_82596_init(void)
+static int sni_82596_init(void)
 {
        printk(KERN_INFO SNI_82596_DRIVER_VERSION "\n");
        return platform_driver_register(&sni_82596_driver);
index b9773d2291927e4164197b20ca78a00694c6528d..6529d31595a7e595f4ebd9e55929d017253c2c17 100644 (file)
@@ -6,7 +6,7 @@ config NET_VENDOR_IBM
        bool "IBM devices"
        default y
        depends on MCA || PPC_PSERIES || PPC_PSERIES || PPC_DCR || \
-                  (IBMEBUS && INET && SPARSEMEM)
+                  (IBMEBUS && SPARSEMEM)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
@@ -33,8 +33,7 @@ source "drivers/net/ethernet/ibm/emac/Kconfig"
 
 config EHEA
        tristate "eHEA Ethernet support"
-       depends on IBMEBUS && INET && SPARSEMEM
-       select INET_LRO
+       depends on IBMEBUS && SPARSEMEM
        ---help---
          This driver supports the IBM pSeries eHEA ethernet adapter.
 
index f4d2da0db1b149938e7c9d0e9905dfaa7db2849f..19b64de7124b9ae51e0649b887bc1b208c7627b3 100644 (file)
@@ -98,10 +98,10 @@ static struct ehea_fw_handle_array ehea_fw_handles;
 static struct ehea_bcmc_reg_array ehea_bcmc_regs;
 
 
-static int __devinit ehea_probe_adapter(struct platform_device *dev,
-                                       const struct of_device_id *id);
+static int ehea_probe_adapter(struct platform_device *dev,
+                             const struct of_device_id *id);
 
-static int __devexit ehea_remove(struct platform_device *dev);
+static int ehea_remove(struct platform_device *dev);
 
 static struct of_device_id ehea_device_table[] = {
        {
@@ -2909,7 +2909,7 @@ static ssize_t ehea_show_port_id(struct device *dev,
 static DEVICE_ATTR(log_port_id, S_IRUSR | S_IRGRP | S_IROTH, ehea_show_port_id,
                   NULL);
 
-static void __devinit logical_port_release(struct device *dev)
+static void logical_port_release(struct device *dev)
 {
        struct ehea_port *port = container_of(dev, struct ehea_port, ofdev.dev);
        of_node_put(port->ofdev.dev.of_node);
@@ -3028,7 +3028,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
        ehea_set_ethtool_ops(dev);
 
        dev->hw_features = NETIF_F_SG | NETIF_F_TSO
-                     | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO;
+                     | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX;
        dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
                      | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
                      | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
@@ -3257,8 +3257,8 @@ static void ehea_remove_device_sysfs(struct platform_device *dev)
        device_remove_file(&dev->dev, &dev_attr_remove_port);
 }
 
-static int __devinit ehea_probe_adapter(struct platform_device *dev,
-                                       const struct of_device_id *id)
+static int ehea_probe_adapter(struct platform_device *dev,
+                             const struct of_device_id *id)
 {
        struct ehea_adapter *adapter;
        const u64 *adapter_handle;
@@ -3364,7 +3364,7 @@ out:
        return ret;
 }
 
-static int __devexit ehea_remove(struct platform_device *dev)
+static int ehea_remove(struct platform_device *dev)
 {
        struct ehea_adapter *adapter = dev_get_drvdata(&dev->dev);
        int i;
index a0fe6e3fce61a5ad7b4b17b7de723e0798ab9086..256bdb8e19948390eeb4e73513b475e377350849 100644 (file)
@@ -2261,8 +2261,8 @@ struct emac_depentry {
 #define        EMAC_DEP_PREV_IDX       5
 #define        EMAC_DEP_COUNT          6
 
-static int __devinit emac_check_deps(struct emac_instance *dev,
-                                    struct emac_depentry *deps)
+static int emac_check_deps(struct emac_instance *dev,
+                          struct emac_depentry *deps)
 {
        int i, there = 0;
        struct device_node *np;
@@ -2314,8 +2314,8 @@ static void emac_put_deps(struct emac_instance *dev)
                of_dev_put(dev->tah_dev);
 }
 
-static int __devinit emac_of_bus_notify(struct notifier_block *nb,
-                                       unsigned long action, void *data)
+static int emac_of_bus_notify(struct notifier_block *nb, unsigned long action,
+                             void *data)
 {
        /* We are only intereted in device addition */
        if (action == BUS_NOTIFY_BOUND_DRIVER)
@@ -2323,11 +2323,11 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb,
        return 0;
 }
 
-static struct notifier_block emac_of_bus_notifier __devinitdata = {
+static struct notifier_block emac_of_bus_notifier = {
        .notifier_call = emac_of_bus_notify
 };
 
-static int __devinit emac_wait_deps(struct emac_instance *dev)
+static int emac_wait_deps(struct emac_instance *dev)
 {
        struct emac_depentry deps[EMAC_DEP_COUNT];
        int i, err;
@@ -2367,8 +2367,8 @@ static int __devinit emac_wait_deps(struct emac_instance *dev)
        return err;
 }
 
-static int __devinit emac_read_uint_prop(struct device_node *np, const char *name,
-                                        u32 *val, int fatal)
+static int emac_read_uint_prop(struct device_node *np, const char *name,
+                              u32 *val, int fatal)
 {
        int len;
        const u32 *prop = of_get_property(np, name, &len);
@@ -2382,7 +2382,7 @@ static int __devinit emac_read_uint_prop(struct device_node *np, const char *nam
        return 0;
 }
 
-static int __devinit emac_init_phy(struct emac_instance *dev)
+static int emac_init_phy(struct emac_instance *dev)
 {
        struct device_node *np = dev->ofdev->dev.of_node;
        struct net_device *ndev = dev->ndev;
@@ -2518,7 +2518,7 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
        return 0;
 }
 
-static int __devinit emac_init_config(struct emac_instance *dev)
+static int emac_init_config(struct emac_instance *dev)
 {
        struct device_node *np = dev->ofdev->dev.of_node;
        const void *p;
@@ -2703,7 +2703,7 @@ static const struct net_device_ops emac_gige_netdev_ops = {
        .ndo_change_mtu         = emac_change_mtu,
 };
 
-static int __devinit emac_probe(struct platform_device *ofdev)
+static int emac_probe(struct platform_device *ofdev)
 {
        struct net_device *ndev;
        struct emac_instance *dev;
@@ -2930,7 +2930,7 @@ static int __devinit emac_probe(struct platform_device *ofdev)
        return err;
 }
 
-static int __devexit emac_remove(struct platform_device *ofdev)
+static int emac_remove(struct platform_device *ofdev)
 {
        struct emac_instance *dev = dev_get_drvdata(&ofdev->dev);
 
index 479e43e2f1ef842cee474af85625cebd8ed30606..50ea12bfb579ebe47fd2d58ed082810e6e513cfa 100644 (file)
@@ -33,8 +33,7 @@
 
 static int mal_count;
 
-int __devinit mal_register_commac(struct mal_instance  *mal,
-                                 struct mal_commac     *commac)
+int mal_register_commac(struct mal_instance *mal, struct mal_commac *commac)
 {
        unsigned long flags;
 
@@ -517,7 +516,7 @@ void *mal_dump_regs(struct mal_instance *mal, void *buf)
        return regs + 1;
 }
 
-static int __devinit mal_probe(struct platform_device *ofdev)
+static int mal_probe(struct platform_device *ofdev)
 {
        struct mal_instance *mal;
        int err = 0, i, bd_size;
@@ -729,7 +728,7 @@ static int __devinit mal_probe(struct platform_device *ofdev)
        return err;
 }
 
-static int __devexit mal_remove(struct platform_device *ofdev)
+static int mal_remove(struct platform_device *ofdev)
 {
        struct mal_instance *mal = dev_get_drvdata(&ofdev->dev);
 
@@ -738,13 +737,11 @@ static int __devexit mal_remove(struct platform_device *ofdev)
        /* Synchronize with scheduled polling */
        napi_disable(&mal->napi);
 
-       if (!list_empty(&mal->list)) {
+       if (!list_empty(&mal->list))
                /* This is *very* bad */
-               printk(KERN_EMERG
+               WARN(1, KERN_EMERG
                       "mal%d: commac list is not empty on remove!\n",
                       mal->index);
-               WARN_ON(1);
-       }
 
        dev_set_drvdata(&ofdev->dev, NULL);
 
index d3123282e18ec3b8de290899bd6117df14995fa3..39251765b55d444c8dbc0ab0e380e89546d4a964 100644 (file)
@@ -93,7 +93,7 @@ static inline u32 rgmii_mode_mask(int mode, int input)
        }
 }
 
-int __devinit rgmii_attach(struct platform_device *ofdev, int input, int mode)
+int rgmii_attach(struct platform_device *ofdev, int input, int mode)
 {
        struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
        struct rgmii_regs __iomem *p = dev->base;
@@ -228,7 +228,7 @@ void *rgmii_dump_regs(struct platform_device *ofdev, void *buf)
 }
 
 
-static int __devinit rgmii_probe(struct platform_device *ofdev)
+static int rgmii_probe(struct platform_device *ofdev)
 {
        struct device_node *np = ofdev->dev.of_node;
        struct rgmii_instance *dev;
@@ -289,7 +289,7 @@ static int __devinit rgmii_probe(struct platform_device *ofdev)
        return rc;
 }
 
-static int __devexit rgmii_remove(struct platform_device *ofdev)
+static int rgmii_remove(struct platform_device *ofdev)
 {
        struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 
index 872912ef518d163f6a4df7108e53fad0bb658afc..795f1393e2b6d006fd568e91d22bfd58dc7d08d4 100644 (file)
@@ -23,7 +23,7 @@
 #include "emac.h"
 #include "core.h"
 
-int __devinit tah_attach(struct platform_device *ofdev, int channel)
+int tah_attach(struct platform_device *ofdev, int channel)
 {
        struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
 
@@ -87,7 +87,7 @@ void *tah_dump_regs(struct platform_device *ofdev, void *buf)
        return regs + 1;
 }
 
-static int __devinit tah_probe(struct platform_device *ofdev)
+static int tah_probe(struct platform_device *ofdev)
 {
        struct device_node *np = ofdev->dev.of_node;
        struct tah_instance *dev;
@@ -135,7 +135,7 @@ static int __devinit tah_probe(struct platform_device *ofdev)
        return rc;
 }
 
-static int __devexit tah_remove(struct platform_device *ofdev)
+static int tah_remove(struct platform_device *ofdev)
 {
        struct tah_instance *dev = dev_get_drvdata(&ofdev->dev);
 
index 415e9b4d54086ce6e7e8a2afdeeb2ea1582a2f10..f91202f42125d3088c6fbb69ac9c87b3417dfb07 100644 (file)
@@ -82,7 +82,7 @@ static inline u32 zmii_mode_mask(int mode, int input)
        }
 }
 
-int __devinit zmii_attach(struct platform_device *ofdev, int input, int *mode)
+int zmii_attach(struct platform_device *ofdev, int input, int *mode)
 {
        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
        struct zmii_regs __iomem *p = dev->base;
@@ -231,7 +231,7 @@ void *zmii_dump_regs(struct platform_device *ofdev, void *buf)
        return regs + 1;
 }
 
-static int __devinit zmii_probe(struct platform_device *ofdev)
+static int zmii_probe(struct platform_device *ofdev)
 {
        struct device_node *np = ofdev->dev.of_node;
        struct zmii_instance *dev;
@@ -282,7 +282,7 @@ static int __devinit zmii_probe(struct platform_device *ofdev)
        return rc;
 }
 
-static int __devexit zmii_remove(struct platform_device *ofdev)
+static int zmii_remove(struct platform_device *ofdev)
 {
        struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev);
 
index b68d28a130e664e2042bbb9a4335710964f861a7..f2fdbb79837eafcc7baf00d070efb48251bd1f7a 100644 (file)
@@ -1324,8 +1324,7 @@ static const struct net_device_ops ibmveth_netdev_ops = {
 #endif
 };
 
-static int __devinit ibmveth_probe(struct vio_dev *dev,
-                                  const struct vio_device_id *id)
+static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id)
 {
        int rc, i;
        struct net_device *netdev;
@@ -1426,7 +1425,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev,
        return 0;
 }
 
-static int __devexit ibmveth_remove(struct vio_dev *dev)
+static int ibmveth_remove(struct vio_dev *dev)
 {
        struct net_device *netdev = dev_get_drvdata(&dev->dev);
        struct ibmveth_adapter *adapter = netdev_priv(netdev);
@@ -1593,7 +1592,7 @@ static int ibmveth_resume(struct device *dev)
        return 0;
 }
 
-static struct vio_device_id ibmveth_device_table[] __devinitdata = {
+static struct vio_device_id ibmveth_device_table[] = {
        { "network", "IBM,l-lan"},
        { "", "" }
 };
index 1b563bb959c27d10a14d0cb0f3881c0f5a0962b5..068d78151658819ba5a88895df55942d59134e83 100644 (file)
@@ -2167,7 +2167,7 @@ static const struct ethtool_ops ipg_ethtool_ops = {
        .nway_reset   = ipg_nway_reset,
 };
 
-static void __devexit ipg_remove(struct pci_dev *pdev)
+static void ipg_remove(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct ipg_nic_private *sp = netdev_priv(dev);
@@ -2199,8 +2199,7 @@ static const struct net_device_ops ipg_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit ipg_probe(struct pci_dev *pdev,
-                              const struct pci_device_id *id)
+static int ipg_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        unsigned int i = id->driver_data;
        struct ipg_nic_private *sp;
@@ -2296,7 +2295,7 @@ static struct pci_driver ipg_pci_driver = {
        .name           = IPG_DRIVER_NAME,
        .id_table       = ipg_pci_tbl,
        .probe          = ipg_probe,
-       .remove         = __devexit_p(ipg_remove),
+       .remove         = ipg_remove,
 };
 
 static int __init ipg_init_module(void)
index 0cafe4fe9406125af6375cd8859b1919ab0d62d4..ddee4060948a3688d884b3591bdc7aee4d992992 100644 (file)
@@ -93,6 +93,7 @@ config E1000E
 config IGB
        tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
        depends on PCI
+       select PTP_1588_CLOCK
        ---help---
          This driver supports Intel(R) 82575/82576 gigabit ethernet family of
          adapters.  For more information on how to identify your adapter, go
@@ -120,19 +121,6 @@ config IGB_DCA
          driver.  DCA is a method for warming the CPU cache before data
          is used, with the intent of lessening the impact of cache misses.
 
-config IGB_PTP
-       bool "PTP Hardware Clock (PHC)"
-       default n
-       depends on IGB && EXPERIMENTAL
-       select PPS
-       select PTP_1588_CLOCK
-       ---help---
-         Say Y here if you want to use PTP Hardware Clock (PHC) in the
-         driver.  Only the basic clock operations have been implemented.
-
-         Every timestamp and clock read operations must consult the
-         overflow counter to form a correct time value.
-
 config IGBVF
        tristate "Intel(R) 82576 Virtual Function Ethernet support"
        depends on PCI
@@ -178,8 +166,9 @@ config IXGB
 
 config IXGBE
        tristate "Intel(R) 10GbE PCI Express adapters support"
-       depends on PCI && INET
+       depends on PCI
        select MDIO
+       select PTP_1588_CLOCK
        ---help---
          This driver supports Intel(R) 10GbE PCI Express family of
          adapters.  For more information on how to identify your adapter, go
@@ -222,19 +211,6 @@ config IXGBE_DCB
 
          If unsure, say N.
 
-config IXGBE_PTP
-       bool "PTP Clock Support"
-       default n
-       depends on IXGBE && EXPERIMENTAL
-       select PPS
-       select PTP_1588_CLOCK
-       ---help---
-         Say Y here if you want support for 1588 Timestamping with a
-         PHC device, using the PTP 1588 Clock support. This is
-         required to enable timestamping support for the device.
-
-         If unsure, say N.
-
 config IXGBEVF
        tristate "Intel(R) 82599 Virtual Function Ethernet support"
        depends on PCI_MSI
index 29ce9bd27f94ea21490f5b6c626d5a709a05ccd9..a59f0779e1c3a00a2603c54eb21343cd962945b5 100644 (file)
@@ -2829,8 +2829,7 @@ static const struct net_device_ops e100_netdev_ops = {
        .ndo_set_features       = e100_set_features,
 };
 
-static int __devinit e100_probe(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct nic *nic;
@@ -2981,7 +2980,7 @@ err_out_free_dev:
        return err;
 }
 
-static void __devexit e100_remove(struct pci_dev *pdev)
+static void e100_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
 
@@ -3167,7 +3166,7 @@ static struct pci_driver e100_driver = {
        .name =         DRV_NAME,
        .id_table =     e100_id_table,
        .probe =        e100_probe,
-       .remove =       __devexit_p(e100_remove),
+       .remove =       e100_remove,
 #ifdef CONFIG_PM
        /* Power Management hooks */
        .suspend =      e100_suspend,
index 3d6839528761c77462f0fee647d8fab1984913ef..8fedd2451538c255d0238a7f367bbb2d402aa2c8 100644 (file)
@@ -107,6 +107,7 @@ u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = {
 };
 
 static DEFINE_SPINLOCK(e1000_eeprom_lock);
+static DEFINE_SPINLOCK(e1000_phy_lock);
 
 /**
  * e1000_set_phy_type - Set the phy type member in the hw struct.
@@ -2830,19 +2831,25 @@ static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw)
 s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data)
 {
        u32 ret_val;
+       unsigned long flags;
 
        e_dbg("e1000_read_phy_reg");
 
+       spin_lock_irqsave(&e1000_phy_lock, flags);
+
        if ((hw->phy_type == e1000_phy_igp) &&
            (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
                ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
                                                 (u16) reg_addr);
-               if (ret_val)
+               if (ret_val) {
+                       spin_unlock_irqrestore(&e1000_phy_lock, flags);
                        return ret_val;
+               }
        }
 
        ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
                                        phy_data);
+       spin_unlock_irqrestore(&e1000_phy_lock, flags);
 
        return ret_val;
 }
@@ -2965,19 +2972,25 @@ static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr,
 s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data)
 {
        u32 ret_val;
+       unsigned long flags;
 
        e_dbg("e1000_write_phy_reg");
 
+       spin_lock_irqsave(&e1000_phy_lock, flags);
+
        if ((hw->phy_type == e1000_phy_igp) &&
            (reg_addr > MAX_PHY_MULTI_PAGE_REG)) {
                ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT,
                                                 (u16) reg_addr);
-               if (ret_val)
+               if (ret_val) {
+                       spin_unlock_irqrestore(&e1000_phy_lock, flags);
                        return ret_val;
+               }
        }
 
        ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
                                         phy_data);
+       spin_unlock_irqrestore(&e1000_phy_lock, flags);
 
        return ret_val;
 }
index 222bfaff4622959df30eb7b89f25a2f7764dcc32..294da56b824c3d0c4259b76f01858c80914fccbf 100644 (file)
@@ -111,7 +111,7 @@ void e1000_update_stats(struct e1000_adapter *adapter);
 static int e1000_init_module(void);
 static void e1000_exit_module(void);
 static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void __devexit e1000_remove(struct pci_dev *pdev);
+static void e1000_remove(struct pci_dev *pdev);
 static int e1000_alloc_queues(struct e1000_adapter *adapter);
 static int e1000_sw_init(struct e1000_adapter *adapter);
 static int e1000_open(struct net_device *netdev);
@@ -202,7 +202,7 @@ static struct pci_driver e1000_driver = {
        .name     = e1000_driver_name,
        .id_table = e1000_pci_tbl,
        .probe    = e1000_probe,
-       .remove   = __devexit_p(e1000_remove),
+       .remove   = e1000_remove,
 #ifdef CONFIG_PM
        /* Power Management Hooks */
        .suspend  = e1000_suspend,
@@ -938,8 +938,7 @@ static int e1000_init_hw_struct(struct e1000_adapter *adapter,
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  **/
-static int __devinit e1000_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct e1000_adapter *adapter;
@@ -1273,7 +1272,7 @@ err_pci_reg:
  * memory.
  **/
 
-static void __devexit e1000_remove(struct pci_dev *pdev)
+static void e1000_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -1309,7 +1308,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
  * e1000_init_hw_struct MUST be called before this function
  **/
 
-static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+static int e1000_sw_init(struct e1000_adapter *adapter)
 {
        adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
 
@@ -1340,7 +1339,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
  * number of queues at compile-time.
  **/
 
-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
+static int e1000_alloc_queues(struct e1000_adapter *adapter)
 {
        adapter->tx_ring = kcalloc(adapter->num_tx_queues,
                                   sizeof(struct e1000_tx_ring), GFP_KERNEL);
index 1301eba8b57adca90d79ce68ca75d7c81ec05494..750fc0194f3731d52de240aae5d29b7a4ac0f220 100644 (file)
@@ -45,7 +45,7 @@
 
 #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
 #define E1000_PARAM(X, desc) \
-       static int __devinitdata X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
+       static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \
        static unsigned int num_##X; \
        module_param_array_named(X, X, int, &num_##X, 0); \
        MODULE_PARM_DESC(X, desc);
@@ -205,9 +205,9 @@ struct e1000_option {
        } arg;
 };
 
-static int __devinit e1000_validate_option(unsigned int *value,
-                                          const struct e1000_option *opt,
-                                          struct e1000_adapter *adapter)
+static int e1000_validate_option(unsigned int *value,
+                                const struct e1000_option *opt,
+                                struct e1000_adapter *adapter)
 {
        if (*value == OPTION_UNSET) {
                *value = opt->def;
@@ -268,7 +268,7 @@ static void e1000_check_copper_options(struct e1000_adapter *adapter);
  * in a variable in the adapter structure.
  **/
 
-void __devinit e1000_check_options(struct e1000_adapter *adapter)
+void e1000_check_options(struct e1000_adapter *adapter)
 {
        struct e1000_option opt;
        int bd = adapter->bd_number;
@@ -534,7 +534,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter)
  * Handles speed and duplex options on fiber adapters
  **/
 
-static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
+static void e1000_check_fiber_options(struct e1000_adapter *adapter)
 {
        int bd = adapter->bd_number;
        if (num_Speed > bd) {
@@ -560,7 +560,7 @@ static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter)
  * Handles speed and duplex options on copper adapters
  **/
 
-static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter)
+static void e1000_check_copper_options(struct e1000_adapter *adapter)
 {
        struct e1000_option opt;
        unsigned int speed, dplx, an;
index 4dd18a1f45d27b7fd95ba6d486f509a7bce24a4d..e73c2c35599375a45bc253783df6cdfd2b91385d 100644 (file)
@@ -26,8 +26,7 @@
 
 *******************************************************************************/
 
-/*
- * 80003ES2LAN Gigabit Ethernet Controller (Copper)
+/* 80003ES2LAN Gigabit Ethernet Controller (Copper)
  * 80003ES2LAN Gigabit Ethernet Controller (Serdes)
  */
 
@@ -80,7 +79,8 @@
                                                           1 = 50-80M
                                                           2 = 80-110M
                                                           3 = 110-140M
-                                                          4 = >140M */
+                                                          4 = >140M
+                                                       */
 
 /* Kumeran Mode Control Register (Page 193, Register 16) */
 #define GG82563_KMCR_PASS_FALSE_CARRIER                 0x0800
@@ -95,8 +95,7 @@
 /* In-Band Control Register (Page 194, Register 18) */
 #define GG82563_ICR_DIS_PADDING                         0x0010 /* Disable Padding */
 
-/*
- * A table for the GG82563 cable length where the range is defined
+/* A table for the GG82563 cable length where the range is defined
  * with a lower bound at "index" and the upper bound at
  * "index + 5".
  */
@@ -183,8 +182,7 @@ static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
        size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
                          E1000_EECD_SIZE_EX_SHIFT);
 
-       /*
-        * Added to a constant, "size" becomes the left-shift value
+       /* Added to a constant, "size" becomes the left-shift value
         * for setting word_size.
         */
        size += NVM_WORD_SIZE_BASE_SHIFT;
@@ -375,8 +373,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
                if (!(swfw_sync & (fwmask | swmask)))
                        break;
 
-               /*
-                * Firmware currently using resource (fwmask)
+               /* Firmware currently using resource (fwmask)
                 * or other software thread using resource (swmask)
                 */
                e1000e_put_hw_semaphore(hw);
@@ -442,8 +439,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
                page_select = GG82563_PHY_PAGE_SELECT;
        } else {
-               /*
-                * Use Alternative Page Select register to access
+               /* Use Alternative Page Select register to access
                 * registers 30 and 31
                 */
                page_select = GG82563_PHY_PAGE_SELECT_ALT;
@@ -457,8 +453,7 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        }
 
        if (hw->dev_spec.e80003es2lan.mdic_wa_enable) {
-               /*
-                * The "ready" bit in the MDIC register may be incorrectly set
+               /* The "ready" bit in the MDIC register may be incorrectly set
                 * before the device has completed the "Page Select" MDI
                 * transaction.  So we wait 200us after each MDI command...
                 */
@@ -513,8 +508,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
                page_select = GG82563_PHY_PAGE_SELECT;
        } else {
-               /*
-                * Use Alternative Page Select register to access
+               /* Use Alternative Page Select register to access
                 * registers 30 and 31
                 */
                page_select = GG82563_PHY_PAGE_SELECT_ALT;
@@ -528,8 +522,7 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
        }
 
        if (hw->dev_spec.e80003es2lan.mdic_wa_enable) {
-               /*
-                * The "ready" bit in the MDIC register may be incorrectly set
+               /* The "ready" bit in the MDIC register may be incorrectly set
                 * before the device has completed the "Page Select" MDI
                 * transaction.  So we wait 200us after each MDI command...
                 */
@@ -618,8 +611,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
        u16 phy_data;
        bool link;
 
-       /*
-        * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
+       /* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
         * forced whenever speed and duplex are forced.
         */
        ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
@@ -657,8 +649,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
                        return ret_val;
 
                if (!link) {
-                       /*
-                        * We didn't get link.
+                       /* We didn't get link.
                         * Reset the DSP and cross our fingers.
                         */
                        ret_val = e1000e_phy_reset_dsp(hw);
@@ -677,8 +668,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Resetting the phy means we need to verify the TX_CLK corresponds
+       /* Resetting the phy means we need to verify the TX_CLK corresponds
         * to the link speed.  10Mbps -> 2.5MHz, else 25MHz.
         */
        phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
@@ -687,8 +677,7 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
        else
                phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
 
-       /*
-        * In addition, we must re-enable CRS on Tx for both half and full
+       /* In addition, we must re-enable CRS on Tx for both half and full
         * duplex.
         */
        phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
@@ -766,8 +755,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
        s32 ret_val;
        u16 kum_reg_data;
 
-       /*
-        * Prevent the PCI-E bus from sticking if there is no TLP connection
+       /* Prevent the PCI-E bus from sticking if there is no TLP connection
         * on the last TLP read/write transaction when MAC is reset.
         */
        ret_val = e1000e_disable_pcie_master(hw);
@@ -899,8 +887,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
                        hw->dev_spec.e80003es2lan.mdic_wa_enable = false;
        }
 
-       /*
-        * Clear all of the statistics registers (clear on read).  It is
+       /* Clear all of the statistics registers (clear on read).  It is
         * important that we do this after we have tried to establish link
         * because the symbol error count will increment wildly if there
         * is no link.
@@ -945,8 +932,7 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
                reg |= (1 << 28);
        ew32(TARC(1), reg);
 
-       /*
-        * Disable IPv6 extension header parsing because some malformed
+       /* Disable IPv6 extension header parsing because some malformed
         * IPv6 headers can hang the Rx.
         */
        reg = er32(RFCTL);
@@ -979,8 +965,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Options:
+       /* Options:
         *   MDI/MDI-X = 0 (default)
         *   0 - Auto for all speeds
         *   1 - MDI mode
@@ -1006,8 +991,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
                break;
        }
 
-       /*
-        * Options:
+       /* Options:
         *   disable_polarity_correction = 0 (default)
         *       Automatic Correction for Reversed Cable Polarity
         *   0 - Disabled
@@ -1065,8 +1049,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Do not init these registers when the HW is in IAMT mode, since the
+       /* Do not init these registers when the HW is in IAMT mode, since the
         * firmware will have already initialized them.  We only initialize
         * them if the HW is not in IAMT mode.
         */
@@ -1087,8 +1070,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
                        return ret_val;
        }
 
-       /*
-        * Workaround: Disable padding in Kumeran interface in the MAC
+       /* Workaround: Disable padding in Kumeran interface in the MAC
         * and in the PHY to avoid CRC errors.
         */
        ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data);
@@ -1121,8 +1103,7 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
        ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
        ew32(CTRL, ctrl);
 
-       /*
-        * Set the mac to wait the maximum time between each
+       /* Set the mac to wait the maximum time between each
         * iteration and increase the max iterations when
         * polling the phy; this fixes erroneous timeouts at 10Mbps.
         */
@@ -1352,8 +1333,7 @@ static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
 {
        s32 ret_val = 0;
 
-       /*
-        * If there's an alternate MAC address place it in RAR0
+       /* If there's an alternate MAC address place it in RAR0
         * so that it will override the Si installed default perm
         * address.
         */
index c98586408005a0dbbb557e4ae22fc3f49ba04a48..c77d010d5c5992da6c25761f6d1e1747f12d3273 100644 (file)
@@ -26,8 +26,7 @@
 
 *******************************************************************************/
 
-/*
- * 82571EB Gigabit Ethernet Controller
+/* 82571EB Gigabit Ethernet Controller
  * 82571EB Gigabit Ethernet Controller (Copper)
  * 82571EB Gigabit Ethernet Controller (Fiber)
  * 82571EB Dual Port Gigabit Mezzanine Adapter
@@ -191,8 +190,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
                if (((eecd >> 15) & 0x3) == 0x3) {
                        nvm->type = e1000_nvm_flash_hw;
                        nvm->word_size = 2048;
-                       /*
-                        * Autonomous Flash update bit must be cleared due
+                       /* Autonomous Flash update bit must be cleared due
                         * to Flash update issue.
                         */
                        eecd &= ~E1000_EECD_AUPDEN;
@@ -204,8 +202,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)
                nvm->type = e1000_nvm_eeprom_spi;
                size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
                                  E1000_EECD_SIZE_EX_SHIFT);
-               /*
-                * Added to a constant, "size" becomes the left-shift value
+               /* Added to a constant, "size" becomes the left-shift value
                 * for setting word_size.
                 */
                size += NVM_WORD_SIZE_BASE_SHIFT;
@@ -291,8 +288,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
 
                /* FWSM register */
                mac->has_fwsm = true;
-               /*
-                * ARC supported; valid only if manageability features are
+               /* ARC supported; valid only if manageability features are
                 * enabled.
                 */
                mac->arc_subsystem_valid = !!(er32(FWSM) &
@@ -314,8 +310,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
                break;
        }
 
-       /*
-        * Ensure that the inter-port SWSM.SMBI lock bit is clear before
+       /* Ensure that the inter-port SWSM.SMBI lock bit is clear before
         * first NVM or PHY access. This should be done for single-port
         * devices, and for one port only on dual-port devices so that
         * for those devices we can still use the SMBI lock to synchronize
@@ -352,11 +347,8 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
                ew32(SWSM, swsm & ~E1000_SWSM_SMBI);
        }
 
-       /*
-        * Initialize device specific counter of SMBI acquisition
-        * timeouts.
-        */
-        hw->dev_spec.e82571.smb_counter = 0;
+       /* Initialize device specific counter of SMBI acquisition timeouts. */
+       hw->dev_spec.e82571.smb_counter = 0;
 
        return 0;
 }
@@ -445,8 +437,7 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
-               /*
-                * The 82571 firmware may still be configuring the PHY.
+               /* The 82571 firmware may still be configuring the PHY.
                 * In this case, we cannot access the PHY until the
                 * configuration is done.  So we explicitly set the
                 * PHY ID.
@@ -492,8 +483,7 @@ static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw)
        s32 fw_timeout = hw->nvm.word_size + 1;
        s32 i = 0;
 
-       /*
-        * If we have timedout 3 times on trying to acquire
+       /* If we have timedout 3 times on trying to acquire
         * the inter-port SMBI semaphore, there is old code
         * operating on the other port, and it is not
         * releasing SMBI. Modify the number of times that
@@ -787,8 +777,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * If our nvm is an EEPROM, then we're done
+       /* If our nvm is an EEPROM, then we're done
         * otherwise, commit the checksum to the flash NVM.
         */
        if (hw->nvm.type != e1000_nvm_flash_hw)
@@ -806,8 +795,7 @@ static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw)
 
        /* Reset the firmware if using STM opcode. */
        if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) {
-               /*
-                * The enabling of and the actual reset must be done
+               /* The enabling of and the actual reset must be done
                 * in two write cycles.
                 */
                ew32(HICR, E1000_HICR_FW_RESET_ENABLE);
@@ -867,8 +855,7 @@ static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
        u32 i, eewr = 0;
        s32 ret_val = 0;
 
-       /*
-        * A check for invalid values:  offset too large, too many words,
+       /* A check for invalid values:  offset too large, too many words,
         * and not enough words.
         */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
@@ -957,8 +944,7 @@ static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active)
        } else {
                data &= ~IGP02E1000_PM_D0_LPLU;
                ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
-               /*
-                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
                 * during Dx states where the power conservation is most
                 * important.  During driver activity we should enable
                 * SmartSpeed, so performance is maintained.
@@ -1002,8 +988,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
        u32 ctrl, ctrl_ext, eecd, tctl;
        s32 ret_val;
 
-       /*
-        * Prevent the PCI-E bus from sticking if there is no TLP connection
+       /* Prevent the PCI-E bus from sticking if there is no TLP connection
         * on the last TLP read/write transaction when MAC is reset.
         */
        ret_val = e1000e_disable_pcie_master(hw);
@@ -1021,8 +1006,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
 
        usleep_range(10000, 20000);
 
-       /*
-        * Must acquire the MDIO ownership before MAC reset.
+       /* Must acquire the MDIO ownership before MAC reset.
         * Ownership defaults to firmware after a reset.
         */
        switch (hw->mac.type) {
@@ -1067,8 +1051,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
                /* We don't want to continue accessing MAC registers. */
                return ret_val;
 
-       /*
-        * Phy configuration from NVM just starts after EECD_AUTO_RD is set.
+       /* Phy configuration from NVM just starts after EECD_AUTO_RD is set.
         * Need to wait for Phy configuration completion before accessing
         * NVM and Phy.
         */
@@ -1076,8 +1059,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
-               /*
-                * REQ and GNT bits need to be cleared when using AUTO_RD
+               /* REQ and GNT bits need to be cleared when using AUTO_RD
                 * to access the EEPROM.
                 */
                eecd = er32(EECD);
@@ -1138,8 +1120,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
        e_dbg("Initializing the IEEE VLAN\n");
        mac->ops.clear_vfta(hw);
 
-       /* Setup the receive address. */
-       /*
+       /* Setup the receive address.
         * If, however, a locally administered address was assigned to the
         * 82571, we must reserve a RAR for it to work around an issue where
         * resetting one port will reload the MAC on the other port.
@@ -1183,8 +1164,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
                break;
        }
 
-       /*
-        * Clear all of the statistics registers (clear on read).  It is
+       /* Clear all of the statistics registers (clear on read).  It is
         * important that we do this after we have tried to establish link
         * because the symbol error count will increment wildly if there
         * is no link.
@@ -1281,8 +1261,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
                ew32(PBA_ECC, reg);
        }
 
-       /*
-        * Workaround for hardware errata.
+       /* Workaround for hardware errata.
         * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572
         */
        if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) {
@@ -1291,8 +1270,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
                ew32(CTRL_EXT, reg);
        }
 
-       /*
-        * Disable IPv6 extension header parsing because some malformed
+       /* Disable IPv6 extension header parsing because some malformed
         * IPv6 headers can hang the Rx.
         */
        if (hw->mac.type <= e1000_82573) {
@@ -1309,8 +1287,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
                reg |= (1 << 22);
                ew32(GCR, reg);
 
-               /*
-                * Workaround for hardware errata.
+               /* Workaround for hardware errata.
                 * apply workaround for hardware errata documented in errata
                 * docs Fixes issue where some error prone or unreliable PCIe
                 * completions are occurring, particularly with ASPM enabled.
@@ -1344,8 +1321,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw)
        case e1000_82574:
        case e1000_82583:
                if (hw->mng_cookie.vlan_id != 0) {
-                       /*
-                        * The VFTA is a 4096b bit-field, each identifying
+                       /* The VFTA is a 4096b bit-field, each identifying
                         * a single VLAN ID.  The following operations
                         * determine which 32b entry (i.e. offset) into the
                         * array we want to set the VLAN ID (i.e. bit) of
@@ -1362,8 +1338,7 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw)
                break;
        }
        for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
-               /*
-                * If the offset we want to clear is the same offset of the
+               /* If the offset we want to clear is the same offset of the
                 * manageability VLAN ID, then clear all bits except that of
                 * the manageability unit.
                 */
@@ -1401,8 +1376,7 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw)
 
        ctrl = hw->mac.ledctl_mode2;
        if (!(E1000_STATUS_LU & er32(STATUS))) {
-               /*
-                * If no link, then turn LED on by setting the invert bit
+               /* If no link, then turn LED on by setting the invert bit
                 * for each LED that's "on" (0x0E) in ledctl_mode2.
                 */
                for (i = 0; i < 4; i++)
@@ -1427,8 +1401,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
        u16 receive_errors = 0;
        s32 ret_val = 0;
 
-       /*
-        * Read PHY Receive Error counter first, if its is max - all F's then
+       /* Read PHY Receive Error counter first, if its is max - all F's then
         * read the Base1000T status register If both are max then PHY is hung.
         */
        ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors);
@@ -1458,8 +1431,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
  **/
 static s32 e1000_setup_link_82571(struct e1000_hw *hw)
 {
-       /*
-        * 82573 does not have a word in the NVM to determine
+       /* 82573 does not have a word in the NVM to determine
         * the default flow control setting, so we explicitly
         * set it to full.
         */
@@ -1526,8 +1498,7 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
        switch (hw->mac.type) {
        case e1000_82571:
        case e1000_82572:
-               /*
-                * If SerDes loopback mode is entered, there is no form
+               /* If SerDes loopback mode is entered, there is no form
                 * of reset to take the adapter out of that mode.  So we
                 * have to explicitly take the adapter out of loopback
                 * mode.  This prevents drivers from twiddling their thumbs
@@ -1584,8 +1555,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                switch (mac->serdes_link_state) {
                case e1000_serdes_link_autoneg_complete:
                        if (!(status & E1000_STATUS_LU)) {
-                               /*
-                                * We have lost link, retry autoneg before
+                               /* We have lost link, retry autoneg before
                                 * reporting link failure
                                 */
                                mac->serdes_link_state =
@@ -1598,8 +1568,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                        break;
 
                case e1000_serdes_link_forced_up:
-                       /*
-                        * If we are receiving /C/ ordered sets, re-enable
+                       /* If we are receiving /C/ ordered sets, re-enable
                         * auto-negotiation in the TXCW register and disable
                         * forced link in the Device Control register in an
                         * attempt to auto-negotiate with our link partner.
@@ -1619,8 +1588,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
 
                case e1000_serdes_link_autoneg_progress:
                        if (rxcw & E1000_RXCW_C) {
-                               /*
-                                * We received /C/ ordered sets, meaning the
+                               /* We received /C/ ordered sets, meaning the
                                 * link partner has autonegotiated, and we can
                                 * trust the Link Up (LU) status bit.
                                 */
@@ -1636,8 +1604,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                                        e_dbg("AN_PROG   -> DOWN\n");
                                }
                        } else {
-                               /*
-                                * The link partner did not autoneg.
+                               /* The link partner did not autoneg.
                                 * Force link up and full duplex, and change
                                 * state to forced.
                                 */
@@ -1660,8 +1627,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
 
                case e1000_serdes_link_down:
                default:
-                       /*
-                        * The link was down but the receiver has now gained
+                       /* The link was down but the receiver has now gained
                         * valid sync, so lets see if we can bring the link
                         * up.
                         */
@@ -1679,8 +1645,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                        mac->serdes_link_state = e1000_serdes_link_down;
                        e_dbg("ANYSTATE  -> DOWN\n");
                } else {
-                       /*
-                        * Check several times, if SYNCH bit and CONFIG
+                       /* Check several times, if SYNCH bit and CONFIG
                         * bit both are consistently 1 then simply ignore
                         * the IV bit and restart Autoneg
                         */
@@ -1780,8 +1745,7 @@ void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state)
 
        /* If workaround is activated... */
        if (state)
-               /*
-                * Hold a copy of the LAA in RAR[14] This is done so that
+               /* Hold a copy of the LAA in RAR[14] This is done so that
                 * between the time RAR[0] gets clobbered and the time it
                 * gets fixed, the actual LAA is in one of the RARs and no
                 * incoming packets directed to this port are dropped.
@@ -1810,8 +1774,7 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
        if (nvm->type != e1000_nvm_flash_hw)
                return 0;
 
-       /*
-        * Check bit 4 of word 10h.  If it is 0, firmware is done updating
+       /* Check bit 4 of word 10h.  If it is 0, firmware is done updating
         * 10h-12h.  Checksum may need to be fixed.
         */
        ret_val = e1000_read_nvm(hw, 0x10, 1, &data);
@@ -1819,8 +1782,7 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw)
                return ret_val;
 
        if (!(data & 0x10)) {
-               /*
-                * Read 0x23 and check bit 15.  This bit is a 1
+               /* Read 0x23 and check bit 15.  This bit is a 1
                 * when the checksum has already been fixed.  If
                 * the checksum is still wrong and this bit is a
                 * 1, we need to return bad checksum.  Otherwise,
@@ -1852,8 +1814,7 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
        if (hw->mac.type == e1000_82571) {
                s32 ret_val = 0;
 
-               /*
-                * If there's an alternate MAC address place it in RAR0
+               /* If there's an alternate MAC address place it in RAR0
                 * so that it will override the Si installed default perm
                 * address.
                 */
index 76edbc1be33b4d1151e72c24c1f621c830c3a039..02a12b69555f6fb5d71fe2089992f5fad5e354cc 100644 (file)
 #define E1000_RCTL_BSEX           0x02000000    /* Buffer size extension */
 #define E1000_RCTL_SECRC          0x04000000    /* Strip Ethernet CRC */
 
-/*
- * Use byte values for the following shift parameters
+/* Use byte values for the following shift parameters
  * Usage:
  *     psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) &
  *                  E1000_PSRCTL_BSIZE0_MASK) |
 #define E1000_CTRL_VME      0x40000000  /* IEEE VLAN mode enable */
 #define E1000_CTRL_PHY_RST  0x80000000  /* PHY Reset */
 
-/*
- * Bit definitions for the Management Data IO (MDIO) and Management Data
+/* Bit definitions for the Management Data IO (MDIO) and Management Data
  * Clock (MDC) pins in the Device Control Register.
  */
 
 #define E1000_PBA_ECC_STAT_CLR      0x00000002 /* Clear ECC error counter */
 #define E1000_PBA_ECC_INT_EN        0x00000004 /* Enable ICR bit 5 for ECC */
 
-/*
- * This defines the bits that are set in the Interrupt Mask
+/* This defines the bits that are set in the Interrupt Mask
  * Set/Read Register.  Each bit is documented below:
  *   o RXT0   = Receiver Timer Interrupt (ring 0)
  *   o TXDW   = Transmit Descriptor Written Back
 /* 802.1q VLAN Packet Size */
 #define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
 
-/* Receive Address */
-/*
+/* Receive Address
  * Number of high/low register pairs in the RAR. The RAR (Receive Address
  * Registers) holds the directed and multicast addresses that we monitor.
  * Technically, we have 16 spots.  However, we reserve one of these spots
 #define MAX_PHY_REG_ADDRESS    0x1F  /* 5 bit address bus (0-0x1F) */
 #define MAX_PHY_MULTI_PAGE_REG 0xF
 
-/* Bit definitions for valid PHY IDs. */
-/*
+/* Bit definitions for valid PHY IDs.
  * I = Integrated
  * E = External
  */
 #define M88E1000_PSCR_AUTO_X_1000T     0x0040
 /* Auto crossover enabled all speeds */
 #define M88E1000_PSCR_AUTO_X_MODE      0x0060
-/*
- * 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold)
+/* 1=Enable Extended 10BASE-T distance (Lower 10BASE-T Rx Threshold)
  * 0=Normal 10BASE-T Rx Threshold
  */
 #define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */
 
 #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7
 
-/*
- * Number of times we will attempt to autonegotiate before downshifting if we
+/* Number of times we will attempt to autonegotiate before downshifting if we
  * are the master
  */
 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00
 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X   0x0000
-/*
- * Number of times we will attempt to autonegotiate before downshifting if we
+/* Number of times we will attempt to autonegotiate before downshifting if we
  * are the slave
  */
 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK  0x0300
 #define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \
                            ((reg) & MAX_PHY_REG_ADDRESS))
 
-/*
- * Bits...
+/* Bits...
  * 15-5: page
  * 4-0: register offset
  */
index 04668b47a1df1a65f98eef94bea619d7a0c0c71d..6782a2eea1bcbfb893681b8d26428d8b0410981b 100644 (file)
@@ -161,8 +161,7 @@ struct e1000_info;
 /* Time to wait before putting the device into D3 if there's no link (in ms). */
 #define LINK_TIMEOUT           100
 
-/*
- * Count for polling __E1000_RESET condition every 10-20msec.
+/* Count for polling __E1000_RESET condition every 10-20msec.
  * Experimentation has shown the reset can take approximately 210msec.
  */
 #define E1000_CHECK_RESET_COUNT                25
@@ -172,8 +171,7 @@ struct e1000_info;
 #define BURST_RDTR                     0x20
 #define BURST_RADV                     0x20
 
-/*
- * in the case of WTHRESH, it appears at least the 82571/2 hardware
+/* in the case of WTHRESH, it appears at least the 82571/2 hardware
  * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when
  * WTHRESH=4, so a setting of 5 gives the most efficient bus
  * utilization but to avoid possible Tx stalls, set it to 1
@@ -214,8 +212,7 @@ struct e1000_ps_page {
        u64 dma; /* must be u64 - written to hw */
 };
 
-/*
- * wrappers around a pointer to a socket buffer,
+/* wrappers around a pointer to a socket buffer,
  * so a DMA handle can be stored along with the buffer
  */
 struct e1000_buffer {
@@ -305,9 +302,7 @@ struct e1000_adapter {
        u16 tx_itr;
        u16 rx_itr;
 
-       /*
-        * Tx
-        */
+       /* Tx */
        struct e1000_ring *tx_ring /* One per active queue */
                                                ____cacheline_aligned_in_smp;
        u32 tx_fifo_limit;
@@ -340,9 +335,7 @@ struct e1000_adapter {
        u32 tx_fifo_size;
        u32 tx_dma_failed;
 
-       /*
-        * Rx
-        */
+       /* Rx */
        bool (*clean_rx) (struct e1000_ring *ring, int *work_done,
                          int work_to_do) ____cacheline_aligned_in_smp;
        void (*alloc_rx_buf) (struct e1000_ring *ring, int cleaned_count,
index c11ac2756667bbf7205be4b5d1c903b00e7c3e4b..f95bc6ee1c227c89a2e158fde491dc03ef173b4b 100644 (file)
@@ -214,7 +214,8 @@ static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx)
        mac->autoneg = 0;
 
        /* Make sure dplx is at most 1 bit and lsb of speed is not set
-        * for the switch() below to work */
+        * for the switch() below to work
+        */
        if ((spd & 1) || (dplx & ~1))
                goto err_inval;
 
@@ -263,8 +264,7 @@ static int e1000_set_settings(struct net_device *netdev,
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
 
-       /*
-        * When SoL/IDER sessions are active, autoneg/speed/duplex
+       /* When SoL/IDER sessions are active, autoneg/speed/duplex
         * cannot be changed
         */
        if (hw->phy.ops.check_reset_block &&
@@ -273,8 +273,7 @@ static int e1000_set_settings(struct net_device *netdev,
                return -EINVAL;
        }
 
-       /*
-        * MDI setting is only allowed when autoneg enabled because
+       /* MDI setting is only allowed when autoneg enabled because
         * some hardware doesn't allow MDI setting when speed or
         * duplex is forced.
         */
@@ -316,8 +315,7 @@ static int e1000_set_settings(struct net_device *netdev,
 
        /* MDI-X => 2; MDI => 1; Auto => 3 */
        if (ecmd->eth_tp_mdix_ctrl) {
-               /*
-                * fix up the value for auto (3 => 0) as zero is mapped
+               /* fix up the value for auto (3 => 0) as zero is mapped
                 * internally to auto
                 */
                if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO)
@@ -454,8 +452,8 @@ static void e1000_get_regs(struct net_device *netdev,
        regs_buff[12] = adapter->hw.phy.type;  /* PHY type (IGP=1, M88=0) */
 
        /* ethtool doesn't use anything past this point, so all this
-        * code is likely legacy junk for apps that may or may not
-        * exist */
+        * code is likely legacy junk for apps that may or may not exist
+        */
        if (hw->phy.type == e1000_phy_m88) {
                e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
                regs_buff[13] = (u32)phy_data; /* cable length */
@@ -598,8 +596,7 @@ static int e1000_set_eeprom(struct net_device *netdev,
        if (ret_val)
                goto out;
 
-       /*
-        * Update the checksum over the first part of the EEPROM if needed
+       /* Update the checksum over the first part of the EEPROM if needed
         * and flush shadow RAM for applicable controllers
         */
        if ((first_word <= NVM_CHECKSUM_REG) ||
@@ -623,8 +620,7 @@ static void e1000_get_drvinfo(struct net_device *netdev,
        strlcpy(drvinfo->version, e1000e_driver_version,
                sizeof(drvinfo->version));
 
-       /*
-        * EEPROM image version # is reported as firmware version # for
+       /* EEPROM image version # is reported as firmware version # for
         * PCI-E controllers
         */
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
@@ -708,8 +704,7 @@ static int e1000_set_ringparam(struct net_device *netdev,
 
        e1000e_down(adapter);
 
-       /*
-        * We can't just free everything and then setup again, because the
+       /* We can't just free everything and then setup again, because the
         * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring
         * structs.  First, attempt to allocate new resources...
         */
@@ -813,8 +808,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
        u32 mask;
        u32 wlock_mac = 0;
 
-       /*
-        * The status register is Read Only, so a write should fail.
+       /* The status register is Read Only, so a write should fail.
         * Some bits that get toggled are ignored.
         */
        switch (mac->type) {
@@ -996,8 +990,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                }
 
                if (!shared_int) {
-                       /*
-                        * Disable the interrupt to be reported in
+                       /* Disable the interrupt to be reported in
                         * the cause register and then force the same
                         * interrupt and see if one gets posted.  If
                         * an interrupt was posted to the bus, the
@@ -1015,8 +1008,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                        }
                }
 
-               /*
-                * Enable the interrupt to be reported in
+               /* Enable the interrupt to be reported in
                 * the cause register and then force the same
                 * interrupt and see if one gets posted.  If
                 * an interrupt was not posted to the bus, the
@@ -1034,8 +1026,7 @@ static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data)
                }
 
                if (!shared_int) {
-                       /*
-                        * Disable the other interrupts to be reported in
+                       /* Disable the other interrupts to be reported in
                         * the cause register and then force the other
                         * interrupts and see if any get posted.  If
                         * an interrupt was posted to the bus, the
@@ -1378,8 +1369,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
            hw->phy.type == e1000_phy_m88) {
                ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */
        } else {
-               /*
-                * Set the ILOS bit on the fiber Nic if half duplex link is
+               /* Set the ILOS bit on the fiber Nic if half duplex link is
                 * detected.
                 */
                if ((er32(STATUS) & E1000_STATUS_FD) == 0)
@@ -1388,8 +1378,7 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
 
        ew32(CTRL, ctrl_reg);
 
-       /*
-        * Disable the receiver on the PHY so when a cable is plugged in, the
+       /* Disable the receiver on the PHY so when a cable is plugged in, the
         * PHY does not begin to autoneg when a cable is reconnected to the NIC.
         */
        if (hw->phy.type == e1000_phy_m88)
@@ -1408,8 +1397,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
 
        /* special requirements for 82571/82572 fiber adapters */
 
-       /*
-        * jump through hoops to make sure link is up because serdes
+       /* jump through hoops to make sure link is up because serdes
         * link is hardwired up
         */
        ctrl |= E1000_CTRL_SLU;
@@ -1429,8 +1417,7 @@ static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter)
                ew32(CTRL, ctrl);
        }
 
-       /*
-        * special write to serdes control register to enable SerDes analog
+       /* special write to serdes control register to enable SerDes analog
         * loopback
         */
 #define E1000_SERDES_LB_ON 0x410
@@ -1448,8 +1435,7 @@ static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter)
        u32 ctrlext = er32(CTRL_EXT);
        u32 ctrl = er32(CTRL);
 
-       /*
-        * save CTRL_EXT to restore later, reuse an empty variable (unused
+       /* save CTRL_EXT to restore later, reuse an empty variable (unused
         * on mac_type 80003es2lan)
         */
        adapter->tx_fifo_head = ctrlext;
@@ -1585,8 +1571,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
 
        ew32(RDT(0), rx_ring->count - 1);
 
-       /*
-        * Calculate the loop count based on the largest descriptor ring
+       /* Calculate the loop count based on the largest descriptor ring
         * The idea is to wrap the largest ring a number of times using 64
         * send/receive pairs during each loop
         */
@@ -1627,8 +1612,7 @@ static int e1000_run_loopback_test(struct e1000_adapter *adapter)
                        l++;
                        if (l == rx_ring->count)
                                l = 0;
-                       /*
-                        * time + 20 msecs (200 msecs on 2.4) is more than
+                       /* time + 20 msecs (200 msecs on 2.4) is more than
                         * enough time to complete the receives, if it's
                         * exceeded, break and error off
                         */
@@ -1649,10 +1633,7 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data)
 {
        struct e1000_hw *hw = &adapter->hw;
 
-       /*
-        * PHY loopback cannot be performed if SoL/IDER
-        * sessions are active
-        */
+       /* PHY loopback cannot be performed if SoL/IDER sessions are active */
        if (hw->phy.ops.check_reset_block &&
            hw->phy.ops.check_reset_block(hw)) {
                e_err("Cannot do PHY loopback test when SoL/IDER is active.\n");
@@ -1686,8 +1667,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
                int i = 0;
                hw->mac.serdes_has_link = false;
 
-               /*
-                * On some blade server designs, link establishment
+               /* On some blade server designs, link establishment
                 * could take as long as 2-3 minutes
                 */
                do {
@@ -1701,8 +1681,7 @@ static int e1000_link_test(struct e1000_adapter *adapter, u64 *data)
        } else {
                hw->mac.ops.check_for_link(hw);
                if (hw->mac.autoneg)
-                       /*
-                        * On some Phy/switch combinations, link establishment
+                       /* On some Phy/switch combinations, link establishment
                         * can take a few seconds more than expected.
                         */
                        msleep(5000);
index d37bfd96c987277980d4ec7b2e2db85f7e1dcf36..cf217777586c246561120c0877516f22d3ff6b89 100644 (file)
@@ -85,8 +85,7 @@ enum e1e_registers {
        E1000_FCRTL    = 0x02160, /* Flow Control Receive Threshold Low - RW */
        E1000_FCRTH    = 0x02168, /* Flow Control Receive Threshold High - RW */
        E1000_PSRCTL   = 0x02170, /* Packet Split Receive Control - RW */
-/*
- * Convenience macros
+/* Convenience macros
  *
  * Note: "_n" is the queue number of the register to be written to.
  *
@@ -800,8 +799,7 @@ struct e1000_mac_operations {
        s32  (*read_mac_addr)(struct e1000_hw *);
 };
 
-/*
- * When to use various PHY register access functions:
+/* When to use various PHY register access functions:
  *
  *                 Func   Caller
  *   Function      Does   Does    When to use
index e3a7b07df6294781559a72537d7949b711e82d00..976336547607e31caef68c8eaf528ddac78682da 100644 (file)
@@ -26,8 +26,7 @@
 
 *******************************************************************************/
 
-/*
- * 82562G 10/100 Network Connection
+/* 82562G 10/100 Network Connection
  * 82562G-2 10/100 Network Connection
  * 82562GT 10/100 Network Connection
  * 82562GT-2 10/100 Network Connection
@@ -354,8 +353,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
                return true;
        }
 
-       /*
-        * In case the PHY needs to be in mdio slow mode,
+       /* In case the PHY needs to be in mdio slow mode,
         * set slow mode and try to get the PHY id again.
         */
        hw->phy.ops.release(hw);
@@ -386,8 +384,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
                return ret_val;
        }
 
-       /*
-        * The MAC-PHY interconnect may be in SMBus mode.  If the PHY is
+       /* The MAC-PHY interconnect may be in SMBus mode.  If the PHY is
         * inaccessible and resetting the PHY is not blocked, toggle the
         * LANPHYPC Value bit to force the interconnect to PCIe mode.
         */
@@ -396,8 +393,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
                if (e1000_phy_is_accessible_pchlan(hw))
                        break;
 
-               /*
-                * Before toggling LANPHYPC, see if PHY is accessible by
+               /* Before toggling LANPHYPC, see if PHY is accessible by
                 * forcing MAC to SMBus mode first.
                 */
                mac_reg = er32(CTRL_EXT);
@@ -406,8 +402,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 
                /* fall-through */
        case e1000_pch2lan:
-               /*
-                * Gate automatic PHY configuration by hardware on
+               /* Gate automatic PHY configuration by hardware on
                 * non-managed 82579
                 */
                if ((hw->mac.type == e1000_pch2lan) &&
@@ -474,8 +469,7 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
 
        hw->phy.ops.release(hw);
 
-       /*
-        * Reset the PHY before any access to it.  Doing so, ensures
+       /* Reset the PHY before any access to it.  Doing so, ensures
         * that the PHY is in a known good state before we read/write
         * PHY registers.  The generic reset is sufficient here,
         * because we haven't determined the PHY type yet.
@@ -536,8 +530,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
                        /* fall-through */
                case e1000_pch2lan:
                case e1000_pch_lpt:
-                       /*
-                        * In case the PHY needs to be in mdio slow mode,
+                       /* In case the PHY needs to be in mdio slow mode,
                         * set slow mode and try to get the PHY id again.
                         */
                        ret_val = e1000_set_mdio_slow_mode_hv(hw);
@@ -593,8 +586,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
        phy->ops.power_up               = e1000_power_up_phy_copper;
        phy->ops.power_down             = e1000_power_down_phy_copper_ich8lan;
 
-       /*
-        * We may need to do this twice - once for IGP and if that fails,
+       /* We may need to do this twice - once for IGP and if that fails,
         * we'll set BM func pointers and try again
         */
        ret_val = e1000e_determine_phy_address(hw);
@@ -679,8 +671,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
 
        gfpreg = er32flash(ICH_FLASH_GFPREG);
 
-       /*
-        * sector_X_addr is a "sector"-aligned address (4096 bytes)
+       /* sector_X_addr is a "sector"-aligned address (4096 bytes)
         * Add 1 to sector_end_addr since this sector is included in
         * the overall size.
         */
@@ -690,8 +681,7 @@ static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
        /* flash_base_addr is byte-aligned */
        nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT;
 
-       /*
-        * find total size of the NVM, then cut in half since the total
+       /* find total size of the NVM, then cut in half since the total
         * size represents two separate NVM banks.
         */
        nvm->flash_bank_size = (sector_end_addr - sector_base_addr)
@@ -788,8 +778,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
        if (mac->type == e1000_ich8lan)
                e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
 
-       /*
-        * Gate automatic PHY configuration by hardware on managed
+       /* Gate automatic PHY configuration by hardware on managed
         * 82579 and i217
         */
        if ((mac->type == e1000_pch2lan || mac->type == e1000_pch_lpt) &&
@@ -840,8 +829,7 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
                        goto release;
                e1e_rphy_locked(hw, I82579_EMI_DATA, &dev_spec->eee_lp_ability);
 
-               /*
-                * EEE is not supported in 100Half, so ignore partner's EEE
+               /* EEE is not supported in 100Half, so ignore partner's EEE
                 * in 100 ability if full-duplex is not advertised.
                 */
                e1e_rphy_locked(hw, PHY_LP_ABILITY, &phy_reg);
@@ -869,8 +857,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
        bool link;
        u16 phy_reg;
 
-       /*
-        * We only want to go out to the PHY registers to see if Auto-Neg
+       /* We only want to go out to the PHY registers to see if Auto-Neg
         * has completed and/or if our link status has changed.  The
         * get_link_status flag is set upon receiving a Link Status
         * Change or Rx Sequence Error interrupt.
@@ -878,8 +865,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
        if (!mac->get_link_status)
                return 0;
 
-       /*
-        * First we want to see if the MII Status Register reports
+       /* First we want to see if the MII Status Register reports
         * link.  If so, then we want to get the current speed/duplex
         * of the PHY.
         */
@@ -914,8 +900,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                                return ret_val;
                }
 
-               /*
-                * Workaround for PCHx parts in half-duplex:
+               /* Workaround for PCHx parts in half-duplex:
                 * Set the number of preambles removed from the packet
                 * when it is passed from the PHY to the MAC to prevent
                 * the MAC from misinterpreting the packet type.
@@ -932,8 +917,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                break;
        }
 
-       /*
-        * Check if there was DownShift, must be checked
+       /* Check if there was DownShift, must be checked
         * immediately after link-up
         */
        e1000e_check_downshift(hw);
@@ -943,22 +927,19 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * If we are forcing speed/duplex, then we simply return since
+       /* If we are forcing speed/duplex, then we simply return since
         * we have already determined whether we have link or not.
         */
        if (!mac->autoneg)
                return -E1000_ERR_CONFIG;
 
-       /*
-        * Auto-Neg is enabled.  Auto Speed Detection takes care
+       /* Auto-Neg is enabled.  Auto Speed Detection takes care
         * of MAC speed/duplex configuration.  So we only need to
         * configure Collision Distance in the MAC.
         */
        mac->ops.config_collision_dist(hw);
 
-       /*
-        * Configure Flow Control now that Auto-Neg has completed.
+       /* Configure Flow Control now that Auto-Neg has completed.
         * First, we need to restore the desired flow control
         * settings because we may have had to re-autoneg with a
         * different link partner.
@@ -1000,8 +981,7 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
        if (rc)
                return rc;
 
-       /*
-        * Disable Jumbo Frame support on parts with Intel 10/100 PHY or
+       /* Disable Jumbo Frame support on parts with Intel 10/100 PHY or
         * on parts with MACsec enabled in NVM (reflected in CTRL_EXT).
         */
        if ((adapter->hw.phy.type == e1000_phy_ife) ||
@@ -1191,8 +1171,7 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
 {
        u32 rar_low, rar_high;
 
-       /*
-        * HW expects these in little endian so we reverse the byte order
+       /* HW expects these in little endian so we reverse the byte order
         * from network order (big endian) to little endian
         */
        rar_low = ((u32)addr[0] |
@@ -1256,8 +1235,7 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
        u32 rar_low, rar_high;
        u32 wlock_mac;
 
-       /*
-        * HW expects these in little endian so we reverse the byte order
+       /* HW expects these in little endian so we reverse the byte order
         * from network order (big endian) to little endian
         */
        rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
@@ -1277,8 +1255,7 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
                return;
        }
 
-       /*
-        * The manageability engine (ME) can lock certain SHRAR registers that
+       /* The manageability engine (ME) can lock certain SHRAR registers that
         * it is using - those registers are unavailable for use.
         */
        if (index < hw->mac.rar_entry_count) {
@@ -1387,8 +1364,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
        s32 ret_val = 0;
        u16 word_addr, reg_data, reg_addr, phy_page = 0;
 
-       /*
-        * Initialize the PHY from the NVM on ICH platforms.  This
+       /* Initialize the PHY from the NVM on ICH platforms.  This
         * is needed due to an issue where the NVM configuration is
         * not properly autoloaded after power transitions.
         * Therefore, after each PHY reset, we will load the
@@ -1422,8 +1398,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
        if (!(data & sw_cfg_mask))
                goto release;
 
-       /*
-        * Make sure HW does not configure LCD from PHY
+       /* Make sure HW does not configure LCD from PHY
         * extended configuration before SW configuration
         */
        data = er32(EXTCNF_CTRL);
@@ -1443,8 +1418,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
        if (((hw->mac.type == e1000_pchlan) &&
             !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) ||
            (hw->mac.type > e1000_pchlan)) {
-               /*
-                * HW configures the SMBus address and LEDs when the
+               /* HW configures the SMBus address and LEDs when the
                 * OEM and LCD Write Enable bits are set in the NVM.
                 * When both NVM bits are cleared, SW will configure
                 * them instead.
@@ -1748,8 +1722,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
        }
 
        if (hw->phy.type == e1000_phy_82578) {
-               /*
-                * Return registers to default by doing a soft reset then
+               /* Return registers to default by doing a soft reset then
                 * writing 0x3140 to the control register.
                 */
                if (hw->phy.revision < 2) {
@@ -1769,8 +1742,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Configure the K1 Si workaround during phy reset assuming there is
+       /* Configure the K1 Si workaround during phy reset assuming there is
         * link so that it disables K1 if link is in 1Gbps.
         */
        ret_val = e1000_k1_gig_workaround_hv(hw, true);
@@ -1853,8 +1825,7 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
                return ret_val;
 
        if (enable) {
-               /*
-                * Write Rx addresses (rar_entry_count for RAL/H, +4 for
+               /* Write Rx addresses (rar_entry_count for RAL/H, +4 for
                 * SHRAL/H) and initial CRC values to the MAC
                 */
                for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
@@ -2131,8 +2102,7 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
                udelay(100);
        } while ((!data) && --loop);
 
-       /*
-        * If basic configuration is incomplete before the above loop
+       /* If basic configuration is incomplete before the above loop
         * count reaches 0, loading the configuration from NVM will
         * leave the PHY in a bad state possibly resulting in no link.
         */
@@ -2299,8 +2269,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
                if (phy->type != e1000_phy_igp_3)
                        return 0;
 
-               /*
-                * Call gig speed drop workaround on LPLU before accessing
+               /* Call gig speed drop workaround on LPLU before accessing
                 * any PHY registers
                 */
                if (hw->mac.type == e1000_ich8lan)
@@ -2319,8 +2288,7 @@ static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
                if (phy->type != e1000_phy_igp_3)
                        return 0;
 
-               /*
-                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
                 * during Dx states where the power conservation is most
                 * important.  During driver activity we should enable
                 * SmartSpeed, so performance is maintained.
@@ -2382,8 +2350,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
                if (phy->type != e1000_phy_igp_3)
                        return 0;
 
-               /*
-                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
                 * during Dx states where the power conservation is most
                 * important.  During driver activity we should enable
                 * SmartSpeed, so performance is maintained.
@@ -2420,8 +2387,7 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
                if (phy->type != e1000_phy_igp_3)
                        return 0;
 
-               /*
-                * Call gig speed drop workaround on LPLU before accessing
+               /* Call gig speed drop workaround on LPLU before accessing
                 * any PHY registers
                 */
                if (hw->mac.type == e1000_ich8lan)
@@ -2589,8 +2555,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
 
        ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
 
-       /*
-        * Either we should have a hardware SPI cycle in progress
+       /* Either we should have a hardware SPI cycle in progress
         * bit to check against, in order to start a new cycle or
         * FDONE bit should be changed in the hardware so that it
         * is 1 after hardware reset, which can then be used as an
@@ -2599,8 +2564,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
         */
 
        if (!hsfsts.hsf_status.flcinprog) {
-               /*
-                * There is no cycle running at present,
+               /* There is no cycle running at present,
                 * so we can start a cycle.
                 * Begin by setting Flash Cycle Done.
                 */
@@ -2610,8 +2574,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
        } else {
                s32 i;
 
-               /*
-                * Otherwise poll for sometime so the current
+               /* Otherwise poll for sometime so the current
                 * cycle has a chance to end before giving up.
                 */
                for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
@@ -2623,8 +2586,7 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
                        udelay(1);
                }
                if (!ret_val) {
-                       /*
-                        * Successful in waiting for previous cycle to timeout,
+                       /* Successful in waiting for previous cycle to timeout,
                         * now set the Flash Cycle Done.
                         */
                        hsfsts.hsf_status.flcdone = 1;
@@ -2753,8 +2715,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
                ret_val = e1000_flash_cycle_ich8lan(hw,
                                                ICH_FLASH_READ_COMMAND_TIMEOUT);
 
-               /*
-                * Check if FCERR is set to 1, if set to 1, clear it
+               /* Check if FCERR is set to 1, if set to 1, clear it
                 * and try the whole sequence a few more times, else
                 * read in (shift in) the Flash Data0, the order is
                 * least significant byte first msb to lsb
@@ -2767,8 +2728,7 @@ static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
                                *data = (u16)(flash_data & 0x0000FFFF);
                        break;
                } else {
-                       /*
-                        * If we've gotten here, then things are probably
+                       /* If we've gotten here, then things are probably
                         * completely hosed, but if the error condition is
                         * detected, it won't hurt to give it another try...
                         * ICH_FLASH_CYCLE_REPEAT_COUNT times.
@@ -2849,8 +2809,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 
        nvm->ops.acquire(hw);
 
-       /*
-        * We're writing to the opposite bank so if we're on bank 1,
+       /* We're writing to the opposite bank so if we're on bank 1,
         * write to bank 0 etc.  We also need to erase the segment that
         * is going to be written
         */
@@ -2875,8 +2834,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
        }
 
        for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
-               /*
-                * Determine whether to write the value stored
+               /* Determine whether to write the value stored
                 * in the other NVM bank or a modified value stored
                 * in the shadow RAM
                 */
@@ -2890,8 +2848,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                                break;
                }
 
-               /*
-                * If the word is 0x13, then make sure the signature bits
+               /* If the word is 0x13, then make sure the signature bits
                 * (15:14) are 11b until the commit has completed.
                 * This will allow us to write 10b which indicates the
                 * signature is valid.  We want to do this after the write
@@ -2920,8 +2877,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                        break;
        }
 
-       /*
-        * Don't bother writing the segment valid bits if sector
+       /* Don't bother writing the segment valid bits if sector
         * programming failed.
         */
        if (ret_val) {
@@ -2930,8 +2886,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
                goto release;
        }
 
-       /*
-        * Finally validate the new segment by setting bit 15:14
+       /* Finally validate the new segment by setting bit 15:14
         * to 10b in word 0x13 , this can be done without an
         * erase as well since these bits are 11 to start with
         * and we need to change bit 14 to 0b
@@ -2948,8 +2903,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
        if (ret_val)
                goto release;
 
-       /*
-        * And invalidate the previously valid segment by setting
+       /* And invalidate the previously valid segment by setting
         * its signature word (0x13) high_byte to 0b. This can be
         * done without an erase because flash erase sets all bits
         * to 1's. We can write 1's to 0's without an erase
@@ -2968,8 +2922,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
 release:
        nvm->ops.release(hw);
 
-       /*
-        * Reload the EEPROM, or else modifications will not appear
+       /* Reload the EEPROM, or else modifications will not appear
         * until after the next adapter reset.
         */
        if (!ret_val) {
@@ -2997,8 +2950,7 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
        s32 ret_val;
        u16 data;
 
-       /*
-        * Read 0x19 and check bit 6.  If this bit is 0, the checksum
+       /* Read 0x19 and check bit 6.  If this bit is 0, the checksum
         * needs to be fixed.  This bit is an indication that the NVM
         * was prepared by OEM software and did not calculate the
         * checksum...a likely scenario.
@@ -3048,8 +3000,7 @@ void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
        pr0.range.wpe = true;
        ew32flash(ICH_FLASH_PR0, pr0.regval);
 
-       /*
-        * Lock down a subset of GbE Flash Control Registers, e.g.
+       /* Lock down a subset of GbE Flash Control Registers, e.g.
         * PR0 to prevent the write-protection from being lifted.
         * Once FLOCKDN is set, the registers protected by it cannot
         * be written until FLOCKDN is cleared by a hardware reset.
@@ -3109,8 +3060,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
 
                ew32flash(ICH_FLASH_FDATA0, flash_data);
 
-               /*
-                * check if FCERR is set to 1 , if set to 1, clear it
+               /* check if FCERR is set to 1 , if set to 1, clear it
                 * and try the whole sequence a few more times else done
                 */
                ret_val = e1000_flash_cycle_ich8lan(hw,
@@ -3118,8 +3068,7 @@ static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
                if (!ret_val)
                        break;
 
-               /*
-                * If we're here, then things are most likely
+               /* If we're here, then things are most likely
                 * completely hosed, but if the error condition
                 * is detected, it won't hurt to give it another
                 * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
@@ -3207,8 +3156,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
 
        hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
 
-       /*
-        * Determine HW Sector size: Read BERASE bits of hw flash status
+       /* Determine HW Sector size: Read BERASE bits of hw flash status
         * register
         * 00: The Hw sector is 256 bytes, hence we need to erase 16
         *     consecutive sectors.  The start index for the nth Hw sector
@@ -3253,16 +3201,14 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
                        if (ret_val)
                                return ret_val;
 
-                       /*
-                        * Write a value 11 (block Erase) in Flash
+                       /* Write a value 11 (block Erase) in Flash
                         * Cycle field in hw flash control
                         */
                        hsflctl.regval = er16flash(ICH_FLASH_HSFCTL);
                        hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
                        ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval);
 
-                       /*
-                        * Write the last 24 bits of an index within the
+                       /* Write the last 24 bits of an index within the
                         * block into Flash Linear address field in Flash
                         * Address.
                         */
@@ -3274,8 +3220,7 @@ static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
                        if (!ret_val)
                                break;
 
-                       /*
-                        * Check if FCERR is set to 1.  If 1,
+                       /* Check if FCERR is set to 1.  If 1,
                         * clear it and try the whole sequence
                         * a few more times else Done
                         */
@@ -3403,8 +3348,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
 
        ret_val = e1000e_get_bus_info_pcie(hw);
 
-       /*
-        * ICH devices are "PCI Express"-ish.  They have
+       /* ICH devices are "PCI Express"-ish.  They have
         * a configuration space, but do not contain
         * PCI Express Capability registers, so bus width
         * must be hardcoded.
@@ -3429,8 +3373,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        u32 ctrl, reg;
        s32 ret_val;
 
-       /*
-        * Prevent the PCI-E bus from sticking if there is no TLP connection
+       /* Prevent the PCI-E bus from sticking if there is no TLP connection
         * on the last TLP read/write transaction when MAC is reset.
         */
        ret_val = e1000e_disable_pcie_master(hw);
@@ -3440,8 +3383,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        e_dbg("Masking off all interrupts\n");
        ew32(IMC, 0xffffffff);
 
-       /*
-        * Disable the Transmit and Receive units.  Then delay to allow
+       /* Disable the Transmit and Receive units.  Then delay to allow
         * any pending transactions to complete before we hit the MAC
         * with the global reset.
         */
@@ -3474,15 +3416,13 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        ctrl = er32(CTRL);
 
        if (!hw->phy.ops.check_reset_block(hw)) {
-               /*
-                * Full-chip reset requires MAC and PHY reset at the same
+               /* Full-chip reset requires MAC and PHY reset at the same
                 * time to make sure the interface between MAC and the
                 * external PHY is reset.
                 */
                ctrl |= E1000_CTRL_PHY_RST;
 
-               /*
-                * Gate automatic PHY configuration by hardware on
+               /* Gate automatic PHY configuration by hardware on
                 * non-managed 82579
                 */
                if ((hw->mac.type == e1000_pch2lan) &&
@@ -3516,8 +3456,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
                        return ret_val;
        }
 
-       /*
-        * For PCH, this write will make sure that any noise
+       /* For PCH, this write will make sure that any noise
         * will be detected as a CRC error and be dropped rather than show up
         * as a bad packet to the DMA engine.
         */
@@ -3569,8 +3508,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
        for (i = 0; i < mac->mta_reg_count; i++)
                E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
 
-       /*
-        * The 82578 Rx buffer will stall if wakeup is enabled in host and
+       /* The 82578 Rx buffer will stall if wakeup is enabled in host and
         * the ME.  Disable wakeup by clearing the host wakeup bit.
         * Reset the phy after disabling host wakeup to reset the Rx buffer.
         */
@@ -3600,8 +3538,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
                 E1000_TXDCTL_MAX_TX_DESC_PREFETCH;
        ew32(TXDCTL(1), txdctl);
 
-       /*
-        * ICH8 has opposite polarity of no_snoop bits.
+       /* ICH8 has opposite polarity of no_snoop bits.
         * By default, we should use snoop behavior.
         */
        if (mac->type == e1000_ich8lan)
@@ -3614,8 +3551,7 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
        ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
        ew32(CTRL_EXT, ctrl_ext);
 
-       /*
-        * Clear all of the statistics registers (clear on read).  It is
+       /* Clear all of the statistics registers (clear on read).  It is
         * important that we do this after we have tried to establish link
         * because the symbol error count will increment wildly if there
         * is no link.
@@ -3676,15 +3612,13 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
                ew32(STATUS, reg);
        }
 
-       /*
-        * work-around descriptor data corruption issue during nfs v2 udp
+       /* work-around descriptor data corruption issue during nfs v2 udp
         * traffic, just disable the nfs filtering capability
         */
        reg = er32(RFCTL);
        reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
 
-       /*
-        * Disable IPv6 extension header parsing because some malformed
+       /* Disable IPv6 extension header parsing because some malformed
         * IPv6 headers can hang the Rx.
         */
        if (hw->mac.type == e1000_ich8lan)
@@ -3709,8 +3643,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
        if (hw->phy.ops.check_reset_block(hw))
                return 0;
 
-       /*
-        * ICH parts do not have a word in the NVM to determine
+       /* ICH parts do not have a word in the NVM to determine
         * the default flow control setting, so we explicitly
         * set it to full.
         */
@@ -3722,8 +3655,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
                        hw->fc.requested_mode = e1000_fc_full;
        }
 
-       /*
-        * Save off the requested flow control mode for use later.  Depending
+       /* Save off the requested flow control mode for use later.  Depending
         * on the link partner's capabilities, we may or may not use this mode.
         */
        hw->fc.current_mode = hw->fc.requested_mode;
@@ -3771,8 +3703,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
        ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
        ew32(CTRL, ctrl);
 
-       /*
-        * Set the mac to wait the maximum time between each iteration
+       /* Set the mac to wait the maximum time between each iteration
         * and increase the max iterations when polling the phy;
         * this fixes erroneous timeouts at 10Mbps.
         */
@@ -3892,8 +3823,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
        if (!dev_spec->kmrn_lock_loss_workaround_enabled)
                return 0;
 
-       /*
-        * Make sure link is up before proceeding.  If not just return.
+       /* Make sure link is up before proceeding.  If not just return.
         * Attempting this while link is negotiating fouled up link
         * stability
         */
@@ -3925,8 +3855,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
                     E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
        ew32(PHY_CTRL, phy_ctrl);
 
-       /*
-        * Call gig speed drop workaround on Gig disable before accessing
+       /* Call gig speed drop workaround on Gig disable before accessing
         * any PHY registers
         */
        e1000e_gig_downshift_workaround_ich8lan(hw);
@@ -3983,8 +3912,7 @@ void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
                        E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
                ew32(PHY_CTRL, reg);
 
-               /*
-                * Call gig speed drop workaround on Gig disable before
+               /* Call gig speed drop workaround on Gig disable before
                 * accessing any PHY registers
                 */
                if (hw->mac.type == e1000_ich8lan)
@@ -4078,8 +4006,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
                                goto release;
                        e1e_rphy_locked(hw, I82579_EMI_DATA, &eee_advert);
 
-                       /*
-                        * Disable LPLU if both link partners support 100BaseT
+                       /* Disable LPLU if both link partners support 100BaseT
                         * EEE and 100Full is advertised on both ends of the
                         * link.
                         */
@@ -4091,8 +4018,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
                                              E1000_PHY_CTRL_NOND0A_LPLU);
                }
 
-               /*
-                * For i217 Intel Rapid Start Technology support,
+               /* For i217 Intel Rapid Start Technology support,
                 * when the system is going into Sx and no manageability engine
                 * is present, the driver must configure proxy to reset only on
                 * power good.  LPI (Low Power Idle) state must also reset only
@@ -4106,8 +4032,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
                        phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
                        e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg);
 
-                       /*
-                        * Set bit enable LPI (EEE) to reset only on
+                       /* Set bit enable LPI (EEE) to reset only on
                         * power good.
                         */
                        e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg);
@@ -4120,8 +4045,7 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
                        e1e_wphy_locked(hw, I217_MEMPWR, phy_reg);
                }
 
-               /*
-                * Enable MTA to reset for Intel Rapid Start Technology
+               /* Enable MTA to reset for Intel Rapid Start Technology
                 * Support
                 */
                e1e_rphy_locked(hw, I217_CGFREG, &phy_reg);
@@ -4175,8 +4099,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
                return;
        }
 
-       /*
-        * For i217 Intel Rapid Start Technology support when the system
+       /* For i217 Intel Rapid Start Technology support when the system
         * is transitioning from Sx and no manageability engine is present
         * configure SMBus to restore on reset, disable proxy, and enable
         * the reset on MTA (Multicast table array).
@@ -4191,8 +4114,7 @@ void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
                }
 
                if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
-                       /*
-                        * Restore clear on SMB if no manageability engine
+                       /* Restore clear on SMB if no manageability engine
                         * is present
                         */
                        ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg);
@@ -4298,8 +4220,7 @@ static s32 e1000_led_on_pchlan(struct e1000_hw *hw)
        u16 data = (u16)hw->mac.ledctl_mode2;
        u32 i, led;
 
-       /*
-        * If no link, then turn LED on by setting the invert bit
+       /* If no link, then turn LED on by setting the invert bit
         * for each LED that's mode is "link_up" in ledctl_mode2.
         */
        if (!(er32(STATUS) & E1000_STATUS_LU)) {
@@ -4329,8 +4250,7 @@ static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
        u16 data = (u16)hw->mac.ledctl_mode1;
        u32 i, led;
 
-       /*
-        * If no link, then turn LED off by clearing the invert bit
+       /* If no link, then turn LED off by clearing the invert bit
         * for each LED that's mode is "link_up" in ledctl_mode1.
         */
        if (!(er32(STATUS) & E1000_STATUS_LU)) {
@@ -4375,8 +4295,7 @@ static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
        } else {
                ret_val = e1000e_get_auto_rd_done(hw);
                if (ret_val) {
-                       /*
-                        * When auto config read does not complete, do not
+                       /* When auto config read does not complete, do not
                         * return with an error. This can happen in situations
                         * where there is no eeprom and prevents getting link.
                         */
index a13439928488c7aeab640d0a99f0833a5e74f203..54d9dafaf126609f4e9796b80f8d92de2c966745 100644 (file)
@@ -73,8 +73,7 @@ void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
        struct e1000_bus_info *bus = &hw->bus;
        u32 reg;
 
-       /*
-        * The status register reports the correct function number
+       /* The status register reports the correct function number
         * for the device regardless of function swap state.
         */
        reg = er32(STATUS);
@@ -210,8 +209,7 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
                return 0;
        }
 
-       /*
-        * We have a valid alternate MAC address, and we want to treat it the
+       /* We have a valid alternate MAC address, and we want to treat it the
         * same as the normal permanent MAC address stored by the HW into the
         * RAR. Do this by mapping this address into RAR0.
         */
@@ -233,8 +231,7 @@ void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
 {
        u32 rar_low, rar_high;
 
-       /*
-        * HW expects these in little endian so we reverse the byte order
+       /* HW expects these in little endian so we reverse the byte order
         * from network order (big endian) to little endian
         */
        rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) |
@@ -246,8 +243,7 @@ void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
        if (rar_low || rar_high)
                rar_high |= E1000_RAH_AV;
 
-       /*
-        * Some bridges will combine consecutive 32-bit writes into
+       /* Some bridges will combine consecutive 32-bit writes into
         * a single burst write, which will malfunction on some parts.
         * The flushes avoid this.
         */
@@ -273,15 +269,13 @@ static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr)
        /* Register count multiplied by bits per register */
        hash_mask = (hw->mac.mta_reg_count * 32) - 1;
 
-       /*
-        * For a mc_filter_type of 0, bit_shift is the number of left-shifts
+       /* For a mc_filter_type of 0, bit_shift is the number of left-shifts
         * where 0xFF would still fall within the hash mask.
         */
        while (hash_mask >> bit_shift != 0xFF)
                bit_shift++;
 
-       /*
-        * The portion of the address that is used for the hash table
+       /* The portion of the address that is used for the hash table
         * is determined by the mc_filter_type setting.
         * The algorithm is such that there is a total of 8 bits of shifting.
         * The bit_shift for a mc_filter_type of 0 represents the number of
@@ -423,8 +417,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
        s32 ret_val;
        bool link;
 
-       /*
-        * We only want to go out to the PHY registers to see if Auto-Neg
+       /* We only want to go out to the PHY registers to see if Auto-Neg
         * has completed and/or if our link status has changed.  The
         * get_link_status flag is set upon receiving a Link Status
         * Change or Rx Sequence Error interrupt.
@@ -432,8 +425,7 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
        if (!mac->get_link_status)
                return 0;
 
-       /*
-        * First we want to see if the MII Status Register reports
+       /* First we want to see if the MII Status Register reports
         * link.  If so, then we want to get the current speed/duplex
         * of the PHY.
         */
@@ -446,28 +438,24 @@ s32 e1000e_check_for_copper_link(struct e1000_hw *hw)
 
        mac->get_link_status = false;
 
-       /*
-        * Check if there was DownShift, must be checked
+       /* Check if there was DownShift, must be checked
         * immediately after link-up
         */
        e1000e_check_downshift(hw);
 
-       /*
-        * If we are forcing speed/duplex, then we simply return since
+       /* If we are forcing speed/duplex, then we simply return since
         * we have already determined whether we have link or not.
         */
        if (!mac->autoneg)
                return -E1000_ERR_CONFIG;
 
-       /*
-        * Auto-Neg is enabled.  Auto Speed Detection takes care
+       /* Auto-Neg is enabled.  Auto Speed Detection takes care
         * of MAC speed/duplex configuration.  So we only need to
         * configure Collision Distance in the MAC.
         */
        mac->ops.config_collision_dist(hw);
 
-       /*
-        * Configure Flow Control now that Auto-Neg has completed.
+       /* Configure Flow Control now that Auto-Neg has completed.
         * First, we need to restore the desired flow control
         * settings because we may have had to re-autoneg with a
         * different link partner.
@@ -498,8 +486,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
        status = er32(STATUS);
        rxcw = er32(RXCW);
 
-       /*
-        * If we don't have link (auto-negotiation failed or link partner
+       /* If we don't have link (auto-negotiation failed or link partner
         * cannot auto-negotiate), the cable is plugged in (we have signal),
         * and our link partner is not trying to auto-negotiate with us (we
         * are receiving idles or data), we need to force link up. We also
@@ -530,8 +517,7 @@ s32 e1000e_check_for_fiber_link(struct e1000_hw *hw)
                        return ret_val;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-               /*
-                * If we are forcing link and we are receiving /C/ ordered
+               /* If we are forcing link and we are receiving /C/ ordered
                 * sets, re-enable auto-negotiation in the TXCW register
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
@@ -565,8 +551,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
        status = er32(STATUS);
        rxcw = er32(RXCW);
 
-       /*
-        * If we don't have link (auto-negotiation failed or link partner
+       /* If we don't have link (auto-negotiation failed or link partner
         * cannot auto-negotiate), and our link partner is not trying to
         * auto-negotiate with us (we are receiving idles or data),
         * we need to force link up. We also need to give auto-negotiation
@@ -595,8 +580,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
                        return ret_val;
                }
        } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) {
-               /*
-                * If we are forcing link and we are receiving /C/ ordered
+               /* If we are forcing link and we are receiving /C/ ordered
                 * sets, re-enable auto-negotiation in the TXCW register
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
@@ -607,8 +591,7 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
 
                mac->serdes_has_link = true;
        } else if (!(E1000_TXCW_ANE & er32(TXCW))) {
-               /*
-                * If we force link for non-auto-negotiation switch, check
+               /* If we force link for non-auto-negotiation switch, check
                 * link status based on MAC synchronization for internal
                 * serdes media type.
                 */
@@ -665,8 +648,7 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
        s32 ret_val;
        u16 nvm_data;
 
-       /*
-        * Read and store word 0x0F of the EEPROM. This word contains bits
+       /* Read and store word 0x0F of the EEPROM. This word contains bits
         * that determine the hardware's default PAUSE (flow control) mode,
         * a bit that determines whether the HW defaults to enabling or
         * disabling auto-negotiation, and the direction of the
@@ -705,15 +687,13 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw)
 {
        s32 ret_val;
 
-       /*
-        * In the case of the phy reset being blocked, we already have a link.
+       /* In the case of the phy reset being blocked, we already have a link.
         * We do not need to set it up again.
         */
        if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw))
                return 0;
 
-       /*
-        * If requested flow control is set to default, set flow control
+       /* If requested flow control is set to default, set flow control
         * based on the EEPROM flow control settings.
         */
        if (hw->fc.requested_mode == e1000_fc_default) {
@@ -722,8 +702,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw)
                        return ret_val;
        }
 
-       /*
-        * Save off the requested flow control mode for use later.  Depending
+       /* Save off the requested flow control mode for use later.  Depending
         * on the link partner's capabilities, we may or may not use this mode.
         */
        hw->fc.current_mode = hw->fc.requested_mode;
@@ -735,8 +714,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Initialize the flow control address, type, and PAUSE timer
+       /* Initialize the flow control address, type, and PAUSE timer
         * registers to their default values.  This is done even if flow
         * control is disabled, because it does not hurt anything to
         * initialize these registers.
@@ -763,8 +741,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
        struct e1000_mac_info *mac = &hw->mac;
        u32 txcw;
 
-       /*
-        * Check for a software override of the flow control settings, and
+       /* Check for a software override of the flow control settings, and
         * setup the device accordingly.  If auto-negotiation is enabled, then
         * software will have to set the "PAUSE" bits to the correct value in
         * the Transmit Config Word Register (TXCW) and re-start auto-
@@ -786,8 +763,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
                break;
        case e1000_fc_rx_pause:
-               /*
-                * Rx Flow control is enabled and Tx Flow control is disabled
+               /* Rx Flow control is enabled and Tx Flow control is disabled
                 * by a software over-ride. Since there really isn't a way to
                 * advertise that we are capable of Rx Pause ONLY, we will
                 * advertise that we support both symmetric and asymmetric Rx
@@ -797,15 +773,13 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
                break;
        case e1000_fc_tx_pause:
-               /*
-                * Tx Flow control is enabled, and Rx Flow control is disabled,
+               /* Tx Flow control is enabled, and Rx Flow control is disabled,
                 * by a software over-ride.
                 */
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR);
                break;
        case e1000_fc_full:
-               /*
-                * Flow control (both Rx and Tx) is enabled by a software
+               /* Flow control (both Rx and Tx) is enabled by a software
                 * over-ride.
                 */
                txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK);
@@ -835,8 +809,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
        u32 i, status;
        s32 ret_val;
 
-       /*
-        * If we have a signal (the cable is plugged in, or assumed true for
+       /* If we have a signal (the cable is plugged in, or assumed true for
         * serdes media) then poll for a "Link-Up" indication in the Device
         * Status Register.  Time-out if a link isn't seen in 500 milliseconds
         * seconds (Auto-negotiation should complete in less than 500
@@ -851,8 +824,7 @@ static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw)
        if (i == FIBER_LINK_UP_LIMIT) {
                e_dbg("Never got a valid link from auto-neg!!!\n");
                mac->autoneg_failed = true;
-               /*
-                * AutoNeg failed to achieve a link, so we'll call
+               /* AutoNeg failed to achieve a link, so we'll call
                 * mac->check_for_link. This routine will force the
                 * link up if we detect a signal. This will allow us to
                 * communicate with non-autonegotiating link partners.
@@ -894,8 +866,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Since auto-negotiation is enabled, take the link out of reset (the
+       /* Since auto-negotiation is enabled, take the link out of reset (the
         * link will be in reset, because we previously reset the chip). This
         * will restart auto-negotiation.  If auto-negotiation is successful
         * then the link-up status bit will be set and the flow control enable
@@ -907,8 +878,7 @@ s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw)
        e1e_flush();
        usleep_range(1000, 2000);
 
-       /*
-        * For these adapters, the SW definable pin 1 is set when the optics
+       /* For these adapters, the SW definable pin 1 is set when the optics
         * detect a signal.  If we have a signal, then poll for a "Link-Up"
         * indication.
         */
@@ -954,16 +924,14 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
 {
        u32 fcrtl = 0, fcrth = 0;
 
-       /*
-        * Set the flow control receive threshold registers.  Normally,
+       /* Set the flow control receive threshold registers.  Normally,
         * these registers will be set to a default threshold that may be
         * adjusted later by the driver's runtime code.  However, if the
         * ability to transmit pause frames is not enabled, then these
         * registers will be set to 0.
         */
        if (hw->fc.current_mode & e1000_fc_tx_pause) {
-               /*
-                * We need to set up the Receive Threshold high and low water
+               /* We need to set up the Receive Threshold high and low water
                 * marks as well as (optionally) enabling the transmission of
                 * XON frames.
                 */
@@ -995,8 +963,7 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
 
        ctrl = er32(CTRL);
 
-       /*
-        * Because we didn't get link via the internal auto-negotiation
+       /* Because we didn't get link via the internal auto-negotiation
         * mechanism (we either forced link or we got link via PHY
         * auto-neg), we have to manually enable/disable transmit an
         * receive flow control.
@@ -1057,8 +1024,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
        u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
        u16 speed, duplex;
 
-       /*
-        * Check for the case where we have fiber media and auto-neg failed
+       /* Check for the case where we have fiber media and auto-neg failed
         * so we had to force link.  In this case, we need to force the
         * configuration of the MAC to match the "fc" parameter.
         */
@@ -1076,15 +1042,13 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                return ret_val;
        }
 
-       /*
-        * Check for the case where we have copper media and auto-neg is
+       /* Check for the case where we have copper media and auto-neg is
         * enabled.  In this case, we need to check and see if Auto-Neg
         * has completed, and if so, how the PHY and link partner has
         * flow control configured.
         */
        if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) {
-               /*
-                * Read the MII Status Register and check to see if AutoNeg
+               /* Read the MII Status Register and check to see if AutoNeg
                 * has completed.  We read this twice because this reg has
                 * some "sticky" (latched) bits.
                 */
@@ -1100,8 +1064,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                        return ret_val;
                }
 
-               /*
-                * The AutoNeg process has completed, so we now need to
+               /* The AutoNeg process has completed, so we now need to
                 * read both the Auto Negotiation Advertisement
                 * Register (Address 4) and the Auto_Negotiation Base
                 * Page Ability Register (Address 5) to determine how
@@ -1115,8 +1078,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                if (ret_val)
                        return ret_val;
 
-               /*
-                * Two bits in the Auto Negotiation Advertisement Register
+               /* Two bits in the Auto Negotiation Advertisement Register
                 * (Address 4) and two bits in the Auto Negotiation Base
                 * Page Ability Register (Address 5) determine flow control
                 * for both the PHY and the link partner.  The following
@@ -1151,8 +1113,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                 */
                if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
                    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
-                       /*
-                        * Now we need to check if the user selected Rx ONLY
+                       /* Now we need to check if the user selected Rx ONLY
                         * of pause frames.  In this case, we had to advertise
                         * FULL flow control because we could not advertise Rx
                         * ONLY. Hence, we must now check to see if we need to
@@ -1166,8 +1127,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                                e_dbg("Flow Control = Rx PAUSE frames only.\n");
                        }
                }
-               /*
-                * For receiving PAUSE frames ONLY.
+               /* For receiving PAUSE frames ONLY.
                 *
                 *   LOCAL DEVICE  |   LINK PARTNER
                 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
@@ -1181,8 +1141,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                        hw->fc.current_mode = e1000_fc_tx_pause;
                        e_dbg("Flow Control = Tx PAUSE frames only.\n");
                }
-               /*
-                * For transmitting PAUSE frames ONLY.
+               /* For transmitting PAUSE frames ONLY.
                 *
                 *   LOCAL DEVICE  |   LINK PARTNER
                 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
@@ -1196,16 +1155,14 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                        hw->fc.current_mode = e1000_fc_rx_pause;
                        e_dbg("Flow Control = Rx PAUSE frames only.\n");
                } else {
-                       /*
-                        * Per the IEEE spec, at this point flow control
+                       /* Per the IEEE spec, at this point flow control
                         * should be disabled.
                         */
                        hw->fc.current_mode = e1000_fc_none;
                        e_dbg("Flow Control = NONE.\n");
                }
 
-               /*
-                * Now we need to do one last check...  If we auto-
+               /* Now we need to do one last check...  If we auto-
                 * negotiated to HALF DUPLEX, flow control should not be
                 * enabled per IEEE 802.3 spec.
                 */
@@ -1218,8 +1175,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
                if (duplex == HALF_DUPLEX)
                        hw->fc.current_mode = e1000_fc_none;
 
-               /*
-                * Now we call a subroutine to actually force the MAC
+               /* Now we call a subroutine to actually force the MAC
                 * controller to use the correct flow control settings.
                 */
                ret_val = e1000e_force_mac_fc(hw);
@@ -1520,8 +1476,7 @@ s32 e1000e_blink_led_generic(struct e1000_hw *hw)
                ledctl_blink = E1000_LEDCTL_LED0_BLINK |
                    (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT);
        } else {
-               /*
-                * set the blink bit for each LED that's "on" (0x0E)
+               /* set the blink bit for each LED that's "on" (0x0E)
                 * in ledctl_mode2
                 */
                ledctl_blink = hw->mac.ledctl_mode2;
index bacc950fc684ee35c1d2ad0003098f4b890b9685..6dc47beb3adce59a46116bc37bc5e14ec931e109 100644 (file)
@@ -143,8 +143,7 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
                return hw->mac.tx_pkt_filtering;
        }
 
-       /*
-        * If we can't read from the host interface for whatever
+       /* If we can't read from the host interface for whatever
         * reason, disable filtering.
         */
        ret_val = e1000_mng_enable_host_if(hw);
@@ -163,8 +162,7 @@ bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw)
        hdr->checksum = 0;
        csum = e1000_calculate_checksum((u8 *)hdr,
                                        E1000_MNG_DHCP_COOKIE_LENGTH);
-       /*
-        * If either the checksums or signature don't match, then
+       /* If either the checksums or signature don't match, then
         * the cookie area isn't considered valid, in which case we
         * take the safe route of assuming Tx filtering is enabled.
         */
@@ -252,8 +250,7 @@ static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer,
        /* Calculate length in DWORDs */
        length >>= 2;
 
-       /*
-        * The device driver writes the relevant command block into the
+       /* The device driver writes the relevant command block into the
         * ram area.
         */
        for (i = 0; i < length; i++) {
index f444eb0b76d8d9c0c7147b8dc4a9fa7266d517b9..fbf75fdca99422743f35d3d9a114fcdef235563f 100644 (file)
@@ -146,9 +146,11 @@ static const struct e1000_reg_info e1000_reg_info_tbl[] = {
        {0, NULL}
 };
 
-/*
+/**
  * e1000_regdump - register printout routine
- */
+ * @hw: pointer to the HW structure
+ * @reginfo: pointer to the register info table
+ **/
 static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo)
 {
        int n = 0;
@@ -196,9 +198,10 @@ static void e1000e_dump_ps_pages(struct e1000_adapter *adapter,
        }
 }
 
-/*
+/**
  * e1000e_dump - Print registers, Tx-ring and Rx-ring
- */
+ * @adapter: board private structure
+ **/
 static void e1000e_dump(struct e1000_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
@@ -623,8 +626,7 @@ map_skb:
                rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
 
                if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
-                       /*
-                        * Force memory writes to complete before letting h/w
+                       /* Force memory writes to complete before letting h/w
                         * know there are new descriptors to fetch.  (Only
                         * applicable for weak-ordered memory model archs,
                         * such as IA-64).
@@ -692,8 +694,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring,
                                        goto no_buffers;
                                }
                        }
-                       /*
-                        * Refresh the desc even if buffer_addrs
+                       /* Refresh the desc even if buffer_addrs
                         * didn't change because each write-back
                         * erases this info.
                         */
@@ -726,8 +727,7 @@ static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring,
                rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma);
 
                if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) {
-                       /*
-                        * Force memory writes to complete before letting h/w
+                       /* Force memory writes to complete before letting h/w
                         * know there are new descriptors to fetch.  (Only
                         * applicable for weak-ordered memory model archs,
                         * such as IA-64).
@@ -817,7 +817,8 @@ check_page:
                /* Force memory writes to complete before letting h/w
                 * know there are new descriptors to fetch.  (Only
                 * applicable for weak-ordered memory model archs,
-                * such as IA-64). */
+                * such as IA-64).
+                */
                wmb();
                if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA)
                        e1000e_update_rdt_wa(rx_ring, i);
@@ -891,8 +892,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
 
                length = le16_to_cpu(rx_desc->wb.upper.length);
 
-               /*
-                * !EOP means multiple descriptors were used to store a single
+               /* !EOP means multiple descriptors were used to store a single
                 * packet, if that's the case we need to toss it.  In fact, we
                 * need to toss every packet with the EOP bit clear and the
                 * next frame that _does_ have the EOP bit set, as it is by
@@ -933,8 +933,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done,
                total_rx_bytes += length;
                total_rx_packets++;
 
-               /*
-                * code added for copybreak, this should improve
+               /* code added for copybreak, this should improve
                 * performance for small packets with large amounts
                 * of reassembly being done in the stack
                 */
@@ -1032,15 +1031,13 @@ static void e1000_print_hw_hang(struct work_struct *work)
 
        if (!adapter->tx_hang_recheck &&
            (adapter->flags2 & FLAG2_DMA_BURST)) {
-               /*
-                * May be block on write-back, flush and detect again
+               /* May be block on write-back, flush and detect again
                 * flush pending descriptor writebacks to memory
                 */
                ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
                /* execute the writes immediately */
                e1e_flush();
-               /*
-                * Due to rare timing issues, write to TIDV again to ensure
+               /* Due to rare timing issues, write to TIDV again to ensure
                 * the write is successful
                 */
                ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
@@ -1169,8 +1166,7 @@ static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring)
        }
 
        if (adapter->detect_tx_hung) {
-               /*
-                * Detect a transmit hang in hardware, this serializes the
+               /* Detect a transmit hang in hardware, this serializes the
                 * check with the clearing of time_stamp and movement of i
                 */
                adapter->detect_tx_hung = false;
@@ -1270,14 +1266,12 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
                skb_put(skb, length);
 
                {
-                       /*
-                        * this looks ugly, but it seems compiler issues make
+                       /* this looks ugly, but it seems compiler issues make
                         * it more efficient than reusing j
                         */
                        int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]);
 
-                       /*
-                        * page alloc/put takes too long and effects small
+                       /* page alloc/put takes too long and effects small
                         * packet throughput, so unsplit small packets and
                         * save the alloc/put only valid in softirq (napi)
                         * context to call kmap_*
@@ -1288,8 +1282,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done,
 
                                ps_page = &buffer_info->ps_pages[0];
 
-                               /*
-                                * there is no documentation about how to call
+                               /* there is no documentation about how to call
                                 * kmap_atomic, so we can't hold the mapping
                                 * very long
                                 */
@@ -1486,14 +1479,16 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
                                    skb_shinfo(rxtop)->nr_frags,
                                    buffer_info->page, 0, length);
                                /* re-use the current skb, we only consumed the
-                                * page */
+                                * page
+                                */
                                buffer_info->skb = skb;
                                skb = rxtop;
                                rxtop = NULL;
                                e1000_consume_page(buffer_info, skb, length);
                        } else {
                                /* no chain, got EOP, this buf is the packet
-                                * copybreak to save the put_page/alloc_page */
+                                * copybreak to save the put_page/alloc_page
+                                */
                                if (length <= copybreak &&
                                    skb_tailroom(skb) >= length) {
                                        u8 *vaddr;
@@ -1502,7 +1497,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done,
                                               length);
                                        kunmap_atomic(vaddr);
                                        /* re-use the page, so don't erase
-                                        * buffer_info->page */
+                                        * buffer_info->page
+                                        */
                                        skb_put(skb, length);
                                } else {
                                        skb_fill_page_desc(skb, 0,
@@ -1656,22 +1652,17 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
        struct e1000_hw *hw = &adapter->hw;
        u32 icr = er32(ICR);
 
-       /*
-        * read ICR disables interrupts using IAM
-        */
-
+       /* read ICR disables interrupts using IAM */
        if (icr & E1000_ICR_LSC) {
                hw->mac.get_link_status = true;
-               /*
-                * ICH8 workaround-- Call gig speed drop workaround on cable
+               /* ICH8 workaround-- Call gig speed drop workaround on cable
                 * disconnect (LSC) before accessing any PHY registers
                 */
                if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
                    (!(er32(STATUS) & E1000_STATUS_LU)))
                        schedule_work(&adapter->downshift_task);
 
-               /*
-                * 80003ES2LAN workaround-- For packet buffer work-around on
+               /* 80003ES2LAN workaround-- For packet buffer work-around on
                 * link down event; disable receives here in the ISR and reset
                 * adapter in watchdog
                 */
@@ -1713,31 +1704,27 @@ static irqreturn_t e1000_intr(int irq, void *data)
        if (!icr || test_bit(__E1000_DOWN, &adapter->state))
                return IRQ_NONE;  /* Not our interrupt */
 
-       /*
-        * IMS will not auto-mask if INT_ASSERTED is not set, and if it is
+       /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
         * not set, then the adapter didn't send an interrupt
         */
        if (!(icr & E1000_ICR_INT_ASSERTED))
                return IRQ_NONE;
 
-       /*
-        * Interrupt Auto-Mask...upon reading ICR,
+       /* Interrupt Auto-Mask...upon reading ICR,
         * interrupts are masked.  No need for the
         * IMC write
         */
 
        if (icr & E1000_ICR_LSC) {
                hw->mac.get_link_status = true;
-               /*
-                * ICH8 workaround-- Call gig speed drop workaround on cable
+               /* ICH8 workaround-- Call gig speed drop workaround on cable
                 * disconnect (LSC) before accessing any PHY registers
                 */
                if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) &&
                    (!(er32(STATUS) & E1000_STATUS_LU)))
                        schedule_work(&adapter->downshift_task);
 
-               /*
-                * 80003ES2LAN workaround--
+               /* 80003ES2LAN workaround--
                 * For packet buffer work-around on link down event;
                 * disable receives here in the ISR and
                 * reset adapter in watchdog
@@ -2469,8 +2456,7 @@ static void e1000_set_itr(struct e1000_adapter *adapter)
 
 set_itr_now:
        if (new_itr != adapter->itr) {
-               /*
-                * this attempts to bias the interrupt rate towards Bulk
+               /* this attempts to bias the interrupt rate towards Bulk
                 * by adding intermediate steps when interrupt rate is
                 * increasing
                 */
@@ -2517,7 +2503,7 @@ void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr)
  * e1000_alloc_queues - Allocate memory for all rings
  * @adapter: board private structure to initialize
  **/
-static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
+static int e1000_alloc_queues(struct e1000_adapter *adapter)
 {
        int size = sizeof(struct e1000_ring);
 
@@ -2740,8 +2726,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
 
        manc = er32(MANC);
 
-       /*
-        * enable receiving management packets to the host. this will probably
+       /* enable receiving management packets to the host. this will probably
         * generate destination unreachable messages from the host OS, but
         * the packets will be handled on SMBUS
         */
@@ -2754,8 +2739,7 @@ static void e1000_init_manageability_pt(struct e1000_adapter *adapter)
                break;
        case e1000_82574:
        case e1000_82583:
-               /*
-                * Check if IPMI pass-through decision filter already exists;
+               /* Check if IPMI pass-through decision filter already exists;
                 * if so, enable it.
                 */
                for (i = 0, j = 0; i < 8; i++) {
@@ -2827,8 +2811,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
                u32 txdctl = er32(TXDCTL(0));
                txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH |
                            E1000_TXDCTL_WTHRESH);
-               /*
-                * set up some performance related parameters to encourage the
+               /* set up some performance related parameters to encourage the
                 * hardware to use the bus more efficiently in bursts, depends
                 * on the tx_int_delay to be enabled,
                 * wthresh = 1 ==> burst write is disabled to avoid Tx stalls
@@ -2845,8 +2828,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter)
 
        if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) {
                tarc = er32(TARC(0));
-               /*
-                * set the speed mode bit, we'll clear it if we're not at
+               /* set the speed mode bit, we'll clear it if we're not at
                 * gigabit link later
                 */
 #define SPEED_MODE_BIT (1 << 21)
@@ -2967,8 +2949,7 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
        rfctl |= E1000_RFCTL_EXTEN;
        ew32(RFCTL, rfctl);
 
-       /*
-        * 82571 and greater support packet-split where the protocol
+       /* 82571 and greater support packet-split where the protocol
         * header is placed in skb->data and the packet data is
         * placed in pages hanging off of skb_shinfo(skb)->nr_frags.
         * In the case of a non-split, skb->data is linearly filled,
@@ -3016,7 +2997,8 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
        /* This is useful for sniffing bad packets. */
        if (adapter->netdev->features & NETIF_F_RXALL) {
                /* UPE and MPE will be handled by normal PROMISC logic
-                * in e1000e_set_rx_mode */
+                * in e1000e_set_rx_mode
+                */
                rctl |= (E1000_RCTL_SBP | /* Receive bad packets */
                         E1000_RCTL_BAM | /* RX All Bcast Pkts */
                         E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */
@@ -3071,8 +3053,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
        usleep_range(10000, 20000);
 
        if (adapter->flags2 & FLAG2_DMA_BURST) {
-               /*
-                * set the writeback threshold (only takes effect if the RDTR
+               /* set the writeback threshold (only takes effect if the RDTR
                 * is set). set GRAN=1 and write back up to 0x4 worth, and
                 * enable prefetching of 0x20 Rx descriptors
                 * granularity = 01
@@ -3083,8 +3064,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
                ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE);
                ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE);
 
-               /*
-                * override the delay timers for enabling bursting, only if
+               /* override the delay timers for enabling bursting, only if
                 * the value was not set by the user via module options
                 */
                if (adapter->rx_int_delay == DEFAULT_RDTR)
@@ -3108,8 +3088,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
        ew32(CTRL_EXT, ctrl_ext);
        e1e_flush();
 
-       /*
-        * Setup the HW Rx Head and Tail Descriptor Pointers and
+       /* Setup the HW Rx Head and Tail Descriptor Pointers and
         * the Base and Length of the Rx Descriptor Ring
         */
        rdba = rx_ring->dma;
@@ -3130,8 +3109,7 @@ static void e1000_configure_rx(struct e1000_adapter *adapter)
        ew32(RXCSUM, rxcsum);
 
        if (adapter->hw.mac.type == e1000_pch2lan) {
-               /*
-                * With jumbo frames, excessive C-state transition
+               /* With jumbo frames, excessive C-state transition
                 * latencies result in dropped transactions.
                 */
                if (adapter->netdev->mtu > ETH_DATA_LEN) {
@@ -3216,8 +3194,7 @@ static int e1000e_write_uc_addr_list(struct net_device *netdev)
        if (!netdev_uc_empty(netdev) && rar_entries) {
                struct netdev_hw_addr *ha;
 
-               /*
-                * write the addresses in reverse order to avoid write
+               /* write the addresses in reverse order to avoid write
                 * combining
                 */
                netdev_for_each_uc_addr(ha, netdev) {
@@ -3269,8 +3246,7 @@ static void e1000e_set_rx_mode(struct net_device *netdev)
                if (netdev->flags & IFF_ALLMULTI) {
                        rctl |= E1000_RCTL_MPE;
                } else {
-                       /*
-                        * Write addresses to the MTA, if the attempt fails
+                       /* Write addresses to the MTA, if the attempt fails
                         * then we should just turn on promiscuous mode so
                         * that we can at least receive multicast traffic
                         */
@@ -3279,8 +3255,7 @@ static void e1000e_set_rx_mode(struct net_device *netdev)
                                rctl |= E1000_RCTL_MPE;
                }
                e1000e_vlan_filter_enable(adapter);
-               /*
-                * Write addresses to available RAR registers, if there is not
+               /* Write addresses to available RAR registers, if there is not
                 * sufficient space to store all the addresses then enable
                 * unicast promiscuous mode
                 */
@@ -3315,8 +3290,7 @@ static void e1000e_setup_rss_hash(struct e1000_adapter *adapter)
        for (i = 0; i < 32; i++)
                ew32(RETA(i), 0);
 
-       /*
-        * Disable raw packet checksumming so that RSS hash is placed in
+       /* Disable raw packet checksumming so that RSS hash is placed in
         * descriptor on writeback.
         */
        rxcsum = er32(RXCSUM);
@@ -3408,8 +3382,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
        ew32(PBA, pba);
 
        if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) {
-               /*
-                * To maintain wire speed transmits, the Tx FIFO should be
+               /* To maintain wire speed transmits, the Tx FIFO should be
                 * large enough to accommodate two full transmit packets,
                 * rounded up to the next 1KB and expressed in KB.  Likewise,
                 * the Rx FIFO should be large enough to accommodate at least
@@ -3421,8 +3394,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
                tx_space = pba >> 16;
                /* lower 16 bits has Rx packet buffer allocation size in KB */
                pba &= 0xffff;
-               /*
-                * the Tx fifo also stores 16 bytes of information about the Tx
+               /* the Tx fifo also stores 16 bytes of information about the Tx
                 * but don't include ethernet FCS because hardware appends it
                 */
                min_tx_space = (adapter->max_frame_size +
@@ -3435,8 +3407,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
                min_rx_space = ALIGN(min_rx_space, 1024);
                min_rx_space >>= 10;
 
-               /*
-                * If current Tx allocation is less than the min Tx FIFO size,
+               /* If current Tx allocation is less than the min Tx FIFO size,
                 * and the min Tx FIFO size is less than the current Rx FIFO
                 * allocation, take space away from current Rx allocation
                 */
@@ -3444,8 +3415,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
                    ((min_tx_space - tx_space) < pba)) {
                        pba -= min_tx_space - tx_space;
 
-                       /*
-                        * if short on Rx space, Rx wins and must trump Tx
+                       /* if short on Rx space, Rx wins and must trump Tx
                         * adjustment
                         */
                        if (pba < min_rx_space)
@@ -3455,8 +3425,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
                ew32(PBA, pba);
        }
 
-       /*
-        * flow control settings
+       /* flow control settings
         *
         * The high water mark must be low enough to fit one full frame
         * (or the size used for early receive) above it in the Rx FIFO.
@@ -3490,8 +3459,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
                fc->low_water = fc->high_water - 8;
                break;
        case e1000_pchlan:
-               /*
-                * Workaround PCH LOM adapter hangs with certain network
+               /* Workaround PCH LOM adapter hangs with certain network
                 * loads.  If hangs persist, try disabling Tx flow control.
                 */
                if (adapter->netdev->mtu > ETH_DATA_LEN) {
@@ -3516,8 +3484,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
                break;
        }
 
-       /*
-        * Alignment of Tx data is on an arbitrary byte boundary with the
+       /* Alignment of Tx data is on an arbitrary byte boundary with the
         * maximum size per Tx descriptor limited only to the transmit
         * allocation of the packet buffer minus 96 bytes with an upper
         * limit of 24KB due to receive synchronization limitations.
@@ -3525,8 +3492,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
        adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96,
                                       24 << 10);
 
-       /*
-        * Disable Adaptive Interrupt Moderation if 2 full packets cannot
+       /* Disable Adaptive Interrupt Moderation if 2 full packets cannot
         * fit in receive buffer.
         */
        if (adapter->itr_setting & 0x3) {
@@ -3549,8 +3515,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
        /* Allow time for pending master requests to run */
        mac->ops.reset_hw(hw);
 
-       /*
-        * For parts with AMT enabled, let the firmware know
+       /* For parts with AMT enabled, let the firmware know
         * that the network interface is in control
         */
        if (adapter->flags & FLAG_HAS_AMT)
@@ -3579,8 +3544,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
        if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) &&
            !(adapter->flags & FLAG_SMART_POWER_DOWN)) {
                u16 phy_data = 0;
-               /*
-                * speed up time to link by disabling smart power down, ignore
+               /* speed up time to link by disabling smart power down, ignore
                 * the return value of this function because there is nothing
                 * different we would do if it failed
                 */
@@ -3628,8 +3592,7 @@ static void e1000e_flush_descriptors(struct e1000_adapter *adapter)
        /* execute the writes immediately */
        e1e_flush();
 
-       /*
-        * due to rare timing issues, write to TIDV/RDTR again to ensure the
+       /* due to rare timing issues, write to TIDV/RDTR again to ensure the
         * write is successful
         */
        ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD);
@@ -3647,8 +3610,7 @@ void e1000e_down(struct e1000_adapter *adapter)
        struct e1000_hw *hw = &adapter->hw;
        u32 tctl, rctl;
 
-       /*
-        * signal that we're down so the interrupt handler does not
+       /* signal that we're down so the interrupt handler does not
         * reschedule our watchdog timer
         */
        set_bit(__E1000_DOWN, &adapter->state);
@@ -3691,8 +3653,7 @@ void e1000e_down(struct e1000_adapter *adapter)
        if (!pci_channel_offline(adapter->pdev))
                e1000e_reset(adapter);
 
-       /*
-        * TODO: for power management, we could drop the link and
+       /* TODO: for power management, we could drop the link and
         * pci_disable_device here.
         */
 }
@@ -3715,7 +3676,7 @@ void e1000e_reinit_locked(struct e1000_adapter *adapter)
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  **/
-static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
+static int e1000_sw_init(struct e1000_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
 
@@ -3755,8 +3716,7 @@ static irqreturn_t e1000_intr_msi_test(int irq, void *data)
        e_dbg("icr is %08X\n", icr);
        if (icr & E1000_ICR_RXSEQ) {
                adapter->flags &= ~FLAG_MSI_TEST_FAILED;
-               /*
-                * Force memory writes to complete before acknowledging the
+               /* Force memory writes to complete before acknowledging the
                 * interrupt is handled.
                 */
                wmb();
@@ -3786,7 +3746,8 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
        e1000e_reset_interrupt_capability(adapter);
 
        /* Assume that the test fails, if it succeeds then the test
-        * MSI irq handler will unset this flag */
+        * MSI irq handler will unset this flag
+        */
        adapter->flags |= FLAG_MSI_TEST_FAILED;
 
        err = pci_enable_msi(adapter->pdev);
@@ -3800,8 +3761,7 @@ static int e1000_test_msi_interrupt(struct e1000_adapter *adapter)
                goto msi_test_failed;
        }
 
-       /*
-        * Force memory writes to complete before enabling and firing an
+       /* Force memory writes to complete before enabling and firing an
         * interrupt.
         */
        wmb();
@@ -3901,8 +3861,7 @@ static int e1000_open(struct net_device *netdev)
        if (err)
                goto err_setup_rx;
 
-       /*
-        * If AMT is enabled, let the firmware know that the network
+       /* If AMT is enabled, let the firmware know that the network
         * interface is now open and reset the part to a known state.
         */
        if (adapter->flags & FLAG_HAS_AMT) {
@@ -3923,8 +3882,7 @@ static int e1000_open(struct net_device *netdev)
                                   PM_QOS_CPU_DMA_LATENCY,
                                   PM_QOS_DEFAULT_VALUE);
 
-       /*
-        * before we allocate an interrupt, we must be ready to handle it.
+       /* before we allocate an interrupt, we must be ready to handle it.
         * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
         * as soon as we call pci_request_irq, so we have to setup our
         * clean_rx handler before we do so.
@@ -3935,8 +3893,7 @@ static int e1000_open(struct net_device *netdev)
        if (err)
                goto err_req_irq;
 
-       /*
-        * Work around PCIe errata with MSI interrupts causing some chipsets to
+       /* Work around PCIe errata with MSI interrupts causing some chipsets to
         * ignore e1000e MSI messages, which means we need to test our MSI
         * interrupt now
         */
@@ -4017,16 +3974,14 @@ static int e1000_close(struct net_device *netdev)
        e1000e_free_tx_resources(adapter->tx_ring);
        e1000e_free_rx_resources(adapter->rx_ring);
 
-       /*
-        * kill manageability vlan ID if supported, but not if a vlan with
+       /* kill manageability vlan ID if supported, but not if a vlan with
         * the same ID is registered on the host OS (let 8021q kill it)
         */
        if (adapter->hw.mng_cookie.status &
            E1000_MNG_DHCP_COOKIE_STATUS_VLAN)
                e1000_vlan_rx_kill_vid(netdev, adapter->mng_vlan_id);
 
-       /*
-        * If AMT is enabled, let the firmware know that the network
+       /* If AMT is enabled, let the firmware know that the network
         * interface is now closed
         */
        if ((adapter->flags & FLAG_HAS_AMT) &&
@@ -4065,8 +4020,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p)
                /* activate the work around */
                e1000e_set_laa_state_82571(&adapter->hw, 1);
 
-               /*
-                * Hold a copy of the LAA in RAR[14] This is done so that
+               /* Hold a copy of the LAA in RAR[14] This is done so that
                 * between the time RAR[0] gets clobbered  and the time it
                 * gets fixed (in e1000_watchdog), the actual LAA is in one
                 * of the RARs and no incoming packets directed to this port
@@ -4099,10 +4053,13 @@ static void e1000e_update_phy_task(struct work_struct *work)
        e1000_get_phy_info(&adapter->hw);
 }
 
-/*
+/**
+ * e1000_update_phy_info - timre call-back to update PHY info
+ * @data: pointer to adapter cast into an unsigned long
+ *
  * Need to wait a few seconds after link up to get diagnostic information from
  * the phy
- */
+ **/
 static void e1000_update_phy_info(unsigned long data)
 {
        struct e1000_adapter *adapter = (struct e1000_adapter *) data;
@@ -4129,8 +4086,7 @@ static void e1000e_update_phy_stats(struct e1000_adapter *adapter)
        if (ret_val)
                return;
 
-       /*
-        * A page set is expensive so check if already on desired page.
+       /* A page set is expensive so check if already on desired page.
         * If not, set to the page with the PHY status registers.
         */
        hw->phy.addr = 1;
@@ -4201,8 +4157,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
        struct e1000_hw *hw = &adapter->hw;
        struct pci_dev *pdev = adapter->pdev;
 
-       /*
-        * Prevent stats update while adapter is being reset, or if the pci
+       /* Prevent stats update while adapter is being reset, or if the pci
         * connection is down.
         */
        if (adapter->link_speed == 0)
@@ -4270,8 +4225,7 @@ static void e1000e_update_stats(struct e1000_adapter *adapter)
 
        /* Rx Errors */
 
-       /*
-        * RLEC on some newer hardware can be incorrect so build
+       /* RLEC on some newer hardware can be incorrect so build
         * our own version based on RUC and ROC
         */
        netdev->stats.rx_errors = adapter->stats.rxerrc +
@@ -4323,8 +4277,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
                if (ret_val)
                        e_warn("Error reading PHY register\n");
        } else {
-               /*
-                * Do not read PHY registers if link is not up
+               /* Do not read PHY registers if link is not up
                 * Set values to typical power-on defaults
                 */
                phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX);
@@ -4362,8 +4315,7 @@ static bool e1000e_has_link(struct e1000_adapter *adapter)
        bool link_active = false;
        s32 ret_val = 0;
 
-       /*
-        * get_link_status is set on LSC (link status) interrupt or
+       /* get_link_status is set on LSC (link status) interrupt or
         * Rx sequence error interrupt.  get_link_status will stay
         * false until the check_for_link establishes link
         * for copper adapters ONLY
@@ -4415,8 +4367,7 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
 
-       /*
-        * With 82574 controllers, PHY needs to be checked periodically
+       /* With 82574 controllers, PHY needs to be checked periodically
         * for hung state and reset, if two calls return true
         */
        if (e1000_check_phy_82574(hw))
@@ -4484,8 +4435,7 @@ static void e1000_watchdog_task(struct work_struct *work)
                                                   &adapter->link_speed,
                                                   &adapter->link_duplex);
                        e1000_print_link_info(adapter);
-                       /*
-                        * On supported PHYs, check for duplex mismatch only
+                       /* On supported PHYs, check for duplex mismatch only
                         * if link has autonegotiated at 10/100 half
                         */
                        if ((hw->phy.type == e1000_phy_igp_3 ||
@@ -4515,8 +4465,7 @@ static void e1000_watchdog_task(struct work_struct *work)
                                break;
                        }
 
-                       /*
-                        * workaround: re-program speed mode bit after
+                       /* workaround: re-program speed mode bit after
                         * link-up event
                         */
                        if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) &&
@@ -4527,8 +4476,7 @@ static void e1000_watchdog_task(struct work_struct *work)
                                ew32(TARC(0), tarc0);
                        }
 
-                       /*
-                        * disable TSO for pcie and 10/100 speeds, to avoid
+                       /* disable TSO for pcie and 10/100 speeds, to avoid
                         * some hardware issues
                         */
                        if (!(adapter->flags & FLAG_TSO_FORCE)) {
@@ -4549,16 +4497,14 @@ static void e1000_watchdog_task(struct work_struct *work)
                                }
                        }
 
-                       /*
-                        * enable transmits in the hardware, need to do this
+                       /* enable transmits in the hardware, need to do this
                         * after setting TARC(0)
                         */
                        tctl = er32(TCTL);
                        tctl |= E1000_TCTL_EN;
                        ew32(TCTL, tctl);
 
-                        /*
-                        * Perform any post-link-up configuration before
+                       /* Perform any post-link-up configuration before
                         * reporting link up.
                         */
                        if (phy->ops.cfg_on_link_up)
@@ -4609,8 +4555,7 @@ link_up:
 
        if (!netif_carrier_ok(netdev) &&
            (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) {
-               /*
-                * We've lost link, so the controller stops DMA,
+               /* We've lost link, so the controller stops DMA,
                 * but we've got queued Tx work that's never going
                 * to get done, so reset controller to flush Tx.
                 * (Do the reset outside of interrupt context).
@@ -4622,8 +4567,7 @@ link_up:
 
        /* Simple mode for Interrupt Throttle Rate (ITR) */
        if (adapter->itr_setting == 4) {
-               /*
-                * Symmetric Tx/Rx gets a reduced ITR=2000;
+               /* Symmetric Tx/Rx gets a reduced ITR=2000;
                 * Total asymmetrical Tx or Rx gets ITR=8000;
                 * everyone else is between 2000-8000.
                 */
@@ -4648,8 +4592,7 @@ link_up:
        /* Force detection of hung controller every watchdog period */
        adapter->detect_tx_hung = true;
 
-       /*
-        * With 82571 controllers, LAA may be overwritten due to controller
+       /* With 82571 controllers, LAA may be overwritten due to controller
         * reset from the other port. Set the appropriate LAA in RAR[0]
         */
        if (e1000e_get_laa_state_82571(hw))
@@ -4948,8 +4891,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count)
        if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS))
                tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS));
 
-       /*
-        * Force memory writes to complete before letting h/w
+       /* Force memory writes to complete before letting h/w
         * know there are new descriptors to fetch.  (Only
         * applicable for weak-ordered memory model archs,
         * such as IA-64).
@@ -4963,8 +4905,7 @@ static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count)
        else
                writel(i, tx_ring->tail);
 
-       /*
-        * we need this if more than one processor can write to our tail
+       /* we need this if more than one processor can write to our tail
         * at a time, it synchronizes IO on IA64/Altix systems
         */
        mmiowb();
@@ -5014,15 +4955,13 @@ static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size)
        struct e1000_adapter *adapter = tx_ring->adapter;
 
        netif_stop_queue(adapter->netdev);
-       /*
-        * Herbert's original patch had:
+       /* Herbert's original patch had:
         *  smp_mb__after_netif_stop_queue();
         * but since that doesn't exist yet, just open code it.
         */
        smp_mb();
 
-       /*
-        * We need to check again in a case another CPU has just
+       /* We need to check again in a case another CPU has just
         * made room available.
         */
        if (e1000_desc_unused(tx_ring) < size)
@@ -5067,18 +5006,26 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
+       /* The minimum packet size with TCTL.PSP set is 17 bytes so
+        * pad skb in order to meet this minimum size requirement
+        */
+       if (unlikely(skb->len < 17)) {
+               if (skb_pad(skb, 17 - skb->len))
+                       return NETDEV_TX_OK;
+               skb->len = 17;
+               skb_set_tail_pointer(skb, 17);
+       }
+
        mss = skb_shinfo(skb)->gso_size;
        if (mss) {
                u8 hdr_len;
 
-               /*
-                * TSO Workaround for 82571/2/3 Controllers -- if skb->data
+               /* TSO Workaround for 82571/2/3 Controllers -- if skb->data
                 * points to just header, pull a few bytes of payload from
                 * frags into skb->data
                 */
                hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-               /*
-                * we do this workaround for ES2LAN, but it is un-necessary,
+               /* we do this workaround for ES2LAN, but it is un-necessary,
                 * avoiding it could save a lot of cycles
                 */
                if (skb->data_len && (hdr_len == len)) {
@@ -5109,8 +5056,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
        if (adapter->hw.mac.tx_pkt_filtering)
                e1000_transfer_dhcp_info(adapter, skb);
 
-       /*
-        * need: count + 2 desc gap to keep tail from touching
+       /* need: count + 2 desc gap to keep tail from touching
         * head, otherwise try next time
         */
        if (e1000_maybe_stop_tx(tx_ring, count + 2))
@@ -5134,8 +5080,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
        else if (e1000_tx_csum(tx_ring, skb))
                tx_flags |= E1000_TX_FLAGS_CSUM;
 
-       /*
-        * Old method was to assume IPv4 packet by default if TSO was enabled.
+       /* Old method was to assume IPv4 packet by default if TSO was enabled.
         * 82571 hardware supports TSO capabilities for IPv6 as well...
         * no longer assume, we must.
         */
@@ -5222,8 +5167,7 @@ struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
 
        /* Rx Errors */
 
-       /*
-        * RLEC on some newer hardware can be incorrect so build
+       /* RLEC on some newer hardware can be incorrect so build
         * our own version based on RUC and ROC
         */
        stats->rx_errors = adapter->stats.rxerrc +
@@ -5292,8 +5236,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu)
        if (netif_running(netdev))
                e1000e_down(adapter);
 
-       /*
-        * NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
+       /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN
         * means we reserve 2 more, this pushes us to allocate from the next
         * larger slab size.
         * i.e. RXBUFFER_2048 --> size-4096 slab
@@ -5555,8 +5498,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
        if (adapter->hw.phy.type == e1000_phy_igp_3)
                e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
 
-       /*
-        * Release control of h/w to f/w.  If f/w is AMT enabled, this
+       /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant.
         */
        e1000e_release_hw_control(adapter);
@@ -5583,8 +5525,7 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
 
-       /*
-        * The pci-e switch on some quad port adapters will report a
+       /* The pci-e switch on some quad port adapters will report a
         * correctable error when the MAC transitions from D0 to D3.  To
         * prevent this we need to mask off the correctable errors on the
         * downstream port of the pci-e switch.
@@ -5613,8 +5554,7 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
 #else
 static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state)
 {
-       /*
-        * Both device and parent should have the same ASPM setting.
+       /* Both device and parent should have the same ASPM setting.
         * Disable ASPM in downstream component first and then upstream.
         */
        pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, state);
@@ -5708,8 +5648,7 @@ static int __e1000_resume(struct pci_dev *pdev)
 
        netif_device_attach(netdev);
 
-       /*
-        * If the controller has AMT, do not set DRV_LOAD until the interface
+       /* If the controller has AMT, do not set DRV_LOAD until the interface
         * is up.  For all other cases, let the f/w know that the h/w is now
         * under the control of the driver.
         */
@@ -5837,7 +5776,10 @@ static irqreturn_t e1000_intr_msix(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-/*
+/**
+ * e1000_netpoll
+ * @netdev: network interface device structure
+ *
  * Polling 'interrupt' - used by things like netconsole to send skbs
  * without having to re-enable interrupts. It's not called while
  * the interrupt routine is executing.
@@ -5962,8 +5904,7 @@ static void e1000_io_resume(struct pci_dev *pdev)
 
        netif_device_attach(netdev);
 
-       /*
-        * If the controller has AMT, do not set DRV_LOAD until the interface
+       /* If the controller has AMT, do not set DRV_LOAD until the interface
         * is up.  For all other cases, let the f/w know that the h/w is now
         * under the control of the driver.
         */
@@ -6083,8 +6024,7 @@ static const struct net_device_ops e1000e_netdev_ops = {
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  **/
-static int __devinit e1000_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct e1000_adapter *adapter;
@@ -6262,14 +6202,12 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        if (e1000e_enable_mng_pass_thru(&adapter->hw))
                adapter->flags |= FLAG_MNG_PT_ENABLED;
 
-       /*
-        * before reading the NVM, reset the controller to
+       /* before reading the NVM, reset the controller to
         * put the device in a known good starting state
         */
        adapter->hw.mac.ops.reset_hw(&adapter->hw);
 
-       /*
-        * systems with ASPM and others may see the checksum fail on the first
+       /* systems with ASPM and others may see the checksum fail on the first
         * attempt. Let's give it a few tries
         */
        for (i = 0;; i++) {
@@ -6324,8 +6262,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        adapter->rx_ring->count = E1000_DEFAULT_RXD;
        adapter->tx_ring->count = E1000_DEFAULT_TXD;
 
-       /*
-        * Initial Wake on LAN setting - If APM wake is enabled in
+       /* Initial Wake on LAN setting - If APM wake is enabled in
         * the EEPROM, enable the ACPI Magic Packet filter
         */
        if (adapter->flags & FLAG_APME_IN_WUC) {
@@ -6349,8 +6286,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        if (eeprom_data & eeprom_apme_mask)
                adapter->eeprom_wol |= E1000_WUFC_MAG;
 
-       /*
-        * now that we have the eeprom settings, apply the special cases
+       /* now that we have the eeprom settings, apply the special cases
         * where the eeprom may be wrong or the board simply won't support
         * wake on lan on a particular port
         */
@@ -6367,8 +6303,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        /* reset the hardware with the new settings */
        e1000e_reset(adapter);
 
-       /*
-        * If the controller has AMT, do not set DRV_LOAD until the interface
+       /* If the controller has AMT, do not set DRV_LOAD until the interface
         * is up.  For all other cases, let the f/w know that the h/w is now
         * under the control of the driver.
         */
@@ -6425,14 +6360,13 @@ err_dma:
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  **/
-static void __devexit e1000_remove(struct pci_dev *pdev)
+static void e1000_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
        bool down = test_bit(__E1000_DOWN, &adapter->state);
 
-       /*
-        * The timers may be rescheduled, so explicitly disable them
+       /* The timers may be rescheduled, so explicitly disable them
         * from being rescheduled.
         */
        if (!down)
@@ -6457,8 +6391,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
        if (pci_dev_run_wake(pdev))
                pm_runtime_get_noresume(&pdev->dev);
 
-       /*
-        * Release control of h/w to f/w.  If f/w is AMT enabled, this
+       /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant.
         */
        e1000e_release_hw_control(adapter);
@@ -6578,7 +6511,7 @@ static struct pci_driver e1000_driver = {
        .name     = e1000e_driver_name,
        .id_table = e1000_pci_tbl,
        .probe    = e1000_probe,
-       .remove   = __devexit_p(e1000_remove),
+       .remove   = e1000_remove,
 #ifdef CONFIG_PM
        .driver   = {
                .pm = &e1000_pm_ops,
index a969f1af1b4ee22f3fb2ff0693c54498232df3fb..b6468804cb2e74e8e317622ae4f36067c8f8780e 100644 (file)
@@ -279,8 +279,7 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
                e1e_flush();
                udelay(1);
 
-               /*
-                * Read "Status Register" repeatedly until the LSB is cleared.
+               /* Read "Status Register" repeatedly until the LSB is cleared.
                 * The EEPROM will signal that the command has been completed
                 * by clearing bit 0 of the internal status register.  If it's
                 * not cleared within 'timeout', then error out.
@@ -321,8 +320,7 @@ s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
        u32 i, eerd = 0;
        s32 ret_val = 0;
 
-       /*
-        * A check for invalid values:  offset too large, too many words,
+       /* A check for invalid values:  offset too large, too many words,
         * too many words for the offset, and not enough words.
         */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
@@ -364,8 +362,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
        s32 ret_val;
        u16 widx = 0;
 
-       /*
-        * A check for invalid values:  offset too large, too many words,
+       /* A check for invalid values:  offset too large, too many words,
         * and not enough words.
         */
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
@@ -393,8 +390,7 @@ s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 
                e1000_standby_nvm(hw);
 
-               /*
-                * Some SPI eeproms use the 8th address bit embedded in the
+               /* Some SPI eeproms use the 8th address bit embedded in the
                 * opcode
                 */
                if ((nvm->address_bits == 8) && (offset >= 128))
@@ -461,8 +457,7 @@ s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
                return ret_val;
        }
 
-       /*
-        * if nvm_data is not ptr guard the PBA must be in legacy format which
+       /* if nvm_data is not ptr guard the PBA must be in legacy format which
         * means pba_ptr is actually our second data word for the PBA number
         * and we can decode it into an ascii string
         */
index dfbfa7fd98c36f6ccacd82cfe9b083f2a7ab4baf..89d536dd7ff51e3cbcd688f682cd00a84e000ce7 100644 (file)
 
 #include "e1000.h"
 
-/*
- * This is the only thing that needs to be changed to adjust the
+/* This is the only thing that needs to be changed to adjust the
  * maximum number of ports that the driver can manage.
  */
-
 #define E1000_MAX_NIC 32
 
 #define OPTION_UNSET   -1
@@ -49,22 +47,19 @@ module_param(copybreak, uint, 0644);
 MODULE_PARM_DESC(copybreak,
        "Maximum size of packet that is copied to a new buffer on receive");
 
-/*
- * All parameters are treated the same, as an integer array of values.
+/* All parameters are treated the same, as an integer array of values.
  * This macro just reduces the need to repeat the same declaration code
  * over and over (plus this helps to avoid typo bugs).
  */
-
 #define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET }
 #define E1000_PARAM(X, desc)                                   \
-       static int __devinitdata X[E1000_MAX_NIC+1]             \
+       static int X[E1000_MAX_NIC+1]           \
                = E1000_PARAM_INIT;                             \
        static unsigned int num_##X;                            \
        module_param_array_named(X, X, int, &num_##X, 0);       \
        MODULE_PARM_DESC(X, desc);
 
-/*
- * Transmit Interrupt Delay in units of 1.024 microseconds
+/* Transmit Interrupt Delay in units of 1.024 microseconds
  * Tx interrupt delay needs to typically be set to something non-zero
  *
  * Valid Range: 0-65535
@@ -74,8 +69,7 @@ E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay");
 #define MAX_TXDELAY 0xFFFF
 #define MIN_TXDELAY 0
 
-/*
- * Transmit Absolute Interrupt Delay in units of 1.024 microseconds
+/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds
  *
  * Valid Range: 0-65535
  */
@@ -84,8 +78,7 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay");
 #define MAX_TXABSDELAY 0xFFFF
 #define MIN_TXABSDELAY 0
 
-/*
- * Receive Interrupt Delay in units of 1.024 microseconds
+/* Receive Interrupt Delay in units of 1.024 microseconds
  * hardware will likely hang if you set this to anything but zero.
  *
  * Valid Range: 0-65535
@@ -94,8 +87,7 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay");
 #define MAX_RXDELAY 0xFFFF
 #define MIN_RXDELAY 0
 
-/*
- * Receive Absolute Interrupt Delay in units of 1.024 microseconds
+/* Receive Absolute Interrupt Delay in units of 1.024 microseconds
  *
  * Valid Range: 0-65535
  */
@@ -103,8 +95,7 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay");
 #define MAX_RXABSDELAY 0xFFFF
 #define MIN_RXABSDELAY 0
 
-/*
- * Interrupt Throttle Rate (interrupts/sec)
+/* Interrupt Throttle Rate (interrupts/sec)
  *
  * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative
  */
@@ -113,8 +104,7 @@ E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate");
 #define MAX_ITR 100000
 #define MIN_ITR 100
 
-/*
- * IntMode (Interrupt Mode)
+/* IntMode (Interrupt Mode)
  *
  * Valid Range: varies depending on kernel configuration & hardware support
  *
@@ -132,8 +122,7 @@ E1000_PARAM(IntMode, "Interrupt Mode");
 #define MAX_INTMODE    2
 #define MIN_INTMODE    0
 
-/*
- * Enable Smart Power Down of the PHY
+/* Enable Smart Power Down of the PHY
  *
  * Valid Range: 0, 1
  *
@@ -141,8 +130,7 @@ E1000_PARAM(IntMode, "Interrupt Mode");
  */
 E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
 
-/*
- * Enable Kumeran Lock Loss workaround
+/* Enable Kumeran Lock Loss workaround
  *
  * Valid Range: 0, 1
  *
@@ -150,8 +138,7 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down");
  */
 E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
 
-/*
- * Write Protect NVM
+/* Write Protect NVM
  *
  * Valid Range: 0, 1
  *
@@ -159,8 +146,7 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
  */
 E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
 
-/*
- * Enable CRC Stripping
+/* Enable CRC Stripping
  *
  * Valid Range: 0, 1
  *
@@ -186,9 +172,9 @@ struct e1000_option {
        } arg;
 };
 
-static int __devinit e1000_validate_option(unsigned int *value,
-                                          const struct e1000_option *opt,
-                                          struct e1000_adapter *adapter)
+static int e1000_validate_option(unsigned int *value,
+                                const struct e1000_option *opt,
+                                struct e1000_adapter *adapter)
 {
        if (*value == OPTION_UNSET) {
                *value = opt->def;
@@ -249,7 +235,7 @@ static int __devinit e1000_validate_option(unsigned int *value,
  * value exists, a default value is used.  The final value is stored
  * in a variable in the adapter structure.
  **/
-void __devinit e1000e_check_options(struct e1000_adapter *adapter)
+void e1000e_check_options(struct e1000_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
        int bd = adapter->bd_number;
@@ -351,8 +337,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
                if (num_InterruptThrottleRate > bd) {
                        adapter->itr = InterruptThrottleRate[bd];
 
-                       /*
-                        * Make sure a message is printed for non-special
+                       /* Make sure a message is printed for non-special
                         * values. And in case of an invalid option, display
                         * warning, use default and go through itr/itr_setting
                         * adjustment logic below
@@ -361,14 +346,12 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
                            e1000_validate_option(&adapter->itr, &opt, adapter))
                                adapter->itr = opt.def;
                } else {
-                       /*
-                        * If no option specified, use default value and go
+                       /* If no option specified, use default value and go
                         * through the logic below to adjust itr/itr_setting
                         */
                        adapter->itr = opt.def;
 
-                       /*
-                        * Make sure a message is printed for non-special
+                       /* Make sure a message is printed for non-special
                         * default values
                         */
                        if (adapter->itr > 4)
@@ -400,8 +383,7 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
                                 opt.name);
                        break;
                default:
-                       /*
-                        * Save the setting, because the dynamic bits
+                       /* Save the setting, because the dynamic bits
                         * change itr.
                         *
                         * Clear the lower two bits because
index fc62a3f3a5bec8b3e7ce0fba893ae50add89f22a..28b38ff37e843a028f89d7fab86827a777e5a098 100644 (file)
@@ -193,8 +193,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                return -E1000_ERR_PARAM;
        }
 
-       /*
-        * Set up Op-code, Phy Address, and register offset in the MDI
+       /* Set up Op-code, Phy Address, and register offset in the MDI
         * Control register.  The MAC will take care of interfacing with the
         * PHY to retrieve the desired data.
         */
@@ -204,8 +203,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 
        ew32(MDIC, mdic);
 
-       /*
-        * Poll the ready bit to see if the MDI read completed
+       /* Poll the ready bit to see if the MDI read completed
         * Increasing the time out as testing showed failures with
         * the lower time out
         */
@@ -225,8 +223,7 @@ s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
        }
        *data = (u16) mdic;
 
-       /*
-        * Allow some time after each MDIC transaction to avoid
+       /* Allow some time after each MDIC transaction to avoid
         * reading duplicate data in the next MDIC transaction.
         */
        if (hw->mac.type == e1000_pch2lan)
@@ -253,8 +250,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                return -E1000_ERR_PARAM;
        }
 
-       /*
-        * Set up Op-code, Phy Address, and register offset in the MDI
+       /* Set up Op-code, Phy Address, and register offset in the MDI
         * Control register.  The MAC will take care of interfacing with the
         * PHY to retrieve the desired data.
         */
@@ -265,8 +261,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 
        ew32(MDIC, mdic);
 
-       /*
-        * Poll the ready bit to see if the MDI read completed
+       /* Poll the ready bit to see if the MDI read completed
         * Increasing the time out as testing showed failures with
         * the lower time out
         */
@@ -285,8 +280,7 @@ s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
                return -E1000_ERR_PHY;
        }
 
-       /*
-        * Allow some time after each MDIC transaction to avoid
+       /* Allow some time after each MDIC transaction to avoid
         * reading duplicate data in the next MDIC transaction.
         */
        if (hw->mac.type == e1000_pch2lan)
@@ -708,8 +702,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
        phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
-       /*
-        * Options:
+       /* Options:
         *   0 - Auto (default)
         *   1 - MDI mode
         *   2 - MDI-X mode
@@ -754,8 +747,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
        if (phy->type != e1000_phy_bm)
                phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
 
-       /*
-        * Options:
+       /* Options:
         *   MDI/MDI-X = 0 (default)
         *   0 - Auto for all speeds
         *   1 - MDI mode
@@ -780,8 +772,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
                break;
        }
 
-       /*
-        * Options:
+       /* Options:
         *   disable_polarity_correction = 0 (default)
         *       Automatic Correction for Reversed Cable Polarity
         *   0 - Disabled
@@ -818,8 +809,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw)
        if ((phy->type == e1000_phy_m88) &&
            (phy->revision < E1000_REVISION_4) &&
            (phy->id != BME1000_E_PHY_ID_R2)) {
-               /*
-                * Force TX_CLK in the Extended PHY Specific Control Register
+               /* Force TX_CLK in the Extended PHY Specific Control Register
                 * to 25MHz clock.
                 */
                ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
@@ -899,8 +889,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
                return ret_val;
        }
 
-       /*
-        * Wait 100ms for MAC to configure PHY from NVM settings, to avoid
+       /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid
         * timeout issues when LFS is enabled.
         */
        msleep(100);
@@ -936,8 +925,7 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw)
 
        /* set auto-master slave resolution settings */
        if (hw->mac.autoneg) {
-               /*
-                * when autonegotiation advertisement is only 1000Mbps then we
+               /* when autonegotiation advertisement is only 1000Mbps then we
                 * should disable SmartSpeed and enable Auto MasterSlave
                 * resolution as hardware default.
                 */
@@ -1001,16 +989,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                        return ret_val;
        }
 
-       /*
-        * Need to parse both autoneg_advertised and fc and set up
+       /* Need to parse both autoneg_advertised and fc and set up
         * the appropriate PHY registers.  First we will parse for
         * autoneg_advertised software override.  Since we can advertise
         * a plethora of combinations, we need to check each bit
         * individually.
         */
 
-       /*
-        * First we clear all the 10/100 mb speed bits in the Auto-Neg
+       /* First we clear all the 10/100 mb speed bits in the Auto-Neg
         * Advertisement Register (Address 4) and the 1000 mb speed bits in
         * the  1000Base-T Control Register (Address 9).
         */
@@ -1056,8 +1042,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
        }
 
-       /*
-        * Check for a software override of the flow control settings, and
+       /* Check for a software override of the flow control settings, and
         * setup the PHY advertisement registers accordingly.  If
         * auto-negotiation is enabled, then software will have to set the
         * "PAUSE" bits to the correct value in the Auto-Negotiation
@@ -1076,15 +1061,13 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
         */
        switch (hw->fc.current_mode) {
        case e1000_fc_none:
-               /*
-                * Flow control (Rx & Tx) is completely disabled by a
+               /* Flow control (Rx & Tx) is completely disabled by a
                 * software over-ride.
                 */
                mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
                break;
        case e1000_fc_rx_pause:
-               /*
-                * Rx Flow control is enabled, and Tx Flow control is
+               /* Rx Flow control is enabled, and Tx Flow control is
                 * disabled, by a software over-ride.
                 *
                 * Since there really isn't a way to advertise that we are
@@ -1096,16 +1079,14 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
                mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
                break;
        case e1000_fc_tx_pause:
-               /*
-                * Tx Flow control is enabled, and Rx Flow control is
+               /* Tx Flow control is enabled, and Rx Flow control is
                 * disabled, by a software over-ride.
                 */
                mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
                mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
                break;
        case e1000_fc_full:
-               /*
-                * Flow control (both Rx and Tx) is enabled by a software
+               /* Flow control (both Rx and Tx) is enabled by a software
                 * over-ride.
                 */
                mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
@@ -1142,14 +1123,12 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
        s32 ret_val;
        u16 phy_ctrl;
 
-       /*
-        * Perform some bounds checking on the autoneg advertisement
+       /* Perform some bounds checking on the autoneg advertisement
         * parameter.
         */
        phy->autoneg_advertised &= phy->autoneg_mask;
 
-       /*
-        * If autoneg_advertised is zero, we assume it was not defaulted
+       /* If autoneg_advertised is zero, we assume it was not defaulted
         * by the calling code so we set to advertise full capability.
         */
        if (!phy->autoneg_advertised)
@@ -1163,8 +1142,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
        }
        e_dbg("Restarting Auto-Neg\n");
 
-       /*
-        * Restart auto-negotiation by setting the Auto Neg Enable bit and
+       /* Restart auto-negotiation by setting the Auto Neg Enable bit and
         * the Auto Neg Restart bit in the PHY control register.
         */
        ret_val = e1e_rphy(hw, PHY_CONTROL, &phy_ctrl);
@@ -1176,8 +1154,7 @@ static s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Does the user want to wait for Auto-Neg to complete here, or
+       /* Does the user want to wait for Auto-Neg to complete here, or
         * check at a later time (for example, callback routine).
         */
        if (phy->autoneg_wait_to_complete) {
@@ -1208,16 +1185,14 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
        bool link;
 
        if (hw->mac.autoneg) {
-               /*
-                * Setup autoneg and flow control advertisement and perform
+               /* Setup autoneg and flow control advertisement and perform
                 * autonegotiation.
                 */
                ret_val = e1000_copper_link_autoneg(hw);
                if (ret_val)
                        return ret_val;
        } else {
-               /*
-                * PHY will be set to 10H, 10F, 100H or 100F
+               /* PHY will be set to 10H, 10F, 100H or 100F
                 * depending on user settings.
                 */
                e_dbg("Forcing Speed and Duplex\n");
@@ -1228,8 +1203,7 @@ s32 e1000e_setup_copper_link(struct e1000_hw *hw)
                }
        }
 
-       /*
-        * Check link status. Wait up to 100 microseconds for link to become
+       /* Check link status. Wait up to 100 microseconds for link to become
         * valid.
         */
        ret_val = e1000e_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
@@ -1273,8 +1247,7 @@ s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Clear Auto-Crossover to force MDI manually.  IGP requires MDI
+       /* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
         * forced whenever speed and duplex are forced.
         */
        ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
@@ -1328,8 +1301,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
        u16 phy_data;
        bool link;
 
-       /*
-        * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
+       /* Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
         * forced whenever speed and duplex are forced.
         */
        ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
@@ -1370,8 +1342,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
                        if (hw->phy.type != e1000_phy_m88) {
                                e_dbg("Link taking longer than expected.\n");
                        } else {
-                               /*
-                                * We didn't get link.
+                               /* We didn't get link.
                                 * Reset the DSP and cross our fingers.
                                 */
                                ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT,
@@ -1398,8 +1369,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * Resetting the phy means we need to re-force TX_CLK in the
+       /* Resetting the phy means we need to re-force TX_CLK in the
         * Extended PHY Specific Control Register to 25MHz clock from
         * the reset value of 2.5MHz.
         */
@@ -1408,8 +1378,7 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
        if (ret_val)
                return ret_val;
 
-       /*
-        * In addition, we must re-enable CRS on Tx for both half and full
+       /* In addition, we must re-enable CRS on Tx for both half and full
         * duplex.
         */
        ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
@@ -1573,8 +1542,7 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active)
                ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data);
                if (ret_val)
                        return ret_val;
-               /*
-                * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
+               /* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
                 * during Dx states where the power conservation is most
                 * important.  During driver activity we should enable
                 * SmartSpeed, so performance is maintained.
@@ -1702,8 +1670,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
        s32 ret_val;
        u16 data, offset, mask;
 
-       /*
-        * Polarity is determined based on the speed of
+       /* Polarity is determined based on the speed of
         * our connection.
         */
        ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data);
@@ -1715,8 +1682,7 @@ s32 e1000_check_polarity_igp(struct e1000_hw *hw)
                offset  = IGP01E1000_PHY_PCS_INIT_REG;
                mask    = IGP01E1000_PHY_POLARITY_MASK;
        } else {
-               /*
-                * This really only applies to 10Mbps since
+               /* This really only applies to 10Mbps since
                 * there is no polarity for 100Mbps (always 0).
                 */
                offset  = IGP01E1000_PHY_PORT_STATUS;
@@ -1745,8 +1711,7 @@ s32 e1000_check_polarity_ife(struct e1000_hw *hw)
        s32 ret_val;
        u16 phy_data, offset, mask;
 
-       /*
-        * Polarity is determined based on the reversal feature being enabled.
+       /* Polarity is determined based on the reversal feature being enabled.
         */
        if (phy->polarity_correction) {
                offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
@@ -1791,8 +1756,7 @@ static s32 e1000_wait_autoneg(struct e1000_hw *hw)
                msleep(100);
        }
 
-       /*
-        * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
+       /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
         * has completed.
         */
        return ret_val;
@@ -1814,15 +1778,13 @@ s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
        u16 i, phy_status;
 
        for (i = 0; i < iterations; i++) {
-               /*
-                * Some PHYs require the PHY_STATUS register to be read
+               /* Some PHYs require the PHY_STATUS register to be read
                 * twice due to the link bit being sticky.  No harm doing
                 * it across the board.
                 */
                ret_val = e1e_rphy(hw, PHY_STATUS, &phy_status);
                if (ret_val)
-                       /*
-                        * If the first read fails, another entity may have
+                       /* If the first read fails, another entity may have
                         * ownership of the resources, wait and try again to
                         * see if they have relinquished the resources yet.
                         */
@@ -1913,8 +1875,7 @@ s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw)
                if (ret_val)
                        return ret_val;
 
-               /*
-                * Getting bits 15:9, which represent the combination of
+               /* Getting bits 15:9, which represent the combination of
                 * coarse and fine gain values.  The result is a number
                 * that can be put into the lookup table to obtain the
                 * approximate cable length.
@@ -2285,15 +2246,13 @@ s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw)
        e1e_wphy(hw, 0x1796, 0x0008);
        /* Change cg_icount + enable integbp for channels BCD */
        e1e_wphy(hw, 0x1798, 0xD008);
-       /*
-        * Change cg_icount + enable integbp + change prop_factor_master
+       /* Change cg_icount + enable integbp + change prop_factor_master
         * to 8 for channel A
         */
        e1e_wphy(hw, 0x1898, 0xD918);
        /* Disable AHT in Slave mode on channel A */
        e1e_wphy(hw, 0x187A, 0x0800);
-       /*
-        * Enable LPLU and disable AN to 1000 in non-D0a states,
+       /* Enable LPLU and disable AN to 1000 in non-D0a states,
         * Enable SPD+B2B
         */
        e1e_wphy(hw, 0x0019, 0x008D);
@@ -2417,8 +2376,7 @@ s32 e1000e_determine_phy_address(struct e1000_hw *hw)
                        e1000e_get_phy_id(hw);
                        phy_type = e1000e_get_phy_type_from_id(hw->phy.id);
 
-                       /*
-                        * If phy_type is valid, break - we found our
+                       /* If phy_type is valid, break - we found our
                         * PHY address
                         */
                        if (phy_type  != e1000_phy_unknown)
@@ -2478,8 +2436,7 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
                u32 page_shift, page_select;
 
-               /*
-                * Page select is register 31 for phy address 1 and 22 for
+               /* Page select is register 31 for phy address 1 and 22 for
                 * phy address 2 and 3. Page select is shifted only for
                 * phy address 1.
                 */
@@ -2537,8 +2494,7 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
                u32 page_shift, page_select;
 
-               /*
-                * Page select is register 31 for phy address 1 and 22 for
+               /* Page select is register 31 for phy address 1 and 22 for
                 * phy address 2 and 3. Page select is shifted only for
                 * phy address 1.
                 */
@@ -2683,8 +2639,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
                return ret_val;
        }
 
-       /*
-        * Enable both PHY wakeup mode and Wakeup register page writes.
+       /* Enable both PHY wakeup mode and Wakeup register page writes.
         * Prevent a power state change by disabling ME and Host PHY wakeup.
         */
        temp = *phy_reg;
@@ -2698,8 +2653,7 @@ s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
                return ret_val;
        }
 
-       /*
-        * Select Host Wakeup Registers page - caller now able to write
+       /* Select Host Wakeup Registers page - caller now able to write
         * registers on the Wakeup registers page
         */
        return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
@@ -3038,8 +2992,7 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
                if (page == HV_INTC_FC_PAGE_START)
                        page = 0;
 
-               /*
-                * Workaround MDIO accesses being disabled after entering IEEE
+               /* Workaround MDIO accesses being disabled after entering IEEE
                 * Power Down (when bit 11 of the PHY Control register is set)
                 */
                if ((hw->phy.type == e1000_phy_82578) &&
index 97c197fd4a8e5215fa5dea76d4785cd5d765a6d1..624476cfa727cc32efc39a8846fb3720742077ed 100644 (file)
@@ -34,6 +34,4 @@ obj-$(CONFIG_IGB) += igb.o
 
 igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
            e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
-           e1000_i210.o
-
-igb-$(CONFIG_IGB_PTP) += igb_ptp.o
+           e1000_i210.o igb_ptp.o
index ca4641e2f74870c1bac8c147ad231b19ba660e12..fdaaf2709d0ae660480e3c6525e116481a369c4c 100644 (file)
@@ -319,6 +319,7 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
                nvm->ops.acquire = igb_acquire_nvm_i210;
                nvm->ops.release = igb_release_nvm_i210;
                nvm->ops.read    = igb_read_nvm_srrd_i210;
+               nvm->ops.write   = igb_write_nvm_srwr_i210;
                nvm->ops.valid_led_default = igb_valid_led_default_i210;
                break;
        case e1000_i211:
@@ -1027,6 +1028,15 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw)
                 * continue to check for link.
                 */
                hw->mac.get_link_status = !hw->mac.serdes_has_link;
+
+               /* Configure Flow Control now that Auto-Neg has completed.
+                * First, we need to restore the desired flow control
+                * settings because we may have had to re-autoneg with a
+                * different link partner.
+                */
+               ret_val = igb_config_fc_after_link_up(hw);
+               if (ret_val)
+                       hw_dbg("Error configuring flow control\n");
        } else {
                ret_val = igb_check_for_copper_link(hw);
        }
@@ -1277,12 +1287,20 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
 {
        u32 ctrl;
        s32  ret_val;
+       u32 phpm_reg;
 
        ctrl = rd32(E1000_CTRL);
        ctrl |= E1000_CTRL_SLU;
        ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
        wr32(E1000_CTRL, ctrl);
 
+       /* Clear Go Link Disconnect bit */
+       if (hw->mac.type >= e1000_82580) {
+               phpm_reg = rd32(E1000_82580_PHY_POWER_MGMT);
+               phpm_reg &= ~E1000_82580_PM_GO_LINKD;
+               wr32(E1000_82580_PHY_POWER_MGMT, phpm_reg);
+       }
+
        ret_val = igb_setup_serdes_link_82575(hw);
        if (ret_val)
                goto out;
@@ -1336,7 +1354,7 @@ out:
  **/
 static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
 {
-       u32 ctrl_ext, ctrl_reg, reg;
+       u32 ctrl_ext, ctrl_reg, reg, anadv_reg;
        bool pcs_autoneg;
        s32 ret_val = E1000_SUCCESS;
        u16 data;
@@ -1424,27 +1442,45 @@ static s32 igb_setup_serdes_link_82575(struct e1000_hw *hw)
        reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
                E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
 
-       /*
-        * We force flow control to prevent the CTRL register values from being
-        * overwritten by the autonegotiated flow control values
-        */
-       reg |= E1000_PCS_LCTL_FORCE_FCTRL;
-
        if (pcs_autoneg) {
                /* Set PCS register for autoneg */
                reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
                       E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
+
+               /* Disable force flow control for autoneg */
+               reg &= ~E1000_PCS_LCTL_FORCE_FCTRL;
+
+               /* Configure flow control advertisement for autoneg */
+               anadv_reg = rd32(E1000_PCS_ANADV);
+               anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE);
+               switch (hw->fc.requested_mode) {
+               case e1000_fc_full:
+               case e1000_fc_rx_pause:
+                       anadv_reg |= E1000_TXCW_ASM_DIR;
+                       anadv_reg |= E1000_TXCW_PAUSE;
+                       break;
+               case e1000_fc_tx_pause:
+                       anadv_reg |= E1000_TXCW_ASM_DIR;
+                       break;
+               default:
+                       break;
+               }
+               wr32(E1000_PCS_ANADV, anadv_reg);
+
                hw_dbg("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
        } else {
                /* Set PCS register for forced link */
                reg |= E1000_PCS_LCTL_FSD;        /* Force Speed */
 
+               /* Force flow control for forced link */
+               reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+
                hw_dbg("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
        }
 
        wr32(E1000_PCS_LCTL, reg);
 
-       if (!igb_sgmii_active_82575(hw))
+       if (!pcs_autoneg && !igb_sgmii_active_82575(hw))
                igb_force_mac_fc(hw);
 
        return ret_val;
@@ -1918,6 +1954,12 @@ static s32 igb_reset_hw_82580(struct e1000_hw *hw)
 
        hw->dev_spec._82575.global_device_reset = false;
 
+       /* due to hw errata, global device reset doesn't always
+        * work on 82580
+        */
+       if (hw->mac.type == e1000_82580)
+               global_device_reset = false;
+
        /* Get current control state. */
        ctrl = rd32(E1000_CTRL);
 
@@ -2233,19 +2275,16 @@ s32 igb_set_eee_i350(struct e1000_hw *hw)
 
        /* enable or disable per user setting */
        if (!(hw->dev_spec._82575.eee_disable)) {
-               ipcnfg |= (E1000_IPCNFG_EEE_1G_AN |
-                       E1000_IPCNFG_EEE_100M_AN);
-               eeer |= (E1000_EEER_TX_LPI_EN |
-                       E1000_EEER_RX_LPI_EN |
+               u32 eee_su = rd32(E1000_EEE_SU);
+
+               ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
+               eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
                        E1000_EEER_LPI_FC);
 
-               /* keep the LPI clock running before EEE is enabled */
-               if (hw->mac.type == e1000_i210 || hw->mac.type == e1000_i211) {
-                       u32 eee_su;
-                       eee_su = rd32(E1000_EEE_SU);
-                       eee_su &= ~E1000_EEE_SU_LPI_CLK_STP;
-                       wr32(E1000_EEE_SU, eee_su);
-               }
+               /* This bit should not be set in normal operation. */
+               if (eee_su & E1000_EEE_SU_LPI_CLK_STP)
+                       hw_dbg("LPI Clock Stop Bit should not be set!\n");
+
 
        } else {
                ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN |
index e85c453f5428cf31723373468d51f64099e10fca..44b76b3b6816692f2bcea6682950791a92164bda 100644 (file)
@@ -172,10 +172,13 @@ struct e1000_adv_tx_context_desc {
 #define E1000_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
 #define E1000_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */
 #define E1000_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
+#define E1000_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */
 
 #define E1000_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
 #define E1000_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
+#define E1000_DCA_TXCTRL_DESC_RRO_EN (1 << 9) /* Tx rd Desc Relax Order */
 #define E1000_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
+#define E1000_DCA_TXCTRL_DATA_RRO_EN (1 << 13) /* Tx rd data Relax Order */
 
 /* Additional DCA related definitions, note change in position of CPUID */
 #define E1000_DCA_TXCTRL_CPUID_MASK_82576 0xFF000000 /* Tx CPUID Mask */
index de4b41ec3c402da0829357edc5f77c1821369a5e..45dce06eff264d77dd5d6b350ef2e3a1dd94447f 100644 (file)
 #define FLOW_CONTROL_ADDRESS_HIGH 0x00000100
 #define FLOW_CONTROL_TYPE         0x8808
 
+/* Transmit Config Word */
+#define E1000_TXCW_ASM_DIR     0x00000100 /* TXCW astm pause direction */
+#define E1000_TXCW_PAUSE       0x00000080 /* TXCW sym pause request */
+
 /* 802.1q VLAN Packet Size */
 #define VLAN_TAG_SIZE              4    /* 802.3ac tag (not DMA'd) */
 #define E1000_VLAN_FILTER_TBL_SIZE 128  /* VLAN Filter Table (4096 bits) */
 /* mPHY Near End Digital Loopback Override Bit */
 #define E1000_MPHY_PCS_CLK_REG_DIGINELBEN 0x10
 
+#define E1000_PCS_LCTL_FORCE_FCTRL     0x80
+#define E1000_PCS_LSTS_AN_COMPLETE     0x10000
+
 /* PHY Control Register */
 #define MII_CR_FULL_DUPLEX      0x0100  /* FDX =1, half duplex =0 */
 #define MII_CR_RESTART_AUTO_NEG 0x0200  /* Restart auto negotiation */
 /* NVM Word Offsets */
 #define NVM_COMPAT                 0x0003
 #define NVM_ID_LED_SETTINGS        0x0004 /* SERDES output amplitude */
+#define NVM_VERSION                0x0005
 #define NVM_INIT_CONTROL2_REG      0x000F
 #define NVM_INIT_CONTROL3_PORT_B   0x0014
 #define NVM_INIT_CONTROL3_PORT_A   0x0024
 #define NVM_LED_1_CFG              0x001C
 #define NVM_LED_0_2_CFG            0x001F
 
+/* NVM version defines */
+#define NVM_ETRACK_WORD            0x0042
+#define NVM_COMB_VER_OFF           0x0083
+#define NVM_COMB_VER_PTR           0x003d
+#define NVM_MAJOR_MASK             0xF000
+#define NVM_MINOR_MASK             0x0FF0
+#define NVM_BUILD_MASK             0x000F
+#define NVM_COMB_VER_MASK          0x00FF
+#define NVM_MAJOR_SHIFT                12
+#define NVM_MINOR_SHIFT                 4
+#define NVM_COMB_VER_SHFT               8
+#define NVM_VER_INVALID            0xFFFF
+#define NVM_ETRACK_SHIFT               16
 
 #define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */
 #define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */
 #define E1000_EEER_FRC_AN            0x10000000  /* Enable EEE in loopback */
 #define E1000_EEER_LPI_FC            0x00040000  /* EEE Enable on FC */
 #define E1000_EEE_SU_LPI_CLK_STP     0X00800000  /* EEE LPI Clock Stop */
+#define E1000_EEER_EEE_NEG           0x20000000  /* EEE capability nego */
 
 /* SerDes Control */
 #define E1000_GEN_CTL_READY             0x80000000
index 77a5f939bc7413ed84c5dfb7e2aa97a166047743..fbcdbebb0b5fce2c4108a130e24d490cbada6cf7 100644 (file)
 #include "e1000_hw.h"
 #include "e1000_i210.h"
 
-static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw);
-static void igb_put_hw_semaphore_i210(struct e1000_hw *hw);
-static s32 igb_write_nvm_srwr(struct e1000_hw *hw, u16 offset, u16 words,
-                               u16 *data);
-static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw);
+/**
+ * igb_get_hw_semaphore_i210 - Acquire hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Acquire the HW semaphore to access the PHY or NVM
+ */
+static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
+{
+       u32 swsm;
+       s32 ret_val = E1000_SUCCESS;
+       s32 timeout = hw->nvm.word_size + 1;
+       s32 i = 0;
+
+       /* Get the FW semaphore. */
+       for (i = 0; i < timeout; i++) {
+               swsm = rd32(E1000_SWSM);
+               wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
+
+               /* Semaphore acquired if bit latched */
+               if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
+                       break;
+
+               udelay(50);
+       }
+
+       if (i == timeout) {
+               /* Release semaphores */
+               igb_put_hw_semaphore(hw);
+               hw_dbg("Driver can't access the NVM\n");
+               ret_val = -E1000_ERR_NVM;
+               goto out;
+       }
+
+out:
+       return ret_val;
+}
 
 /**
  *  igb_acquire_nvm_i210 - Request for access to EEPROM
@@ -67,6 +98,23 @@ void igb_release_nvm_i210(struct e1000_hw *hw)
        igb_release_swfw_sync_i210(hw, E1000_SWFW_EEP_SM);
 }
 
+/**
+ *  igb_put_hw_semaphore_i210 - Release hardware semaphore
+ *  @hw: pointer to the HW structure
+ *
+ *  Release hardware semaphore used to access the PHY or NVM
+ */
+static void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
+{
+       u32 swsm;
+
+       swsm = rd32(E1000_SWSM);
+
+       swsm &= ~E1000_SWSM_SWESMBI;
+
+       wr32(E1000_SWSM, swsm);
+}
+
 /**
  *  igb_acquire_swfw_sync_i210 - Acquire SW/FW semaphore
  *  @hw: pointer to the HW structure
@@ -137,60 +185,6 @@ void igb_release_swfw_sync_i210(struct e1000_hw *hw, u16 mask)
        igb_put_hw_semaphore_i210(hw);
 }
 
-/**
- *  igb_get_hw_semaphore_i210 - Acquire hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Acquire the HW semaphore to access the PHY or NVM
- **/
-static s32 igb_get_hw_semaphore_i210(struct e1000_hw *hw)
-{
-       u32 swsm;
-       s32 ret_val = E1000_SUCCESS;
-       s32 timeout = hw->nvm.word_size + 1;
-       s32 i = 0;
-
-       /* Get the FW semaphore. */
-       for (i = 0; i < timeout; i++) {
-               swsm = rd32(E1000_SWSM);
-               wr32(E1000_SWSM, swsm | E1000_SWSM_SWESMBI);
-
-               /* Semaphore acquired if bit latched */
-               if (rd32(E1000_SWSM) & E1000_SWSM_SWESMBI)
-                       break;
-
-               udelay(50);
-       }
-
-       if (i == timeout) {
-               /* Release semaphores */
-               igb_put_hw_semaphore(hw);
-               hw_dbg("Driver can't access the NVM\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
-       }
-
-out:
-       return ret_val;
-}
-
-/**
- *  igb_put_hw_semaphore_i210 - Release hardware semaphore
- *  @hw: pointer to the HW structure
- *
- *  Release hardware semaphore used to access the PHY or NVM
- **/
-static void igb_put_hw_semaphore_i210(struct e1000_hw *hw)
-{
-       u32 swsm;
-
-       swsm = rd32(E1000_SWSM);
-
-       swsm &= ~E1000_SWSM_SWESMBI;
-
-       wr32(E1000_SWSM, swsm);
-}
-
 /**
  *  igb_read_nvm_srrd_i210 - Reads Shadow Ram using EERD register
  *  @hw: pointer to the HW structure
@@ -228,49 +222,6 @@ s32 igb_read_nvm_srrd_i210(struct e1000_hw *hw, u16 offset, u16 words,
        return status;
 }
 
-/**
- *  igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
- *  @hw: pointer to the HW structure
- *  @offset: offset within the Shadow RAM to be written to
- *  @words: number of words to write
- *  @data: 16 bit word(s) to be written to the Shadow RAM
- *
- *  Writes data to Shadow RAM at offset using EEWR register.
- *
- *  If e1000_update_nvm_checksum is not called after this function , the
- *  data will not be committed to FLASH and also Shadow RAM will most likely
- *  contain an invalid checksum.
- *
- *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
- *  partially written.
- **/
-s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
-                             u16 *data)
-{
-       s32 status = E1000_SUCCESS;
-       u16 i, count;
-
-       /* We cannot hold synchronization semaphores for too long,
-        * because of forceful takeover procedure. However it is more efficient
-        * to write in bursts than synchronizing access for each word. */
-       for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
-               count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
-                       E1000_EERD_EEWR_MAX_COUNT : (words - i);
-               if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
-                       status = igb_write_nvm_srwr(hw, offset, count,
-                                                     data + i);
-                       hw->nvm.ops.release(hw);
-               } else {
-                       status = E1000_ERR_SWFW_SYNC;
-               }
-
-               if (status != E1000_SUCCESS)
-                       break;
-       }
-
-       return status;
-}
-
 /**
  *  igb_write_nvm_srwr - Write to Shadow Ram using EEWR
  *  @hw: pointer to the HW structure
@@ -328,6 +279,50 @@ out:
        return ret_val;
 }
 
+/**
+ *  igb_write_nvm_srwr_i210 - Write to Shadow RAM using EEWR
+ *  @hw: pointer to the HW structure
+ *  @offset: offset within the Shadow RAM to be written to
+ *  @words: number of words to write
+ *  @data: 16 bit word(s) to be written to the Shadow RAM
+ *
+ *  Writes data to Shadow RAM at offset using EEWR register.
+ *
+ *  If e1000_update_nvm_checksum is not called after this function , the
+ *  data will not be committed to FLASH and also Shadow RAM will most likely
+ *  contain an invalid checksum.
+ *
+ *  If error code is returned, data and Shadow RAM may be inconsistent - buffer
+ *  partially written.
+ */
+s32 igb_write_nvm_srwr_i210(struct e1000_hw *hw, u16 offset, u16 words,
+                             u16 *data)
+{
+       s32 status = E1000_SUCCESS;
+       u16 i, count;
+
+       /* We cannot hold synchronization semaphores for too long,
+        * because of forceful takeover procedure. However it is more efficient
+        * to write in bursts than synchronizing access for each word.
+        */
+       for (i = 0; i < words; i += E1000_EERD_EEWR_MAX_COUNT) {
+               count = (words - i) / E1000_EERD_EEWR_MAX_COUNT > 0 ?
+                       E1000_EERD_EEWR_MAX_COUNT : (words - i);
+               if (hw->nvm.ops.acquire(hw) == E1000_SUCCESS) {
+                       status = igb_write_nvm_srwr(hw, offset, count,
+                                                     data + i);
+                       hw->nvm.ops.release(hw);
+               } else {
+                       status = E1000_ERR_SWFW_SYNC;
+               }
+
+               if (status != E1000_SUCCESS)
+                       break;
+       }
+
+       return status;
+}
+
 /**
  *  igb_read_nvm_i211 - Read NVM wrapper function for I211
  *  @hw: pointer to the HW structure
@@ -350,16 +345,40 @@ s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
                if (ret_val != E1000_SUCCESS)
                        hw_dbg("MAC Addr not found in iNVM\n");
                break;
-       case NVM_ID_LED_SETTINGS:
        case NVM_INIT_CTRL_2:
+               ret_val = igb_read_invm_i211(hw, (u8)offset, data);
+               if (ret_val != E1000_SUCCESS) {
+                       *data = NVM_INIT_CTRL_2_DEFAULT_I211;
+                       ret_val = E1000_SUCCESS;
+               }
+               break;
        case NVM_INIT_CTRL_4:
+               ret_val = igb_read_invm_i211(hw, (u8)offset, data);
+               if (ret_val != E1000_SUCCESS) {
+                       *data = NVM_INIT_CTRL_4_DEFAULT_I211;
+                       ret_val = E1000_SUCCESS;
+               }
+               break;
        case NVM_LED_1_CFG:
+               ret_val = igb_read_invm_i211(hw, (u8)offset, data);
+               if (ret_val != E1000_SUCCESS) {
+                       *data = NVM_LED_1_CFG_DEFAULT_I211;
+                       ret_val = E1000_SUCCESS;
+               }
+               break;
        case NVM_LED_0_2_CFG:
                igb_read_invm_i211(hw, offset, data);
+               if (ret_val != E1000_SUCCESS) {
+                       *data = NVM_LED_0_2_CFG_DEFAULT_I211;
+                       ret_val = E1000_SUCCESS;
+               }
                break;
-       case NVM_COMPAT:
-               *data = ID_LED_DEFAULT_I210;
-               break;
+       case NVM_ID_LED_SETTINGS:
+               ret_val = igb_read_invm_i211(hw, (u8)offset, data);
+               if (ret_val != E1000_SUCCESS) {
+                       *data = ID_LED_RESERVED_FFFF;
+                       ret_val = E1000_SUCCESS;
+               }
        case NVM_SUB_DEV_ID:
                *data = hw->subsystem_device_id;
                break;
@@ -422,6 +441,100 @@ s32 igb_read_invm_i211(struct e1000_hw *hw, u16 address, u16 *data)
        return status;
 }
 
+/**
+ *  igb_read_invm_version - Reads iNVM version and image type
+ *  @hw: pointer to the HW structure
+ *  @invm_ver: version structure for the version read
+ *
+ *  Reads iNVM version and image type.
+ **/
+s32 igb_read_invm_version(struct e1000_hw *hw,
+                         struct e1000_fw_version *invm_ver) {
+       u32 *record = NULL;
+       u32 *next_record = NULL;
+       u32 i = 0;
+       u32 invm_dword = 0;
+       u32 invm_blocks = E1000_INVM_SIZE - (E1000_INVM_ULT_BYTES_SIZE /
+                                            E1000_INVM_RECORD_SIZE_IN_BYTES);
+       u32 buffer[E1000_INVM_SIZE];
+       s32 status = -E1000_ERR_INVM_VALUE_NOT_FOUND;
+       u16 version = 0;
+
+       /* Read iNVM memory */
+       for (i = 0; i < E1000_INVM_SIZE; i++) {
+               invm_dword = rd32(E1000_INVM_DATA_REG(i));
+               buffer[i] = invm_dword;
+       }
+
+       /* Read version number */
+       for (i = 1; i < invm_blocks; i++) {
+               record = &buffer[invm_blocks - i];
+               next_record = &buffer[invm_blocks - i + 1];
+
+               /* Check if we have first version location used */
+               if ((i == 1) && ((*record & E1000_INVM_VER_FIELD_ONE) == 0)) {
+                       version = 0;
+                       status = E1000_SUCCESS;
+                       break;
+               }
+               /* Check if we have second version location used */
+               else if ((i == 1) &&
+                        ((*record & E1000_INVM_VER_FIELD_TWO) == 0)) {
+                       version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
+                       status = E1000_SUCCESS;
+                       break;
+               }
+               /* Check if we have odd version location
+                * used and it is the last one used
+                */
+               else if ((((*record & E1000_INVM_VER_FIELD_ONE) == 0) &&
+                        ((*record & 0x3) == 0)) || (((*record & 0x3) != 0) &&
+                        (i != 1))) {
+                       version = (*next_record & E1000_INVM_VER_FIELD_TWO)
+                                 >> 13;
+                       status = E1000_SUCCESS;
+                       break;
+               }
+               /* Check if we have even version location
+                * used and it is the last one used
+                */
+               else if (((*record & E1000_INVM_VER_FIELD_TWO) == 0) &&
+                        ((*record & 0x3) == 0)) {
+                       version = (*record & E1000_INVM_VER_FIELD_ONE) >> 3;
+                       status = E1000_SUCCESS;
+                       break;
+               }
+       }
+
+       if (status == E1000_SUCCESS) {
+               invm_ver->invm_major = (version & E1000_INVM_MAJOR_MASK)
+                                       >> E1000_INVM_MAJOR_SHIFT;
+               invm_ver->invm_minor = version & E1000_INVM_MINOR_MASK;
+       }
+       /* Read Image Type */
+       for (i = 1; i < invm_blocks; i++) {
+               record = &buffer[invm_blocks - i];
+               next_record = &buffer[invm_blocks - i + 1];
+
+               /* Check if we have image type in first location used */
+               if ((i == 1) && ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) {
+                       invm_ver->invm_img_type = 0;
+                       status = E1000_SUCCESS;
+                       break;
+               }
+               /* Check if we have image type in first location used */
+               else if ((((*record & 0x3) == 0) &&
+                        ((*record & E1000_INVM_IMGTYPE_FIELD) == 0)) ||
+                        ((((*record & 0x3) != 0) && (i != 1)))) {
+                       invm_ver->invm_img_type =
+                               (*next_record & E1000_INVM_IMGTYPE_FIELD) >> 23;
+                       status = E1000_SUCCESS;
+                       break;
+               }
+       }
+       return status;
+}
+
 /**
  *  igb_validate_nvm_checksum_i210 - Validate EEPROM checksum
  *  @hw: pointer to the HW structure
@@ -518,6 +631,28 @@ out:
        return ret_val;
 }
 
+/**
+ *  igb_pool_flash_update_done_i210 - Pool FLUDONE status.
+ *  @hw: pointer to the HW structure
+ *
+ */
+static s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
+{
+       s32 ret_val = -E1000_ERR_NVM;
+       u32 i, reg;
+
+       for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
+               reg = rd32(E1000_EECD);
+               if (reg & E1000_EECD_FLUDONE_I210) {
+                       ret_val = E1000_SUCCESS;
+                       break;
+               }
+               udelay(5);
+       }
+
+       return ret_val;
+}
+
 /**
  *  igb_update_flash_i210 - Commit EEPROM to the flash
  *  @hw: pointer to the HW structure
@@ -547,28 +682,6 @@ out:
        return ret_val;
 }
 
-/**
- *  igb_pool_flash_update_done_i210 - Pool FLUDONE status.
- *  @hw: pointer to the HW structure
- *
- **/
-s32 igb_pool_flash_update_done_i210(struct e1000_hw *hw)
-{
-       s32 ret_val = -E1000_ERR_NVM;
-       u32 i, reg;
-
-       for (i = 0; i < E1000_FLUDONE_ATTEMPTS; i++) {
-               reg = rd32(E1000_EECD);
-               if (reg & E1000_EECD_FLUDONE_I210) {
-                       ret_val = E1000_SUCCESS;
-                       break;
-               }
-               udelay(5);
-       }
-
-       return ret_val;
-}
-
 /**
  *  igb_valid_led_default_i210 - Verify a valid default LED config
  *  @hw: pointer to the HW structure
index 5dc2bd3f50bc1df3076d59e61ba1f30209bacc5b..1c89358a99ab84b384f4d6819dd550aa7cc2a34d 100644 (file)
@@ -43,6 +43,8 @@ extern void igb_release_nvm_i210(struct e1000_hw *hw);
 extern s32 igb_valid_led_default_i210(struct e1000_hw *hw, u16 *data);
 extern s32 igb_read_nvm_i211(struct e1000_hw *hw, u16 offset, u16 words,
                               u16 *data);
+extern s32 igb_read_invm_version(struct e1000_hw *hw,
+                                struct e1000_fw_version *invm_ver);
 
 #define E1000_STM_OPCODE               0xDB00
 #define E1000_EEPROM_FLASH_SIZE_WORD   0x11
@@ -65,6 +67,15 @@ enum E1000_INVM_STRUCTURE_TYPE {
 
 #define E1000_INVM_RSA_KEY_SHA256_DATA_SIZE_IN_DWORDS  8
 #define E1000_INVM_CSR_AUTOLOAD_DATA_SIZE_IN_DWORDS    1
+#define E1000_INVM_ULT_BYTES_SIZE                      8
+#define E1000_INVM_RECORD_SIZE_IN_BYTES                        4
+#define E1000_INVM_VER_FIELD_ONE                       0x1FF8
+#define E1000_INVM_VER_FIELD_TWO                       0x7FE000
+#define E1000_INVM_IMGTYPE_FIELD                       0x1F800000
+
+#define E1000_INVM_MAJOR_MASK          0x3F0
+#define E1000_INVM_MINOR_MASK          0xF
+#define E1000_INVM_MAJOR_SHIFT         4
 
 #define ID_LED_DEFAULT_I210            ((ID_LED_OFF1_ON2  << 8) | \
                                         (ID_LED_OFF1_OFF2 <<  4) | \
@@ -73,4 +84,10 @@ enum E1000_INVM_STRUCTURE_TYPE {
                                         (ID_LED_DEF1_DEF2 <<  4) | \
                                         (ID_LED_DEF1_DEF2))
 
+/* NVM offset defaults for i211 device */
+#define NVM_INIT_CTRL_2_DEFAULT_I211   0X7243
+#define NVM_INIT_CTRL_4_DEFAULT_I211   0x00C1
+#define NVM_LED_1_CFG_DEFAULT_I211     0x0184
+#define NVM_LED_0_2_CFG_DEFAULT_I211   0x200C
+
 #endif
index 819c145ac762229df4330ea1d79110133e43e0e9..101e6e4da97fb5287852d555409618c7cf7bf854 100644 (file)
@@ -839,6 +839,7 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
        s32 ret_val = 0;
+       u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg;
        u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
        u16 speed, duplex;
 
@@ -1040,6 +1041,129 @@ s32 igb_config_fc_after_link_up(struct e1000_hw *hw)
                        goto out;
                }
        }
+       /* Check for the case where we have SerDes media and auto-neg is
+        * enabled.  In this case, we need to check and see if Auto-Neg
+        * has completed, and if so, how the PHY and link partner has
+        * flow control configured.
+        */
+       if ((hw->phy.media_type == e1000_media_type_internal_serdes)
+               && mac->autoneg) {
+               /* Read the PCS_LSTS and check to see if AutoNeg
+                * has completed.
+                */
+               pcs_status_reg = rd32(E1000_PCS_LSTAT);
+
+               if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) {
+                       hw_dbg("PCS Auto Neg has not completed.\n");
+                       return ret_val;
+               }
+
+               /* The AutoNeg process has completed, so we now need to
+                * read both the Auto Negotiation Advertisement
+                * Register (PCS_ANADV) and the Auto_Negotiation Base
+                * Page Ability Register (PCS_LPAB) to determine how
+                * flow control was negotiated.
+                */
+               pcs_adv_reg = rd32(E1000_PCS_ANADV);
+               pcs_lp_ability_reg = rd32(E1000_PCS_LPAB);
+
+               /* Two bits in the Auto Negotiation Advertisement Register
+                * (PCS_ANADV) and two bits in the Auto Negotiation Base
+                * Page Ability Register (PCS_LPAB) determine flow control
+                * for both the PHY and the link partner.  The following
+                * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+                * 1999, describes these PAUSE resolution bits and how flow
+                * control is determined based upon these settings.
+                * NOTE:  DC = Don't Care
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+                *-------|---------|-------|---------|--------------------
+                *   0   |    0    |  DC   |   DC    | e1000_fc_none
+                *   0   |    1    |   0   |   DC    | e1000_fc_none
+                *   0   |    1    |   1   |    0    | e1000_fc_none
+                *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+                *   1   |    0    |   0   |   DC    | e1000_fc_none
+                *   1   |   DC    |   1   |   DC    | e1000_fc_full
+                *   1   |    1    |   0   |    0    | e1000_fc_none
+                *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+                *
+                * Are both PAUSE bits set to 1?  If so, this implies
+                * Symmetric Flow Control is enabled at both ends.  The
+                * ASM_DIR bits are irrelevant per the spec.
+                *
+                * For Symmetric Flow Control:
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   1   |   DC    |   1   |   DC    | e1000_fc_full
+                *
+                */
+               if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                   (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) {
+                       /* Now we need to check if the user selected Rx ONLY
+                        * of pause frames.  In this case, we had to advertise
+                        * FULL flow control because we could not advertise Rx
+                        * ONLY. Hence, we must now check to see if we need to
+                        * turn OFF the TRANSMISSION of PAUSE frames.
+                        */
+                       if (hw->fc.requested_mode == e1000_fc_full) {
+                               hw->fc.current_mode = e1000_fc_full;
+                               hw_dbg("Flow Control = FULL.\n");
+                       } else {
+                               hw->fc.current_mode = e1000_fc_rx_pause;
+                               hw_dbg("Flow Control = Rx PAUSE frames only.\n");
+                       }
+               }
+               /* For receiving PAUSE frames ONLY.
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+                */
+               else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                         (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+                         (pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+                         (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+                       hw->fc.current_mode = e1000_fc_tx_pause;
+                       hw_dbg("Flow Control = Tx PAUSE frames only.\n");
+               }
+               /* For transmitting PAUSE frames ONLY.
+                *
+                *   LOCAL DEVICE  |   LINK PARTNER
+                * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+                *-------|---------|-------|---------|--------------------
+                *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+                */
+               else if ((pcs_adv_reg & E1000_TXCW_PAUSE) &&
+                        (pcs_adv_reg & E1000_TXCW_ASM_DIR) &&
+                        !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) &&
+                        (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) {
+                       hw->fc.current_mode = e1000_fc_rx_pause;
+                       hw_dbg("Flow Control = Rx PAUSE frames only.\n");
+               } else {
+                       /* Per the IEEE spec, at this point flow control
+                        * should be disabled.
+                        */
+                       hw->fc.current_mode = e1000_fc_none;
+                       hw_dbg("Flow Control = NONE.\n");
+               }
+
+               /* Now we call a subroutine to actually force the MAC
+                * controller to use the correct flow control settings.
+                */
+               pcs_ctrl_reg = rd32(E1000_PCS_LCTL);
+               pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL;
+               wr32(E1000_PCS_LCTL, pcs_ctrl_reg);
+
+               ret_val = igb_force_mac_fc(hw);
+               if (ret_val) {
+                       hw_dbg("Error forcing flow control settings\n");
+                       return ret_val;
+               }
+       }
 
 out:
        return ret_val;
@@ -1391,6 +1515,10 @@ s32 igb_validate_mdi_setting(struct e1000_hw *hw)
 {
        s32 ret_val = 0;
 
+       /* All MDI settings are supported on 82580 and newer. */
+       if (hw->mac.type >= e1000_82580)
+               goto out;
+
        if (!hw->mac.autoneg && (hw->phy.mdix == 0 || hw->phy.mdix == 3)) {
                hw_dbg("Invalid MDI setting detected\n");
                hw->phy.mdix = 1;
index cbddc4e51e30d9c304b11c75250d04ddde39c5b7..e2b2c4b9c951fd704a5d452f00e6efd190ec307b 100644 (file)
@@ -33,6 +33,7 @@
 #include "e1000_phy.h"
 #include "e1000_nvm.h"
 #include "e1000_defines.h"
+#include "e1000_i210.h"
 
 /*
  * Functions that should not be called directly from drivers but can be used
index aa5fcdf3f357f033947857716d1f102310ebacab..fbb7604db364f59729bb3f6c36d41758d4cf40ba 100644 (file)
@@ -438,7 +438,7 @@ out:
 s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
 {
        struct e1000_nvm_info *nvm = &hw->nvm;
-       s32 ret_val;
+       s32 ret_val = -E1000_ERR_NVM;
        u16 widx = 0;
 
        /*
@@ -448,22 +448,21 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
        if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
            (words == 0)) {
                hw_dbg("nvm parameter(s) out of bounds\n");
-               ret_val = -E1000_ERR_NVM;
-               goto out;
+               return ret_val;
        }
 
-       ret_val = hw->nvm.ops.acquire(hw);
-       if (ret_val)
-               goto out;
-
-       msleep(10);
-
        while (widx < words) {
                u8 write_opcode = NVM_WRITE_OPCODE_SPI;
 
-               ret_val = igb_ready_nvm_eeprom(hw);
+               ret_val = nvm->ops.acquire(hw);
                if (ret_val)
-                       goto release;
+                       return ret_val;
+
+               ret_val = igb_ready_nvm_eeprom(hw);
+               if (ret_val) {
+                       nvm->ops.release(hw);
+                       return ret_val;
+               }
 
                igb_standby_nvm(hw);
 
@@ -497,13 +496,10 @@ s32 igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
                                break;
                        }
                }
+               usleep_range(1000, 2000);
+               nvm->ops.release(hw);
        }
 
-       msleep(10);
-release:
-       hw->nvm.ops.release(hw);
-
-out:
        return ret_val;
 }
 
@@ -710,3 +706,74 @@ s32 igb_update_nvm_checksum(struct e1000_hw *hw)
 out:
        return ret_val;
 }
+
+/**
+ *  igb_get_fw_version - Get firmware version information
+ *  @hw: pointer to the HW structure
+ *  @fw_vers: pointer to output structure
+ *
+ *  unsupported MAC types will return all 0 version structure
+ **/
+void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers)
+{
+       u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset;
+       u16 fw_version;
+
+       memset(fw_vers, 0, sizeof(struct e1000_fw_version));
+
+       switch (hw->mac.type) {
+       case e1000_i211:
+               igb_read_invm_version(hw, fw_vers);
+               return;
+       case e1000_82575:
+       case e1000_82576:
+       case e1000_82580:
+       case e1000_i350:
+       case e1000_i210:
+               break;
+       default:
+               return;
+       }
+       /* basic eeprom version numbers */
+       hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
+       fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK) >> NVM_MAJOR_SHIFT;
+       fw_vers->eep_minor = (fw_version & NVM_MINOR_MASK);
+
+       /* etrack id */
+       hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
+       hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
+       fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) | eeprom_verl;
+
+       switch (hw->mac.type) {
+       case e1000_i210:
+       case e1000_i350:
+               /* find combo image version */
+               hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
+               if ((comb_offset != 0x0) && (comb_offset != NVM_VER_INVALID)) {
+
+                       hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
+                                        + 1), 1, &comb_verh);
+                       hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
+                                        1, &comb_verl);
+
+                       /* get Option Rom version if it exists and is valid */
+                       if ((comb_verh && comb_verl) &&
+                           ((comb_verh != NVM_VER_INVALID) &&
+                            (comb_verl != NVM_VER_INVALID))) {
+
+                               fw_vers->or_valid = true;
+                               fw_vers->or_major =
+                                       comb_verl >> NVM_COMB_VER_SHFT;
+                               fw_vers->or_build =
+                                       ((comb_verl << NVM_COMB_VER_SHFT)
+                                       | (comb_verh >> NVM_COMB_VER_SHFT));
+                               fw_vers->or_patch =
+                                       comb_verh & NVM_COMB_VER_MASK;
+                       }
+               }
+               break;
+       default:
+               break;
+       }
+       return;
+}
index 825b0228cac0ac5c17dcd9a903240b9a17d95e6b..7012d458c6f7eff8df5ae1c0e25cd4a5abaa486d 100644 (file)
@@ -40,4 +40,20 @@ s32  igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  igb_validate_nvm_checksum(struct e1000_hw *hw);
 s32  igb_update_nvm_checksum(struct e1000_hw *hw);
 
+struct e1000_fw_version {
+       u32 etrack_id;
+       u16 eep_major;
+       u16 eep_minor;
+
+       u8 invm_major;
+       u8 invm_minor;
+       u8 invm_img_type;
+
+       bool or_valid;
+       u16 or_major;
+       u16 or_build;
+       u16 or_patch;
+};
+void igb_get_fw_version(struct e1000_hw *hw, struct e1000_fw_version *fw_vers);
+
 #endif
index 3404bc79f4cadf76382c5dbfca62b4d4ebe1f693..fe76004aca4e7a8464811629d9cfec18dac2f8b2 100644 (file)
@@ -1207,20 +1207,25 @@ s32 igb_phy_force_speed_duplex_m88(struct e1000_hw *hw)
        u16 phy_data;
        bool link;
 
-       /*
-        * Clear Auto-Crossover to force MDI manually.  M88E1000 requires MDI
-        * forced whenever speed and duplex are forced.
-        */
-       ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
-       if (ret_val)
-               goto out;
+       /* I210 and I211 devices support Auto-Crossover in forced operation. */
+       if (phy->type != e1000_phy_i210) {
+               /*
+                * Clear Auto-Crossover to force MDI manually.  M88E1000
+                * requires MDI forced whenever speed and duplex are forced.
+                */
+               ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                           &phy_data);
+               if (ret_val)
+                       goto out;
 
-       phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
-       ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
-       if (ret_val)
-               goto out;
+               phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
+               ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
+                                            phy_data);
+               if (ret_val)
+                       goto out;
 
-       hw_dbg("M88E1000 PSCR: %X\n", phy_data);
+               hw_dbg("M88E1000 PSCR: %X\n", phy_data);
+       }
 
        ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
        if (ret_val)
@@ -1710,6 +1715,26 @@ s32 igb_get_cable_length_m88_gen2(struct e1000_hw *hw)
 
        switch (hw->phy.id) {
        case I210_I_PHY_ID:
+               /* Get cable length from PHY Cable Diagnostics Control Reg */
+               ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+                                           (I347AT4_PCDL + phy->addr),
+                                           &phy_data);
+               if (ret_val)
+                       return ret_val;
+
+               /* Check if the unit of cable length is meters or cm */
+               ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
+                                           I347AT4_PCDC, &phy_data2);
+               if (ret_val)
+                       return ret_val;
+
+               is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
+
+               /* Populate the phy structure with cable length in meters */
+               phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
+               phy->cable_length = phy_data / (is_cm ? 100 : 1);
+               break;
        case I347AT4_E_PHY_ID:
                /* Remember the original page select and set it to 7 */
                ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
index 6ac3299bfcb9fefe23845b294a72e2119563ec36..ed282f877d9a0b08df7b7a2673d0e3d0d67c5216 100644 (file)
@@ -124,6 +124,7 @@ s32  igb_check_polarity_m88(struct e1000_hw *hw);
 #define E1000_82580_PM_SPD             0x0001 /* Smart Power Down */
 #define E1000_82580_PM_D0_LPLU         0x0002 /* For D0a states */
 #define E1000_82580_PM_D3_LPLU         0x0004 /* For all other states */
+#define E1000_82580_PM_GO_LINKD                0x0020 /* Go Link Disconnect */
 
 /* Enable flexible speed on link-up */
 #define IGP02E1000_PM_D0_LPLU             0x0002 /* For D0a states */
index 8aad230c0592e03f5f3b753f636f0a38dd35d4a3..17f1686ee411fe3e63aea5fdcfacaa1abe6e8ee1 100644 (file)
 #include "e1000_mac.h"
 #include "e1000_82575.h"
 
-#ifdef CONFIG_IGB_PTP
 #include <linux/clocksource.h>
 #include <linux/net_tstamp.h>
 #include <linux/ptp_clock_kernel.h>
-#endif /* CONFIG_IGB_PTP */
 #include <linux/bitops.h>
 #include <linux/if_vlan.h>
 
 struct igb_adapter;
 
+#define E1000_PCS_CFG_IGN_SD               1
+
 /* Interrupt defines */
 #define IGB_START_ITR                    648 /* ~6000 ints/sec */
 #define IGB_4K_ITR                       980
@@ -132,9 +132,10 @@ struct vf_data_storage {
 #define MAXIMUM_ETHERNET_VLAN_SIZE 1522
 
 /* Supported Rx Buffer Sizes */
-#define IGB_RXBUFFER_256   256
-#define IGB_RXBUFFER_16384 16384
-#define IGB_RX_HDR_LEN     IGB_RXBUFFER_256
+#define IGB_RXBUFFER_256       256
+#define IGB_RXBUFFER_2048      2048
+#define IGB_RX_HDR_LEN         IGB_RXBUFFER_256
+#define IGB_RX_BUFSZ           IGB_RXBUFFER_2048
 
 /* How many Tx Descriptors do we need to call netif_wake_queue ? */
 #define IGB_TX_QUEUE_WAKE      16
@@ -151,11 +152,18 @@ struct vf_data_storage {
 
 #define IGB_MNG_VLAN_NONE -1
 
-#define IGB_TX_FLAGS_CSUM              0x00000001
-#define IGB_TX_FLAGS_VLAN              0x00000002
-#define IGB_TX_FLAGS_TSO               0x00000004
-#define IGB_TX_FLAGS_IPV4              0x00000008
-#define IGB_TX_FLAGS_TSTAMP            0x00000010
+enum igb_tx_flags {
+       /* cmd_type flags */
+       IGB_TX_FLAGS_VLAN       = 0x01,
+       IGB_TX_FLAGS_TSO        = 0x02,
+       IGB_TX_FLAGS_TSTAMP     = 0x04,
+
+       /* olinfo flags */
+       IGB_TX_FLAGS_IPV4       = 0x10,
+       IGB_TX_FLAGS_CSUM       = 0x20,
+};
+
+/* VLAN info */
 #define IGB_TX_FLAGS_VLAN_MASK         0xffff0000
 #define IGB_TX_FLAGS_VLAN_SHIFT        16
 
@@ -174,11 +182,9 @@ struct igb_tx_buffer {
 };
 
 struct igb_rx_buffer {
-       struct sk_buff *skb;
        dma_addr_t dma;
        struct page *page;
-       dma_addr_t page_dma;
-       u32 page_offset;
+       unsigned int page_offset;
 };
 
 struct igb_tx_queue_stats {
@@ -205,22 +211,6 @@ struct igb_ring_container {
        u8 itr;                         /* current ITR setting for ring */
 };
 
-struct igb_q_vector {
-       struct igb_adapter *adapter;    /* backlink */
-       int cpu;                        /* CPU for DCA */
-       u32 eims_value;                 /* EIMS mask value */
-
-       struct igb_ring_container rx, tx;
-
-       struct napi_struct napi;
-
-       u16 itr_val;
-       u8 set_itr;
-       void __iomem *itr_register;
-
-       char name[IFNAMSIZ + 9];
-};
-
 struct igb_ring {
        struct igb_q_vector *q_vector;  /* backlink to q_vector */
        struct net_device *netdev;      /* back pointer to net_device */
@@ -232,15 +222,17 @@ struct igb_ring {
        void *desc;                     /* descriptor ring memory */
        unsigned long flags;            /* ring specific flags */
        void __iomem *tail;             /* pointer to ring tail register */
+       dma_addr_t dma;                 /* phys address of the ring */
+       unsigned int  size;             /* length of desc. ring in bytes */
 
        u16 count;                      /* number of desc. in the ring */
        u8 queue_index;                 /* logical index of the ring*/
        u8 reg_idx;                     /* physical index of the ring */
-       u32 size;                       /* length of desc. ring in bytes */
 
        /* everything past this point are written often */
-       u16 next_to_clean ____cacheline_aligned_in_smp;
+       u16 next_to_clean;
        u16 next_to_use;
+       u16 next_to_alloc;
 
        union {
                /* TX */
@@ -251,12 +243,30 @@ struct igb_ring {
                };
                /* RX */
                struct {
+                       struct sk_buff *skb;
                        struct igb_rx_queue_stats rx_stats;
                        struct u64_stats_sync rx_syncp;
                };
        };
-       /* Items past this point are only used during ring alloc / free */
-       dma_addr_t dma;                /* phys address of the ring */
+} ____cacheline_internodealigned_in_smp;
+
+struct igb_q_vector {
+       struct igb_adapter *adapter;    /* backlink */
+       int cpu;                        /* CPU for DCA */
+       u32 eims_value;                 /* EIMS mask value */
+
+       u16 itr_val;
+       u8 set_itr;
+       void __iomem *itr_register;
+
+       struct igb_ring_container rx, tx;
+
+       struct napi_struct napi;
+       struct rcu_head rcu;    /* to avoid race with update stats on free */
+       char name[IFNAMSIZ + 9];
+
+       /* for dynamic allocation of rings associated with this q_vector */
+       struct igb_ring ring[0] ____cacheline_internodealigned_in_smp;
 };
 
 enum e1000_ring_flags_t {
@@ -362,8 +372,6 @@ struct igb_adapter {
        u32 eims_other;
 
        /* to not mess up cache alignment, always add to the bottom */
-       u32 eeprom_wol;
-
        u16 tx_ring_count;
        u16 rx_ring_count;
        unsigned int vfs_allocated_count;
@@ -373,7 +381,6 @@ struct igb_adapter {
        u32 wvbr;
        u32 *shadow_vfta;
 
-#ifdef CONFIG_IGB_PTP
        struct ptp_clock *ptp_clock;
        struct ptp_clock_info ptp_caps;
        struct delayed_work ptp_overflow_work;
@@ -382,17 +389,19 @@ struct igb_adapter {
        spinlock_t tmreg_lock;
        struct cyclecounter cc;
        struct timecounter tc;
-#endif /* CONFIG_IGB_PTP */
 
        char fw_version[32];
 };
 
-#define IGB_FLAG_HAS_MSI           (1 << 0)
-#define IGB_FLAG_DCA_ENABLED       (1 << 1)
-#define IGB_FLAG_QUAD_PORT_A       (1 << 2)
-#define IGB_FLAG_QUEUE_PAIRS       (1 << 3)
-#define IGB_FLAG_DMAC              (1 << 4)
-#define IGB_FLAG_PTP               (1 << 5)
+#define IGB_FLAG_HAS_MSI               (1 << 0)
+#define IGB_FLAG_DCA_ENABLED           (1 << 1)
+#define IGB_FLAG_QUAD_PORT_A           (1 << 2)
+#define IGB_FLAG_QUEUE_PAIRS           (1 << 3)
+#define IGB_FLAG_DMAC                  (1 << 4)
+#define IGB_FLAG_PTP                   (1 << 5)
+#define IGB_FLAG_RSS_FIELD_IPV4_UDP    (1 << 6)
+#define IGB_FLAG_RSS_FIELD_IPV6_UDP    (1 << 7)
+#define IGB_FLAG_WOL_SUPPORTED         (1 << 8)
 
 /* DMA Coalescing defines */
 #define IGB_MIN_TXPBSIZE           20408
@@ -436,18 +445,27 @@ extern bool igb_has_link(struct igb_adapter *adapter);
 extern void igb_set_ethtool_ops(struct net_device *);
 extern void igb_power_up_link(struct igb_adapter *);
 extern void igb_set_fw_version(struct igb_adapter *);
-#ifdef CONFIG_IGB_PTP
 extern void igb_ptp_init(struct igb_adapter *adapter);
 extern void igb_ptp_stop(struct igb_adapter *adapter);
 extern void igb_ptp_reset(struct igb_adapter *adapter);
 extern void igb_ptp_tx_work(struct work_struct *work);
 extern void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter);
-extern void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
-                               union e1000_adv_rx_desc *rx_desc,
+extern void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
+                               struct sk_buff *skb);
+extern void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+                               unsigned char *va,
                                struct sk_buff *skb);
+static inline void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
+                                      union e1000_adv_rx_desc *rx_desc,
+                                      struct sk_buff *skb)
+{
+       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TS) &&
+           !igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP))
+               igb_ptp_rx_rgtstamp(q_vector, skb);
+}
+
 extern int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
                                  struct ifreq *ifr, int cmd);
-#endif /* CONFIG_IGB_PTP */
 
 static inline s32 igb_reset_phy(struct e1000_hw *hw)
 {
index 2ea012849825224af910ba7189aa850b58610806..bfe9208c4b1879db6a52695328d1640a7f3e2064 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/highmem.h>
 
 #include "igb.h"
 
@@ -1623,6 +1624,20 @@ static int igb_setup_loopback_test(struct igb_adapter *adapter)
                reg &= ~E1000_CONNSW_ENRGSRC;
                wr32(E1000_CONNSW, reg);
 
+               /* Unset sigdetect for SERDES loopback on
+                * 82580 and i350 devices.
+                */
+               switch (hw->mac.type) {
+               case e1000_82580:
+               case e1000_i350:
+                       reg = rd32(E1000_PCS_CFG0);
+                       reg |= E1000_PCS_CFG_IGN_SD;
+                       wr32(E1000_PCS_CFG0, reg);
+                       break;
+               default:
+                       break;
+               }
+
                /* Set PCS register for forced speed */
                reg = rd32(E1000_PCS_LCTL);
                reg &= ~E1000_PCS_LCTL_AN_ENABLE;     /* Disable Autoneg*/
@@ -1685,16 +1700,24 @@ static void igb_create_lbtest_frame(struct sk_buff *skb,
        memset(&skb->data[frame_size + 12], 0xAF, 1);
 }
 
-static int igb_check_lbtest_frame(struct sk_buff *skb, unsigned int frame_size)
+static int igb_check_lbtest_frame(struct igb_rx_buffer *rx_buffer,
+                                 unsigned int frame_size)
 {
-       frame_size /= 2;
-       if (*(skb->data + 3) == 0xFF) {
-               if ((*(skb->data + frame_size + 10) == 0xBE) &&
-                  (*(skb->data + frame_size + 12) == 0xAF)) {
-                       return 0;
-               }
-       }
-       return 13;
+       unsigned char *data;
+       bool match = true;
+
+       frame_size >>= 1;
+
+       data = kmap(rx_buffer->page);
+
+       if (data[3] != 0xFF ||
+           data[frame_size + 10] != 0xBE ||
+           data[frame_size + 12] != 0xAF)
+               match = false;
+
+       kunmap(rx_buffer->page);
+
+       return match;
 }
 
 static int igb_clean_test_rings(struct igb_ring *rx_ring,
@@ -1704,9 +1727,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
        union e1000_adv_rx_desc *rx_desc;
        struct igb_rx_buffer *rx_buffer_info;
        struct igb_tx_buffer *tx_buffer_info;
-       struct netdev_queue *txq;
        u16 rx_ntc, tx_ntc, count = 0;
-       unsigned int total_bytes = 0, total_packets = 0;
 
        /* initialize next to clean and descriptor values */
        rx_ntc = rx_ring->next_to_clean;
@@ -1717,21 +1738,24 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
                /* check rx buffer */
                rx_buffer_info = &rx_ring->rx_buffer_info[rx_ntc];
 
-               /* unmap rx buffer, will be remapped by alloc_rx_buffers */
-               dma_unmap_single(rx_ring->dev,
-                                rx_buffer_info->dma,
-                                IGB_RX_HDR_LEN,
-                                DMA_FROM_DEVICE);
-               rx_buffer_info->dma = 0;
+               /* sync Rx buffer for CPU read */
+               dma_sync_single_for_cpu(rx_ring->dev,
+                                       rx_buffer_info->dma,
+                                       IGB_RX_BUFSZ,
+                                       DMA_FROM_DEVICE);
 
                /* verify contents of skb */
-               if (!igb_check_lbtest_frame(rx_buffer_info->skb, size))
+               if (igb_check_lbtest_frame(rx_buffer_info, size))
                        count++;
 
+               /* sync Rx buffer for device write */
+               dma_sync_single_for_device(rx_ring->dev,
+                                          rx_buffer_info->dma,
+                                          IGB_RX_BUFSZ,
+                                          DMA_FROM_DEVICE);
+
                /* unmap buffer on tx side */
                tx_buffer_info = &tx_ring->tx_buffer_info[tx_ntc];
-               total_bytes += tx_buffer_info->bytecount;
-               total_packets += tx_buffer_info->gso_segs;
                igb_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
 
                /* increment rx/tx next to clean counters */
@@ -1746,8 +1770,7 @@ static int igb_clean_test_rings(struct igb_ring *rx_ring,
                rx_desc = IGB_RX_DESC(rx_ring, rx_ntc);
        }
 
-       txq = netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
-       netdev_tx_completed_queue(txq, total_packets, total_bytes);
+       netdev_tx_reset_queue(txring_txq(tx_ring));
 
        /* re-map buffers to ring, store next to clean values */
        igb_alloc_rx_buffers(rx_ring, count);
@@ -1957,54 +1980,6 @@ static void igb_diag_test(struct net_device *netdev,
        msleep_interruptible(4 * 1000);
 }
 
-static int igb_wol_exclusion(struct igb_adapter *adapter,
-                            struct ethtool_wolinfo *wol)
-{
-       struct e1000_hw *hw = &adapter->hw;
-       int retval = 1; /* fail by default */
-
-       switch (hw->device_id) {
-       case E1000_DEV_ID_82575GB_QUAD_COPPER:
-               /* WoL not supported */
-               wol->supported = 0;
-               break;
-       case E1000_DEV_ID_82575EB_FIBER_SERDES:
-       case E1000_DEV_ID_82576_FIBER:
-       case E1000_DEV_ID_82576_SERDES:
-               /* Wake events not supported on port B */
-               if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) {
-                       wol->supported = 0;
-                       break;
-               }
-               /* return success for non excluded adapter ports */
-               retval = 0;
-               break;
-       case E1000_DEV_ID_82576_QUAD_COPPER:
-       case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
-               /* quad port adapters only support WoL on port A */
-               if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) {
-                       wol->supported = 0;
-                       break;
-               }
-               /* return success for non excluded adapter ports */
-               retval = 0;
-               break;
-       default:
-               /* dual port cards only support WoL on port A from now on
-                * unless it was enabled in the eeprom for port B
-                * so exclude FUNC_1 ports from having WoL enabled */
-               if ((rd32(E1000_STATUS) & E1000_STATUS_FUNC_MASK) &&
-                   !adapter->eeprom_wol) {
-                       wol->supported = 0;
-                       break;
-               }
-
-               retval = 0;
-       }
-
-       return retval;
-}
-
 static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2014,10 +1989,7 @@ static void igb_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
                         WAKE_PHY;
        wol->wolopts = 0;
 
-       /* this function will set ->supported = 0 and return 1 if wol is not
-        * supported by this hardware */
-       if (igb_wol_exclusion(adapter, wol) ||
-           !device_can_wakeup(&adapter->pdev->dev))
+       if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
                return;
 
        /* apply any specific unsupported masks here */
@@ -2045,8 +2017,7 @@ static int igb_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE))
                return -EOPNOTSUPP;
 
-       if (igb_wol_exclusion(adapter, wol) ||
-           !device_can_wakeup(&adapter->pdev->dev))
+       if (!(adapter->flags & IGB_FLAG_WOL_SUPPORTED))
                return wol->wolopts ? -EOPNOTSUPP : 0;
 
        /* these settings will always override what we currently have */
@@ -2301,7 +2272,6 @@ static int igb_get_ts_info(struct net_device *dev,
        struct igb_adapter *adapter = netdev_priv(dev);
 
        switch (adapter->hw.mac.type) {
-#ifdef CONFIG_IGB_PTP
        case e1000_82576:
        case e1000_82580:
        case e1000_i350:
@@ -2337,12 +2307,288 @@ static int igb_get_ts_info(struct net_device *dev,
                                (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
 
                return 0;
-#endif /* CONFIG_IGB_PTP */
        default:
                return -EOPNOTSUPP;
        }
 }
 
+static int igb_get_rss_hash_opts(struct igb_adapter *adapter,
+                                struct ethtool_rxnfc *cmd)
+{
+       cmd->data = 0;
+
+       /* Report default options for RSS on igb */
+       switch (cmd->flow_type) {
+       case TCP_V4_FLOW:
+               cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+       case UDP_V4_FLOW:
+               if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+                       cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+       case SCTP_V4_FLOW:
+       case AH_ESP_V4_FLOW:
+       case AH_V4_FLOW:
+       case ESP_V4_FLOW:
+       case IPV4_FLOW:
+               cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+               break;
+       case TCP_V6_FLOW:
+               cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+       case UDP_V6_FLOW:
+               if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+                       cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
+       case SCTP_V6_FLOW:
+       case AH_ESP_V6_FLOW:
+       case AH_V6_FLOW:
+       case ESP_V6_FLOW:
+       case IPV6_FLOW:
+               cmd->data |= RXH_IP_SRC | RXH_IP_DST;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int igb_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
+                          u32 *rule_locs)
+{
+       struct igb_adapter *adapter = netdev_priv(dev);
+       int ret = -EOPNOTSUPP;
+
+       switch (cmd->cmd) {
+       case ETHTOOL_GRXRINGS:
+               cmd->data = adapter->num_rx_queues;
+               ret = 0;
+               break;
+       case ETHTOOL_GRXFH:
+               ret = igb_get_rss_hash_opts(adapter, cmd);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+#define UDP_RSS_FLAGS (IGB_FLAG_RSS_FIELD_IPV4_UDP | \
+                      IGB_FLAG_RSS_FIELD_IPV6_UDP)
+static int igb_set_rss_hash_opt(struct igb_adapter *adapter,
+                               struct ethtool_rxnfc *nfc)
+{
+       u32 flags = adapter->flags;
+
+       /* RSS does not support anything other than hashing
+        * to queues on src and dst IPs and ports
+        */
+       if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST |
+                         RXH_L4_B_0_1 | RXH_L4_B_2_3))
+               return -EINVAL;
+
+       switch (nfc->flow_type) {
+       case TCP_V4_FLOW:
+       case TCP_V6_FLOW:
+               if (!(nfc->data & RXH_IP_SRC) ||
+                   !(nfc->data & RXH_IP_DST) ||
+                   !(nfc->data & RXH_L4_B_0_1) ||
+                   !(nfc->data & RXH_L4_B_2_3))
+                       return -EINVAL;
+               break;
+       case UDP_V4_FLOW:
+               if (!(nfc->data & RXH_IP_SRC) ||
+                   !(nfc->data & RXH_IP_DST))
+                       return -EINVAL;
+               switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+               case 0:
+                       flags &= ~IGB_FLAG_RSS_FIELD_IPV4_UDP;
+                       break;
+               case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+                       flags |= IGB_FLAG_RSS_FIELD_IPV4_UDP;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case UDP_V6_FLOW:
+               if (!(nfc->data & RXH_IP_SRC) ||
+                   !(nfc->data & RXH_IP_DST))
+                       return -EINVAL;
+               switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
+               case 0:
+                       flags &= ~IGB_FLAG_RSS_FIELD_IPV6_UDP;
+                       break;
+               case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
+                       flags |= IGB_FLAG_RSS_FIELD_IPV6_UDP;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               break;
+       case AH_ESP_V4_FLOW:
+       case AH_V4_FLOW:
+       case ESP_V4_FLOW:
+       case SCTP_V4_FLOW:
+       case AH_ESP_V6_FLOW:
+       case AH_V6_FLOW:
+       case ESP_V6_FLOW:
+       case SCTP_V6_FLOW:
+               if (!(nfc->data & RXH_IP_SRC) ||
+                   !(nfc->data & RXH_IP_DST) ||
+                   (nfc->data & RXH_L4_B_0_1) ||
+                   (nfc->data & RXH_L4_B_2_3))
+                       return -EINVAL;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       /* if we changed something we need to update flags */
+       if (flags != adapter->flags) {
+               struct e1000_hw *hw = &adapter->hw;
+               u32 mrqc = rd32(E1000_MRQC);
+
+               if ((flags & UDP_RSS_FLAGS) &&
+                   !(adapter->flags & UDP_RSS_FLAGS))
+                       dev_err(&adapter->pdev->dev,
+                               "enabling UDP RSS: fragmented packets may arrive out of order to the stack above\n");
+
+               adapter->flags = flags;
+
+               /* Perform hash on these packet types */
+               mrqc |= E1000_MRQC_RSS_FIELD_IPV4 |
+                       E1000_MRQC_RSS_FIELD_IPV4_TCP |
+                       E1000_MRQC_RSS_FIELD_IPV6 |
+                       E1000_MRQC_RSS_FIELD_IPV6_TCP;
+
+               mrqc &= ~(E1000_MRQC_RSS_FIELD_IPV4_UDP |
+                         E1000_MRQC_RSS_FIELD_IPV6_UDP);
+
+               if (flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+                       mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP;
+
+               if (flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+                       mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP;
+
+               wr32(E1000_MRQC, mrqc);
+       }
+
+       return 0;
+}
+
+static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+       struct igb_adapter *adapter = netdev_priv(dev);
+       int ret = -EOPNOTSUPP;
+
+       switch (cmd->cmd) {
+       case ETHTOOL_SRXFH:
+               ret = igb_set_rss_hash_opt(adapter, cmd);
+               break;
+       default:
+               break;
+       }
+
+       return ret;
+}
+
+static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
+{
+       struct igb_adapter *adapter = netdev_priv(netdev);
+       struct e1000_hw *hw = &adapter->hw;
+       u32 ipcnfg, eeer;
+
+       if ((hw->mac.type < e1000_i350) ||
+           (hw->phy.media_type != e1000_media_type_copper))
+               return -EOPNOTSUPP;
+
+       edata->supported = (SUPPORTED_1000baseT_Full |
+                           SUPPORTED_100baseT_Full);
+
+       ipcnfg = rd32(E1000_IPCNFG);
+       eeer = rd32(E1000_EEER);
+
+       /* EEE status on negotiated link */
+       if (ipcnfg & E1000_IPCNFG_EEE_1G_AN)
+               edata->advertised = ADVERTISED_1000baseT_Full;
+
+       if (ipcnfg & E1000_IPCNFG_EEE_100M_AN)
+               edata->advertised |= ADVERTISED_100baseT_Full;
+
+       if (eeer & E1000_EEER_EEE_NEG)
+               edata->eee_active = true;
+
+       edata->eee_enabled = !hw->dev_spec._82575.eee_disable;
+
+       if (eeer & E1000_EEER_TX_LPI_EN)
+               edata->tx_lpi_enabled = true;
+
+       /* Report correct negotiated EEE status for devices that
+        * wrongly report EEE at half-duplex
+        */
+       if (adapter->link_duplex == HALF_DUPLEX) {
+               edata->eee_enabled = false;
+               edata->eee_active = false;
+               edata->tx_lpi_enabled = false;
+               edata->advertised &= ~edata->advertised;
+       }
+
+       return 0;
+}
+
+static int igb_set_eee(struct net_device *netdev,
+                      struct ethtool_eee *edata)
+{
+       struct igb_adapter *adapter = netdev_priv(netdev);
+       struct e1000_hw *hw = &adapter->hw;
+       struct ethtool_eee eee_curr;
+       s32 ret_val;
+
+       if ((hw->mac.type < e1000_i350) ||
+           (hw->phy.media_type != e1000_media_type_copper))
+               return -EOPNOTSUPP;
+
+       ret_val = igb_get_eee(netdev, &eee_curr);
+       if (ret_val)
+               return ret_val;
+
+       if (eee_curr.eee_enabled) {
+               if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) {
+                       dev_err(&adapter->pdev->dev,
+                               "Setting EEE tx-lpi is not supported\n");
+                       return -EINVAL;
+               }
+
+               /* Tx LPI timer is not implemented currently */
+               if (edata->tx_lpi_timer) {
+                       dev_err(&adapter->pdev->dev,
+                               "Setting EEE Tx LPI timer is not supported\n");
+                       return -EINVAL;
+               }
+
+               if (eee_curr.advertised != edata->advertised) {
+                       dev_err(&adapter->pdev->dev,
+                               "Setting EEE Advertisement is not supported\n");
+                       return -EINVAL;
+               }
+
+       } else if (!edata->eee_enabled) {
+               dev_err(&adapter->pdev->dev,
+                       "Setting EEE options are not supported with EEE disabled\n");
+                       return -EINVAL;
+               }
+
+       if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) {
+               hw->dev_spec._82575.eee_disable = !edata->eee_enabled;
+               igb_set_eee_i350(hw);
+
+               /* reset link */
+               if (!netif_running(netdev))
+                       igb_reset(adapter);
+       }
+
+       return 0;
+}
+
 static int igb_ethtool_begin(struct net_device *netdev)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
@@ -2383,6 +2629,10 @@ static const struct ethtool_ops igb_ethtool_ops = {
        .get_coalesce           = igb_get_coalesce,
        .set_coalesce           = igb_set_coalesce,
        .get_ts_info            = igb_get_ts_info,
+       .get_rxnfc              = igb_get_rxnfc,
+       .set_rxnfc              = igb_set_rxnfc,
+       .get_eee                = igb_get_eee,
+       .set_eee                = igb_set_eee,
        .begin                  = igb_ethtool_begin,
        .complete               = igb_ethtool_complete,
 };
index e1ceb37ef12e406fd7ff6dff13b08c18548fcea6..31cfe2ec75dfb32b7da36311214c0ac2606015f4 100644 (file)
@@ -60,8 +60,8 @@
 #include "igb.h"
 
 #define MAJ 4
-#define MIN 0
-#define BUILD 1
+#define MIN 1
+#define BUILD 2
 #define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
 __stringify(BUILD) "-k"
 char igb_driver_name[] = "igb";
@@ -118,10 +118,11 @@ static void igb_free_all_tx_resources(struct igb_adapter *);
 static void igb_free_all_rx_resources(struct igb_adapter *);
 static void igb_setup_mrqc(struct igb_adapter *);
 static int igb_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit igb_remove(struct pci_dev *pdev);
+static void igb_remove(struct pci_dev *pdev);
 static int igb_sw_init(struct igb_adapter *);
 static int igb_open(struct net_device *);
 static int igb_close(struct net_device *);
+static void igb_configure(struct igb_adapter *);
 static void igb_configure_tx(struct igb_adapter *);
 static void igb_configure_rx(struct igb_adapter *);
 static void igb_clean_all_tx_rings(struct igb_adapter *);
@@ -228,7 +229,7 @@ static struct pci_driver igb_driver = {
        .name     = igb_driver_name,
        .id_table = igb_pci_tbl,
        .probe    = igb_probe,
-       .remove   = __devexit_p(igb_remove),
+       .remove   = igb_remove,
 #ifdef CONFIG_PM
        .driver.pm = &igb_pm_ops,
 #endif
@@ -534,31 +535,27 @@ rx_ring_summary:
 
                        if (staterr & E1000_RXD_STAT_DD) {
                                /* Descriptor Done */
-                               pr_info("%s[0x%03X]     %016llX %016llX -------"
-                                       "--------- %p%s\n", "RWB", i,
+                               pr_info("%s[0x%03X]     %016llX %016llX ---------------- %s\n",
+                                       "RWB", i,
                                        le64_to_cpu(u0->a),
                                        le64_to_cpu(u0->b),
-                                       buffer_info->skb, next_desc);
+                                       next_desc);
                        } else {
-                               pr_info("%s[0x%03X]     %016llX %016llX %016llX"
-                                       " %p%s\n", "R  ", i,
+                               pr_info("%s[0x%03X]     %016llX %016llX %016llX %s\n",
+                                       "R  ", i,
                                        le64_to_cpu(u0->a),
                                        le64_to_cpu(u0->b),
                                        (u64)buffer_info->dma,
-                                       buffer_info->skb, next_desc);
+                                       next_desc);
 
                                if (netif_msg_pktdata(adapter) &&
-                                   buffer_info->dma && buffer_info->skb) {
-                                       print_hex_dump(KERN_INFO, "",
-                                                 DUMP_PREFIX_ADDRESS,
-                                                 16, 1, buffer_info->skb->data,
-                                                 IGB_RX_HDR_LEN, true);
+                                   buffer_info->dma && buffer_info->page) {
                                        print_hex_dump(KERN_INFO, "",
                                          DUMP_PREFIX_ADDRESS,
                                          16, 1,
                                          page_address(buffer_info->page) +
                                                      buffer_info->page_offset,
-                                         PAGE_SIZE/2, true);
+                                         IGB_RX_BUFSZ, true);
                                }
                        }
                }
@@ -656,80 +653,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter)
        }
 }
 
-static void igb_free_queues(struct igb_adapter *adapter)
-{
-       int i;
-
-       for (i = 0; i < adapter->num_tx_queues; i++) {
-               kfree(adapter->tx_ring[i]);
-               adapter->tx_ring[i] = NULL;
-       }
-       for (i = 0; i < adapter->num_rx_queues; i++) {
-               kfree(adapter->rx_ring[i]);
-               adapter->rx_ring[i] = NULL;
-       }
-       adapter->num_rx_queues = 0;
-       adapter->num_tx_queues = 0;
-}
-
-/**
- * igb_alloc_queues - Allocate memory for all rings
- * @adapter: board private structure to initialize
- *
- * We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time.
- **/
-static int igb_alloc_queues(struct igb_adapter *adapter)
-{
-       struct igb_ring *ring;
-       int i;
-
-       for (i = 0; i < adapter->num_tx_queues; i++) {
-               ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
-               if (!ring)
-                       goto err;
-               ring->count = adapter->tx_ring_count;
-               ring->queue_index = i;
-               ring->dev = &adapter->pdev->dev;
-               ring->netdev = adapter->netdev;
-               /* For 82575, context index must be unique per ring. */
-               if (adapter->hw.mac.type == e1000_82575)
-                       set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
-               adapter->tx_ring[i] = ring;
-       }
-
-       for (i = 0; i < adapter->num_rx_queues; i++) {
-               ring = kzalloc(sizeof(struct igb_ring), GFP_KERNEL);
-               if (!ring)
-                       goto err;
-               ring->count = adapter->rx_ring_count;
-               ring->queue_index = i;
-               ring->dev = &adapter->pdev->dev;
-               ring->netdev = adapter->netdev;
-               /* set flag indicating ring supports SCTP checksum offload */
-               if (adapter->hw.mac.type >= e1000_82576)
-                       set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
-
-               /*
-                * On i350, i210, and i211, loopback VLAN packets
-                * have the tag byte-swapped.
-                * */
-               if (adapter->hw.mac.type >= e1000_i350)
-                       set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
-
-               adapter->rx_ring[i] = ring;
-       }
-
-       igb_cache_ring_register(adapter);
-
-       return 0;
-
-err:
-       igb_free_queues(adapter);
-
-       return -ENOMEM;
-}
-
 /**
  *  igb_write_ivar - configure ivar for given MSI-X vector
  *  @hw: pointer to the HW structure
@@ -909,17 +832,18 @@ static int igb_request_msix(struct igb_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
        struct e1000_hw *hw = &adapter->hw;
-       int i, err = 0, vector = 0;
+       int i, err = 0, vector = 0, free_vector = 0;
 
        err = request_irq(adapter->msix_entries[vector].vector,
                          igb_msix_other, 0, netdev->name, adapter);
        if (err)
-               goto out;
-       vector++;
+               goto err_out;
 
        for (i = 0; i < adapter->num_q_vectors; i++) {
                struct igb_q_vector *q_vector = adapter->q_vector[i];
 
+               vector++;
+
                q_vector->itr_register = hw->hw_addr + E1000_EITR(vector);
 
                if (q_vector->rx.ring && q_vector->tx.ring)
@@ -938,13 +862,22 @@ static int igb_request_msix(struct igb_adapter *adapter)
                                  igb_msix_ring, 0, q_vector->name,
                                  q_vector);
                if (err)
-                       goto out;
-               vector++;
+                       goto err_free;
        }
 
        igb_configure_msix(adapter);
        return 0;
-out:
+
+err_free:
+       /* free already assigned IRQs */
+       free_irq(adapter->msix_entries[free_vector++].vector, adapter);
+
+       vector--;
+       for (i = 0; i < vector; i++) {
+               free_irq(adapter->msix_entries[free_vector++].vector,
+                        adapter->q_vector[i]);
+       }
+err_out:
        return err;
 }
 
@@ -959,6 +892,35 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
        }
 }
 
+/**
+ * igb_free_q_vector - Free memory allocated for specific interrupt vector
+ * @adapter: board private structure to initialize
+ * @v_idx: Index of vector to be freed
+ *
+ * This function frees the memory allocated to the q_vector.  In addition if
+ * NAPI is enabled it will delete any references to the NAPI struct prior
+ * to freeing the q_vector.
+ **/
+static void igb_free_q_vector(struct igb_adapter *adapter, int v_idx)
+{
+       struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+
+       if (q_vector->tx.ring)
+               adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;
+
+       if (q_vector->rx.ring)
+               adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL;
+
+       adapter->q_vector[v_idx] = NULL;
+       netif_napi_del(&q_vector->napi);
+
+       /*
+        * ixgbe_get_stats64() might access the rings on this vector,
+        * we must wait a grace period before freeing it.
+        */
+       kfree_rcu(q_vector, rcu);
+}
+
 /**
  * igb_free_q_vectors - Free memory allocated for interrupt vectors
  * @adapter: board private structure to initialize
@@ -969,17 +931,14 @@ static void igb_reset_interrupt_capability(struct igb_adapter *adapter)
  **/
 static void igb_free_q_vectors(struct igb_adapter *adapter)
 {
-       int v_idx;
+       int v_idx = adapter->num_q_vectors;
 
-       for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
-               struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
-               adapter->q_vector[v_idx] = NULL;
-               if (!q_vector)
-                       continue;
-               netif_napi_del(&q_vector->napi);
-               kfree(q_vector);
-       }
+       adapter->num_tx_queues = 0;
+       adapter->num_rx_queues = 0;
        adapter->num_q_vectors = 0;
+
+       while (v_idx--)
+               igb_free_q_vector(adapter, v_idx);
 }
 
 /**
@@ -990,7 +949,6 @@ static void igb_free_q_vectors(struct igb_adapter *adapter)
  */
 static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
 {
-       igb_free_queues(adapter);
        igb_free_q_vectors(adapter);
        igb_reset_interrupt_capability(adapter);
 }
@@ -1001,11 +959,14 @@ static void igb_clear_interrupt_scheme(struct igb_adapter *adapter)
  * Attempt to configure interrupts using the best available
  * capabilities of the hardware and kernel.
  **/
-static int igb_set_interrupt_capability(struct igb_adapter *adapter)
+static void igb_set_interrupt_capability(struct igb_adapter *adapter, bool msix)
 {
        int err;
        int numvecs, i;
 
+       if (!msix)
+               goto msi_only;
+
        /* Number of supported queues. */
        adapter->num_rx_queues = adapter->rss_queues;
        if (adapter->vfs_allocated_count)
@@ -1038,7 +999,7 @@ static int igb_set_interrupt_capability(struct igb_adapter *adapter)
                              adapter->msix_entries,
                              numvecs);
        if (err == 0)
-               goto out;
+               return;
 
        igb_reset_interrupt_capability(adapter);
 
@@ -1068,105 +1029,183 @@ msi_only:
        adapter->num_q_vectors = 1;
        if (!pci_enable_msi(adapter->pdev))
                adapter->flags |= IGB_FLAG_HAS_MSI;
-out:
-       /* Notify the stack of the (possibly) reduced queue counts. */
-       rtnl_lock();
-       netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues);
-       err = netif_set_real_num_rx_queues(adapter->netdev,
-               adapter->num_rx_queues);
-       rtnl_unlock();
-       return err;
+}
+
+static void igb_add_ring(struct igb_ring *ring,
+                        struct igb_ring_container *head)
+{
+       head->ring = ring;
+       head->count++;
 }
 
 /**
- * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * igb_alloc_q_vector - Allocate memory for a single interrupt vector
  * @adapter: board private structure to initialize
+ * @v_count: q_vectors allocated on adapter, used for ring interleaving
+ * @v_idx: index of vector in adapter struct
+ * @txr_count: total number of Tx rings to allocate
+ * @txr_idx: index of first Tx ring to allocate
+ * @rxr_count: total number of Rx rings to allocate
+ * @rxr_idx: index of first Rx ring to allocate
  *
- * We allocate one q_vector per queue interrupt.  If allocation fails we
- * return -ENOMEM.
+ * We allocate one q_vector.  If allocation fails we return -ENOMEM.
  **/
-static int igb_alloc_q_vectors(struct igb_adapter *adapter)
+static int igb_alloc_q_vector(struct igb_adapter *adapter,
+                             int v_count, int v_idx,
+                             int txr_count, int txr_idx,
+                             int rxr_count, int rxr_idx)
 {
        struct igb_q_vector *q_vector;
-       struct e1000_hw *hw = &adapter->hw;
-       int v_idx;
+       struct igb_ring *ring;
+       int ring_count, size;
 
-       for (v_idx = 0; v_idx < adapter->num_q_vectors; v_idx++) {
-               q_vector = kzalloc(sizeof(struct igb_q_vector),
-                                  GFP_KERNEL);
-               if (!q_vector)
-                       goto err_out;
-               q_vector->adapter = adapter;
-               q_vector->itr_register = hw->hw_addr + E1000_EITR(0);
-               q_vector->itr_val = IGB_START_ITR;
-               netif_napi_add(adapter->netdev, &q_vector->napi, igb_poll, 64);
-               adapter->q_vector[v_idx] = q_vector;
+       /* igb only supports 1 Tx and/or 1 Rx queue per vector */
+       if (txr_count > 1 || rxr_count > 1)
+               return -ENOMEM;
+
+       ring_count = txr_count + rxr_count;
+       size = sizeof(struct igb_q_vector) +
+              (sizeof(struct igb_ring) * ring_count);
+
+       /* allocate q_vector and rings */
+       q_vector = kzalloc(size, GFP_KERNEL);
+       if (!q_vector)
+               return -ENOMEM;
+
+       /* initialize NAPI */
+       netif_napi_add(adapter->netdev, &q_vector->napi,
+                      igb_poll, 64);
+
+       /* tie q_vector and adapter together */
+       adapter->q_vector[v_idx] = q_vector;
+       q_vector->adapter = adapter;
+
+       /* initialize work limits */
+       q_vector->tx.work_limit = adapter->tx_work_limit;
+
+       /* initialize ITR configuration */
+       q_vector->itr_register = adapter->hw.hw_addr + E1000_EITR(0);
+       q_vector->itr_val = IGB_START_ITR;
+
+       /* initialize pointer to rings */
+       ring = q_vector->ring;
+
+       if (txr_count) {
+               /* assign generic ring traits */
+               ring->dev = &adapter->pdev->dev;
+               ring->netdev = adapter->netdev;
+
+               /* configure backlink on ring */
+               ring->q_vector = q_vector;
+
+               /* update q_vector Tx values */
+               igb_add_ring(ring, &q_vector->tx);
+
+               /* For 82575, context index must be unique per ring. */
+               if (adapter->hw.mac.type == e1000_82575)
+                       set_bit(IGB_RING_FLAG_TX_CTX_IDX, &ring->flags);
+
+               /* apply Tx specific ring traits */
+               ring->count = adapter->tx_ring_count;
+               ring->queue_index = txr_idx;
+
+               /* assign ring to adapter */
+               adapter->tx_ring[txr_idx] = ring;
+
+               /* push pointer to next ring */
+               ring++;
        }
 
-       return 0;
+       if (rxr_count) {
+               /* assign generic ring traits */
+               ring->dev = &adapter->pdev->dev;
+               ring->netdev = adapter->netdev;
 
-err_out:
-       igb_free_q_vectors(adapter);
-       return -ENOMEM;
-}
+               /* configure backlink on ring */
+               ring->q_vector = q_vector;
 
-static void igb_map_rx_ring_to_vector(struct igb_adapter *adapter,
-                                      int ring_idx, int v_idx)
-{
-       struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+               /* update q_vector Rx values */
+               igb_add_ring(ring, &q_vector->rx);
 
-       q_vector->rx.ring = adapter->rx_ring[ring_idx];
-       q_vector->rx.ring->q_vector = q_vector;
-       q_vector->rx.count++;
-       q_vector->itr_val = adapter->rx_itr_setting;
-       if (q_vector->itr_val && q_vector->itr_val <= 3)
-               q_vector->itr_val = IGB_START_ITR;
-}
+               /* set flag indicating ring supports SCTP checksum offload */
+               if (adapter->hw.mac.type >= e1000_82576)
+                       set_bit(IGB_RING_FLAG_RX_SCTP_CSUM, &ring->flags);
 
-static void igb_map_tx_ring_to_vector(struct igb_adapter *adapter,
-                                      int ring_idx, int v_idx)
-{
-       struct igb_q_vector *q_vector = adapter->q_vector[v_idx];
+               /*
+                * On i350, i210, and i211, loopback VLAN packets
+                * have the tag byte-swapped.
+                * */
+               if (adapter->hw.mac.type >= e1000_i350)
+                       set_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags);
 
-       q_vector->tx.ring = adapter->tx_ring[ring_idx];
-       q_vector->tx.ring->q_vector = q_vector;
-       q_vector->tx.count++;
-       q_vector->itr_val = adapter->tx_itr_setting;
-       q_vector->tx.work_limit = adapter->tx_work_limit;
-       if (q_vector->itr_val && q_vector->itr_val <= 3)
-               q_vector->itr_val = IGB_START_ITR;
+               /* apply Rx specific ring traits */
+               ring->count = adapter->rx_ring_count;
+               ring->queue_index = rxr_idx;
+
+               /* assign ring to adapter */
+               adapter->rx_ring[rxr_idx] = ring;
+       }
+
+       return 0;
 }
 
+
 /**
- * igb_map_ring_to_vector - maps allocated queues to vectors
+ * igb_alloc_q_vectors - Allocate memory for interrupt vectors
+ * @adapter: board private structure to initialize
  *
- * This function maps the recently allocated queues to vectors.
+ * We allocate one q_vector per queue interrupt.  If allocation fails we
+ * return -ENOMEM.
  **/
-static int igb_map_ring_to_vector(struct igb_adapter *adapter)
+static int igb_alloc_q_vectors(struct igb_adapter *adapter)
 {
-       int i;
-       int v_idx = 0;
+       int q_vectors = adapter->num_q_vectors;
+       int rxr_remaining = adapter->num_rx_queues;
+       int txr_remaining = adapter->num_tx_queues;
+       int rxr_idx = 0, txr_idx = 0, v_idx = 0;
+       int err;
 
-       if ((adapter->num_q_vectors < adapter->num_rx_queues) ||
-           (adapter->num_q_vectors < adapter->num_tx_queues))
-               return -ENOMEM;
+       if (q_vectors >= (rxr_remaining + txr_remaining)) {
+               for (; rxr_remaining; v_idx++) {
+                       err = igb_alloc_q_vector(adapter, q_vectors, v_idx,
+                                                0, 0, 1, rxr_idx);
 
-       if (adapter->num_q_vectors >=
-           (adapter->num_rx_queues + adapter->num_tx_queues)) {
-               for (i = 0; i < adapter->num_rx_queues; i++)
-                       igb_map_rx_ring_to_vector(adapter, i, v_idx++);
-               for (i = 0; i < adapter->num_tx_queues; i++)
-                       igb_map_tx_ring_to_vector(adapter, i, v_idx++);
-       } else {
-               for (i = 0; i < adapter->num_rx_queues; i++) {
-                       if (i < adapter->num_tx_queues)
-                               igb_map_tx_ring_to_vector(adapter, i, v_idx);
-                       igb_map_rx_ring_to_vector(adapter, i, v_idx++);
+                       if (err)
+                               goto err_out;
+
+                       /* update counts and index */
+                       rxr_remaining--;
+                       rxr_idx++;
                }
-               for (; i < adapter->num_tx_queues; i++)
-                       igb_map_tx_ring_to_vector(adapter, i, v_idx++);
        }
+
+       for (; v_idx < q_vectors; v_idx++) {
+               int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_idx);
+               int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_idx);
+               err = igb_alloc_q_vector(adapter, q_vectors, v_idx,
+                                        tqpv, txr_idx, rqpv, rxr_idx);
+
+               if (err)
+                       goto err_out;
+
+               /* update counts and index */
+               rxr_remaining -= rqpv;
+               txr_remaining -= tqpv;
+               rxr_idx++;
+               txr_idx++;
+       }
+
        return 0;
+
+err_out:
+       adapter->num_tx_queues = 0;
+       adapter->num_rx_queues = 0;
+       adapter->num_q_vectors = 0;
+
+       while (v_idx--)
+               igb_free_q_vector(adapter, v_idx);
+
+       return -ENOMEM;
 }
 
 /**
@@ -1174,14 +1213,12 @@ static int igb_map_ring_to_vector(struct igb_adapter *adapter)
  *
  * This function initializes the interrupts and allocates all of the queues.
  **/
-static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
+static int igb_init_interrupt_scheme(struct igb_adapter *adapter, bool msix)
 {
        struct pci_dev *pdev = adapter->pdev;
        int err;
 
-       err = igb_set_interrupt_capability(adapter);
-       if (err)
-               return err;
+       igb_set_interrupt_capability(adapter, msix);
 
        err = igb_alloc_q_vectors(adapter);
        if (err) {
@@ -1189,24 +1226,10 @@ static int igb_init_interrupt_scheme(struct igb_adapter *adapter)
                goto err_alloc_q_vectors;
        }
 
-       err = igb_alloc_queues(adapter);
-       if (err) {
-               dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
-               goto err_alloc_queues;
-       }
-
-       err = igb_map_ring_to_vector(adapter);
-       if (err) {
-               dev_err(&pdev->dev, "Invalid q_vector to ring mapping\n");
-               goto err_map_queues;
-       }
-
+       igb_cache_ring_register(adapter);
 
        return 0;
-err_map_queues:
-       igb_free_queues(adapter);
-err_alloc_queues:
-       igb_free_q_vectors(adapter);
+
 err_alloc_q_vectors:
        igb_reset_interrupt_capability(adapter);
        return err;
@@ -1229,29 +1252,17 @@ static int igb_request_irq(struct igb_adapter *adapter)
                if (!err)
                        goto request_done;
                /* fall back to MSI */
-               igb_clear_interrupt_scheme(adapter);
-               if (!pci_enable_msi(pdev))
-                       adapter->flags |= IGB_FLAG_HAS_MSI;
                igb_free_all_tx_resources(adapter);
                igb_free_all_rx_resources(adapter);
-               adapter->num_tx_queues = 1;
-               adapter->num_rx_queues = 1;
-               adapter->num_q_vectors = 1;
-               err = igb_alloc_q_vectors(adapter);
-               if (err) {
-                       dev_err(&pdev->dev,
-                               "Unable to allocate memory for vectors\n");
-                       goto request_done;
-               }
-               err = igb_alloc_queues(adapter);
-               if (err) {
-                       dev_err(&pdev->dev,
-                               "Unable to allocate memory for queues\n");
-                       igb_free_q_vectors(adapter);
+
+               igb_clear_interrupt_scheme(adapter);
+               err = igb_init_interrupt_scheme(adapter, false);
+               if (err)
                        goto request_done;
-               }
+
                igb_setup_all_tx_resources(adapter);
                igb_setup_all_rx_resources(adapter);
+               igb_configure(adapter);
        }
 
        igb_assign_vector(adapter->q_vector[0], 0);
@@ -1587,8 +1598,7 @@ void igb_reset(struct igb_adapter *adapter)
        struct e1000_hw *hw = &adapter->hw;
        struct e1000_mac_info *mac = &hw->mac;
        struct e1000_fc_info *fc = &hw->fc;
-       u32 pba = 0, tx_space, min_tx_space, min_rx_space;
-       u16 hwm;
+       u32 pba = 0, tx_space, min_tx_space, min_rx_space, hwm;
 
        /* Repartition Pba for greater than 9k mtu
         * To take effect CTRL.RST is required.
@@ -1663,7 +1673,7 @@ void igb_reset(struct igb_adapter *adapter)
        hwm = min(((pba << 10) * 9 / 10),
                        ((pba << 10) - 2 * adapter->max_frame_size));
 
-       fc->high_water = hwm & 0xFFF0;  /* 16-byte granularity */
+       fc->high_water = hwm & 0xFFFFFFF0;      /* 16-byte granularity */
        fc->low_water = fc->high_water - 16;
        fc->pause_time = 0xFFFF;
        fc->send_xon = 1;
@@ -1706,10 +1716,8 @@ void igb_reset(struct igb_adapter *adapter)
        /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
        wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE);
 
-#ifdef CONFIG_IGB_PTP
        /* Re-enable PTP, where applicable. */
        igb_ptp_reset(adapter);
-#endif /* CONFIG_IGB_PTP */
 
        igb_get_phy_info(hw);
 }
@@ -1783,58 +1791,34 @@ static const struct net_device_ops igb_netdev_ops = {
 void igb_set_fw_version(struct igb_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
-       u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset;
-       u16 major, build, patch, fw_version;
-       u32 etrack_id;
-
-       hw->nvm.ops.read(hw, 5, 1, &fw_version);
-       if (adapter->hw.mac.type != e1000_i211) {
-               hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh);
-               hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl);
-               etrack_id = (eeprom_verh << IGB_ETRACK_SHIFT) | eeprom_verl;
-
-               /* combo image version needs to be found */
-               hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
-               if ((comb_offset != 0x0) &&
-                   (comb_offset != IGB_NVM_VER_INVALID)) {
-                       hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
-                                        + 1), 1, &comb_verh);
-                       hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
-                                        1, &comb_verl);
-
-                       /* Only display Option Rom if it exists and is valid */
-                       if ((comb_verh && comb_verl) &&
-                           ((comb_verh != IGB_NVM_VER_INVALID) &&
-                            (comb_verl != IGB_NVM_VER_INVALID))) {
-                               major = comb_verl >> IGB_COMB_VER_SHFT;
-                               build = (comb_verl << IGB_COMB_VER_SHFT) |
-                                       (comb_verh >> IGB_COMB_VER_SHFT);
-                               patch = comb_verh & IGB_COMB_VER_MASK;
-                               snprintf(adapter->fw_version,
-                                        sizeof(adapter->fw_version),
-                                        "%d.%d%d, 0x%08x, %d.%d.%d",
-                                        (fw_version & IGB_MAJOR_MASK) >>
-                                        IGB_MAJOR_SHIFT,
-                                        (fw_version & IGB_MINOR_MASK) >>
-                                        IGB_MINOR_SHIFT,
-                                        (fw_version & IGB_BUILD_MASK),
-                                        etrack_id, major, build, patch);
-                               goto out;
-                       }
-               }
-               snprintf(adapter->fw_version, sizeof(adapter->fw_version),
-                        "%d.%d%d, 0x%08x",
-                        (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT,
-                        (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT,
-                        (fw_version & IGB_BUILD_MASK), etrack_id);
-       } else {
+       struct e1000_fw_version fw;
+
+       igb_get_fw_version(hw, &fw);
+
+       switch (hw->mac.type) {
+       case e1000_i211:
                snprintf(adapter->fw_version, sizeof(adapter->fw_version),
-                        "%d.%d%d",
-                        (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT,
-                        (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT,
-                        (fw_version & IGB_BUILD_MASK));
+                        "%2d.%2d-%d",
+                        fw.invm_major, fw.invm_minor, fw.invm_img_type);
+               break;
+
+       default:
+               /* if option is rom valid, display its version too */
+               if (fw.or_valid) {
+                       snprintf(adapter->fw_version,
+                                sizeof(adapter->fw_version),
+                                "%d.%d, 0x%08x, %d.%d.%d",
+                                fw.eep_major, fw.eep_minor, fw.etrack_id,
+                                fw.or_major, fw.or_build, fw.or_patch);
+               /* no option rom */
+               } else {
+                       snprintf(adapter->fw_version,
+                                sizeof(adapter->fw_version),
+                                "%d.%d, 0x%08x",
+                                fw.eep_major, fw.eep_minor, fw.etrack_id);
+               }
+               break;
        }
-out:
        return;
 }
 
@@ -1849,8 +1833,7 @@ out:
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  **/
-static int __devinit igb_probe(struct pci_dev *pdev,
-                              const struct pci_device_id *ent)
+static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct igb_adapter *adapter;
@@ -1861,7 +1844,6 @@ static int __devinit igb_probe(struct pci_dev *pdev,
        const struct e1000_info *ei = igb_info_tbl[ent->driver_data];
        unsigned long mmio_start, mmio_len;
        int err, pci_using_dac;
-       u16 eeprom_apme_mask = IGB_EEPROM_APME;
        u8 part_str[E1000_PBANUM_LENGTH];
 
        /* Catch broken hardware that put the wrong VF device ID in
@@ -2069,28 +2051,27 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 
        igb_validate_mdi_setting(hw);
 
-       /* Initial Wake on LAN setting If APM wake is enabled in the EEPROM,
-        * enable the ACPI Magic Packet filter
-        */
-
+       /* By default, support wake on port A */
        if (hw->bus.func == 0)
-               hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
-       else if (hw->mac.type >= e1000_82580)
+               adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
+
+       /* Check the NVM for wake support on non-port A ports */
+       if (hw->mac.type >= e1000_82580)
                hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
                                 NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
                                 &eeprom_data);
        else if (hw->bus.func == 1)
                hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_B, 1, &eeprom_data);
 
-       if (eeprom_data & eeprom_apme_mask)
-               adapter->eeprom_wol |= E1000_WUFC_MAG;
+       if (eeprom_data & IGB_EEPROM_APME)
+               adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
 
        /* now that we have the eeprom settings, apply the special cases where
         * the eeprom may be wrong or the board simply won't support wake on
         * lan on a particular port */
        switch (pdev->device) {
        case E1000_DEV_ID_82575GB_QUAD_COPPER:
-               adapter->eeprom_wol = 0;
+               adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
                break;
        case E1000_DEV_ID_82575EB_FIBER_SERDES:
        case E1000_DEV_ID_82576_FIBER:
@@ -2098,24 +2079,38 @@ static int __devinit igb_probe(struct pci_dev *pdev,
                /* Wake events only supported on port A for dual fiber
                 * regardless of eeprom setting */
                if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1)
-                       adapter->eeprom_wol = 0;
+                       adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
                break;
        case E1000_DEV_ID_82576_QUAD_COPPER:
        case E1000_DEV_ID_82576_QUAD_COPPER_ET2:
                /* if quad port adapter, disable WoL on all but port A */
                if (global_quad_port_a != 0)
-                       adapter->eeprom_wol = 0;
+                       adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
                else
                        adapter->flags |= IGB_FLAG_QUAD_PORT_A;
                /* Reset for multiple quad port adapters */
                if (++global_quad_port_a == 4)
                        global_quad_port_a = 0;
                break;
+       default:
+               /* If the device can't wake, don't set software support */
+               if (!device_can_wakeup(&adapter->pdev->dev))
+                       adapter->flags &= ~IGB_FLAG_WOL_SUPPORTED;
        }
 
        /* initialize the wol settings based on the eeprom settings */
-       adapter->wol = adapter->eeprom_wol;
-       device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+       if (adapter->flags & IGB_FLAG_WOL_SUPPORTED)
+               adapter->wol |= E1000_WUFC_MAG;
+
+       /* Some vendors want WoL disabled by default, but still supported */
+       if ((hw->mac.type == e1000_i350) &&
+           (pdev->subsystem_vendor == PCI_VENDOR_ID_HP)) {
+               adapter->flags |= IGB_FLAG_WOL_SUPPORTED;
+               adapter->wol = 0;
+       }
+
+       device_set_wakeup_enable(&adapter->pdev->dev,
+                                adapter->flags & IGB_FLAG_WOL_SUPPORTED);
 
        /* reset the hardware with the new settings */
        igb_reset(adapter);
@@ -2141,10 +2136,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
 
 #endif
 
-#ifdef CONFIG_IGB_PTP
        /* do hw tstamp init after resetting */
        igb_ptp_init(adapter);
-#endif /* CONFIG_IGB_PTP */
 
        dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
        /* print bus type/speed/width info */
@@ -2212,16 +2205,14 @@ err_dma:
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  **/
-static void __devexit igb_remove(struct pci_dev *pdev)
+static void igb_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct igb_adapter *adapter = netdev_priv(netdev);
        struct e1000_hw *hw = &adapter->hw;
 
        pm_runtime_get_noresume(&pdev->dev);
-#ifdef CONFIG_IGB_PTP
        igb_ptp_stop(adapter);
-#endif /* CONFIG_IGB_PTP */
 
        /*
         * The watchdog timer may be rescheduled, so explicitly
@@ -2294,7 +2285,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
  * mor expensive time wise to disable SR-IOV than it is to allocate and free
  * the memory for the VFs.
  **/
-static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
+static void igb_probe_vfs(struct igb_adapter *adapter)
 {
 #ifdef CONFIG_PCI_IOV
        struct pci_dev *pdev = adapter->pdev;
@@ -2355,7 +2346,7 @@ out:
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  **/
-static int __devinit igb_sw_init(struct igb_adapter *adapter)
+static int igb_sw_init(struct igb_adapter *adapter)
 {
        struct e1000_hw *hw = &adapter->hw;
        struct net_device *netdev = adapter->netdev;
@@ -2461,7 +2452,7 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
                                GFP_ATOMIC);
 
        /* This call may decrease the number of queues */
-       if (igb_init_interrupt_scheme(adapter)) {
+       if (igb_init_interrupt_scheme(adapter, true)) {
                dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
                return -ENOMEM;
        }
@@ -2531,6 +2522,17 @@ static int __igb_open(struct net_device *netdev, bool resuming)
        if (err)
                goto err_req_irq;
 
+       /* Notify the stack of the actual queue counts. */
+       err = netif_set_real_num_tx_queues(adapter->netdev,
+                                          adapter->num_tx_queues);
+       if (err)
+               goto err_set_queues;
+
+       err = netif_set_real_num_rx_queues(adapter->netdev,
+                                          adapter->num_rx_queues);
+       if (err)
+               goto err_set_queues;
+
        /* From here on the code is the same as igb_up() */
        clear_bit(__IGB_DOWN, &adapter->state);
 
@@ -2560,6 +2562,8 @@ static int __igb_open(struct net_device *netdev, bool resuming)
 
        return 0;
 
+err_set_queues:
+       igb_free_irq(adapter);
 err_req_irq:
        igb_release_hw_control(adapter);
        igb_power_down_link(adapter);
@@ -2637,10 +2641,8 @@ int igb_setup_tx_resources(struct igb_ring *tx_ring)
        tx_ring->size = tx_ring->count * sizeof(union e1000_adv_tx_desc);
        tx_ring->size = ALIGN(tx_ring->size, 4096);
 
-       tx_ring->desc = dma_alloc_coherent(dev,
-                                          tx_ring->size,
-                                          &tx_ring->dma,
-                                          GFP_KERNEL);
+       tx_ring->desc = dma_alloc_coherent(dev, tx_ring->size,
+                                          &tx_ring->dma, GFP_KERNEL);
        if (!tx_ring->desc)
                goto err;
 
@@ -2777,18 +2779,16 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
        if (!rx_ring->rx_buffer_info)
                goto err;
 
-
        /* Round up to nearest 4K */
        rx_ring->size = rx_ring->count * sizeof(union e1000_adv_rx_desc);
        rx_ring->size = ALIGN(rx_ring->size, 4096);
 
-       rx_ring->desc = dma_alloc_coherent(dev,
-                                          rx_ring->size,
-                                          &rx_ring->dma,
-                                          GFP_KERNEL);
+       rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,
+                                          &rx_ring->dma, GFP_KERNEL);
        if (!rx_ring->desc)
                goto err;
 
+       rx_ring->next_to_alloc = 0;
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
 
@@ -2893,18 +2893,21 @@ static void igb_setup_mrqc(struct igb_adapter *adapter)
 
        /* Don't need to set TUOFL or IPOFL, they default to 1 */
        wr32(E1000_RXCSUM, rxcsum);
-       /*
-        * Generate RSS hash based on TCP port numbers and/or
-        * IPv4/v6 src and dst addresses since UDP cannot be
-        * hashed reliably due to IP fragmentation
-        */
 
+       /* Generate RSS hash based on packet types, TCP/UDP
+        * port numbers and/or IPv4/v6 src and dst addresses
+        */
        mrqc = E1000_MRQC_RSS_FIELD_IPV4 |
               E1000_MRQC_RSS_FIELD_IPV4_TCP |
               E1000_MRQC_RSS_FIELD_IPV6 |
               E1000_MRQC_RSS_FIELD_IPV6_TCP |
               E1000_MRQC_RSS_FIELD_IPV6_TCP_EX;
 
+       if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV4_UDP)
+               mrqc |= E1000_MRQC_RSS_FIELD_IPV4_UDP;
+       if (adapter->flags & IGB_FLAG_RSS_FIELD_IPV6_UDP)
+               mrqc |= E1000_MRQC_RSS_FIELD_IPV6_UDP;
+
        /* If VMDq is enabled then we set the appropriate mode for that, else
         * we default to RSS so that an RSS hash is calculated per packet even
         * if we are only using one queue */
@@ -3106,16 +3109,10 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
 
        /* set descriptor configuration */
        srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
-#if (PAGE_SIZE / 2) > IGB_RXBUFFER_16384
-       srrctl |= IGB_RXBUFFER_16384 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-#else
-       srrctl |= (PAGE_SIZE / 2) >> E1000_SRRCTL_BSIZEPKT_SHIFT;
-#endif
-       srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
-#ifdef CONFIG_IGB_PTP
+       srrctl |= IGB_RX_BUFSZ >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+       srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
        if (hw->mac.type >= e1000_82580)
                srrctl |= E1000_SRRCTL_TIMESTAMP;
-#endif /* CONFIG_IGB_PTP */
        /* Only set Drop Enable if we are supporting multiple queues */
        if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1)
                srrctl |= E1000_SRRCTL_DROP_EN;
@@ -3305,36 +3302,27 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
        unsigned long size;
        u16 i;
 
+       if (rx_ring->skb)
+               dev_kfree_skb(rx_ring->skb);
+       rx_ring->skb = NULL;
+
        if (!rx_ring->rx_buffer_info)
                return;
 
        /* Free all the Rx ring sk_buffs */
        for (i = 0; i < rx_ring->count; i++) {
                struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
-               if (buffer_info->dma) {
-                       dma_unmap_single(rx_ring->dev,
-                                        buffer_info->dma,
-                                        IGB_RX_HDR_LEN,
-                                        DMA_FROM_DEVICE);
-                       buffer_info->dma = 0;
-               }
 
-               if (buffer_info->skb) {
-                       dev_kfree_skb(buffer_info->skb);
-                       buffer_info->skb = NULL;
-               }
-               if (buffer_info->page_dma) {
-                       dma_unmap_page(rx_ring->dev,
-                                      buffer_info->page_dma,
-                                      PAGE_SIZE / 2,
-                                      DMA_FROM_DEVICE);
-                       buffer_info->page_dma = 0;
-               }
-               if (buffer_info->page) {
-                       put_page(buffer_info->page);
-                       buffer_info->page = NULL;
-                       buffer_info->page_offset = 0;
-               }
+               if (!buffer_info->page)
+                       continue;
+
+               dma_unmap_page(rx_ring->dev,
+                              buffer_info->dma,
+                              PAGE_SIZE,
+                              DMA_FROM_DEVICE);
+               __free_page(buffer_info->page);
+
+               buffer_info->page = NULL;
        }
 
        size = sizeof(struct igb_rx_buffer) * rx_ring->count;
@@ -3343,6 +3331,7 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
        /* Zero out the descriptor ring */
        memset(rx_ring->desc, 0, rx_ring->size);
 
+       rx_ring->next_to_alloc = 0;
        rx_ring->next_to_clean = 0;
        rx_ring->next_to_use = 0;
 }
@@ -4028,6 +4017,9 @@ static int igb_tso(struct igb_ring *tx_ring,
        u32 vlan_macip_lens, type_tucmd;
        u32 mss_l4len_idx, l4len;
 
+       if (skb->ip_summed != CHECKSUM_PARTIAL)
+               return 0;
+
        if (!skb_is_gso(skb))
                return 0;
 
@@ -4148,26 +4140,32 @@ static void igb_tx_csum(struct igb_ring *tx_ring, struct igb_tx_buffer *first)
        igb_tx_ctxtdesc(tx_ring, vlan_macip_lens, type_tucmd, mss_l4len_idx);
 }
 
-static __le32 igb_tx_cmd_type(u32 tx_flags)
+#define IGB_SET_FLAG(_input, _flag, _result) \
+       ((_flag <= _result) ? \
+        ((u32)(_input & _flag) * (_result / _flag)) : \
+        ((u32)(_input & _flag) / (_flag / _result)))
+
+static u32 igb_tx_cmd_type(struct sk_buff *skb, u32 tx_flags)
 {
        /* set type for advanced descriptor with frame checksum insertion */
-       __le32 cmd_type = cpu_to_le32(E1000_ADVTXD_DTYP_DATA |
-                                     E1000_ADVTXD_DCMD_IFCS |
-                                     E1000_ADVTXD_DCMD_DEXT);
+       u32 cmd_type = E1000_ADVTXD_DTYP_DATA |
+                      E1000_ADVTXD_DCMD_DEXT |
+                      E1000_ADVTXD_DCMD_IFCS;
 
        /* set HW vlan bit if vlan is present */
-       if (tx_flags & IGB_TX_FLAGS_VLAN)
-               cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_VLE);
-
-#ifdef CONFIG_IGB_PTP
-       /* set timestamp bit if present */
-       if (unlikely(tx_flags & IGB_TX_FLAGS_TSTAMP))
-               cmd_type |= cpu_to_le32(E1000_ADVTXD_MAC_TSTAMP);
-#endif /* CONFIG_IGB_PTP */
+       cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_VLAN,
+                                (E1000_ADVTXD_DCMD_VLE));
 
        /* set segmentation bits for TSO */
-       if (tx_flags & IGB_TX_FLAGS_TSO)
-               cmd_type |= cpu_to_le32(E1000_ADVTXD_DCMD_TSE);
+       cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSO,
+                                (E1000_ADVTXD_DCMD_TSE));
+
+       /* set timestamp bit if present */
+       cmd_type |= IGB_SET_FLAG(tx_flags, IGB_TX_FLAGS_TSTAMP,
+                                (E1000_ADVTXD_MAC_TSTAMP));
+
+       /* insert frame checksum */
+       cmd_type ^= IGB_SET_FLAG(skb->no_fcs, 1, E1000_ADVTXD_DCMD_IFCS);
 
        return cmd_type;
 }
@@ -4178,19 +4176,19 @@ static void igb_tx_olinfo_status(struct igb_ring *tx_ring,
 {
        u32 olinfo_status = paylen << E1000_ADVTXD_PAYLEN_SHIFT;
 
-       /* 82575 requires a unique index per ring if any offload is enabled */
-       if ((tx_flags & (IGB_TX_FLAGS_CSUM | IGB_TX_FLAGS_VLAN)) &&
-           test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
+       /* 82575 requires a unique index per ring */
+       if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags))
                olinfo_status |= tx_ring->reg_idx << 4;
 
        /* insert L4 checksum */
-       if (tx_flags & IGB_TX_FLAGS_CSUM) {
-               olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
+       olinfo_status |= IGB_SET_FLAG(tx_flags,
+                                     IGB_TX_FLAGS_CSUM,
+                                     (E1000_TXD_POPTS_TXSM << 8));
 
-               /* insert IPv4 checksum */
-               if (tx_flags & IGB_TX_FLAGS_IPV4)
-                       olinfo_status |= E1000_TXD_POPTS_IXSM << 8;
-       }
+       /* insert IPv4 checksum */
+       olinfo_status |= IGB_SET_FLAG(tx_flags,
+                                     IGB_TX_FLAGS_IPV4,
+                                     (E1000_TXD_POPTS_IXSM << 8));
 
        tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
 }
@@ -4209,33 +4207,37 @@ static void igb_tx_map(struct igb_ring *tx_ring,
        struct sk_buff *skb = first->skb;
        struct igb_tx_buffer *tx_buffer;
        union e1000_adv_tx_desc *tx_desc;
+       struct skb_frag_struct *frag;
        dma_addr_t dma;
-       struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
-       unsigned int data_len = skb->data_len;
-       unsigned int size = skb_headlen(skb);
-       unsigned int paylen = skb->len - hdr_len;
-       __le32 cmd_type;
+       unsigned int data_len, size;
        u32 tx_flags = first->tx_flags;
+       u32 cmd_type = igb_tx_cmd_type(skb, tx_flags);
        u16 i = tx_ring->next_to_use;
 
        tx_desc = IGB_TX_DESC(tx_ring, i);
 
-       igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, paylen);
-       cmd_type = igb_tx_cmd_type(tx_flags);
+       igb_tx_olinfo_status(tx_ring, tx_desc, tx_flags, skb->len - hdr_len);
+
+       size = skb_headlen(skb);
+       data_len = skb->data_len;
 
        dma = dma_map_single(tx_ring->dev, skb->data, size, DMA_TO_DEVICE);
-       if (dma_mapping_error(tx_ring->dev, dma))
-               goto dma_error;
 
-       /* record length, and DMA address */
-       dma_unmap_len_set(first, len, size);
-       dma_unmap_addr_set(first, dma, dma);
-       tx_desc->read.buffer_addr = cpu_to_le64(dma);
+       tx_buffer = first;
+
+       for (frag = &skb_shinfo(skb)->frags[0];; frag++) {
+               if (dma_mapping_error(tx_ring->dev, dma))
+                       goto dma_error;
+
+               /* record length, and DMA address */
+               dma_unmap_len_set(tx_buffer, len, size);
+               dma_unmap_addr_set(tx_buffer, dma, dma);
+
+               tx_desc->read.buffer_addr = cpu_to_le64(dma);
 
-       for (;;) {
                while (unlikely(size > IGB_MAX_DATA_PER_TXD)) {
                        tx_desc->read.cmd_type_len =
-                               cmd_type | cpu_to_le32(IGB_MAX_DATA_PER_TXD);
+                               cpu_to_le32(cmd_type ^ IGB_MAX_DATA_PER_TXD);
 
                        i++;
                        tx_desc++;
@@ -4243,18 +4245,18 @@ static void igb_tx_map(struct igb_ring *tx_ring,
                                tx_desc = IGB_TX_DESC(tx_ring, 0);
                                i = 0;
                        }
+                       tx_desc->read.olinfo_status = 0;
 
                        dma += IGB_MAX_DATA_PER_TXD;
                        size -= IGB_MAX_DATA_PER_TXD;
 
-                       tx_desc->read.olinfo_status = 0;
                        tx_desc->read.buffer_addr = cpu_to_le64(dma);
                }
 
                if (likely(!data_len))
                        break;
 
-               tx_desc->read.cmd_type_len = cmd_type | cpu_to_le32(size);
+               tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type ^ size);
 
                i++;
                tx_desc++;
@@ -4262,32 +4264,22 @@ static void igb_tx_map(struct igb_ring *tx_ring,
                        tx_desc = IGB_TX_DESC(tx_ring, 0);
                        i = 0;
                }
+               tx_desc->read.olinfo_status = 0;
 
                size = skb_frag_size(frag);
                data_len -= size;
 
                dma = skb_frag_dma_map(tx_ring->dev, frag, 0,
-                                  size, DMA_TO_DEVICE);
-               if (dma_mapping_error(tx_ring->dev, dma))
-                       goto dma_error;
+                                      size, DMA_TO_DEVICE);
 
                tx_buffer = &tx_ring->tx_buffer_info[i];
-               dma_unmap_len_set(tx_buffer, len, size);
-               dma_unmap_addr_set(tx_buffer, dma, dma);
-
-               tx_desc->read.olinfo_status = 0;
-               tx_desc->read.buffer_addr = cpu_to_le64(dma);
-
-               frag++;
        }
 
-       netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
-
        /* write last descriptor with RS and EOP bits */
-       cmd_type |= cpu_to_le32(size) | cpu_to_le32(IGB_TXD_DCMD);
-       if (unlikely(skb->no_fcs))
-               cmd_type &= ~(cpu_to_le32(E1000_ADVTXD_DCMD_IFCS));
-       tx_desc->read.cmd_type_len = cmd_type;
+       cmd_type |= size | IGB_TXD_DCMD;
+       tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+
+       netdev_tx_sent_queue(txring_txq(tx_ring), first->bytecount);
 
        /* set the timestamp */
        first->time_stamp = jiffies;
@@ -4372,9 +4364,7 @@ static inline int igb_maybe_stop_tx(struct igb_ring *tx_ring, const u16 size)
 netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
                                struct igb_ring *tx_ring)
 {
-#ifdef CONFIG_IGB_PTP
        struct igb_adapter *adapter = netdev_priv(tx_ring->netdev);
-#endif /* CONFIG_IGB_PTP */
        struct igb_tx_buffer *first;
        int tso;
        u32 tx_flags = 0;
@@ -4397,7 +4387,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
        first->bytecount = skb->len;
        first->gso_segs = 1;
 
-#ifdef CONFIG_IGB_PTP
        if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
                     !(adapter->ptp_tx_skb))) {
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
@@ -4407,7 +4396,6 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
                if (adapter->hw.mac.type == e1000_82576)
                        schedule_work(&adapter->ptp_tx_work);
        }
-#endif /* CONFIG_IGB_PTP */
 
        if (vlan_tx_tag_present(skb)) {
                tx_flags |= IGB_TX_FLAGS_VLAN;
@@ -4467,10 +4455,11 @@ static netdev_tx_t igb_xmit_frame(struct sk_buff *skb,
         * The minimum packet size with TCTL.PSP set is 17 so pad the skb
         * in order to meet this minimum size requirement.
         */
-       if (skb->len < 17) {
-               if (skb_padto(skb, 17))
+       if (unlikely(skb->len < 17)) {
+               if (skb_pad(skb, 17 - skb->len))
                        return NETDEV_TX_OK;
                skb->len = 17;
+               skb_set_tail_pointer(skb, 17);
        }
 
        return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
@@ -4800,7 +4789,6 @@ static irqreturn_t igb_msix_other(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
-#ifdef CONFIG_IGB_PTP
        if (icr & E1000_ICR_TS) {
                u32 tsicr = rd32(E1000_TSICR);
 
@@ -4811,7 +4799,6 @@ static irqreturn_t igb_msix_other(int irq, void *data)
                        schedule_work(&adapter->ptp_tx_work);
                }
        }
-#endif /* CONFIG_IGB_PTP */
 
        wr32(E1000_EIMS, adapter->eims_other);
 
@@ -4851,45 +4838,63 @@ static irqreturn_t igb_msix_ring(int irq, void *data)
 }
 
 #ifdef CONFIG_IGB_DCA
+static void igb_update_tx_dca(struct igb_adapter *adapter,
+                             struct igb_ring *tx_ring,
+                             int cpu)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 txctrl = dca3_get_tag(tx_ring->dev, cpu);
+
+       if (hw->mac.type != e1000_82575)
+               txctrl <<= E1000_DCA_TXCTRL_CPUID_SHIFT;
+
+       /*
+        * We can enable relaxed ordering for reads, but not writes when
+        * DCA is enabled.  This is due to a known issue in some chipsets
+        * which will cause the DCA tag to be cleared.
+        */
+       txctrl |= E1000_DCA_TXCTRL_DESC_RRO_EN |
+                 E1000_DCA_TXCTRL_DATA_RRO_EN |
+                 E1000_DCA_TXCTRL_DESC_DCA_EN;
+
+       wr32(E1000_DCA_TXCTRL(tx_ring->reg_idx), txctrl);
+}
+
+static void igb_update_rx_dca(struct igb_adapter *adapter,
+                             struct igb_ring *rx_ring,
+                             int cpu)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u32 rxctrl = dca3_get_tag(&adapter->pdev->dev, cpu);
+
+       if (hw->mac.type != e1000_82575)
+               rxctrl <<= E1000_DCA_RXCTRL_CPUID_SHIFT;
+
+       /*
+        * We can enable relaxed ordering for reads, but not writes when
+        * DCA is enabled.  This is due to a known issue in some chipsets
+        * which will cause the DCA tag to be cleared.
+        */
+       rxctrl |= E1000_DCA_RXCTRL_DESC_RRO_EN |
+                 E1000_DCA_RXCTRL_DESC_DCA_EN;
+
+       wr32(E1000_DCA_RXCTRL(rx_ring->reg_idx), rxctrl);
+}
+
 static void igb_update_dca(struct igb_q_vector *q_vector)
 {
        struct igb_adapter *adapter = q_vector->adapter;
-       struct e1000_hw *hw = &adapter->hw;
        int cpu = get_cpu();
 
        if (q_vector->cpu == cpu)
                goto out_no_update;
 
-       if (q_vector->tx.ring) {
-               int q = q_vector->tx.ring->reg_idx;
-               u32 dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
-               if (hw->mac.type == e1000_82575) {
-                       dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK;
-                       dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-               } else {
-                       dca_txctrl &= ~E1000_DCA_TXCTRL_CPUID_MASK_82576;
-                       dca_txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
-                                     E1000_DCA_TXCTRL_CPUID_SHIFT;
-               }
-               dca_txctrl |= E1000_DCA_TXCTRL_DESC_DCA_EN;
-               wr32(E1000_DCA_TXCTRL(q), dca_txctrl);
-       }
-       if (q_vector->rx.ring) {
-               int q = q_vector->rx.ring->reg_idx;
-               u32 dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
-               if (hw->mac.type == e1000_82575) {
-                       dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK;
-                       dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu);
-               } else {
-                       dca_rxctrl &= ~E1000_DCA_RXCTRL_CPUID_MASK_82576;
-                       dca_rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu) <<
-                                     E1000_DCA_RXCTRL_CPUID_SHIFT;
-               }
-               dca_rxctrl |= E1000_DCA_RXCTRL_DESC_DCA_EN;
-               dca_rxctrl |= E1000_DCA_RXCTRL_HEAD_DCA_EN;
-               dca_rxctrl |= E1000_DCA_RXCTRL_DATA_DCA_EN;
-               wr32(E1000_DCA_RXCTRL(q), dca_rxctrl);
-       }
+       if (q_vector->tx.ring)
+               igb_update_tx_dca(adapter, q_vector->tx.ring, cpu);
+
+       if (q_vector->rx.ring)
+               igb_update_rx_dca(adapter, q_vector->rx.ring, cpu);
+
        q_vector->cpu = cpu;
 out_no_update:
        put_cpu();
@@ -5545,7 +5550,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
-#ifdef CONFIG_IGB_PTP
        if (icr & E1000_ICR_TS) {
                u32 tsicr = rd32(E1000_TSICR);
 
@@ -5556,7 +5560,6 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
                        schedule_work(&adapter->ptp_tx_work);
                }
        }
-#endif /* CONFIG_IGB_PTP */
 
        napi_schedule(&q_vector->napi);
 
@@ -5599,7 +5602,6 @@ static irqreturn_t igb_intr(int irq, void *data)
                        mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
-#ifdef CONFIG_IGB_PTP
        if (icr & E1000_ICR_TS) {
                u32 tsicr = rd32(E1000_TSICR);
 
@@ -5610,7 +5612,6 @@ static irqreturn_t igb_intr(int irq, void *data)
                        schedule_work(&adapter->ptp_tx_work);
                }
        }
-#endif /* CONFIG_IGB_PTP */
 
        napi_schedule(&q_vector->napi);
 
@@ -5840,6 +5841,181 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
        return !!budget;
 }
 
+/**
+ * igb_reuse_rx_page - page flip buffer and store it back on the ring
+ * @rx_ring: rx descriptor ring to store buffers on
+ * @old_buff: donor buffer to have page reused
+ *
+ * Synchronizes page for reuse by the adapter
+ **/
+static void igb_reuse_rx_page(struct igb_ring *rx_ring,
+                             struct igb_rx_buffer *old_buff)
+{
+       struct igb_rx_buffer *new_buff;
+       u16 nta = rx_ring->next_to_alloc;
+
+       new_buff = &rx_ring->rx_buffer_info[nta];
+
+       /* update, and store next to alloc */
+       nta++;
+       rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0;
+
+       /* transfer page from old buffer to new buffer */
+       memcpy(new_buff, old_buff, sizeof(struct igb_rx_buffer));
+
+       /* sync the buffer for use by the device */
+       dma_sync_single_range_for_device(rx_ring->dev, old_buff->dma,
+                                        old_buff->page_offset,
+                                        IGB_RX_BUFSZ,
+                                        DMA_FROM_DEVICE);
+}
+
+/**
+ * igb_add_rx_frag - Add contents of Rx buffer to sk_buff
+ * @rx_ring: rx descriptor ring to transact packets on
+ * @rx_buffer: buffer containing page to add
+ * @rx_desc: descriptor containing length of buffer written by hardware
+ * @skb: sk_buff to place the data into
+ *
+ * This function will add the data contained in rx_buffer->page to the skb.
+ * This is done either through a direct copy if the data in the buffer is
+ * less than the skb header size, otherwise it will just attach the page as
+ * a frag to the skb.
+ *
+ * The function will then update the page offset if necessary and return
+ * true if the buffer can be reused by the adapter.
+ **/
+static bool igb_add_rx_frag(struct igb_ring *rx_ring,
+                           struct igb_rx_buffer *rx_buffer,
+                           union e1000_adv_rx_desc *rx_desc,
+                           struct sk_buff *skb)
+{
+       struct page *page = rx_buffer->page;
+       unsigned int size = le16_to_cpu(rx_desc->wb.upper.length);
+
+       if ((size <= IGB_RX_HDR_LEN) && !skb_is_nonlinear(skb)) {
+               unsigned char *va = page_address(page) + rx_buffer->page_offset;
+
+               if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+                       igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
+                       va += IGB_TS_HDR_LEN;
+                       size -= IGB_TS_HDR_LEN;
+               }
+
+               memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
+
+               /* we can reuse buffer as-is, just make sure it is local */
+               if (likely(page_to_nid(page) == numa_node_id()))
+                       return true;
+
+               /* this page cannot be reused so discard it */
+               put_page(page);
+               return false;
+       }
+
+       skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
+                       rx_buffer->page_offset, size, IGB_RX_BUFSZ);
+
+       /* avoid re-using remote pages */
+       if (unlikely(page_to_nid(page) != numa_node_id()))
+               return false;
+
+#if (PAGE_SIZE < 8192)
+       /* if we are only owner of page we can reuse it */
+       if (unlikely(page_count(page) != 1))
+               return false;
+
+       /* flip page offset to other buffer */
+       rx_buffer->page_offset ^= IGB_RX_BUFSZ;
+
+       /*
+        * since we are the only owner of the page and we need to
+        * increment it, just set the value to 2 in order to avoid
+        * an unnecessary locked operation
+        */
+       atomic_set(&page->_count, 2);
+#else
+       /* move offset up to the next cache line */
+       rx_buffer->page_offset += SKB_DATA_ALIGN(size);
+
+       if (rx_buffer->page_offset > (PAGE_SIZE - IGB_RX_BUFSZ))
+               return false;
+
+       /* bump ref count on page before it is given to the stack */
+       get_page(page);
+#endif
+
+       return true;
+}
+
+static struct sk_buff *igb_fetch_rx_buffer(struct igb_ring *rx_ring,
+                                          union e1000_adv_rx_desc *rx_desc,
+                                          struct sk_buff *skb)
+{
+       struct igb_rx_buffer *rx_buffer;
+       struct page *page;
+
+       rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
+
+       /*
+        * This memory barrier is needed to keep us from reading
+        * any other fields out of the rx_desc until we know the
+        * RXD_STAT_DD bit is set
+        */
+       rmb();
+
+       page = rx_buffer->page;
+       prefetchw(page);
+
+       if (likely(!skb)) {
+               void *page_addr = page_address(page) +
+                                 rx_buffer->page_offset;
+
+               /* prefetch first cache line of first page */
+               prefetch(page_addr);
+#if L1_CACHE_BYTES < 128
+               prefetch(page_addr + L1_CACHE_BYTES);
+#endif
+
+               /* allocate a skb to store the frags */
+               skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+                                               IGB_RX_HDR_LEN);
+               if (unlikely(!skb)) {
+                       rx_ring->rx_stats.alloc_failed++;
+                       return NULL;
+               }
+
+               /*
+                * we will be copying header into skb->data in
+                * pskb_may_pull so it is in our interest to prefetch
+                * it now to avoid a possible cache miss
+                */
+               prefetchw(skb->data);
+       }
+
+       /* we are reusing so sync this buffer for CPU use */
+       dma_sync_single_range_for_cpu(rx_ring->dev,
+                                     rx_buffer->dma,
+                                     rx_buffer->page_offset,
+                                     IGB_RX_BUFSZ,
+                                     DMA_FROM_DEVICE);
+
+       /* pull page into skb */
+       if (igb_add_rx_frag(rx_ring, rx_buffer, rx_desc, skb)) {
+               /* hand second half of page back to the ring */
+               igb_reuse_rx_page(rx_ring, rx_buffer);
+       } else {
+               /* we are not reusing the buffer so unmap it */
+               dma_unmap_page(rx_ring->dev, rx_buffer->dma,
+                              PAGE_SIZE, DMA_FROM_DEVICE);
+       }
+
+       /* clear contents of rx_buffer */
+       rx_buffer->page = NULL;
+
+       return skb;
+}
+
 static inline void igb_rx_checksum(struct igb_ring *ring,
                                   union e1000_adv_rx_desc *rx_desc,
                                   struct sk_buff *skb)
@@ -5889,224 +6065,389 @@ static inline void igb_rx_hash(struct igb_ring *ring,
                skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
 }
 
-static void igb_rx_vlan(struct igb_ring *ring,
-                       union e1000_adv_rx_desc *rx_desc,
-                       struct sk_buff *skb)
+/**
+ * igb_is_non_eop - process handling of non-EOP buffers
+ * @rx_ring: Rx ring being processed
+ * @rx_desc: Rx descriptor for current buffer
+ * @skb: current socket buffer containing buffer in progress
+ *
+ * This function updates next to clean.  If the buffer is an EOP buffer
+ * this function exits returning false, otherwise it will place the
+ * sk_buff in the next buffer to be chained and return true indicating
+ * that this is in fact a non-EOP buffer.
+ **/
+static bool igb_is_non_eop(struct igb_ring *rx_ring,
+                          union e1000_adv_rx_desc *rx_desc)
 {
-       if (igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
-               u16 vid;
-               if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
-                   test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &ring->flags))
-                       vid = be16_to_cpu(rx_desc->wb.upper.vlan);
-               else
-                       vid = le16_to_cpu(rx_desc->wb.upper.vlan);
+       u32 ntc = rx_ring->next_to_clean + 1;
 
-               __vlan_hwaccel_put_tag(skb, vid);
-       }
+       /* fetch, update, and store next to clean */
+       ntc = (ntc < rx_ring->count) ? ntc : 0;
+       rx_ring->next_to_clean = ntc;
+
+       prefetch(IGB_RX_DESC(rx_ring, ntc));
+
+       if (likely(igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)))
+               return false;
+
+       return true;
 }
 
-static inline u16 igb_get_hlen(union e1000_adv_rx_desc *rx_desc)
-{
-       /* HW will not DMA in data larger than the given buffer, even if it
-        * parses the (NFS, of course) header to be larger.  In that case, it
-        * fills the header buffer and spills the rest into the page.
+/**
+ * igb_get_headlen - determine size of header for LRO/GRO
+ * @data: pointer to the start of the headers
+ * @max_len: total length of section to find headers in
+ *
+ * This function is meant to determine the length of headers that will
+ * be recognized by hardware for LRO, and GRO offloads.  The main
+ * motivation of doing this is to only perform one pull for IPv4 TCP
+ * packets so that we can do basic things like calculating the gso_size
+ * based on the average data per packet.
+ **/
+static unsigned int igb_get_headlen(unsigned char *data,
+                                   unsigned int max_len)
+{
+       union {
+               unsigned char *network;
+               /* l2 headers */
+               struct ethhdr *eth;
+               struct vlan_hdr *vlan;
+               /* l3 headers */
+               struct iphdr *ipv4;
+               struct ipv6hdr *ipv6;
+       } hdr;
+       __be16 protocol;
+       u8 nexthdr = 0; /* default to not TCP */
+       u8 hlen;
+
+       /* this should never happen, but better safe than sorry */
+       if (max_len < ETH_HLEN)
+               return max_len;
+
+       /* initialize network frame pointer */
+       hdr.network = data;
+
+       /* set first protocol and move network header forward */
+       protocol = hdr.eth->h_proto;
+       hdr.network += ETH_HLEN;
+
+       /* handle any vlan tag if present */
+       if (protocol == __constant_htons(ETH_P_8021Q)) {
+               if ((hdr.network - data) > (max_len - VLAN_HLEN))
+                       return max_len;
+
+               protocol = hdr.vlan->h_vlan_encapsulated_proto;
+               hdr.network += VLAN_HLEN;
+       }
+
+       /* handle L3 protocols */
+       if (protocol == __constant_htons(ETH_P_IP)) {
+               if ((hdr.network - data) > (max_len - sizeof(struct iphdr)))
+                       return max_len;
+
+               /* access ihl as a u8 to avoid unaligned access on ia64 */
+               hlen = (hdr.network[0] & 0x0F) << 2;
+
+               /* verify hlen meets minimum size requirements */
+               if (hlen < sizeof(struct iphdr))
+                       return hdr.network - data;
+
+               /* record next protocol if header is present */
+               if (!hdr.ipv4->frag_off)
+                       nexthdr = hdr.ipv4->protocol;
+       } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+               if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+                       return max_len;
+
+               /* record next protocol */
+               nexthdr = hdr.ipv6->nexthdr;
+               hlen = sizeof(struct ipv6hdr);
+       } else {
+               return hdr.network - data;
+       }
+
+       /* relocate pointer to start of L4 header */
+       hdr.network += hlen;
+
+       /* finally sort out TCP */
+       if (nexthdr == IPPROTO_TCP) {
+               if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
+                       return max_len;
+
+               /* access doff as a u8 to avoid unaligned access on ia64 */
+               hlen = (hdr.network[12] & 0xF0) >> 2;
+
+               /* verify hlen meets minimum size requirements */
+               if (hlen < sizeof(struct tcphdr))
+                       return hdr.network - data;
+
+               hdr.network += hlen;
+       } else if (nexthdr == IPPROTO_UDP) {
+               if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+                       return max_len;
+
+               hdr.network += sizeof(struct udphdr);
+       }
+
+       /*
+        * If everything has gone correctly hdr.network should be the
+        * data section of the packet and will be the end of the header.
+        * If not then it probably represents the end of the last recognized
+        * header.
         */
-       u16 hlen = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hdr_info) &
-                  E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT;
-       if (hlen > IGB_RX_HDR_LEN)
-               hlen = IGB_RX_HDR_LEN;
-       return hlen;
+       if ((hdr.network - data) < max_len)
+               return hdr.network - data;
+       else
+               return max_len;
 }
 
-static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
+/**
+ * igb_pull_tail - igb specific version of skb_pull_tail
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being adjusted
+ *
+ * This function is an igb specific version of __pskb_pull_tail.  The
+ * main difference between this version and the original function is that
+ * this function can make several assumptions about the state of things
+ * that allow for significant optimizations versus the standard function.
+ * As a result we can do things like drop a frag and maintain an accurate
+ * truesize for the skb.
+ */
+static void igb_pull_tail(struct igb_ring *rx_ring,
+                         union e1000_adv_rx_desc *rx_desc,
+                         struct sk_buff *skb)
 {
-       struct igb_ring *rx_ring = q_vector->rx.ring;
-       union e1000_adv_rx_desc *rx_desc;
-       const int current_node = numa_node_id();
-       unsigned int total_bytes = 0, total_packets = 0;
-       u16 cleaned_count = igb_desc_unused(rx_ring);
-       u16 i = rx_ring->next_to_clean;
+       struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
+       unsigned char *va;
+       unsigned int pull_len;
 
-       rx_desc = IGB_RX_DESC(rx_ring, i);
+       /*
+        * it is valid to use page_address instead of kmap since we are
+        * working with pages allocated out of the lomem pool per
+        * alloc_page(GFP_ATOMIC)
+        */
+       va = skb_frag_address(frag);
 
-       while (igb_test_staterr(rx_desc, E1000_RXD_STAT_DD)) {
-               struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
-               struct sk_buff *skb = buffer_info->skb;
-               union e1000_adv_rx_desc *next_rxd;
+       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+               /* retrieve timestamp from buffer */
+               igb_ptp_rx_pktstamp(rx_ring->q_vector, va, skb);
 
-               buffer_info->skb = NULL;
-               prefetch(skb->data);
+               /* update pointers to remove timestamp header */
+               skb_frag_size_sub(frag, IGB_TS_HDR_LEN);
+               frag->page_offset += IGB_TS_HDR_LEN;
+               skb->data_len -= IGB_TS_HDR_LEN;
+               skb->len -= IGB_TS_HDR_LEN;
 
-               i++;
-               if (i == rx_ring->count)
-                       i = 0;
+               /* move va to start of packet data */
+               va += IGB_TS_HDR_LEN;
+       }
 
-               next_rxd = IGB_RX_DESC(rx_ring, i);
-               prefetch(next_rxd);
+       /*
+        * we need the header to contain the greater of either ETH_HLEN or
+        * 60 bytes if the skb->len is less than 60 for skb_pad.
+        */
+       pull_len = igb_get_headlen(va, IGB_RX_HDR_LEN);
 
-               /*
-                * This memory barrier is needed to keep us from reading
-                * any other fields out of the rx_desc until we know the
-                * RXD_STAT_DD bit is set
-                */
-               rmb();
+       /* align pull length to size of long to optimize memcpy performance */
+       skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long)));
 
-               if (!skb_is_nonlinear(skb)) {
-                       __skb_put(skb, igb_get_hlen(rx_desc));
-                       dma_unmap_single(rx_ring->dev, buffer_info->dma,
-                                        IGB_RX_HDR_LEN,
-                                        DMA_FROM_DEVICE);
-                       buffer_info->dma = 0;
+       /* update all of the pointers */
+       skb_frag_size_sub(frag, pull_len);
+       frag->page_offset += pull_len;
+       skb->data_len -= pull_len;
+       skb->tail += pull_len;
+}
+
+/**
+ * igb_cleanup_headers - Correct corrupted or empty headers
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being fixed
+ *
+ * Address the case where we are pulling data in on pages only
+ * and as such no data is present in the skb header.
+ *
+ * In addition if skb is not at least 60 bytes we need to pad it so that
+ * it is large enough to qualify as a valid Ethernet frame.
+ *
+ * Returns true if an error was encountered and skb was freed.
+ **/
+static bool igb_cleanup_headers(struct igb_ring *rx_ring,
+                               union e1000_adv_rx_desc *rx_desc,
+                               struct sk_buff *skb)
+{
+
+       if (unlikely((igb_test_staterr(rx_desc,
+                                      E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) {
+               struct net_device *netdev = rx_ring->netdev;
+               if (!(netdev->features & NETIF_F_RXALL)) {
+                       dev_kfree_skb_any(skb);
+                       return true;
                }
+       }
 
-               if (rx_desc->wb.upper.length) {
-                       u16 length = le16_to_cpu(rx_desc->wb.upper.length);
+       /* place header in linear portion of buffer */
+       if (skb_is_nonlinear(skb))
+               igb_pull_tail(rx_ring, rx_desc, skb);
 
-                       skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
-                                               buffer_info->page,
-                                               buffer_info->page_offset,
-                                               length);
+       /* if skb_pad returns an error the skb was freed */
+       if (unlikely(skb->len < 60)) {
+               int pad_len = 60 - skb->len;
 
-                       skb->len += length;
-                       skb->data_len += length;
-                       skb->truesize += PAGE_SIZE / 2;
+               if (skb_pad(skb, pad_len))
+                       return true;
+               __skb_put(skb, pad_len);
+       }
 
-                       if ((page_count(buffer_info->page) != 1) ||
-                           (page_to_nid(buffer_info->page) != current_node))
-                               buffer_info->page = NULL;
-                       else
-                               get_page(buffer_info->page);
+       return false;
+}
 
-                       dma_unmap_page(rx_ring->dev, buffer_info->page_dma,
-                                      PAGE_SIZE / 2, DMA_FROM_DEVICE);
-                       buffer_info->page_dma = 0;
-               }
+/**
+ * igb_process_skb_fields - Populate skb header fields from Rx descriptor
+ * @rx_ring: rx descriptor ring packet is being transacted on
+ * @rx_desc: pointer to the EOP Rx descriptor
+ * @skb: pointer to current skb being populated
+ *
+ * This function checks the ring, descriptor, and packet information in
+ * order to populate the hash, checksum, VLAN, timestamp, protocol, and
+ * other fields within the skb.
+ **/
+static void igb_process_skb_fields(struct igb_ring *rx_ring,
+                                  union e1000_adv_rx_desc *rx_desc,
+                                  struct sk_buff *skb)
+{
+       struct net_device *dev = rx_ring->netdev;
 
-               if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)) {
-                       struct igb_rx_buffer *next_buffer;
-                       next_buffer = &rx_ring->rx_buffer_info[i];
-                       buffer_info->skb = next_buffer->skb;
-                       buffer_info->dma = next_buffer->dma;
-                       next_buffer->skb = skb;
-                       next_buffer->dma = 0;
-                       goto next_desc;
-               }
+       igb_rx_hash(rx_ring, rx_desc, skb);
 
-               if (unlikely((igb_test_staterr(rx_desc,
-                                              E1000_RXDEXT_ERR_FRAME_ERR_MASK))
-                            && !(rx_ring->netdev->features & NETIF_F_RXALL))) {
-                       dev_kfree_skb_any(skb);
-                       goto next_desc;
-               }
+       igb_rx_checksum(rx_ring, rx_desc, skb);
 
-#ifdef CONFIG_IGB_PTP
-               igb_ptp_rx_hwtstamp(q_vector, rx_desc, skb);
-#endif /* CONFIG_IGB_PTP */
-               igb_rx_hash(rx_ring, rx_desc, skb);
-               igb_rx_checksum(rx_ring, rx_desc, skb);
-               igb_rx_vlan(rx_ring, rx_desc, skb);
+       igb_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb);
 
-               total_bytes += skb->len;
-               total_packets++;
+       if ((dev->features & NETIF_F_HW_VLAN_RX) &&
+           igb_test_staterr(rx_desc, E1000_RXD_STAT_VP)) {
+               u16 vid;
+               if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) &&
+                   test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags))
+                       vid = be16_to_cpu(rx_desc->wb.upper.vlan);
+               else
+                       vid = le16_to_cpu(rx_desc->wb.upper.vlan);
 
-               skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+               __vlan_hwaccel_put_tag(skb, vid);
+       }
 
-               napi_gro_receive(&q_vector->napi, skb);
+       skb_record_rx_queue(skb, rx_ring->queue_index);
 
-               budget--;
-next_desc:
-               if (!budget)
-                       break;
+       skb->protocol = eth_type_trans(skb, rx_ring->netdev);
+}
+
+static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
+{
+       struct igb_ring *rx_ring = q_vector->rx.ring;
+       struct sk_buff *skb = rx_ring->skb;
+       unsigned int total_bytes = 0, total_packets = 0;
+       u16 cleaned_count = igb_desc_unused(rx_ring);
+
+       do {
+               union e1000_adv_rx_desc *rx_desc;
 
-               cleaned_count++;
                /* return some buffers to hardware, one at a time is too slow */
                if (cleaned_count >= IGB_RX_BUFFER_WRITE) {
                        igb_alloc_rx_buffers(rx_ring, cleaned_count);
                        cleaned_count = 0;
                }
 
-               /* use prefetched values */
-               rx_desc = next_rxd;
-       }
+               rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean);
 
-       rx_ring->next_to_clean = i;
-       u64_stats_update_begin(&rx_ring->rx_syncp);
-       rx_ring->rx_stats.packets += total_packets;
-       rx_ring->rx_stats.bytes += total_bytes;
-       u64_stats_update_end(&rx_ring->rx_syncp);
-       q_vector->rx.total_packets += total_packets;
-       q_vector->rx.total_bytes += total_bytes;
+               if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD))
+                       break;
 
-       if (cleaned_count)
-               igb_alloc_rx_buffers(rx_ring, cleaned_count);
+               /* retrieve a buffer from the ring */
+               skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
 
-       return !!budget;
-}
+               /* exit if we failed to retrieve a buffer */
+               if (!skb)
+                       break;
 
-static bool igb_alloc_mapped_skb(struct igb_ring *rx_ring,
-                                struct igb_rx_buffer *bi)
-{
-       struct sk_buff *skb = bi->skb;
-       dma_addr_t dma = bi->dma;
+               cleaned_count++;
 
-       if (dma)
-               return true;
+               /* fetch next buffer in frame if non-eop */
+               if (igb_is_non_eop(rx_ring, rx_desc))
+                       continue;
 
-       if (likely(!skb)) {
-               skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
-                                               IGB_RX_HDR_LEN);
-               bi->skb = skb;
-               if (!skb) {
-                       rx_ring->rx_stats.alloc_failed++;
-                       return false;
+               /* verify the packet layout is correct */
+               if (igb_cleanup_headers(rx_ring, rx_desc, skb)) {
+                       skb = NULL;
+                       continue;
                }
 
-               /* initialize skb for ring */
-               skb_record_rx_queue(skb, rx_ring->queue_index);
-       }
+               /* probably a little skewed due to removing CRC */
+               total_bytes += skb->len;
 
-       dma = dma_map_single(rx_ring->dev, skb->data,
-                            IGB_RX_HDR_LEN, DMA_FROM_DEVICE);
+               /* populate checksum, timestamp, VLAN, and protocol */
+               igb_process_skb_fields(rx_ring, rx_desc, skb);
 
-       if (dma_mapping_error(rx_ring->dev, dma)) {
-               rx_ring->rx_stats.alloc_failed++;
-               return false;
-       }
+               napi_gro_receive(&q_vector->napi, skb);
 
-       bi->dma = dma;
-       return true;
+               /* reset skb pointer */
+               skb = NULL;
+
+               /* update budget accounting */
+               total_packets++;
+       } while (likely(total_packets < budget));
+
+       /* place incomplete frames back on ring for completion */
+       rx_ring->skb = skb;
+
+       u64_stats_update_begin(&rx_ring->rx_syncp);
+       rx_ring->rx_stats.packets += total_packets;
+       rx_ring->rx_stats.bytes += total_bytes;
+       u64_stats_update_end(&rx_ring->rx_syncp);
+       q_vector->rx.total_packets += total_packets;
+       q_vector->rx.total_bytes += total_bytes;
+
+       if (cleaned_count)
+               igb_alloc_rx_buffers(rx_ring, cleaned_count);
+
+       return (total_packets < budget);
 }
 
 static bool igb_alloc_mapped_page(struct igb_ring *rx_ring,
                                  struct igb_rx_buffer *bi)
 {
        struct page *page = bi->page;
-       dma_addr_t page_dma = bi->page_dma;
-       unsigned int page_offset = bi->page_offset ^ (PAGE_SIZE / 2);
+       dma_addr_t dma;
 
-       if (page_dma)
+       /* since we are recycling buffers we should seldom need to alloc */
+       if (likely(page))
                return true;
 
-       if (!page) {
-               page = __skb_alloc_page(GFP_ATOMIC, bi->skb);
-               bi->page = page;
-               if (unlikely(!page)) {
-                       rx_ring->rx_stats.alloc_failed++;
-                       return false;
-               }
+       /* alloc new page for storage */
+       page = __skb_alloc_page(GFP_ATOMIC | __GFP_COLD, NULL);
+       if (unlikely(!page)) {
+               rx_ring->rx_stats.alloc_failed++;
+               return false;
        }
 
-       page_dma = dma_map_page(rx_ring->dev, page,
-                               page_offset, PAGE_SIZE / 2,
-                               DMA_FROM_DEVICE);
+       /* map page for use */
+       dma = dma_map_page(rx_ring->dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+
+       /*
+        * if mapping failed free memory back to system since
+        * there isn't much point in holding memory we can't use
+        */
+       if (dma_mapping_error(rx_ring->dev, dma)) {
+               __free_page(page);
 
-       if (dma_mapping_error(rx_ring->dev, page_dma)) {
                rx_ring->rx_stats.alloc_failed++;
                return false;
        }
 
-       bi->page_dma = page_dma;
-       bi->page_offset = page_offset;
+       bi->dma = dma;
+       bi->page = page;
+       bi->page_offset = 0;
+
        return true;
 }
 
@@ -6120,22 +6461,23 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
        struct igb_rx_buffer *bi;
        u16 i = rx_ring->next_to_use;
 
+       /* nothing to do */
+       if (!cleaned_count)
+               return;
+
        rx_desc = IGB_RX_DESC(rx_ring, i);
        bi = &rx_ring->rx_buffer_info[i];
        i -= rx_ring->count;
 
-       while (cleaned_count--) {
-               if (!igb_alloc_mapped_skb(rx_ring, bi))
-                       break;
-
-               /* Refresh the desc even if buffer_addrs didn't change
-                * because each write-back erases this info. */
-               rx_desc->read.hdr_addr = cpu_to_le64(bi->dma);
-
+       do {
                if (!igb_alloc_mapped_page(rx_ring, bi))
                        break;
 
-               rx_desc->read.pkt_addr = cpu_to_le64(bi->page_dma);
+               /*
+                * Refresh the desc even if buffer_addrs didn't change
+                * because each write-back erases this info.
+                */
+               rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset);
 
                rx_desc++;
                bi++;
@@ -6148,17 +6490,25 @@ void igb_alloc_rx_buffers(struct igb_ring *rx_ring, u16 cleaned_count)
 
                /* clear the hdr_addr for the next_to_use descriptor */
                rx_desc->read.hdr_addr = 0;
-       }
+
+               cleaned_count--;
+       } while (cleaned_count);
 
        i += rx_ring->count;
 
        if (rx_ring->next_to_use != i) {
+               /* record the next descriptor to use */
                rx_ring->next_to_use = i;
 
-               /* Force memory writes to complete before letting h/w
+               /* update next to alloc since we have filled the ring */
+               rx_ring->next_to_alloc = i;
+
+               /*
+                * Force memory writes to complete before letting h/w
                 * know there are new descriptors to fetch.  (Only
                 * applicable for weak-ordered memory model archs,
-                * such as IA-64). */
+                * such as IA-64).
+                */
                wmb();
                writel(i, rx_ring->tail);
        }
@@ -6207,10 +6557,8 @@ static int igb_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
        case SIOCGMIIREG:
        case SIOCSMIIREG:
                return igb_mii_ioctl(netdev, ifr, cmd);
-#ifdef CONFIG_IGB_PTP
        case SIOCSHWTSTAMP:
                return igb_ptp_hwtstamp_ioctl(netdev, ifr, cmd);
-#endif /* CONFIG_IGB_PTP */
        default:
                return -EOPNOTSUPP;
        }
@@ -6478,7 +6826,7 @@ static int igb_resume(struct device *dev)
        pci_enable_wake(pdev, PCI_D3hot, 0);
        pci_enable_wake(pdev, PCI_D3cold, 0);
 
-       if (igb_init_interrupt_scheme(adapter)) {
+       if (igb_init_interrupt_scheme(adapter, true)) {
                dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
                return -ENOMEM;
        }
@@ -6492,7 +6840,9 @@ static int igb_resume(struct device *dev)
        wr32(E1000_WUS, ~0);
 
        if (netdev->flags & IFF_UP) {
+               rtnl_lock();
                err = __igb_open(netdev, true);
+               rtnl_unlock();
                if (err)
                        return err;
        }
index ee21445157a3e8907a7b01267806d10b3ffab6e2..ab3429729bde4134a0310a6199cf9eb1737369b6 100644 (file)
@@ -441,18 +441,46 @@ void igb_ptp_tx_hwtstamp(struct igb_adapter *adapter)
        adapter->ptp_tx_skb = NULL;
 }
 
-void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
-                        union e1000_adv_rx_desc *rx_desc,
+/**
+ * igb_ptp_rx_pktstamp - retrieve Rx per packet timestamp
+ * @q_vector: Pointer to interrupt specific structure
+ * @va: Pointer to address containing Rx buffer
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the first buffer of an
+ * incoming frame.  The value is stored in little endian format starting on
+ * byte 8.
+ */
+void igb_ptp_rx_pktstamp(struct igb_q_vector *q_vector,
+                        unsigned char *va,
+                        struct sk_buff *skb)
+{
+       __le64 *regval = (__le64 *)va;
+
+       /*
+        * The timestamp is recorded in little endian format.
+        * DWORD: 0        1        2        3
+        * Field: Reserved Reserved SYSTIML  SYSTIMH
+        */
+       igb_ptp_systim_to_hwtstamp(q_vector->adapter, skb_hwtstamps(skb),
+                                  le64_to_cpu(regval[1]));
+}
+
+/**
+ * igb_ptp_rx_rgtstamp - retrieve Rx timestamp stored in register
+ * @q_vector: Pointer to interrupt specific structure
+ * @skb: Buffer containing timestamp and packet
+ *
+ * This function is meant to retrieve a timestamp from the internal registers
+ * of the adapter and store it in the skb.
+ */
+void igb_ptp_rx_rgtstamp(struct igb_q_vector *q_vector,
                         struct sk_buff *skb)
 {
        struct igb_adapter *adapter = q_vector->adapter;
        struct e1000_hw *hw = &adapter->hw;
        u64 regval;
 
-       if (!igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP |
-                                      E1000_RXDADV_STAT_TS))
-               return;
-
        /*
         * If this bit is set, then the RX registers contain the time stamp. No
         * other packet will be time stamped until we read these registers, so
@@ -464,18 +492,11 @@ void igb_ptp_rx_hwtstamp(struct igb_q_vector *q_vector,
         * If nothing went wrong, then it should have a shared tx_flags that we
         * can turn into a skb_shared_hwtstamps.
         */
-       if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
-               u32 *stamp = (u32 *)skb->data;
-               regval = le32_to_cpu(*(stamp + 2));
-               regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32;
-               skb_pull(skb, IGB_TS_HDR_LEN);
-       } else {
-               if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
-                       return;
+       if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
+               return;
 
-               regval = rd32(E1000_RXSTMPL);
-               regval |= (u64)rd32(E1000_RXSTMPH) << 32;
-       }
+       regval = rd32(E1000_RXSTMPL);
+       regval |= (u64)rd32(E1000_RXSTMPH) << 32;
 
        igb_ptp_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
 }
@@ -532,18 +553,6 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
        case HWTSTAMP_FILTER_NONE:
                tsync_rx_ctl = 0;
                break;
-       case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
-       case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
-       case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
-       case HWTSTAMP_FILTER_ALL:
-               /*
-                * register TSYNCRXCFG must be set, therefore it is not
-                * possible to time stamp both Sync and Delay_Req messages
-                * => fall back to time stamping all packets
-                */
-               tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
-               config.rx_filter = HWTSTAMP_FILTER_ALL;
-               break;
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
                tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1;
                tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE;
@@ -554,31 +563,33 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
                tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V1_DELAY_REQ_MESSAGE;
                is_l4 = true;
                break;
+       case HWTSTAMP_FILTER_PTP_V2_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_SYNC:
        case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
        case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
-               tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
-               tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_SYNC_MESSAGE;
-               is_l2 = true;
-               is_l4 = true;
-               config.rx_filter = HWTSTAMP_FILTER_SOME;
-               break;
+       case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
        case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
        case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
-               tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2;
-               tsync_rx_cfg = E1000_TSYNCRXCFG_PTP_V2_DELAY_REQ_MESSAGE;
-               is_l2 = true;
-               is_l4 = true;
-               config.rx_filter = HWTSTAMP_FILTER_SOME;
-               break;
-       case HWTSTAMP_FILTER_PTP_V2_EVENT:
-       case HWTSTAMP_FILTER_PTP_V2_SYNC:
-       case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
                tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2;
                config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
                is_l2 = true;
                is_l4 = true;
                break;
+       case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+       case HWTSTAMP_FILTER_ALL:
+               /* 82576 cannot timestamp all packets, which it needs to do to
+                * support both V1 Sync and Delay_Req messages
+                */
+               if (hw->mac.type != e1000_82576) {
+                       tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
+                       config.rx_filter = HWTSTAMP_FILTER_ALL;
+                       break;
+               }
+               /* fall through */
        default:
+               config.rx_filter = HWTSTAMP_FILTER_NONE;
                return -ERANGE;
        }
 
@@ -596,6 +607,9 @@ int igb_ptp_hwtstamp_ioctl(struct net_device *netdev,
        if ((hw->mac.type >= e1000_82580) && tsync_rx_ctl) {
                tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
                tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
+               config.rx_filter = HWTSTAMP_FILTER_ALL;
+               is_l2 = true;
+               is_l4 = true;
 
                if ((hw->mac.type == e1000_i210) ||
                    (hw->mac.type == e1000_i211)) {
index 3e18045d8f89f69d5e374d246f49a91320399a0c..d9fa999b16856e41f79a750c92d94223dfaa6d98 100644 (file)
@@ -46,6 +46,7 @@
 #define E1000_RXD_ERR_SE        0x02    /* Symbol Error */
 #define E1000_RXD_SPC_VLAN_MASK 0x0FFF  /* VLAN ID is in lower 12 bits */
 
+#define E1000_RXDEXT_STATERR_LB    0x00040000
 #define E1000_RXDEXT_STATERR_CE    0x01000000
 #define E1000_RXDEXT_STATERR_SE    0x02000000
 #define E1000_RXDEXT_STATERR_SEQ   0x04000000
index a895e2f7b34d99b4afa870cfaab801b1061ab9db..fdca7b6727764fb574ffc88a85f47ee81fdc5f23 100644 (file)
@@ -295,7 +295,7 @@ struct igbvf_info {
 
 /* hardware capability, feature, and workaround flags */
 #define IGBVF_FLAG_RX_CSUM_DISABLED             (1 << 0)
-
+#define IGBVF_FLAG_RX_LB_VLAN_BSWAP            (1 << 1)
 #define IGBVF_RX_DESC_ADV(R, i)     \
        (&((((R).desc))[i].rx_desc))
 #define IGBVF_TX_DESC_ADV(R, i)     \
index 0ac11f527a84e289d8d42f693c7ebeff67e198a7..277f5dfe3d900dede1ff0cc83a061a2cc92a6ed4 100644 (file)
@@ -47,7 +47,7 @@
 
 #include "igbvf.h"
 
-#define DRV_VERSION "2.0.1-k"
+#define DRV_VERSION "2.0.2-k"
 char igbvf_driver_name[] = "igbvf";
 const char igbvf_driver_version[] = DRV_VERSION;
 static const char igbvf_driver_string[] =
@@ -107,12 +107,19 @@ static void igbvf_receive_skb(struct igbvf_adapter *adapter,
                               struct sk_buff *skb,
                               u32 status, u16 vlan)
 {
+       u16 vid;
+
        if (status & E1000_RXD_STAT_VP) {
-               u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+               if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) &&
+                   (status & E1000_RXDEXT_STATERR_LB))
+                       vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
+               else
+                       vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK;
                if (test_bit(vid, adapter->active_vlans))
                        __vlan_hwaccel_put_tag(skb, vid);
        }
-       netif_receive_skb(skb);
+
+       napi_gro_receive(&adapter->rx_ring->napi, skb);
 }
 
 static inline void igbvf_rx_checksum_adv(struct igbvf_adapter *adapter,
@@ -184,6 +191,13 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
                                             buffer_info->page_offset,
                                             PAGE_SIZE / 2,
                                             DMA_FROM_DEVICE);
+                       if (dma_mapping_error(&pdev->dev,
+                                             buffer_info->page_dma)) {
+                               __free_page(buffer_info->page);
+                               buffer_info->page = NULL;
+                               dev_err(&pdev->dev, "RX DMA map failed\n");
+                               break;
+                       }
                }
 
                if (!buffer_info->skb) {
@@ -197,6 +211,12 @@ static void igbvf_alloc_rx_buffers(struct igbvf_ring *rx_ring,
                        buffer_info->dma = dma_map_single(&pdev->dev, skb->data,
                                                          bufsz,
                                                          DMA_FROM_DEVICE);
+                       if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+                               dev_kfree_skb(buffer_info->skb);
+                               buffer_info->skb = NULL;
+                               dev_err(&pdev->dev, "RX DMA map failed\n");
+                               goto no_buffers;
+                       }
                }
                /* Refresh the desc even if buffer_addrs didn't change because
                 * each write-back erases this info. */
@@ -1078,7 +1098,7 @@ out:
  * igbvf_alloc_queues - Allocate memory for all rings
  * @adapter: board private structure to initialize
  **/
-static int __devinit igbvf_alloc_queues(struct igbvf_adapter *adapter)
+static int igbvf_alloc_queues(struct igbvf_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
 
@@ -1530,7 +1550,7 @@ void igbvf_reinit_locked(struct igbvf_adapter *adapter)
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  **/
-static int __devinit igbvf_sw_init(struct igbvf_adapter *adapter)
+static int igbvf_sw_init(struct igbvf_adapter *adapter)
 {
        struct net_device *netdev = adapter->netdev;
        s32 rc;
@@ -2598,8 +2618,7 @@ static const struct net_device_ops igbvf_netdev_ops = {
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  **/
-static int __devinit igbvf_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int igbvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct igbvf_adapter *adapter;
@@ -2754,6 +2773,10 @@ static int __devinit igbvf_probe(struct pci_dev *pdev,
        /* reset the hardware with the new settings */
        igbvf_reset(adapter);
 
+       /* set hardware-specific flags */
+       if (adapter->hw.mac.type == e1000_vfadapt_i350)
+               adapter->flags |= IGBVF_FLAG_RX_LB_VLAN_BSWAP;
+
        strcpy(netdev->name, "eth%d");
        err = register_netdev(netdev);
        if (err)
@@ -2794,7 +2817,7 @@ err_dma:
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  **/
-static void __devexit igbvf_remove(struct pci_dev *pdev)
+static void igbvf_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct igbvf_adapter *adapter = netdev_priv(netdev);
@@ -2851,7 +2874,7 @@ static struct pci_driver igbvf_driver = {
        .name     = igbvf_driver_name,
        .id_table = igbvf_pci_tbl,
        .probe    = igbvf_probe,
-       .remove   = __devexit_p(igbvf_remove),
+       .remove   = igbvf_remove,
 #ifdef CONFIG_PM
        /* Power Management Hooks */
        .suspend  = igbvf_suspend,
index d99a2d51b9482bb54926b3bb249ef13a26701201..ae96c10251be9c0ac64c7ca25a72993ae7eae22c 100644 (file)
@@ -73,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, ixgb_pci_tbl);
 static int ixgb_init_module(void);
 static void ixgb_exit_module(void);
 static int ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
-static void __devexit ixgb_remove(struct pci_dev *pdev);
+static void ixgb_remove(struct pci_dev *pdev);
 static int ixgb_sw_init(struct ixgb_adapter *adapter);
 static int ixgb_open(struct net_device *netdev);
 static int ixgb_close(struct net_device *netdev);
@@ -125,7 +125,7 @@ static struct pci_driver ixgb_driver = {
        .name     = ixgb_driver_name,
        .id_table = ixgb_pci_tbl,
        .probe    = ixgb_probe,
-       .remove   = __devexit_p(ixgb_remove),
+       .remove   = ixgb_remove,
        .err_handler = &ixgb_err_handler
 };
 
@@ -391,7 +391,7 @@ static const struct net_device_ops ixgb_netdev_ops = {
  * and a hardware reset occur.
  **/
 
-static int __devinit
+static int
 ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev = NULL;
@@ -558,7 +558,7 @@ err_dma_mask:
  * memory.
  **/
 
-static void __devexit
+static void
 ixgb_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -584,7 +584,7 @@ ixgb_remove(struct pci_dev *pdev)
  * OS network device settings (MTU size).
  **/
 
-static int __devinit
+static int
 ixgb_sw_init(struct ixgb_adapter *adapter)
 {
        struct ixgb_hw *hw = &adapter->hw;
index 07d83ab46e2118ea3f5164a2482e9204bab27ef7..04a60640dddaaaf4f01d85169d61d3e77a3d83e8 100644 (file)
@@ -47,7 +47,7 @@
 
 #define IXGB_PARAM_INIT { [0 ... IXGB_MAX_NIC] = OPTION_UNSET }
 #define IXGB_PARAM(X, desc)                                    \
-       static int __devinitdata X[IXGB_MAX_NIC+1]              \
+       static int X[IXGB_MAX_NIC+1]            \
                = IXGB_PARAM_INIT;                              \
        static unsigned int num_##X = 0;                        \
        module_param_array_named(X, X, int, &num_##X, 0);       \
@@ -199,7 +199,7 @@ struct ixgb_option {
        } arg;
 };
 
-static int __devinit
+static int
 ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
 {
        if (*value == OPTION_UNSET) {
@@ -257,7 +257,7 @@ ixgb_validate_option(unsigned int *value, const struct ixgb_option *opt)
  * in a variable in the adapter structure.
  **/
 
-void __devinit
+void
 ixgb_check_options(struct ixgb_adapter *adapter)
 {
        int bd = adapter->bd_number;
index 89f40e51fc134f0537fe8cf6f9f9c3efca44f94e..f3a632bf8d96f8bd76983e8990c80f1cefe984ac 100644 (file)
@@ -34,11 +34,10 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
 
 ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o ixgbe_debugfs.o\
               ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
-              ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o
+              ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o
 
 ixgbe-$(CONFIG_IXGBE_DCB) +=  ixgbe_dcb.o ixgbe_dcb_82598.o \
                               ixgbe_dcb_82599.o ixgbe_dcb_nl.o
 
-ixgbe-$(CONFIG_IXGBE_PTP) += ixgbe_ptp.o
 ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o
 ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
index 30efc9f0f47a3cea7cf5aee5438b5ad70c208f30..8e786764c60ea186084a7c5b18e9641abeef2a0e 100644 (file)
 #include <linux/aer.h>
 #include <linux/if_vlan.h>
 
-#ifdef CONFIG_IXGBE_PTP
 #include <linux/clocksource.h>
 #include <linux/net_tstamp.h>
 #include <linux/ptp_clock_kernel.h>
-#endif /* CONFIG_IXGBE_PTP */
 
 #include "ixgbe_type.h"
 #include "ixgbe_common.h"
@@ -135,6 +133,7 @@ struct vf_data_storage {
        u16 tx_rate;
        u16 vlan_count;
        u8 spoofchk_enabled;
+       unsigned int vf_api;
 };
 
 struct vf_macvlans {
@@ -482,8 +481,9 @@ struct ixgbe_adapter {
 #define IXGBE_FLAG2_FDIR_REQUIRES_REINIT        (u32)(1 << 7)
 #define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP         (u32)(1 << 8)
 #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP         (u32)(1 << 9)
-#define IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED     (u32)(1 << 10)
+#define IXGBE_FLAG2_PTP_ENABLED                        (u32)(1 << 10)
 #define IXGBE_FLAG2_PTP_PPS_ENABLED            (u32)(1 << 11)
+#define IXGBE_FLAG2_BRIDGE_MODE_VEB            (u32)(1 << 12)
 
        /* Tx fast path data */
        int num_tx_queues;
@@ -571,7 +571,6 @@ struct ixgbe_adapter {
        u32 interrupt_event;
        u32 led_reg;
 
-#ifdef CONFIG_IXGBE_PTP
        struct ptp_clock *ptp_clock;
        struct ptp_clock_info ptp_caps;
        unsigned long last_overflow_check;
@@ -580,8 +579,6 @@ struct ixgbe_adapter {
        struct timecounter tc;
        int rx_hwtstamp_filter;
        u32 base_incval;
-       u32 cycle_speed;
-#endif /* CONFIG_IXGBE_PTP */
 
        /* SR-IOV */
        DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
@@ -600,6 +597,8 @@ struct ixgbe_adapter {
 #ifdef CONFIG_DEBUG_FS
        struct dentry *ixgbe_dbg_adapter;
 #endif /*CONFIG_DEBUG_FS*/
+
+       u8 default_up;
 };
 
 struct ixgbe_fdir_filter {
@@ -691,6 +690,7 @@ extern s32 ixgbe_fdir_erase_perfect_filter_82599(struct ixgbe_hw *hw,
                                                 u16 soft_id);
 extern void ixgbe_atr_compute_perfect_hash_82599(union ixgbe_atr_input *input,
                                                 union ixgbe_atr_input *mask);
+extern bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 extern void ixgbe_set_rx_mode(struct net_device *netdev);
 #ifdef CONFIG_IXGBE_DCB
 extern void ixgbe_set_rx_drop_en(struct ixgbe_adapter *adapter);
@@ -739,7 +739,6 @@ static inline struct netdev_queue *txring_txq(const struct ixgbe_ring *ring)
        return netdev_get_tx_queue(ring->netdev, ring->queue_index);
 }
 
-#ifdef CONFIG_IXGBE_PTP
 extern void ixgbe_ptp_init(struct ixgbe_adapter *adapter);
 extern void ixgbe_ptp_stop(struct ixgbe_adapter *adapter);
 extern void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter);
@@ -751,7 +750,7 @@ extern void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
 extern int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
                                    struct ifreq *ifr, int cmd);
 extern void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter);
+extern void ixgbe_ptp_reset(struct ixgbe_adapter *adapter);
 extern void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr);
-#endif /* CONFIG_IXGBE_PTP */
 
 #endif /* _IXGBE_H_ */
index 1077cb2b38db15f4123eca7d9d71492df86b0a05..1073aea5da4056ec1a82686338d24c71d2dd99e2 100644 (file)
@@ -62,7 +62,6 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
                                          bool autoneg,
                                          bool autoneg_wait_to_complete);
 static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw);
-static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw);
 
 static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 {
@@ -99,9 +98,8 @@ static void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
 static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 {
        s32 ret_val = 0;
-       u32 reg_anlp1 = 0;
-       u32 i = 0;
        u16 list_offset, data_offset, data_value;
+       bool got_lock = false;
 
        if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
                ixgbe_init_mac_link_ops_82599(hw);
@@ -137,28 +135,36 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
                usleep_range(hw->eeprom.semaphore_delay * 1000,
                             hw->eeprom.semaphore_delay * 2000);
 
-               /* Now restart DSP by setting Restart_AN and clearing LMS */
-               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, ((IXGBE_READ_REG(hw,
-                               IXGBE_AUTOC) & ~IXGBE_AUTOC_LMS_MASK) |
-                               IXGBE_AUTOC_AN_RESTART));
-
-               /* Wait for AN to leave state 0 */
-               for (i = 0; i < 10; i++) {
-                       usleep_range(4000, 8000);
-                       reg_anlp1 = IXGBE_READ_REG(hw, IXGBE_ANLP1);
-                       if (reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)
-                               break;
+               /* Need SW/FW semaphore around AUTOC writes if LESM on,
+                * likewise reset_pipeline requires lock as it also writes
+                * AUTOC.
+                */
+               if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+                       ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                                       IXGBE_GSSR_MAC_CSR_SM);
+                       if (ret_val)
+                               goto setup_sfp_out;
+
+                       got_lock = true;
+               }
+
+               /* Restart DSP and set SFI mode */
+               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
+                               IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL));
+
+               ret_val = ixgbe_reset_pipeline_82599(hw);
+
+               if (got_lock) {
+                       hw->mac.ops.release_swfw_sync(hw,
+                                                     IXGBE_GSSR_MAC_CSR_SM);
+                       got_lock = false;
                }
-               if (!(reg_anlp1 & IXGBE_ANLP1_AN_STATE_MASK)) {
-                       hw_dbg(hw, "sfp module setup not complete\n");
+
+               if (ret_val) {
+                       hw_dbg(hw, " sfp module setup not complete\n");
                        ret_val = IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
                        goto setup_sfp_out;
                }
-
-               /* Restart DSP by setting Restart_AN and return to SFI mode */
-               IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (IXGBE_READ_REG(hw,
-                               IXGBE_AUTOC) | IXGBE_AUTOC_LMS_10G_SERIAL |
-                               IXGBE_AUTOC_AN_RESTART));
        }
 
 setup_sfp_out:
@@ -394,14 +400,26 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
        u32 links_reg;
        u32 i;
        s32 status = 0;
+       bool got_lock = false;
+
+       if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+               status = hw->mac.ops.acquire_swfw_sync(hw,
+                                               IXGBE_GSSR_MAC_CSR_SM);
+               if (status)
+                       goto out;
+
+               got_lock = true;
+       }
 
        /* Restart link */
-       autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-       autoc_reg |= IXGBE_AUTOC_AN_RESTART;
-       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+       ixgbe_reset_pipeline_82599(hw);
+
+       if (got_lock)
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
 
        /* Only poll for autoneg to complete if specified to do so */
        if (autoneg_wait_to_complete) {
+               autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
                if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
                     IXGBE_AUTOC_LMS_KX4_KX_KR ||
                    (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
@@ -425,6 +443,7 @@ static s32 ixgbe_start_mac_link_82599(struct ixgbe_hw *hw,
        /* Add delay to filter out noises during initial link setup */
        msleep(50);
 
+out:
        return status;
 }
 
@@ -779,6 +798,7 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
        u32 links_reg;
        u32 i;
        ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
+       bool got_lock = false;
 
        /* Check to see if speed passed in is supported. */
        status = hw->mac.ops.get_link_capabilities(hw, &link_capabilities,
@@ -836,9 +856,26 @@ static s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw,
        }
 
        if (autoc != start_autoc) {
+               /* Need SW/FW semaphore around AUTOC writes if LESM is on,
+                * likewise reset_pipeline requires us to hold this lock as
+                * it also writes to AUTOC.
+                */
+               if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+                       status = hw->mac.ops.acquire_swfw_sync(hw,
+                                                       IXGBE_GSSR_MAC_CSR_SM);
+                       if (status != 0)
+                               goto out;
+
+                       got_lock = true;
+               }
+
                /* Restart link */
-               autoc |= IXGBE_AUTOC_AN_RESTART;
                IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
+               ixgbe_reset_pipeline_82599(hw);
+
+               if (got_lock)
+                       hw->mac.ops.release_swfw_sync(hw,
+                                                     IXGBE_GSSR_MAC_CSR_SM);
 
                /* Only poll for autoneg to complete if specified to do so */
                if (autoneg_wait_to_complete) {
@@ -994,9 +1031,28 @@ mac_reset_top:
                hw->mac.orig_autoc2 = autoc2;
                hw->mac.orig_link_settings_stored = true;
        } else {
-               if (autoc != hw->mac.orig_autoc)
-                       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc |
-                                       IXGBE_AUTOC_AN_RESTART));
+               if (autoc != hw->mac.orig_autoc) {
+                       /* Need SW/FW semaphore around AUTOC writes if LESM is
+                        * on, likewise reset_pipeline requires us to hold
+                        * this lock as it also writes to AUTOC.
+                        */
+                       bool got_lock = false;
+                       if (ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+                               status = hw->mac.ops.acquire_swfw_sync(hw,
+                                                       IXGBE_GSSR_MAC_CSR_SM);
+                               if (status)
+                                       goto reset_hw_out;
+
+                               got_lock = true;
+                       }
+
+                       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
+                       ixgbe_reset_pipeline_82599(hw);
+
+                       if (got_lock)
+                               hw->mac.ops.release_swfw_sync(hw,
+                                                       IXGBE_GSSR_MAC_CSR_SM);
+               }
 
                if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
                    (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
@@ -1022,7 +1078,7 @@ mac_reset_top:
        hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
 
        /* Add the SAN MAC address to the RAR only if it's a valid address */
-       if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+       if (is_valid_ether_addr(hw->mac.san_addr)) {
                hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
                                    hw->mac.san_addr, 0, IXGBE_RAH_AV);
 
@@ -1983,7 +2039,7 @@ fw_version_out:
  *  Returns true if the LESM FW module is present and enabled. Otherwise
  *  returns false. Smart Speed must be disabled if LESM FW module is enabled.
  **/
-static bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
+bool ixgbe_verify_lesm_fw_enabled_82599(struct ixgbe_hw *hw)
 {
        bool lesm_enabled = false;
        u16 fw_offset, fw_lesm_param_offset, fw_lesm_state;
@@ -2080,6 +2136,50 @@ static s32 ixgbe_read_eeprom_82599(struct ixgbe_hw *hw,
        return ret_val;
 }
 
+/**
+ * ixgbe_reset_pipeline_82599 - perform pipeline reset
+ *
+ * @hw: pointer to hardware structure
+ *
+ * Reset pipeline by asserting Restart_AN together with LMS change to ensure
+ * full pipeline reset.  Note - We must hold the SW/FW semaphore before writing
+ * to AUTOC, so this function assumes the semaphore is held.
+ **/
+s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw)
+{
+       s32 i, autoc_reg, ret_val;
+       s32 anlp1_reg = 0;
+
+       autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+       autoc_reg |= IXGBE_AUTOC_AN_RESTART;
+
+       /* Write AUTOC register with toggled LMS[2] bit and Restart_AN */
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg ^ IXGBE_AUTOC_LMS_1G_AN);
+
+       /* Wait for AN to leave state 0 */
+       for (i = 0; i < 10; i++) {
+               usleep_range(4000, 8000);
+               anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
+               if (anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)
+                       break;
+       }
+
+       if (!(anlp1_reg & IXGBE_ANLP1_AN_STATE_MASK)) {
+               hw_dbg(hw, "auto negotiation not completed\n");
+               ret_val = IXGBE_ERR_RESET_FAILED;
+               goto reset_pipeline_out;
+       }
+
+       ret_val = 0;
+
+reset_pipeline_out:
+       /* Write AUTOC register with original LMS field and Restart_AN */
+       IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+       IXGBE_WRITE_FLUSH(hw);
+
+       return ret_val;
+}
+
 static struct ixgbe_mac_operations mac_ops_82599 = {
        .init_hw                = &ixgbe_init_hw_generic,
        .reset_hw               = &ixgbe_reset_hw_82599,
index dbf37e4a45fda722df461cc11eaaf8b2bd0449f8..5e68afdd502ab586c31bf074aac9dd9180475d2a 100644 (file)
@@ -65,13 +65,12 @@ static s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
  *  function check the device id to see if the associated phy supports
  *  autoneg flow control.
  **/
-static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
 {
 
        switch (hw->device_id) {
        case IXGBE_DEV_ID_X540T:
        case IXGBE_DEV_ID_X540T1:
-               return 0;
        case IXGBE_DEV_ID_82599_T3_LOM:
                return 0;
        default:
@@ -90,6 +89,7 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
        s32 ret_val = 0;
        u32 reg = 0, reg_bp = 0;
        u16 reg_cu = 0;
+       bool got_lock = false;
 
        /*
         * Validate the requested mode.  Strict IEEE mode does not allow
@@ -210,8 +210,29 @@ static s32 ixgbe_setup_fc(struct ixgbe_hw *hw)
         *
         */
        if (hw->phy.media_type == ixgbe_media_type_backplane) {
-               reg_bp |= IXGBE_AUTOC_AN_RESTART;
+               /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+                * LESM is on, likewise reset_pipeline requries the lock as
+                * it also writes AUTOC.
+                */
+               if ((hw->mac.type == ixgbe_mac_82599EB) &&
+                   ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+                       ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                                       IXGBE_GSSR_MAC_CSR_SM);
+                       if (ret_val)
+                               goto out;
+
+                       got_lock = true;
+               }
+
                IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+
+               if (hw->mac.type == ixgbe_mac_82599EB)
+                       ixgbe_reset_pipeline_82599(hw);
+
+               if (got_lock)
+                       hw->mac.ops.release_swfw_sync(hw,
+                                                     IXGBE_GSSR_MAC_CSR_SM);
+
        } else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
                    (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
                hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
@@ -1761,30 +1782,6 @@ s32 ixgbe_update_eeprom_checksum_generic(struct ixgbe_hw *hw)
        return status;
 }
 
-/**
- *  ixgbe_validate_mac_addr - Validate MAC address
- *  @mac_addr: pointer to MAC address.
- *
- *  Tests a MAC address to ensure it is a valid Individual Address
- **/
-s32 ixgbe_validate_mac_addr(u8 *mac_addr)
-{
-       s32 status = 0;
-
-       /* Make sure it is not a multicast address */
-       if (IXGBE_IS_MULTICAST(mac_addr))
-               status = IXGBE_ERR_INVALID_MAC_ADDR;
-       /* Not a broadcast address */
-       else if (IXGBE_IS_BROADCAST(mac_addr))
-               status = IXGBE_ERR_INVALID_MAC_ADDR;
-       /* Reject the zero address */
-       else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 &&
-                mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0)
-               status = IXGBE_ERR_INVALID_MAC_ADDR;
-
-       return status;
-}
-
 /**
  *  ixgbe_set_rar_generic - Set Rx address register
  *  @hw: pointer to hardware structure
@@ -1889,8 +1886,7 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
         * to the permanent address.
         * Otherwise, use the permanent address from the eeprom.
         */
-       if (ixgbe_validate_mac_addr(hw->mac.addr) ==
-           IXGBE_ERR_INVALID_MAC_ADDR) {
+       if (!is_valid_ether_addr(hw->mac.addr)) {
                /* Get the MAC address from the RAR0 for later reference */
                hw->mac.ops.get_mac_addr(hw, hw->mac.addr);
 
@@ -2617,6 +2613,7 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
        bool link_up = false;
        u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
        u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+       s32 ret_val = 0;
 
        /*
         * Link must be up to auto-blink the LEDs;
@@ -2625,10 +2622,28 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
        hw->mac.ops.check_link(hw, &speed, &link_up, false);
 
        if (!link_up) {
+               /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+                * LESM is on.
+                */
+               bool got_lock = false;
+
+               if ((hw->mac.type == ixgbe_mac_82599EB) &&
+                   ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+                       ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                                       IXGBE_GSSR_MAC_CSR_SM);
+                       if (ret_val)
+                               goto out;
+
+                       got_lock = true;
+               }
                autoc_reg |= IXGBE_AUTOC_AN_RESTART;
                autoc_reg |= IXGBE_AUTOC_FLU;
                IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
                IXGBE_WRITE_FLUSH(hw);
+
+               if (got_lock)
+                       hw->mac.ops.release_swfw_sync(hw,
+                                                     IXGBE_GSSR_MAC_CSR_SM);
                usleep_range(10000, 20000);
        }
 
@@ -2637,7 +2652,8 @@ s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
        IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
        IXGBE_WRITE_FLUSH(hw);
 
-       return 0;
+out:
+       return ret_val;
 }
 
 /**
@@ -2649,18 +2665,40 @@ s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
 {
        u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
        u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+       s32 ret_val = 0;
+       bool got_lock = false;
+
+       /* Need the SW/FW semaphore around AUTOC writes if 82599 and
+        * LESM is on.
+        */
+       if ((hw->mac.type == ixgbe_mac_82599EB) &&
+           ixgbe_verify_lesm_fw_enabled_82599(hw)) {
+               ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+                                               IXGBE_GSSR_MAC_CSR_SM);
+               if (ret_val)
+                       goto out;
+
+               got_lock = true;
+       }
 
        autoc_reg &= ~IXGBE_AUTOC_FLU;
        autoc_reg |= IXGBE_AUTOC_AN_RESTART;
        IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
 
+       if (hw->mac.type == ixgbe_mac_82599EB)
+               ixgbe_reset_pipeline_82599(hw);
+
+       if (got_lock)
+               hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+
        led_reg &= ~IXGBE_LED_MODE_MASK(index);
        led_reg &= ~IXGBE_LED_BLINK(index);
        led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
        IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
        IXGBE_WRITE_FLUSH(hw);
 
-       return 0;
+out:
+       return ret_val;
 }
 
 /**
index d813d1188c3617156e6e35ed260aaf1ec3ab2482..f7a0970a251cfe1835c5792401a9f0ed3547d118 100644 (file)
@@ -78,9 +78,9 @@ s32 ixgbe_disable_rx_buff_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_buff_generic(struct ixgbe_hw *hw);
 s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
 s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw);
+s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
 void ixgbe_fc_autoneg(struct ixgbe_hw *hw);
 
-s32 ixgbe_validate_mac_addr(u8 *mac_addr);
 s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask);
 void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask);
 s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr);
@@ -107,6 +107,7 @@ void ixgbe_clear_tx_pending(struct ixgbe_hw *hw);
 
 void ixgbe_set_rxpba_generic(struct ixgbe_hw *hw, int num_pb,
                             u32 headroom, int strategy);
+s32 ixgbe_reset_pipeline_82599(struct ixgbe_hw *hw);
 
 #define IXGBE_I2C_THERMAL_SENSOR_ADDR  0xF8
 #define IXGBE_EMC_INTERNAL_DATA                0x00
index 8d3a218890993cb39887b904848403a3f4d547f7..50aa546b8c7a589100be6bd88eac590adf314d98 100644 (file)
@@ -36,20 +36,6 @@ static struct dentry *ixgbe_dbg_root;
 
 static char ixgbe_dbg_reg_ops_buf[256] = "";
 
-/**
- * ixgbe_dbg_reg_ops_open - prep the debugfs pokee data item when opened
- * @inode: inode that was opened
- * @filp:  file info
- *
- * Stash the adapter pointer hiding in the inode into the file pointer where
- * we can find it later in the read and write calls
- **/
-static int ixgbe_dbg_reg_ops_open(struct inode *inode, struct file *filp)
-{
-       filp->private_data = inode->i_private;
-       return 0;
-}
-
 /**
  * ixgbe_dbg_reg_ops_read - read for reg_ops datum
  * @filp: the opened file
@@ -61,23 +47,27 @@ static ssize_t ixgbe_dbg_reg_ops_read(struct file *filp, char __user *buffer,
                                    size_t count, loff_t *ppos)
 {
        struct ixgbe_adapter *adapter = filp->private_data;
-       char buf[256];
-       int bytes_not_copied;
+       char *buf;
        int len;
 
        /* don't allow partial reads */
        if (*ppos != 0)
                return 0;
 
-       len = snprintf(buf, sizeof(buf), "%s: %s\n",
-                      adapter->netdev->name, ixgbe_dbg_reg_ops_buf);
-       if (count < len)
+       buf = kasprintf(GFP_KERNEL, "%s: %s\n",
+                       adapter->netdev->name,
+                       ixgbe_dbg_reg_ops_buf);
+       if (!buf)
+               return -ENOMEM;
+
+       if (count < strlen(buf)) {
+               kfree(buf);
                return -ENOSPC;
-       bytes_not_copied = copy_to_user(buffer, buf, len);
-       if (bytes_not_copied < 0)
-               return bytes_not_copied;
+       }
+
+       len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
 
-       *ppos = len;
+       kfree(buf);
        return len;
 }
 
@@ -93,7 +83,7 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
                                     size_t count, loff_t *ppos)
 {
        struct ixgbe_adapter *adapter = filp->private_data;
-       int bytes_not_copied;
+       int len;
 
        /* don't allow partial writes */
        if (*ppos != 0)
@@ -101,14 +91,15 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
        if (count >= sizeof(ixgbe_dbg_reg_ops_buf))
                return -ENOSPC;
 
-       bytes_not_copied = copy_from_user(ixgbe_dbg_reg_ops_buf, buffer, count);
-       if (bytes_not_copied < 0)
-               return bytes_not_copied;
-       else if (bytes_not_copied < count)
-               count -= bytes_not_copied;
-       else
-               return -ENOSPC;
-       ixgbe_dbg_reg_ops_buf[count] = '\0';
+       len = simple_write_to_buffer(ixgbe_dbg_reg_ops_buf,
+                                    sizeof(ixgbe_dbg_reg_ops_buf)-1,
+                                    ppos,
+                                    buffer,
+                                    count);
+       if (len < 0)
+               return len;
+
+       ixgbe_dbg_reg_ops_buf[len] = '\0';
 
        if (strncmp(ixgbe_dbg_reg_ops_buf, "write", 5) == 0) {
                u32 reg, value;
@@ -142,27 +133,13 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp,
 
 static const struct file_operations ixgbe_dbg_reg_ops_fops = {
        .owner = THIS_MODULE,
-       .open =  ixgbe_dbg_reg_ops_open,
+       .open = simple_open,
        .read =  ixgbe_dbg_reg_ops_read,
        .write = ixgbe_dbg_reg_ops_write,
 };
 
 static char ixgbe_dbg_netdev_ops_buf[256] = "";
 
-/**
- * ixgbe_dbg_netdev_ops_open - prep the debugfs netdev_ops data item
- * @inode: inode that was opened
- * @filp: file info
- *
- * Stash the adapter pointer hiding in the inode into the file pointer
- * where we can find it later in the read and write calls
- **/
-static int ixgbe_dbg_netdev_ops_open(struct inode *inode, struct file *filp)
-{
-       filp->private_data = inode->i_private;
-       return 0;
-}
-
 /**
  * ixgbe_dbg_netdev_ops_read - read for netdev_ops datum
  * @filp: the opened file
@@ -175,23 +152,27 @@ static ssize_t ixgbe_dbg_netdev_ops_read(struct file *filp,
                                         size_t count, loff_t *ppos)
 {
        struct ixgbe_adapter *adapter = filp->private_data;
-       char buf[256];
-       int bytes_not_copied;
+       char *buf;
        int len;
 
        /* don't allow partial reads */
        if (*ppos != 0)
                return 0;
 
-       len = snprintf(buf, sizeof(buf), "%s: %s\n",
-                      adapter->netdev->name, ixgbe_dbg_netdev_ops_buf);
-       if (count < len)
+       buf = kasprintf(GFP_KERNEL, "%s: %s\n",
+                       adapter->netdev->name,
+                       ixgbe_dbg_netdev_ops_buf);
+       if (!buf)
+               return -ENOMEM;
+
+       if (count < strlen(buf)) {
+               kfree(buf);
                return -ENOSPC;
-       bytes_not_copied = copy_to_user(buffer, buf, len);
-       if (bytes_not_copied < 0)
-               return bytes_not_copied;
+       }
+
+       len = simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
 
-       *ppos = len;
+       kfree(buf);
        return len;
 }
 
@@ -207,7 +188,7 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
                                          size_t count, loff_t *ppos)
 {
        struct ixgbe_adapter *adapter = filp->private_data;
-       int bytes_not_copied;
+       int len;
 
        /* don't allow partial writes */
        if (*ppos != 0)
@@ -215,15 +196,15 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
        if (count >= sizeof(ixgbe_dbg_netdev_ops_buf))
                return -ENOSPC;
 
-       bytes_not_copied = copy_from_user(ixgbe_dbg_netdev_ops_buf,
-                                         buffer, count);
-       if (bytes_not_copied < 0)
-               return bytes_not_copied;
-       else if (bytes_not_copied < count)
-               count -= bytes_not_copied;
-       else
-               return -ENOSPC;
-       ixgbe_dbg_netdev_ops_buf[count] = '\0';
+       len = simple_write_to_buffer(ixgbe_dbg_netdev_ops_buf,
+                                    sizeof(ixgbe_dbg_netdev_ops_buf)-1,
+                                    ppos,
+                                    buffer,
+                                    count);
+       if (len < 0)
+               return len;
+
+       ixgbe_dbg_netdev_ops_buf[len] = '\0';
 
        if (strncmp(ixgbe_dbg_netdev_ops_buf, "tx_timeout", 10) == 0) {
                adapter->netdev->netdev_ops->ndo_tx_timeout(adapter->netdev);
@@ -238,7 +219,7 @@ static ssize_t ixgbe_dbg_netdev_ops_write(struct file *filp,
 
 static const struct file_operations ixgbe_dbg_netdev_ops_fops = {
        .owner = THIS_MODULE,
-       .open = ixgbe_dbg_netdev_ops_open,
+       .open = simple_open,
        .read = ixgbe_dbg_netdev_ops_read,
        .write = ixgbe_dbg_netdev_ops_write,
 };
index 56b20d17d0e4c5577828040fddf8bd294868c84d..32685842434565e609a5f8589b67497609074aa4 100644 (file)
@@ -383,6 +383,11 @@ static int ixgbe_set_pauseparam(struct net_device *netdev,
            (adapter->flags & IXGBE_FLAG_DCB_ENABLED))
                return -EINVAL;
 
+       /* some devices do not support autoneg of link flow control */
+       if ((pause->autoneg == AUTONEG_ENABLE) &&
+           (ixgbe_device_supports_autoneg_fc(hw) != 0))
+               return -EINVAL;
+
        fc.disable_fc_autoneg = (pause->autoneg != AUTONEG_ENABLE);
 
        if ((pause->rx_pause && pause->tx_pause) || pause->autoneg)
@@ -887,24 +892,23 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                                struct ethtool_ringparam *ring)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
-       struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
+       struct ixgbe_ring *temp_ring;
        int i, err = 0;
        u32 new_rx_count, new_tx_count;
-       bool need_update = false;
 
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
                return -EINVAL;
 
-       new_rx_count = max_t(u32, ring->rx_pending, IXGBE_MIN_RXD);
-       new_rx_count = min_t(u32, new_rx_count, IXGBE_MAX_RXD);
-       new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE);
-
-       new_tx_count = max_t(u32, ring->tx_pending, IXGBE_MIN_TXD);
-       new_tx_count = min_t(u32, new_tx_count, IXGBE_MAX_TXD);
+       new_tx_count = clamp_t(u32, ring->tx_pending,
+                              IXGBE_MIN_TXD, IXGBE_MAX_TXD);
        new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE);
 
-       if ((new_tx_count == adapter->tx_ring[0]->count) &&
-           (new_rx_count == adapter->rx_ring[0]->count)) {
+       new_rx_count = clamp_t(u32, ring->rx_pending,
+                              IXGBE_MIN_RXD, IXGBE_MAX_RXD);
+       new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE);
+
+       if ((new_tx_count == adapter->tx_ring_count) &&
+           (new_rx_count == adapter->rx_ring_count)) {
                /* nothing to do */
                return 0;
        }
@@ -922,81 +926,80 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
                goto clear_reset;
        }
 
-       temp_tx_ring = vmalloc(adapter->num_tx_queues * sizeof(struct ixgbe_ring));
-       if (!temp_tx_ring) {
+       /* allocate temporary buffer to store rings in */
+       i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues);
+       temp_ring = vmalloc(i * sizeof(struct ixgbe_ring));
+
+       if (!temp_ring) {
                err = -ENOMEM;
                goto clear_reset;
        }
 
+       ixgbe_down(adapter);
+
+       /*
+        * Setup new Tx resources and free the old Tx resources in that order.
+        * We can then assign the new resources to the rings via a memcpy.
+        * The advantage to this approach is that we are guaranteed to still
+        * have resources even in the case of an allocation failure.
+        */
        if (new_tx_count != adapter->tx_ring_count) {
                for (i = 0; i < adapter->num_tx_queues; i++) {
-                       memcpy(&temp_tx_ring[i], adapter->tx_ring[i],
+                       memcpy(&temp_ring[i], adapter->tx_ring[i],
                               sizeof(struct ixgbe_ring));
-                       temp_tx_ring[i].count = new_tx_count;
-                       err = ixgbe_setup_tx_resources(&temp_tx_ring[i]);
+
+                       temp_ring[i].count = new_tx_count;
+                       err = ixgbe_setup_tx_resources(&temp_ring[i]);
                        if (err) {
                                while (i) {
                                        i--;
-                                       ixgbe_free_tx_resources(&temp_tx_ring[i]);
+                                       ixgbe_free_tx_resources(&temp_ring[i]);
                                }
-                               goto clear_reset;
+                               goto err_setup;
                        }
                }
-               need_update = true;
-       }
 
-       temp_rx_ring = vmalloc(adapter->num_rx_queues * sizeof(struct ixgbe_ring));
-       if (!temp_rx_ring) {
-               err = -ENOMEM;
-               goto err_setup;
+               for (i = 0; i < adapter->num_tx_queues; i++) {
+                       ixgbe_free_tx_resources(adapter->tx_ring[i]);
+
+                       memcpy(adapter->tx_ring[i], &temp_ring[i],
+                              sizeof(struct ixgbe_ring));
+               }
+
+               adapter->tx_ring_count = new_tx_count;
        }
 
+       /* Repeat the process for the Rx rings if needed */
        if (new_rx_count != adapter->rx_ring_count) {
                for (i = 0; i < adapter->num_rx_queues; i++) {
-                       memcpy(&temp_rx_ring[i], adapter->rx_ring[i],
+                       memcpy(&temp_ring[i], adapter->rx_ring[i],
                               sizeof(struct ixgbe_ring));
-                       temp_rx_ring[i].count = new_rx_count;
-                       err = ixgbe_setup_rx_resources(&temp_rx_ring[i]);
+
+                       temp_ring[i].count = new_rx_count;
+                       err = ixgbe_setup_rx_resources(&temp_ring[i]);
                        if (err) {
                                while (i) {
                                        i--;
-                                       ixgbe_free_rx_resources(&temp_rx_ring[i]);
+                                       ixgbe_free_rx_resources(&temp_ring[i]);
                                }
                                goto err_setup;
                        }
+
                }
-               need_update = true;
-       }
 
-       /* if rings need to be updated, here's the place to do it in one shot */
-       if (need_update) {
-               ixgbe_down(adapter);
+               for (i = 0; i < adapter->num_rx_queues; i++) {
+                       ixgbe_free_rx_resources(adapter->rx_ring[i]);
 
-               /* tx */
-               if (new_tx_count != adapter->tx_ring_count) {
-                       for (i = 0; i < adapter->num_tx_queues; i++) {
-                               ixgbe_free_tx_resources(adapter->tx_ring[i]);
-                               memcpy(adapter->tx_ring[i], &temp_tx_ring[i],
-                                      sizeof(struct ixgbe_ring));
-                       }
-                       adapter->tx_ring_count = new_tx_count;
+                       memcpy(adapter->rx_ring[i], &temp_ring[i],
+                              sizeof(struct ixgbe_ring));
                }
 
-               /* rx */
-               if (new_rx_count != adapter->rx_ring_count) {
-                       for (i = 0; i < adapter->num_rx_queues; i++) {
-                               ixgbe_free_rx_resources(adapter->rx_ring[i]);
-                               memcpy(adapter->rx_ring[i], &temp_rx_ring[i],
-                                      sizeof(struct ixgbe_ring));
-                       }
-                       adapter->rx_ring_count = new_rx_count;
-               }
-               ixgbe_up(adapter);
+               adapter->rx_ring_count = new_rx_count;
        }
 
-       vfree(temp_rx_ring);
 err_setup:
-       vfree(temp_tx_ring);
+       ixgbe_up(adapter);
+       vfree(temp_ring);
 clear_reset:
        clear_bit(__IXGBE_RESETTING, &adapter->state);
        return err;
@@ -2669,10 +2672,12 @@ static int ixgbe_get_ts_info(struct net_device *dev,
        struct ixgbe_adapter *adapter = netdev_priv(dev);
 
        switch (adapter->hw.mac.type) {
-#ifdef CONFIG_IXGBE_PTP
        case ixgbe_mac_X540:
        case ixgbe_mac_82599EB:
                info->so_timestamping =
+                       SOF_TIMESTAMPING_TX_SOFTWARE |
+                       SOF_TIMESTAMPING_RX_SOFTWARE |
+                       SOF_TIMESTAMPING_SOFTWARE |
                        SOF_TIMESTAMPING_TX_HARDWARE |
                        SOF_TIMESTAMPING_RX_HARDWARE |
                        SOF_TIMESTAMPING_RAW_HARDWARE;
@@ -2692,7 +2697,6 @@ static int ixgbe_get_ts_info(struct net_device *dev,
                        (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) |
                        (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
                break;
-#endif /* CONFIG_IXGBE_PTP */
        default:
                return ethtool_op_get_ts_info(dev, info);
                break;
index ae73ef14fdf341795cf499c5abab207704a70d34..252850d9a3e0925b45bcb3524dd7c6e490540616 100644 (file)
@@ -800,6 +800,10 @@ int ixgbe_fcoe_enable(struct net_device *netdev)
                return -EINVAL;
 
        e_info(drv, "Enabling FCoE offload features.\n");
+
+       if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
+               e_warn(probe, "Enabling FCoE on PF will disable legacy VFs\n");
+
        if (netif_running(netdev))
                netdev->netdev_ops->ndo_stop(netdev);
 
index 17ecbcedd5481d0dcafa46138839088478cbf2c6..8c74f739011dd6a09ddbae19b4cf3bbe663c8a43 100644 (file)
@@ -802,10 +802,13 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
        /* setup affinity mask and node */
        if (cpu != -1)
                cpumask_set_cpu(cpu, &q_vector->affinity_mask);
-       else
-               cpumask_copy(&q_vector->affinity_mask, cpu_online_mask);
        q_vector->numa_node = node;
 
+#ifdef CONFIG_IXGBE_DCA
+       /* initialize CPU for DCA */
+       q_vector->cpu = -1;
+
+#endif
        /* initialize NAPI */
        netif_napi_add(adapter->netdev, &q_vector->napi,
                       ixgbe_poll, 64);
@@ -821,6 +824,21 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter,
        /* initialize pointer to rings */
        ring = q_vector->ring;
 
+       /* intialize ITR */
+       if (txr_count && !rxr_count) {
+               /* tx only vector */
+               if (adapter->tx_itr_setting == 1)
+                       q_vector->itr = IXGBE_10K_ITR;
+               else
+                       q_vector->itr = adapter->tx_itr_setting;
+       } else {
+               /* rx or rx/tx vector */
+               if (adapter->rx_itr_setting == 1)
+                       q_vector->itr = IXGBE_20K_ITR;
+               else
+                       q_vector->itr = adapter->rx_itr_setting;
+       }
+
        while (txr_count) {
                /* assign generic ring traits */
                ring->dev = &adapter->pdev->dev;
index fa3d552e1f4a1e6b0cad19c4e4d5610551866638..20a5af6d87d0e8747027964ba01a03bd7e3ca24c 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/ethtool.h>
 #include <linux/if.h>
 #include <linux/if_vlan.h>
+#include <linux/if_bridge.h>
 #include <linux/prefetch.h>
 #include <scsi/fc/fc_fcoe.h>
 
@@ -62,11 +63,7 @@ char ixgbe_default_device_descr[] =
 static char ixgbe_default_device_descr[] =
                              "Intel(R) 10 Gigabit Network Connection";
 #endif
-#define MAJ 3
-#define MIN 9
-#define BUILD 15
-#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
-       __stringify(BUILD) "-k"
+#define DRV_VERSION "3.11.33-k"
 const char ixgbe_driver_version[] = DRV_VERSION;
 static const char ixgbe_copyright[] =
                                "Copyright (c) 1999-2012 Intel Corporation.";
@@ -335,11 +332,13 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
                goto exit;
 
        dev_info(&adapter->pdev->dev, "TX Rings Summary\n");
-       pr_info("Queue [NTU] [NTC] [bi(ntc)->dma  ] leng ntw timestamp\n");
+       pr_info(" %s     %s              %s        %s\n",
+               "Queue [NTU] [NTC] [bi(ntc)->dma  ]",
+               "leng", "ntw", "timestamp");
        for (n = 0; n < adapter->num_tx_queues; n++) {
                tx_ring = adapter->tx_ring[n];
                tx_buffer = &tx_ring->tx_buffer_info[tx_ring->next_to_clean];
-               pr_info(" %5d %5X %5X %016llX %04X %p %016llX\n",
+               pr_info(" %5d %5X %5X %016llX %08X %p %016llX\n",
                           n, tx_ring->next_to_use, tx_ring->next_to_clean,
                           (u64)dma_unmap_addr(tx_buffer, dma),
                           dma_unmap_len(tx_buffer, len),
@@ -355,13 +354,37 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
 
        /* Transmit Descriptor Formats
         *
-        * Advanced Transmit Descriptor
+        * 82598 Advanced Transmit Descriptor
         *   +--------------------------------------------------------------+
         * 0 |         Buffer Address [63:0]                                |
         *   +--------------------------------------------------------------+
-        * 8 |  PAYLEN  | PORTS  | IDX | STA | DCMD  |DTYP |  RSV |  DTALEN |
+        * 8 |  PAYLEN  | POPTS  | IDX | STA | DCMD  |DTYP |  RSV |  DTALEN |
         *   +--------------------------------------------------------------+
         *   63       46 45    40 39 36 35 32 31   24 23 20 19              0
+        *
+        * 82598 Advanced Transmit Descriptor (Write-Back Format)
+        *   +--------------------------------------------------------------+
+        * 0 |                          RSV [63:0]                          |
+        *   +--------------------------------------------------------------+
+        * 8 |            RSV           |  STA  |          NXTSEQ           |
+        *   +--------------------------------------------------------------+
+        *   63                       36 35   32 31                         0
+        *
+        * 82599+ Advanced Transmit Descriptor
+        *   +--------------------------------------------------------------+
+        * 0 |         Buffer Address [63:0]                                |
+        *   +--------------------------------------------------------------+
+        * 8 |PAYLEN  |POPTS|CC|IDX  |STA  |DCMD  |DTYP |MAC  |RSV  |DTALEN |
+        *   +--------------------------------------------------------------+
+        *   63     46 45 40 39 38 36 35 32 31  24 23 20 19 18 17 16 15     0
+        *
+        * 82599+ Advanced Transmit Descriptor (Write-Back Format)
+        *   +--------------------------------------------------------------+
+        * 0 |                          RSV [63:0]                          |
+        *   +--------------------------------------------------------------+
+        * 8 |            RSV           |  STA  |           RSV             |
+        *   +--------------------------------------------------------------+
+        *   63                       36 35   32 31                         0
         */
 
        for (n = 0; n < adapter->num_tx_queues; n++) {
@@ -369,40 +392,43 @@ static void ixgbe_dump(struct ixgbe_adapter *adapter)
                pr_info("------------------------------------\n");
                pr_info("TX QUEUE INDEX = %d\n", tx_ring->queue_index);
                pr_info("------------------------------------\n");
-               pr_info("T [desc]     [address 63:0  ] "
-                       "[PlPOIdStDDt Ln] [bi->dma       ] "
-                       "leng  ntw timestamp        bi->skb\n");
+               pr_info("%s%s    %s              %s        %s          %s\n",
+                       "T [desc]     [address 63:0  ] ",
+                       "[PlPOIdStDDt Ln] [bi->dma       ] ",
+                       "leng", "ntw", "timestamp", "bi->skb");
 
                for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) {
                        tx_desc = IXGBE_TX_DESC(tx_ring, i);
                        tx_buffer = &tx_ring->tx_buffer_info[i];
                        u0 = (struct my_u0 *)tx_desc;
-                       pr_info("T [0x%03X]    %016llX %016llX %016llX"
-                               " %04X  %p %016llX %p", i,
-                               le64_to_cpu(u0->a),
-                               le64_to_cpu(u0->b),
-                               (u64)dma_unmap_addr(tx_buffer, dma),
-                               dma_unmap_len(tx_buffer, len),
-                               tx_buffer->next_to_watch,
-                               (u64)tx_buffer->time_stamp,
-                               tx_buffer->skb);
-                       if (i == tx_ring->next_to_use &&
-                               i == tx_ring->next_to_clean)
-                               pr_cont(" NTC/U\n");
-                       else if (i == tx_ring->next_to_use)
-                               pr_cont(" NTU\n");
-                       else if (i == tx_ring->next_to_clean)
-                               pr_cont(" NTC\n");
-                       else
-                               pr_cont("\n");
-
-                       if (netif_msg_pktdata(adapter) &&
-                           tx_buffer->skb)
-                               print_hex_dump(KERN_INFO, "",
-                                       DUMP_PREFIX_ADDRESS, 16, 1,
-                                       tx_buffer->skb->data,
+                       if (dma_unmap_len(tx_buffer, len) > 0) {
+                               pr_info("T [0x%03X]    %016llX %016llX %016llX %08X %p %016llX %p",
+                                       i,
+                                       le64_to_cpu(u0->a),
+                                       le64_to_cpu(u0->b),
+                                       (u64)dma_unmap_addr(tx_buffer, dma),
                                        dma_unmap_len(tx_buffer, len),
-                                       true);
+                                       tx_buffer->next_to_watch,
+                                       (u64)tx_buffer->time_stamp,
+                                       tx_buffer->skb);
+                               if (i == tx_ring->next_to_use &&
+                                       i == tx_ring->next_to_clean)
+                                       pr_cont(" NTC/U\n");
+                               else if (i == tx_ring->next_to_use)
+                                       pr_cont(" NTU\n");
+                               else if (i == tx_ring->next_to_clean)
+                                       pr_cont(" NTC\n");
+                               else
+                                       pr_cont("\n");
+
+                               if (netif_msg_pktdata(adapter) &&
+                                   tx_buffer->skb)
+                                       print_hex_dump(KERN_INFO, "",
+                                               DUMP_PREFIX_ADDRESS, 16, 1,
+                                               tx_buffer->skb->data,
+                                               dma_unmap_len(tx_buffer, len),
+                                               true);
+                       }
                }
        }
 
@@ -422,7 +448,9 @@ rx_ring_summary:
 
        dev_info(&adapter->pdev->dev, "RX Rings Dump\n");
 
-       /* Advanced Receive Descriptor (Read) Format
+       /* Receive Descriptor Formats
+        *
+        * 82598 Advanced Receive Descriptor (Read) Format
         *    63                                           1        0
         *    +-----------------------------------------------------+
         *  0 |       Packet Buffer Address [63:1]           |A0/NSE|
@@ -431,27 +459,52 @@ rx_ring_summary:
         *    +-----------------------------------------------------+
         *
         *
-        * Advanced Receive Descriptor (Write-Back) Format
+        * 82598 Advanced Receive Descriptor (Write-Back) Format
         *
         *   63       48 47    32 31  30      21 20 16 15   4 3     0
         *   +------------------------------------------------------+
-        * 0 | Packet     IP     |SPH| HDR_LEN   | RSV|Packet|  RSS |
-        *   | Checksum   Ident  |   |           |    | Type | Type |
+        * 0 |       RSS Hash /  |SPH| HDR_LEN  | RSV |Packet|  RSS |
+        *   | Packet   | IP     |   |          |     | Type | Type |
+        *   | Checksum | Ident  |   |          |     |      |      |
         *   +------------------------------------------------------+
         * 8 | VLAN Tag | Length | Extended Error | Extended Status |
         *   +------------------------------------------------------+
         *   63       48 47    32 31            20 19               0
+        *
+        * 82599+ Advanced Receive Descriptor (Read) Format
+        *    63                                           1        0
+        *    +-----------------------------------------------------+
+        *  0 |       Packet Buffer Address [63:1]           |A0/NSE|
+        *    +----------------------------------------------+------+
+        *  8 |       Header Buffer Address [63:1]           |  DD  |
+        *    +-----------------------------------------------------+
+        *
+        *
+        * 82599+ Advanced Receive Descriptor (Write-Back) Format
+        *
+        *   63       48 47    32 31  30      21 20 17 16   4 3     0
+        *   +------------------------------------------------------+
+        * 0 |RSS / Frag Checksum|SPH| HDR_LEN  |RSC- |Packet|  RSS |
+        *   |/ RTT / PCoE_PARAM |   |          | CNT | Type | Type |
+        *   |/ Flow Dir Flt ID  |   |          |     |      |      |
+        *   +------------------------------------------------------+
+        * 8 | VLAN Tag | Length |Extended Error| Xtnd Status/NEXTP |
+        *   +------------------------------------------------------+
+        *   63       48 47    32 31          20 19                 0
         */
+
        for (n = 0; n < adapter->num_rx_queues; n++) {
                rx_ring = adapter->rx_ring[n];
                pr_info("------------------------------------\n");
                pr_info("RX QUEUE INDEX = %d\n", rx_ring->queue_index);
                pr_info("------------------------------------\n");
-               pr_info("R  [desc]      [ PktBuf     A0] "
-                       "[  HeadBuf   DD] [bi->dma       ] [bi->skb] "
+               pr_info("%s%s%s",
+                       "R  [desc]      [ PktBuf     A0] ",
+                       "[  HeadBuf   DD] [bi->dma       ] [bi->skb       ] ",
                        "<-- Adv Rx Read format\n");
-               pr_info("RWB[desc]      [PcsmIpSHl PtRs] "
-                       "[vl er S cks ln] ---------------- [bi->skb] "
+               pr_info("%s%s%s",
+                       "RWB[desc]      [PcsmIpSHl PtRs] ",
+                       "[vl er S cks ln] ---------------- [bi->skb       ] ",
                        "<-- Adv Rx Write-Back format\n");
 
                for (i = 0; i < rx_ring->count; i++) {
@@ -646,6 +699,7 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        struct ixgbe_hw_stats *hwstats = &adapter->stats;
        u32 xoff[8] = {0};
+       u8 tc;
        int i;
        bool pfc_en = adapter->dcb_cfg.pfc_mode_enable;
 
@@ -659,21 +713,26 @@ static void ixgbe_update_xoff_received(struct ixgbe_adapter *adapter)
 
        /* update stats for each tc, only valid with PFC enabled */
        for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
+               u32 pxoffrxc;
+
                switch (hw->mac.type) {
                case ixgbe_mac_82598EB:
-                       xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+                       pxoffrxc = IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
                        break;
                default:
-                       xoff[i] = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+                       pxoffrxc = IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
                }
-               hwstats->pxoffrxc[i] += xoff[i];
+               hwstats->pxoffrxc[i] += pxoffrxc;
+               /* Get the TC for given UP */
+               tc = netdev_get_prio_tc_map(adapter->netdev, i);
+               xoff[tc] += pxoffrxc;
        }
 
        /* disarm tx queues that have received xoff frames */
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct ixgbe_ring *tx_ring = adapter->tx_ring[i];
-               u8 tc = tx_ring->dcb_tc;
 
+               tc = tx_ring->dcb_tc;
                if (xoff[tc])
                        clear_bit(__IXGBE_HANG_CHECK_ARMED, &tx_ring->state);
        }
@@ -791,10 +850,8 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
                total_bytes += tx_buffer->bytecount;
                total_packets += tx_buffer->gso_segs;
 
-#ifdef CONFIG_IXGBE_PTP
                if (unlikely(tx_buffer->tx_flags & IXGBE_TX_FLAGS_TSTAMP))
                        ixgbe_ptp_tx_hwtstamp(q_vector, tx_buffer->skb);
-#endif
 
                /* free the skb */
                dev_kfree_skb_any(tx_buffer->skb);
@@ -967,7 +1024,6 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
         * which will cause the DCA tag to be cleared.
         */
        rxctrl |= IXGBE_DCA_RXCTRL_DESC_RRO_EN |
-                 IXGBE_DCA_RXCTRL_DATA_DCA_EN |
                  IXGBE_DCA_RXCTRL_DESC_DCA_EN;
 
        IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(reg_idx), rxctrl);
@@ -1244,6 +1300,7 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                struct vlan_hdr *vlan;
                /* l3 headers */
                struct iphdr *ipv4;
+               struct ipv6hdr *ipv6;
        } hdr;
        __be16 protocol;
        u8 nexthdr = 0; /* default to not TCP */
@@ -1281,20 +1338,30 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                if (hlen < sizeof(struct iphdr))
                        return hdr.network - data;
 
+               /* record next protocol if header is present */
+               if (!hdr.ipv4->frag_off)
+                       nexthdr = hdr.ipv4->protocol;
+       } else if (protocol == __constant_htons(ETH_P_IPV6)) {
+               if ((hdr.network - data) > (max_len - sizeof(struct ipv6hdr)))
+                       return max_len;
+
                /* record next protocol */
-               nexthdr = hdr.ipv4->protocol;
-               hdr.network += hlen;
+               nexthdr = hdr.ipv6->nexthdr;
+               hlen = sizeof(struct ipv6hdr);
 #ifdef IXGBE_FCOE
        } else if (protocol == __constant_htons(ETH_P_FCOE)) {
                if ((hdr.network - data) > (max_len - FCOE_HEADER_LEN))
                        return max_len;
-               hdr.network += FCOE_HEADER_LEN;
+               hlen = FCOE_HEADER_LEN;
 #endif
        } else {
                return hdr.network - data;
        }
 
-       /* finally sort out TCP */
+       /* relocate pointer to start of L4 header */
+       hdr.network += hlen;
+
+       /* finally sort out TCP/UDP */
        if (nexthdr == IPPROTO_TCP) {
                if ((hdr.network - data) > (max_len - sizeof(struct tcphdr)))
                        return max_len;
@@ -1307,6 +1374,11 @@ static unsigned int ixgbe_get_headlen(unsigned char *data,
                        return hdr.network - data;
 
                hdr.network += hlen;
+       } else if (nexthdr == IPPROTO_UDP) {
+               if ((hdr.network - data) > (max_len - sizeof(struct udphdr)))
+                       return max_len;
+
+               hdr.network += sizeof(struct udphdr);
        }
 
        /*
@@ -1369,9 +1441,7 @@ static void ixgbe_process_skb_fields(struct ixgbe_ring *rx_ring,
 
        ixgbe_rx_checksum(rx_ring, rx_desc, skb);
 
-#ifdef CONFIG_IXGBE_PTP
        ixgbe_ptp_rx_hwtstamp(rx_ring->q_vector, rx_desc, skb);
-#endif
 
        if ((dev->features & NETIF_F_HW_VLAN_RX) &&
            ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_VP)) {
@@ -1781,7 +1851,7 @@ dma_sync:
  **/
 static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                               struct ixgbe_ring *rx_ring,
-                              int budget)
+                              const int budget)
 {
        unsigned int total_rx_bytes = 0, total_rx_packets = 0;
 #ifdef IXGBE_FCOE
@@ -1832,7 +1902,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
 
                /* probably a little skewed due to removing CRC */
                total_rx_bytes += skb->len;
-               total_rx_packets++;
 
                /* populate checksum, timestamp, VLAN, and protocol */
                ixgbe_process_skb_fields(rx_ring, rx_desc, skb);
@@ -1865,8 +1934,8 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
                ixgbe_rx_skb(q_vector, skb);
 
                /* update budget accounting */
-               budget--;
-       } while (likely(budget));
+               total_rx_packets++;
+       } while (likely(total_rx_packets < budget));
 
        u64_stats_update_begin(&rx_ring->syncp);
        rx_ring->stats.packets += total_rx_packets;
@@ -1878,7 +1947,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
        if (cleaned_count)
                ixgbe_alloc_rx_buffers(rx_ring, cleaned_count);
 
-       return !!budget;
+       return (total_rx_packets < budget);
 }
 
 /**
@@ -1914,20 +1983,6 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
                ixgbe_for_each_ring(ring, q_vector->tx)
                        ixgbe_set_ivar(adapter, 1, ring->reg_idx, v_idx);
 
-               if (q_vector->tx.ring && !q_vector->rx.ring) {
-                       /* tx only vector */
-                       if (adapter->tx_itr_setting == 1)
-                               q_vector->itr = IXGBE_10K_ITR;
-                       else
-                               q_vector->itr = adapter->tx_itr_setting;
-               } else {
-                       /* rx or rx/tx vector */
-                       if (adapter->rx_itr_setting == 1)
-                               q_vector->itr = IXGBE_20K_ITR;
-                       else
-                               q_vector->itr = adapter->rx_itr_setting;
-               }
-
                ixgbe_write_eitr(q_vector);
        }
 
@@ -2324,10 +2379,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
                break;
        }
 
-#ifdef CONFIG_IXGBE_PTP
        if (adapter->hw.mac.type == ixgbe_mac_X540)
                mask |= IXGBE_EIMS_TIMESYNC;
-#endif
 
        if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
            !(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
@@ -2393,10 +2446,8 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
 
        ixgbe_check_fan_failure(adapter, eicr);
 
-#ifdef CONFIG_IXGBE_PTP
        if (unlikely(eicr & IXGBE_EICR_TIMESYNC))
                ixgbe_ptp_check_pps_event(adapter, eicr);
-#endif
 
        /* re-enable the original interrupt state, no lsc, no queues */
        if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -2588,10 +2639,8 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
        }
 
        ixgbe_check_fan_failure(adapter, eicr);
-#ifdef CONFIG_IXGBE_PTP
        if (unlikely(eicr & IXGBE_EICR_TIMESYNC))
                ixgbe_ptp_check_pps_event(adapter, eicr);
-#endif
 
        /* would disable interrupts here but EIAM disabled it */
        napi_schedule(&q_vector->napi);
@@ -2699,12 +2748,6 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_q_vector *q_vector = adapter->q_vector[0];
 
-       /* rx/tx vector */
-       if (adapter->rx_itr_setting == 1)
-               q_vector->itr = IXGBE_20K_ITR;
-       else
-               q_vector->itr = adapter->rx_itr_setting;
-
        ixgbe_write_eitr(q_vector);
 
        ixgbe_set_ivar(adapter, 0, 0, 0);
@@ -3132,14 +3175,6 @@ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
        ixgbe_configure_srrctl(adapter, ring);
        ixgbe_configure_rscctl(adapter, ring);
 
-       /* If operating in IOV mode set RLPML for X540 */
-       if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
-           hw->mac.type == ixgbe_mac_X540) {
-               rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
-               rxdctl |= ((ring->netdev->mtu + ETH_HLEN +
-                           ETH_FCS_LEN + VLAN_HLEN) | IXGBE_RXDCTL_RLPML_EN);
-       }
-
        if (hw->mac.type == ixgbe_mac_82598EB) {
                /*
                 * enable cache line friendly hardware writes:
@@ -3211,7 +3246,8 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
        IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset ^ 1), reg_offset - 1);
        IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), (~0) << vf_shift);
        IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset ^ 1), reg_offset - 1);
-       IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+       if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB)
+               IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
 
        /* Map PF MAC address in RAR Entry 0 to first pool following VFs */
        hw->mac.ops.set_vmdq(hw, 0, VMDQ_P(0));
@@ -3234,8 +3270,6 @@ static void ixgbe_configure_virtualization(struct ixgbe_adapter *adapter)
 
        IXGBE_WRITE_REG(hw, IXGBE_GCR_EXT, gcr_ext);
 
-       /* enable Tx loopback for VF/PF communication */
-       IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
 
        /* Enable MAC Anti-Spoofing */
        hw->mac.ops.set_mac_anti_spoofing(hw, (adapter->num_vfs != 0),
@@ -3263,6 +3297,11 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
                max_frame = IXGBE_FCOE_JUMBO_FRAME_SIZE;
 
 #endif /* IXGBE_FCOE */
+
+       /* adjust max frame to be at least the size of a standard frame */
+       if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN))
+               max_frame = (ETH_FRAME_LEN + ETH_FCS_LEN);
+
        mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
        if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
                mhadd &= ~IXGBE_MHADD_MFS_MASK;
@@ -3271,9 +3310,6 @@ static void ixgbe_set_rx_buffer_len(struct ixgbe_adapter *adapter)
                IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
        }
 
-       /* MHADD will allow an extra 4 bytes past for vlan tagged frames */
-       max_frame += VLAN_HLEN;
-
        hlreg0 = IXGBE_READ_REG(hw, IXGBE_HLREG0);
        /* set jumbo enable since MHADD.MFS is keeping size locked at max_frame */
        hlreg0 |= IXGBE_HLREG0_JUMBOEN;
@@ -4072,11 +4108,8 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
        else
                ixgbe_configure_msi_and_legacy(adapter);
 
-       /* enable the optics for both mult-speed fiber and 82599 SFP+ fiber */
-       if (hw->mac.ops.enable_tx_laser &&
-           ((hw->phy.multispeed_fiber) ||
-            ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
-             (hw->mac.type == ixgbe_mac_82599EB))))
+       /* enable the optics for 82599 SFP+ fiber */
+       if (hw->mac.ops.enable_tx_laser)
                hw->mac.ops.enable_tx_laser(hw);
 
        clear_bit(__IXGBE_DOWN, &adapter->state);
@@ -4192,6 +4225,9 @@ void ixgbe_reset(struct ixgbe_adapter *adapter)
        /* update SAN MAC vmdq pool selection */
        if (hw->mac.san_mac_rar_index)
                hw->mac.ops.set_vmdq_san_mac(hw, VMDQ_P(0));
+
+       if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+               ixgbe_ptp_reset(adapter);
 }
 
 /**
@@ -4393,11 +4429,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
        if (!pci_channel_offline(adapter->pdev))
                ixgbe_reset(adapter);
 
-       /* power down the optics for multispeed fiber and 82599 SFP+ fiber */
-       if (hw->mac.ops.disable_tx_laser &&
-           ((hw->phy.multispeed_fiber) ||
-            ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
-             (hw->mac.type == ixgbe_mac_82599EB))))
+       /* power down the optics for 82599 SFP+ fiber */
+       if (hw->mac.ops.disable_tx_laser)
                hw->mac.ops.disable_tx_laser(hw);
 
        ixgbe_clean_all_tx_rings(adapter);
@@ -4429,11 +4462,12 @@ static void ixgbe_tx_timeout(struct net_device *netdev)
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  **/
-static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
+static int ixgbe_sw_init(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
        struct pci_dev *pdev = adapter->pdev;
        unsigned int rss;
+       u32 fwsm;
 #ifdef CONFIG_IXGBE_DCB
        int j;
        struct tc_configuration *tc;
@@ -4457,7 +4491,9 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
                adapter->max_q_vectors = MAX_Q_VECTORS_82598;
                break;
        case ixgbe_mac_X540:
-               adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
+               fwsm = IXGBE_READ_REG(hw, IXGBE_FWSM);
+               if (fwsm & IXGBE_FWSM_TS_ENABLED)
+                       adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE;
        case ixgbe_mac_82599EB:
                adapter->max_q_vectors = MAX_Q_VECTORS_82599;
                adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE;
@@ -4533,7 +4569,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
        ixgbe_pbthresh_setup(adapter);
        hw->fc.pause_time = IXGBE_DEFAULT_FCPAUSE;
        hw->fc.send_xon = true;
-       hw->fc.disable_fc_autoneg = false;
+       hw->fc.disable_fc_autoneg =
+               (ixgbe_device_supports_autoneg_fc(hw) == 0) ? false : true;
 
 #ifdef CONFIG_PCI_IOV
        /* assign number of SR-IOV VFs */
@@ -4828,14 +4865,14 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu)
                return -EINVAL;
 
        /*
-        * For 82599EB we cannot allow PF to change MTU greater than 1500
-        * in SR-IOV mode as it may cause buffer overruns in guest VFs that
-        * don't allocate and chain buffers correctly.
+        * For 82599EB we cannot allow legacy VFs to enable their receive
+        * paths when MTU greater than 1500 is configured.  So display a
+        * warning that legacy VFs will be disabled.
         */
        if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
            (adapter->hw.mac.type == ixgbe_mac_82599EB) &&
            (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE))
-                       return -EINVAL;
+               e_warn(probe, "Setting MTU > 1500 will disable legacy VFs\n");
 
        e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
 
@@ -4901,6 +4938,8 @@ static int ixgbe_open(struct net_device *netdev)
        if (err)
                goto err_set_queues;
 
+       ixgbe_ptp_init(adapter);
+
        ixgbe_up_complete(adapter);
 
        return 0;
@@ -4932,6 +4971,8 @@ static int ixgbe_close(struct net_device *netdev)
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
+       ixgbe_ptp_stop(adapter);
+
        ixgbe_down(adapter);
        ixgbe_free_irq(adapter);
 
@@ -5022,14 +5063,8 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
        if (wufc) {
                ixgbe_set_rx_mode(netdev);
 
-               /*
-                * enable the optics for both mult-speed fiber and
-                * 82599 SFP+ fiber as we can WoL.
-                */
-               if (hw->mac.ops.enable_tx_laser &&
-                   (hw->phy.multispeed_fiber ||
-                   (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber &&
-                    hw->mac.type == ixgbe_mac_82599EB)))
+               /* enable the optics for 82599 SFP+ fiber as we can WoL */
+               if (hw->mac.ops.enable_tx_laser)
                        hw->mac.ops.enable_tx_laser(hw);
 
                /* turn on all-multi mode if wake on multicast is enabled */
@@ -5442,6 +5477,23 @@ static void ixgbe_watchdog_update_link(struct ixgbe_adapter *adapter)
        adapter->link_speed = link_speed;
 }
 
+static void ixgbe_update_default_up(struct ixgbe_adapter *adapter)
+{
+#ifdef CONFIG_IXGBE_DCB
+       struct net_device *netdev = adapter->netdev;
+       struct dcb_app app = {
+                             .selector = IEEE_8021QAZ_APP_SEL_ETHERTYPE,
+                             .protocol = 0,
+                            };
+       u8 up = 0;
+
+       if (adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE)
+               up = dcb_ieee_getapp_mask(netdev, &app);
+
+       adapter->default_up = (up > 1) ? (ffs(up) - 1) : 0;
+#endif
+}
+
 /**
  * ixgbe_watchdog_link_is_up - update netif_carrier status and
  *                             print link up message
@@ -5482,9 +5534,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
                break;
        }
 
-#ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_start_cyclecounter(adapter);
-#endif
+       if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+               ixgbe_ptp_start_cyclecounter(adapter);
 
        e_info(drv, "NIC Link is Up %s, Flow Control: %s\n",
               (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
@@ -5501,6 +5552,9 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
        netif_carrier_on(netdev);
        ixgbe_check_vf_rate_limit(adapter);
 
+       /* update the default user priority for VFs */
+       ixgbe_update_default_up(adapter);
+
        /* ping all the active vfs to let them know link has changed */
        ixgbe_ping_all_vfs(adapter);
 }
@@ -5526,9 +5580,8 @@ static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *adapter)
        if (ixgbe_is_sfp(hw) && hw->mac.type == ixgbe_mac_82598EB)
                adapter->flags2 |= IXGBE_FLAG2_SEARCH_FOR_SFP;
 
-#ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_start_cyclecounter(adapter);
-#endif
+       if (adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED)
+               ixgbe_ptp_start_cyclecounter(adapter);
 
        e_info(drv, "NIC Link is Down\n");
        netif_carrier_off(netdev);
@@ -5833,9 +5886,7 @@ static void ixgbe_service_task(struct work_struct *work)
        ixgbe_watchdog_subtask(adapter);
        ixgbe_fdir_reinit_subtask(adapter);
        ixgbe_check_hang_subtask(adapter);
-#ifdef CONFIG_IXGBE_PTP
        ixgbe_ptp_overflow_check(adapter);
-#endif
 
        ixgbe_service_event_complete(adapter);
 }
@@ -5988,10 +6039,8 @@ static __le32 ixgbe_tx_cmd_type(u32 tx_flags)
        if (tx_flags & IXGBE_TX_FLAGS_HW_VLAN)
                cmd_type |= cpu_to_le32(IXGBE_ADVTXD_DCMD_VLE);
 
-#ifdef CONFIG_IXGBE_PTP
        if (tx_flags & IXGBE_TX_FLAGS_TSTAMP)
                cmd_type |= cpu_to_le32(IXGBE_ADVTXD_MAC_TSTAMP);
-#endif
 
        /* set segmentation enable bits for TSO/FSO */
 #ifdef IXGBE_FCOE
@@ -6393,12 +6442,10 @@ netdev_tx_t ixgbe_xmit_frame_ring(struct sk_buff *skb,
 
        skb_tx_timestamp(skb);
 
-#ifdef CONFIG_IXGBE_PTP
        if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
                tx_flags |= IXGBE_TX_FLAGS_TSTAMP;
        }
-#endif
 
 #ifdef CONFIG_PCI_IOV
        /*
@@ -6485,6 +6532,7 @@ static netdev_tx_t ixgbe_xmit_frame(struct sk_buff *skb,
                if (skb_pad(skb, 17 - skb->len))
                        return NETDEV_TX_OK;
                skb->len = 17;
+               skb_set_tail_pointer(skb, 17);
        }
 
        tx_ring = adapter->tx_ring[skb->queue_mapping];
@@ -6547,10 +6595,8 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
        switch (cmd) {
-#ifdef CONFIG_IXGBE_PTP
        case SIOCSHWTSTAMP:
                return ixgbe_ptp_hwtstamp_ioctl(adapter, req, cmd);
-#endif
        default:
                return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd);
        }
@@ -6910,13 +6956,16 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
        if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
                return -EOPNOTSUPP;
 
-       if (ndm->ndm_state & NUD_PERMANENT) {
+       /* Hardware does not support aging addresses so if a
+        * ndm_state is given only allow permanent addresses
+        */
+       if (ndm->ndm_state && !(ndm->ndm_state & NUD_PERMANENT)) {
                pr_info("%s: FDB only supports static addresses\n",
                        ixgbe_driver_name);
                return -EINVAL;
        }
 
-       if (is_unicast_ether_addr(addr)) {
+       if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) {
                u32 rar_uc_entries = IXGBE_MAX_PF_MACVLANS;
 
                if (netdev_uc_count(dev) < rar_uc_entries)
@@ -6974,6 +7023,61 @@ static int ixgbe_ndo_fdb_dump(struct sk_buff *skb,
        return idx;
 }
 
+static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
+                                   struct nlmsghdr *nlh)
+{
+       struct ixgbe_adapter *adapter = netdev_priv(dev);
+       struct nlattr *attr, *br_spec;
+       int rem;
+
+       if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+               return -EOPNOTSUPP;
+
+       br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+
+       nla_for_each_nested(attr, br_spec, rem) {
+               __u16 mode;
+               u32 reg = 0;
+
+               if (nla_type(attr) != IFLA_BRIDGE_MODE)
+                       continue;
+
+               mode = nla_get_u16(attr);
+               if (mode == BRIDGE_MODE_VEPA) {
+                       reg = 0;
+                       adapter->flags2 &= ~IXGBE_FLAG2_BRIDGE_MODE_VEB;
+               } else if (mode == BRIDGE_MODE_VEB) {
+                       reg = IXGBE_PFDTXGSWC_VT_LBEN;
+                       adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB;
+               } else
+                       return -EINVAL;
+
+               IXGBE_WRITE_REG(&adapter->hw, IXGBE_PFDTXGSWC, reg);
+
+               e_info(drv, "enabling bridge mode: %s\n",
+                       mode == BRIDGE_MODE_VEPA ? "VEPA" : "VEB");
+       }
+
+       return 0;
+}
+
+static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+                                   struct net_device *dev)
+{
+       struct ixgbe_adapter *adapter = netdev_priv(dev);
+       u16 mode;
+
+       if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED))
+               return 0;
+
+       if (adapter->flags2 & IXGBE_FLAG2_BRIDGE_MODE_VEB)
+               mode = BRIDGE_MODE_VEB;
+       else
+               mode = BRIDGE_MODE_VEPA;
+
+       return ndo_dflt_bridge_getlink(skb, pid, seq, dev, mode);
+}
+
 static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_open               = ixgbe_open,
        .ndo_stop               = ixgbe_close,
@@ -7013,6 +7117,8 @@ static const struct net_device_ops ixgbe_netdev_ops = {
        .ndo_fdb_add            = ixgbe_ndo_fdb_add,
        .ndo_fdb_del            = ixgbe_ndo_fdb_del,
        .ndo_fdb_dump           = ixgbe_ndo_fdb_dump,
+       .ndo_bridge_setlink     = ixgbe_ndo_bridge_setlink,
+       .ndo_bridge_getlink     = ixgbe_ndo_bridge_getlink,
 };
 
 /**
@@ -7042,6 +7148,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
                                break;
                case IXGBE_SUBDEV_ID_82599_SFP:
                case IXGBE_SUBDEV_ID_82599_RNDC:
+               case IXGBE_SUBDEV_ID_82599_ECNA_DP:
                        is_wol_supported = 1;
                        break;
                }
@@ -7079,8 +7186,7 @@ int ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  **/
-static int __devinit ixgbe_probe(struct pci_dev *pdev,
-                                const struct pci_device_id *ent)
+static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct ixgbe_adapter *adapter = NULL;
@@ -7340,7 +7446,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        memcpy(netdev->dev_addr, hw->mac.perm_addr, netdev->addr_len);
        memcpy(netdev->perm_addr, hw->mac.perm_addr, netdev->addr_len);
 
-       if (ixgbe_validate_mac_addr(netdev->perm_addr)) {
+       if (!is_valid_ether_addr(netdev->perm_addr)) {
                e_dev_err("invalid MAC address\n");
                err = -EIO;
                goto err_sw_init;
@@ -7364,10 +7470,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
 
        device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
-#ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_init(adapter);
-#endif /* CONFIG_IXGBE_PTP*/
-
        /* save off EEPROM version number */
        hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh);
        hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
@@ -7420,11 +7522,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
        if (err)
                goto err_register;
 
-       /* power down the optics for multispeed fiber and 82599 SFP+ fiber */
-       if (hw->mac.ops.disable_tx_laser &&
-           ((hw->phy.multispeed_fiber) ||
-            ((hw->mac.ops.get_media_type(hw) == ixgbe_media_type_fiber) &&
-             (hw->mac.type == ixgbe_mac_82599EB))))
+       /* power down the optics for 82599 SFP+ fiber */
+       if (hw->mac.ops.disable_tx_laser)
                hw->mac.ops.disable_tx_laser(hw);
 
        /* carrier off reporting is important to ethtool even BEFORE open */
@@ -7493,7 +7592,7 @@ err_dma:
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  **/
-static void __devexit ixgbe_remove(struct pci_dev *pdev)
+static void ixgbe_remove(struct pci_dev *pdev)
 {
        struct ixgbe_adapter *adapter = pci_get_drvdata(pdev);
        struct net_device *netdev = adapter->netdev;
@@ -7505,9 +7604,6 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
        set_bit(__IXGBE_DOWN, &adapter->state);
        cancel_work_sync(&adapter->service_task);
 
-#ifdef CONFIG_IXGBE_PTP
-       ixgbe_ptp_stop(adapter);
-#endif
 
 #ifdef CONFIG_IXGBE_DCA
        if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
@@ -7736,7 +7832,7 @@ static struct pci_driver ixgbe_driver = {
        .name     = ixgbe_driver_name,
        .id_table = ixgbe_pci_tbl,
        .probe    = ixgbe_probe,
-       .remove   = __devexit_p(ixgbe_remove),
+       .remove   = ixgbe_remove,
 #ifdef CONFIG_PM
        .suspend  = ixgbe_suspend,
        .resume   = ixgbe_resume,
index 310bdd9610757558827d31155ad1bc839d617bfb..42dd65e6ac978906b70bd565c1811a26fda3bb3f 100644 (file)
 /* bits 23:16 are used for exra info for certain messages */
 #define IXGBE_VT_MSGINFO_MASK     (0xFF << IXGBE_VT_MSGINFO_SHIFT)
 
+/* definitions to support mailbox API version negotiation */
+
+/*
+ * Each element denotes a version of the API; existing numbers may not
+ * change; any additions must go at the end
+ */
+enum ixgbe_pfvf_api_rev {
+       ixgbe_mbox_api_10,      /* API version 1.0, linux/freebsd VF driver */
+       ixgbe_mbox_api_20,      /* API version 2.0, solaris Phase1 VF driver */
+       ixgbe_mbox_api_11,      /* API version 1.1, linux/freebsd VF driver */
+       /* This value should always be last */
+       ixgbe_mbox_api_unknown, /* indicates that API version is not known */
+};
+
+/* mailbox API, legacy requests */
 #define IXGBE_VF_RESET            0x01 /* VF requests reset */
 #define IXGBE_VF_SET_MAC_ADDR     0x02 /* VF requests PF to set MAC addr */
 #define IXGBE_VF_SET_MULTICAST    0x03 /* VF requests PF to set MC addr */
 #define IXGBE_VF_SET_VLAN         0x04 /* VF requests PF to set VLAN */
-#define IXGBE_VF_SET_LPE          0x05 /* VF requests PF to set VMOLR.LPE */
-#define IXGBE_VF_SET_MACVLAN      0x06 /* VF requests PF for unicast filter */
+
+/* mailbox API, version 1.0 VF requests */
+#define IXGBE_VF_SET_LPE       0x05 /* VF requests PF to set VMOLR.LPE */
+#define IXGBE_VF_SET_MACVLAN   0x06 /* VF requests PF for unicast filter */
+#define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */
+
+/* mailbox API, version 1.1 VF requests */
+#define IXGBE_VF_GET_QUEUES    0x09 /* get queue configuration */
+
+/* GET_QUEUES return data indices within the mailbox */
+#define IXGBE_VF_TX_QUEUES     1       /* number of Tx queues supported */
+#define IXGBE_VF_RX_QUEUES     2       /* number of Rx queues supported */
+#define IXGBE_VF_TRANS_VLAN    3       /* Indication of port vlan */
+#define IXGBE_VF_DEF_QUEUE     4       /* Default queue offset */
 
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN 4
index d9291316ee9f3aee8bbe54710a6ebcffb37c6ef7..1a751c9d09c47f319e45d76a9c2bbad8573016d3 100644 (file)
@@ -387,6 +387,15 @@ void ixgbe_ptp_check_pps_event(struct ixgbe_adapter *adapter, u32 eicr)
        struct ixgbe_hw *hw = &adapter->hw;
        struct ptp_clock_event event;
 
+       event.type = PTP_CLOCK_PPS;
+
+       /* this check is necessary in case the interrupt was enabled via some
+        * alternative means (ex. debug_fs). Better to check here than
+        * everywhere that calls this function.
+        */
+       if (!adapter->ptp_clock)
+               return;
+
        switch (hw->mac.type) {
        case ixgbe_mac_X540:
                ptp_clock_event(adapter->ptp_clock, &event);
@@ -411,7 +420,7 @@ void ixgbe_ptp_overflow_check(struct ixgbe_adapter *adapter)
        unsigned long elapsed_jiffies = adapter->last_overflow_check - jiffies;
        struct timespec ts;
 
-       if ((adapter->flags2 & IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED) &&
+       if ((adapter->flags2 & IXGBE_FLAG2_PTP_ENABLED) &&
            (elapsed_jiffies >= IXGBE_OVERFLOW_PERIOD)) {
                ixgbe_ptp_gettime(&adapter->ptp_caps, &ts);
                adapter->last_overflow_check = jiffies;
@@ -554,12 +563,14 @@ void ixgbe_ptp_rx_hwtstamp(struct ixgbe_q_vector *q_vector,
        adapter = q_vector->adapter;
        hw = &adapter->hw;
 
+       if (likely(!ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter)))
+               return;
+
        tsyncrxctl = IXGBE_READ_REG(hw, IXGBE_TSYNCRXCTL);
 
        /* Check if we have a valid timestamp and make sure the skb should
         * have been timestamped */
-       if (likely(!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID) ||
-                  !ixgbe_ptp_match(skb, adapter->rx_hwtstamp_filter)))
+       if (!(tsyncrxctl & IXGBE_TSYNCRXCTL_VALID))
                return;
 
        /*
@@ -622,8 +633,7 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
        struct hwtstamp_config config;
        u32 tsync_tx_ctl = IXGBE_TSYNCTXCTL_ENABLED;
        u32 tsync_rx_ctl = IXGBE_TSYNCRXCTL_ENABLED;
-       u32 tsync_rx_mtrl = 0;
-       bool is_l4 = false;
+       u32 tsync_rx_mtrl = PTP_EV_PORT << 16;
        bool is_l2 = false;
        u32 regval;
 
@@ -646,16 +656,15 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
        switch (config.rx_filter) {
        case HWTSTAMP_FILTER_NONE:
                tsync_rx_ctl = 0;
+               tsync_rx_mtrl = 0;
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
                tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
                tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG;
-               is_l4 = true;
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
                tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
                tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
-               is_l4 = true;
                break;
        case HWTSTAMP_FILTER_PTP_V2_EVENT:
        case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
@@ -668,7 +677,6 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
        case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
                tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_EVENT_V2;
                is_l2 = true;
-               is_l4 = true;
                config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
                break;
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
@@ -693,42 +701,15 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
        /* Store filter value for later use */
        adapter->rx_hwtstamp_filter = config.rx_filter;
 
-       /* define ethertype filter for timestamped packets */
+       /* define ethertype filter for timestamping L2 packets */
        if (is_l2)
-               IXGBE_WRITE_REG(hw, IXGBE_ETQF(3),
+               IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588),
                                (IXGBE_ETQF_FILTER_EN | /* enable filter */
                                 IXGBE_ETQF_1588 | /* enable timestamping */
                                 ETH_P_1588));     /* 1588 eth protocol type */
        else
-               IXGBE_WRITE_REG(hw, IXGBE_ETQF(3), 0);
-
-#define PTP_PORT 319
-       /* L4 Queue Filter[3]: filter by destination port and protocol */
-       if (is_l4) {
-               u32 ftqf = (IXGBE_FTQF_PROTOCOL_UDP /* UDP */
-                           | IXGBE_FTQF_POOL_MASK_EN /* Pool not compared */
-                           | IXGBE_FTQF_QUEUE_ENABLE);
-
-               ftqf |= ((IXGBE_FTQF_PROTOCOL_COMP_MASK /* protocol check */
-                         & IXGBE_FTQF_DEST_PORT_MASK /* dest check */
-                         & IXGBE_FTQF_SOURCE_PORT_MASK) /* source check */
-                        << IXGBE_FTQF_5TUPLE_MASK_SHIFT);
+               IXGBE_WRITE_REG(hw, IXGBE_ETQF(IXGBE_ETQF_FILTER_1588), 0);
 
-               IXGBE_WRITE_REG(hw, IXGBE_L34T_IMIR(3),
-                               (3 << IXGBE_IMIR_RX_QUEUE_SHIFT_82599 |
-                                IXGBE_IMIR_SIZE_BP_82599));
-
-               /* enable port check */
-               IXGBE_WRITE_REG(hw, IXGBE_SDPQF(3),
-                               (htons(PTP_PORT) |
-                                htons(PTP_PORT) << 16));
-
-               IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), ftqf);
-
-               tsync_rx_mtrl |= PTP_PORT << 16;
-       } else {
-               IXGBE_WRITE_REG(hw, IXGBE_FTQF(3), 0);
-       }
 
        /* enable/disable TX */
        regval = IXGBE_READ_REG(hw, IXGBE_TSYNCTXCTL);
@@ -759,57 +740,19 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter,
  * ixgbe_ptp_start_cyclecounter - create the cycle counter from hw
  * @adapter: pointer to the adapter structure
  *
- * this function initializes the timecounter and cyclecounter
- * structures for use in generated a ns counter from the arbitrary
- * fixed point cycles registers in the hardware.
- *
- * A change in link speed impacts the frequency of the DMA clock on
- * the device, which is used to generate the cycle counter
- * registers. Therefor this function is called whenever the link speed
- * changes.
- *
- * This function also turns on the SDP pin for clock out feature (X540
- * only), because this is where the shift is first calculated.
+ * This function should be called to set the proper values for the TIMINCA
+ * register and tell the cyclecounter structure what the tick rate of SYSTIME
+ * is. It does not directly modify SYSTIME registers or the timecounter
+ * structure. It should be called whenever a new TIMINCA value is necessary,
+ * such as during initialization or when the link speed changes.
  */
 void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
        u32 incval = 0;
-       u32 timinca = 0;
        u32 shift = 0;
-       u32 cycle_speed;
        unsigned long flags;
 
-       /**
-        * Determine what speed we need to set the cyclecounter
-        * for. It should be different for 100Mb, 1Gb, and 10Gb. Treat
-        * unknown speeds as 10Gb. (Hence why we can't just copy the
-        * link_speed.
-        */
-       switch (adapter->link_speed) {
-       case IXGBE_LINK_SPEED_100_FULL:
-       case IXGBE_LINK_SPEED_1GB_FULL:
-       case IXGBE_LINK_SPEED_10GB_FULL:
-               cycle_speed = adapter->link_speed;
-               break;
-       default:
-               /* cycle speed should be 10Gb when there is no link */
-               cycle_speed = IXGBE_LINK_SPEED_10GB_FULL;
-               break;
-       }
-
-       /*
-        * grab the current TIMINCA value from the register so that it can be
-        * double checked. If the register value has been cleared, it must be
-        * reset to the correct value for generating a cyclecounter. If
-        * TIMINCA is zero, the SYSTIME registers do not increment at all.
-        */
-       timinca = IXGBE_READ_REG(hw, IXGBE_TIMINCA);
-
-       /* Bail if the cycle speed didn't change and TIMINCA is non-zero */
-       if (adapter->cycle_speed == cycle_speed && timinca)
-               return;
-
        /**
         * Scale the NIC cycle counter by a large factor so that
         * relatively small corrections to the frequency can be added
@@ -819,8 +762,12 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
         * to nanoseconds using only a multiplier and a right-shift,
         * and (c) the value must fit within the timinca register space
         * => math based on internal DMA clock rate and available bits
+        *
+        * Note that when there is no link, internal DMA clock is same as when
+        * link speed is 10Gb. Set the registers correctly even when link is
+        * down to preserve the clock setting
         */
-       switch (cycle_speed) {
+       switch (adapter->link_speed) {
        case IXGBE_LINK_SPEED_100_FULL:
                incval = IXGBE_INCVAL_100;
                shift = IXGBE_INCVAL_SHIFT_100;
@@ -830,6 +777,7 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
                shift = IXGBE_INCVAL_SHIFT_1GB;
                break;
        case IXGBE_LINK_SPEED_10GB_FULL:
+       default:
                incval = IXGBE_INCVAL_10GB;
                shift = IXGBE_INCVAL_SHIFT_10GB;
                break;
@@ -857,18 +805,11 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
                return;
        }
 
-       /* reset the system time registers */
-       IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
-       IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
-       IXGBE_WRITE_FLUSH(hw);
-
-       /* store the new cycle speed */
-       adapter->cycle_speed = cycle_speed;
-
+       /* update the base incval used to calculate frequency adjustment */
        ACCESS_ONCE(adapter->base_incval) = incval;
        smp_mb();
 
-       /* grab the ptp lock */
+       /* need lock to prevent incorrect read while modifying cyclecounter */
        spin_lock_irqsave(&adapter->tmreg_lock, flags);
 
        memset(&adapter->cc, 0, sizeof(adapter->cc));
@@ -877,6 +818,31 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
        adapter->cc.shift = shift;
        adapter->cc.mult = 1;
 
+       spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+}
+
+/**
+ * ixgbe_ptp_reset
+ * @adapter: the ixgbe private board structure
+ *
+ * When the MAC resets, all timesync features are reset. This function should be
+ * called to re-enable the PTP clock structure. It will re-init the timecounter
+ * structure based on the kernel time as well as setup the cycle counter data.
+ */
+void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       unsigned long flags;
+
+       /* set SYSTIME registers to 0 just in case */
+       IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0x00000000);
+       IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0x00000000);
+       IXGBE_WRITE_FLUSH(hw);
+
+       ixgbe_ptp_start_cyclecounter(adapter);
+
+       spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
        /* reset the ns time counter */
        timecounter_init(&adapter->tc, &adapter->cc,
                         ktime_to_ns(ktime_get_real()));
@@ -904,7 +870,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 
        switch (adapter->hw.mac.type) {
        case ixgbe_mac_X540:
-               snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+               snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
                adapter->ptp_caps.owner = THIS_MODULE;
                adapter->ptp_caps.max_adj = 250000000;
                adapter->ptp_caps.n_alarm = 0;
@@ -918,7 +884,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
                adapter->ptp_caps.enable = ixgbe_ptp_enable;
                break;
        case ixgbe_mac_82599EB:
-               snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
+               snprintf(adapter->ptp_caps.name, 16, "%s", netdev->name);
                adapter->ptp_caps.owner = THIS_MODULE;
                adapter->ptp_caps.max_adj = 250000000;
                adapter->ptp_caps.n_alarm = 0;
@@ -942,11 +908,6 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 
        spin_lock_init(&adapter->tmreg_lock);
 
-       ixgbe_ptp_start_cyclecounter(adapter);
-
-       /* (Re)start the overflow check */
-       adapter->flags2 |= IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED;
-
        adapter->ptp_clock = ptp_clock_register(&adapter->ptp_caps,
                                                &adapter->pdev->dev);
        if (IS_ERR(adapter->ptp_clock)) {
@@ -955,6 +916,11 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
        } else
                e_dev_info("registered PHC device on %s\n", netdev->name);
 
+       ixgbe_ptp_reset(adapter);
+
+       /* set the flag that PTP has been enabled */
+       adapter->flags2 |= IXGBE_FLAG2_PTP_ENABLED;
+
        return;
 }
 
@@ -967,7 +933,7 @@ void ixgbe_ptp_init(struct ixgbe_adapter *adapter)
 void ixgbe_ptp_stop(struct ixgbe_adapter *adapter)
 {
        /* stop the overflow check task */
-       adapter->flags2 &= ~(IXGBE_FLAG2_OVERFLOW_CHECK_ENABLED |
+       adapter->flags2 &= ~(IXGBE_FLAG2_PTP_ENABLED |
                             IXGBE_FLAG2_PTP_PPS_ENABLED);
 
        ixgbe_ptp_setup_sdp(adapter);
index dce48bf64d9616beacb3ea9b081b6d7aea0730c2..85cddac673ef41716d9a34f027b1bcbb0cfb903d 100644 (file)
@@ -117,6 +117,10 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
                }
        }
 
+       /* Initialize default switching mode VEB */
+       IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, IXGBE_PFDTXGSWC_VT_LBEN);
+       adapter->flags2 |= IXGBE_FLAG2_BRIDGE_MODE_VEB;
+
        /* If call to enable VFs succeeded then allocate memory
         * for per VF control structures.
         */
@@ -150,16 +154,6 @@ void ixgbe_enable_sriov(struct ixgbe_adapter *adapter,
                adapter->flags2 &= ~(IXGBE_FLAG2_RSC_CAPABLE |
                                     IXGBE_FLAG2_RSC_ENABLED);
 
-#ifdef IXGBE_FCOE
-               /*
-                * When SR-IOV is enabled 82599 cannot support jumbo frames
-                * so we must disable FCoE because we cannot support FCoE MTU.
-                */
-               if (adapter->hw.mac.type == ixgbe_mac_82599EB)
-                       adapter->flags &= ~(IXGBE_FLAG_FCOE_ENABLED |
-                                           IXGBE_FLAG_FCOE_CAPABLE);
-#endif
-
                /* enable spoof checking for all VFs */
                for (i = 0; i < adapter->num_vfs; i++)
                        adapter->vfinfo[i].spoofchk_enabled = true;
@@ -265,8 +259,11 @@ void ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
 }
 
 static int ixgbe_set_vf_multicasts(struct ixgbe_adapter *adapter,
-                                  int entries, u16 *hash_list, u32 vf)
+                                  u32 *msgbuf, u32 vf)
 {
+       int entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
+                      >> IXGBE_VT_MSGINFO_SHIFT;
+       u16 *hash_list = (u16 *)&msgbuf[1];
        struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
        struct ixgbe_hw *hw = &adapter->hw;
        int i;
@@ -353,31 +350,89 @@ static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
        return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
 }
 
-static void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf)
+static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       int new_mtu = msgbuf[1];
+       int max_frame = msgbuf[1];
        u32 max_frs;
-       int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
-       /* Only X540 supports jumbo frames in IOV mode */
-       if (adapter->hw.mac.type != ixgbe_mac_X540)
-               return;
+       /*
+        * For 82599EB we have to keep all PFs and VFs operating with
+        * the same max_frame value in order to avoid sending an oversize
+        * frame to a VF.  In order to guarantee this is handled correctly
+        * for all cases we have several special exceptions to take into
+        * account before we can enable the VF for receive
+        */
+       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+               struct net_device *dev = adapter->netdev;
+               int pf_max_frame = dev->mtu + ETH_HLEN;
+               u32 reg_offset, vf_shift, vfre;
+               s32 err = 0;
+
+#ifdef CONFIG_FCOE
+               if (dev->features & NETIF_F_FCOE_MTU)
+                       pf_max_frame = max_t(int, pf_max_frame,
+                                            IXGBE_FCOE_JUMBO_FRAME_SIZE);
+
+#endif /* CONFIG_FCOE */
+               switch (adapter->vfinfo[vf].vf_api) {
+               case ixgbe_mbox_api_11:
+                       /*
+                        * Version 1.1 supports jumbo frames on VFs if PF has
+                        * jumbo frames enabled which means legacy VFs are
+                        * disabled
+                        */
+                       if (pf_max_frame > ETH_FRAME_LEN)
+                               break;
+               default:
+                       /*
+                        * If the PF or VF are running w/ jumbo frames enabled
+                        * we need to shut down the VF Rx path as we cannot
+                        * support jumbo frames on legacy VFs
+                        */
+                       if ((pf_max_frame > ETH_FRAME_LEN) ||
+                           (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)))
+                               err = -EINVAL;
+                       break;
+               }
+
+               /* determine VF receive enable location */
+               vf_shift = vf % 32;
+               reg_offset = vf / 32;
+
+               /* enable or disable receive depending on error */
+               vfre = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
+               if (err)
+                       vfre &= ~(1 << vf_shift);
+               else
+                       vfre |= 1 << vf_shift;
+               IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), vfre);
+
+               if (err) {
+                       e_err(drv, "VF max_frame %d out of range\n", max_frame);
+                       return err;
+               }
+       }
 
        /* MTU < 68 is an error and causes problems on some kernels */
-       if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) {
-               e_err(drv, "VF mtu %d out of range\n", new_mtu);
-               return;
+       if (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) {
+               e_err(drv, "VF max_frame %d out of range\n", max_frame);
+               return -EINVAL;
        }
 
-       max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) &
-                  IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
-       if (max_frs < new_mtu) {
-               max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT;
+       /* pull current max frame size from hardware */
+       max_frs = IXGBE_READ_REG(hw, IXGBE_MAXFRS);
+       max_frs &= IXGBE_MHADD_MFS_MASK;
+       max_frs >>= IXGBE_MHADD_MFS_SHIFT;
+
+       if (max_frs < max_frame) {
+               max_frs = max_frame << IXGBE_MHADD_MFS_SHIFT;
                IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs);
        }
 
-       e_info(hw, "VF requests change max MTU to %d\n", new_mtu);
+       e_info(hw, "VF requests change max MTU to %d\n", max_frame);
+
+       return 0;
 }
 
 static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
@@ -392,35 +447,47 @@ static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
        IXGBE_WRITE_REG(hw, IXGBE_VMOLR(vf), vmolr);
 }
 
-static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter, u32 vid, u32 vf)
+static void ixgbe_set_vmvir(struct ixgbe_adapter *adapter,
+                           u16 vid, u16 qos, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
+       u32 vmvir = vid | (qos << VLAN_PRIO_SHIFT) | IXGBE_VMVIR_VLANA_DEFAULT;
 
-       if (vid)
-               IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf),
-                               (vid | IXGBE_VMVIR_VLANA_DEFAULT));
-       else
-               IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
+       IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), vmvir);
 }
 
+static void ixgbe_clear_vmvir(struct ixgbe_adapter *adapter, u32 vf)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       IXGBE_WRITE_REG(hw, IXGBE_VMVIR(vf), 0);
+}
 static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
+       struct vf_data_storage *vfinfo = &adapter->vfinfo[vf];
        int rar_entry = hw->mac.num_rar_entries - (vf + 1);
+       u8 num_tcs = netdev_get_num_tc(adapter->netdev);
+
+       /* add PF assigned VLAN or VLAN 0 */
+       ixgbe_set_vf_vlan(adapter, true, vfinfo->pf_vlan, vf);
 
        /* reset offloads to defaults */
-       if (adapter->vfinfo[vf].pf_vlan) {
-               ixgbe_set_vf_vlan(adapter, true,
-                                 adapter->vfinfo[vf].pf_vlan, vf);
-               ixgbe_set_vmvir(adapter,
-                               (adapter->vfinfo[vf].pf_vlan |
-                                (adapter->vfinfo[vf].pf_qos <<
-                                 VLAN_PRIO_SHIFT)), vf);
-               ixgbe_set_vmolr(hw, vf, false);
+       ixgbe_set_vmolr(hw, vf, !vfinfo->pf_vlan);
+
+       /* set outgoing tags for VFs */
+       if (!vfinfo->pf_vlan && !vfinfo->pf_qos && !num_tcs) {
+               ixgbe_clear_vmvir(adapter, vf);
        } else {
-               ixgbe_set_vf_vlan(adapter, true, 0, vf);
-               ixgbe_set_vmvir(adapter, 0, vf);
-               ixgbe_set_vmolr(hw, vf, true);
+               if (vfinfo->pf_qos || !num_tcs)
+                       ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
+                                       vfinfo->pf_qos, vf);
+               else
+                       ixgbe_set_vmvir(adapter, vfinfo->pf_vlan,
+                                       adapter->default_up, vf);
+
+               if (vfinfo->spoofchk_enabled)
+                       hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
        }
 
        /* reset multicast table array for vf */
@@ -430,6 +497,9 @@ static inline void ixgbe_vf_reset_event(struct ixgbe_adapter *adapter, u32 vf)
        ixgbe_set_rx_mode(adapter->netdev);
 
        hw->mac.ops.clear_rar(hw, rar_entry);
+
+       /* reset VF api back to unknown */
+       adapter->vfinfo[vf].vf_api = ixgbe_mbox_api_10;
 }
 
 static int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
@@ -521,30 +591,221 @@ int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask)
        return 0;
 }
 
-static inline void ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
+static int ixgbe_vf_reset_msg(struct ixgbe_adapter *adapter, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       u32 reg;
+       unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
+       u32 reg, msgbuf[4];
        u32 reg_offset, vf_shift;
+       u8 *addr = (u8 *)(&msgbuf[1]);
+
+       e_info(probe, "VF Reset msg received from vf %d\n", vf);
+
+       /* reset the filters for the device */
+       ixgbe_vf_reset_event(adapter, vf);
+
+       /* set vf mac address */
+       ixgbe_set_vf_mac(adapter, vf, vf_mac);
 
        vf_shift = vf % 32;
        reg_offset = vf / 32;
 
-       /* enable transmit and receive for vf */
+       /* enable transmit for vf */
        reg = IXGBE_READ_REG(hw, IXGBE_VFTE(reg_offset));
-       reg |= (reg | (1 << vf_shift));
+       reg |= 1 << vf_shift;
        IXGBE_WRITE_REG(hw, IXGBE_VFTE(reg_offset), reg);
 
+       /* enable receive for vf */
        reg = IXGBE_READ_REG(hw, IXGBE_VFRE(reg_offset));
-       reg |= (reg | (1 << vf_shift));
+       reg |= 1 << vf_shift;
+       /*
+        * The 82599 cannot support a mix of jumbo and non-jumbo PF/VFs.
+        * For more info take a look at ixgbe_set_vf_lpe
+        */
+       if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+               struct net_device *dev = adapter->netdev;
+               int pf_max_frame = dev->mtu + ETH_HLEN;
+
+#ifdef CONFIG_FCOE
+               if (dev->features & NETIF_F_FCOE_MTU)
+                       pf_max_frame = max_t(int, pf_max_frame,
+                                            IXGBE_FCOE_JUMBO_FRAME_SIZE);
+
+#endif /* CONFIG_FCOE */
+               if (pf_max_frame > ETH_FRAME_LEN)
+                       reg &= ~(1 << vf_shift);
+       }
        IXGBE_WRITE_REG(hw, IXGBE_VFRE(reg_offset), reg);
 
+       /* enable VF mailbox for further messages */
+       adapter->vfinfo[vf].clear_to_send = true;
+
        /* Enable counting of spoofed packets in the SSVPC register */
        reg = IXGBE_READ_REG(hw, IXGBE_VMECM(reg_offset));
        reg |= (1 << vf_shift);
        IXGBE_WRITE_REG(hw, IXGBE_VMECM(reg_offset), reg);
 
-       ixgbe_vf_reset_event(adapter, vf);
+       /* reply to reset with ack and vf mac address */
+       msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
+       memcpy(addr, vf_mac, ETH_ALEN);
+
+       /*
+        * Piggyback the multicast filter type so VF can compute the
+        * correct vectors
+        */
+       msgbuf[3] = hw->mac.mc_filter_type;
+       ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf);
+
+       return 0;
+}
+
+static int ixgbe_set_vf_mac_addr(struct ixgbe_adapter *adapter,
+                                u32 *msgbuf, u32 vf)
+{
+       u8 *new_mac = ((u8 *)(&msgbuf[1]));
+
+       if (!is_valid_ether_addr(new_mac)) {
+               e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
+               return -1;
+       }
+
+       if (adapter->vfinfo[vf].pf_set_mac &&
+           memcmp(adapter->vfinfo[vf].vf_mac_addresses, new_mac,
+                  ETH_ALEN)) {
+               e_warn(drv,
+                      "VF %d attempted to override administratively set MAC address\n"
+                      "Reload the VF driver to resume operations\n",
+                      vf);
+               return -1;
+       }
+
+       return ixgbe_set_vf_mac(adapter, vf, new_mac) < 0;
+}
+
+static int ixgbe_set_vf_vlan_msg(struct ixgbe_adapter *adapter,
+                                u32 *msgbuf, u32 vf)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       int add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >> IXGBE_VT_MSGINFO_SHIFT;
+       int vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
+       int err;
+       u8 tcs = netdev_get_num_tc(adapter->netdev);
+
+       if (adapter->vfinfo[vf].pf_vlan || tcs) {
+               e_warn(drv,
+                      "VF %d attempted to override administratively set VLAN configuration\n"
+                      "Reload the VF driver to resume operations\n",
+                      vf);
+               return -1;
+       }
+
+       if (add)
+               adapter->vfinfo[vf].vlan_count++;
+       else if (adapter->vfinfo[vf].vlan_count)
+               adapter->vfinfo[vf].vlan_count--;
+
+       err = ixgbe_set_vf_vlan(adapter, add, vid, vf);
+       if (!err && adapter->vfinfo[vf].spoofchk_enabled)
+               hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
+
+       return err;
+}
+
+static int ixgbe_set_vf_macvlan_msg(struct ixgbe_adapter *adapter,
+                                   u32 *msgbuf, u32 vf)
+{
+       u8 *new_mac = ((u8 *)(&msgbuf[1]));
+       int index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
+                   IXGBE_VT_MSGINFO_SHIFT;
+       int err;
+
+       if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
+               e_warn(drv,
+                      "VF %d requested MACVLAN filter but is administratively denied\n",
+                      vf);
+               return -1;
+       }
+
+       /* An non-zero index indicates the VF is setting a filter */
+       if (index) {
+               if (!is_valid_ether_addr(new_mac)) {
+                       e_warn(drv, "VF %d attempted to set invalid mac\n", vf);
+                       return -1;
+               }
+
+               /*
+                * If the VF is allowed to set MAC filters then turn off
+                * anti-spoofing to avoid false positives.
+                */
+               if (adapter->vfinfo[vf].spoofchk_enabled)
+                       ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
+       }
+
+       err = ixgbe_set_vf_macvlan(adapter, vf, index, new_mac);
+       if (err == -ENOSPC)
+               e_warn(drv,
+                      "VF %d has requested a MACVLAN filter but there is no space for it\n",
+                      vf);
+
+       return err < 0;
+}
+
+static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter,
+                                 u32 *msgbuf, u32 vf)
+{
+       int api = msgbuf[1];
+
+       switch (api) {
+       case ixgbe_mbox_api_10:
+       case ixgbe_mbox_api_11:
+               adapter->vfinfo[vf].vf_api = api;
+               return 0;
+       default:
+               break;
+       }
+
+       e_info(drv, "VF %d requested invalid api version %u\n", vf, api);
+
+       return -1;
+}
+
+static int ixgbe_get_vf_queues(struct ixgbe_adapter *adapter,
+                              u32 *msgbuf, u32 vf)
+{
+       struct net_device *dev = adapter->netdev;
+       struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
+       unsigned int default_tc = 0;
+       u8 num_tcs = netdev_get_num_tc(dev);
+
+       /* verify the PF is supporting the correct APIs */
+       switch (adapter->vfinfo[vf].vf_api) {
+       case ixgbe_mbox_api_20:
+       case ixgbe_mbox_api_11:
+               break;
+       default:
+               return -1;
+       }
+
+       /* only allow 1 Tx queue for bandwidth limiting */
+       msgbuf[IXGBE_VF_TX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask);
+       msgbuf[IXGBE_VF_RX_QUEUES] = __ALIGN_MASK(1, ~vmdq->mask);
+
+       /* if TCs > 1 determine which TC belongs to default user priority */
+       if (num_tcs > 1)
+               default_tc = netdev_get_prio_tc_map(dev, adapter->default_up);
+
+       /* notify VF of need for VLAN tag stripping, and correct queue */
+       if (num_tcs)
+               msgbuf[IXGBE_VF_TRANS_VLAN] = num_tcs;
+       else if (adapter->vfinfo[vf].pf_vlan || adapter->vfinfo[vf].pf_qos)
+               msgbuf[IXGBE_VF_TRANS_VLAN] = 1;
+       else
+               msgbuf[IXGBE_VF_TRANS_VLAN] = 0;
+
+       /* notify VF of default queue */
+       msgbuf[IXGBE_VF_DEF_QUEUE] = default_tc;
+
+       return 0;
 }
 
 static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
@@ -553,10 +814,6 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
        u32 msgbuf[IXGBE_VFMAILBOX_SIZE];
        struct ixgbe_hw *hw = &adapter->hw;
        s32 retval;
-       int entries;
-       u16 *hash_list;
-       int add, vid, index;
-       u8 *new_mac;
 
        retval = ixgbe_read_mbx(hw, msgbuf, mbx_size, vf);
 
@@ -572,39 +829,13 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
        /* flush the ack before we write any messages back */
        IXGBE_WRITE_FLUSH(hw);
 
+       if (msgbuf[0] == IXGBE_VF_RESET)
+               return ixgbe_vf_reset_msg(adapter, vf);
+
        /*
         * until the vf completes a virtual function reset it should not be
         * allowed to start any configuration.
         */
-
-       if (msgbuf[0] == IXGBE_VF_RESET) {
-               unsigned char *vf_mac = adapter->vfinfo[vf].vf_mac_addresses;
-               new_mac = (u8 *)(&msgbuf[1]);
-               e_info(probe, "VF Reset msg received from vf %d\n", vf);
-               adapter->vfinfo[vf].clear_to_send = false;
-               ixgbe_vf_reset_msg(adapter, vf);
-               adapter->vfinfo[vf].clear_to_send = true;
-
-               if (is_valid_ether_addr(new_mac) &&
-                   !adapter->vfinfo[vf].pf_set_mac)
-                       ixgbe_set_vf_mac(adapter, vf, vf_mac);
-               else
-                       ixgbe_set_vf_mac(adapter,
-                                vf, adapter->vfinfo[vf].vf_mac_addresses);
-
-               /* reply to reset with ack and vf mac address */
-               msgbuf[0] = IXGBE_VF_RESET | IXGBE_VT_MSGTYPE_ACK;
-               memcpy(new_mac, vf_mac, ETH_ALEN);
-               /*
-                * Piggyback the multicast filter type so VF can compute the
-                * correct vectors
-                */
-               msgbuf[3] = hw->mac.mc_filter_type;
-               ixgbe_write_mbx(hw, msgbuf, IXGBE_VF_PERMADDR_MSG_LEN, vf);
-
-               return retval;
-       }
-
        if (!adapter->vfinfo[vf].clear_to_send) {
                msgbuf[0] |= IXGBE_VT_MSGTYPE_NACK;
                ixgbe_write_mbx(hw, msgbuf, 1, vf);
@@ -613,70 +844,25 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 
        switch ((msgbuf[0] & 0xFFFF)) {
        case IXGBE_VF_SET_MAC_ADDR:
-               new_mac = ((u8 *)(&msgbuf[1]));
-               if (is_valid_ether_addr(new_mac) &&
-                   !adapter->vfinfo[vf].pf_set_mac) {
-                       ixgbe_set_vf_mac(adapter, vf, new_mac);
-               } else if (memcmp(adapter->vfinfo[vf].vf_mac_addresses,
-                                 new_mac, ETH_ALEN)) {
-                       e_warn(drv, "VF %d attempted to override "
-                              "administratively set MAC address\nReload "
-                              "the VF driver to resume operations\n", vf);
-                       retval = -1;
-               }
+               retval = ixgbe_set_vf_mac_addr(adapter, msgbuf, vf);
                break;
        case IXGBE_VF_SET_MULTICAST:
-               entries = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
-                         >> IXGBE_VT_MSGINFO_SHIFT;
-               hash_list = (u16 *)&msgbuf[1];
-               retval = ixgbe_set_vf_multicasts(adapter, entries,
-                                                hash_list, vf);
-               break;
-       case IXGBE_VF_SET_LPE:
-               ixgbe_set_vf_lpe(adapter, msgbuf);
+               retval = ixgbe_set_vf_multicasts(adapter, msgbuf, vf);
                break;
        case IXGBE_VF_SET_VLAN:
-               add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
-                     >> IXGBE_VT_MSGINFO_SHIFT;
-               vid = (msgbuf[1] & IXGBE_VLVF_VLANID_MASK);
-               if (adapter->vfinfo[vf].pf_vlan) {
-                       e_warn(drv, "VF %d attempted to override "
-                              "administratively set VLAN configuration\n"
-                              "Reload the VF driver to resume operations\n",
-                              vf);
-                       retval = -1;
-               } else {
-                       if (add)
-                               adapter->vfinfo[vf].vlan_count++;
-                       else if (adapter->vfinfo[vf].vlan_count)
-                               adapter->vfinfo[vf].vlan_count--;
-                       retval = ixgbe_set_vf_vlan(adapter, add, vid, vf);
-                       if (!retval && adapter->vfinfo[vf].spoofchk_enabled)
-                               hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
-               }
+               retval = ixgbe_set_vf_vlan_msg(adapter, msgbuf, vf);
+               break;
+       case IXGBE_VF_SET_LPE:
+               retval = ixgbe_set_vf_lpe(adapter, msgbuf, vf);
                break;
        case IXGBE_VF_SET_MACVLAN:
-               index = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK) >>
-                       IXGBE_VT_MSGINFO_SHIFT;
-               if (adapter->vfinfo[vf].pf_set_mac && index > 0) {
-                       e_warn(drv, "VF %d requested MACVLAN filter but is "
-                                   "administratively denied\n", vf);
-                       retval = -1;
-                       break;
-               }
-               /*
-                * If the VF is allowed to set MAC filters then turn off
-                * anti-spoofing to avoid false positives.  An index
-                * greater than 0 will indicate the VF is setting a
-                * macvlan MAC filter.
-                */
-               if (index > 0 && adapter->vfinfo[vf].spoofchk_enabled)
-                       ixgbe_ndo_set_vf_spoofchk(adapter->netdev, vf, false);
-               retval = ixgbe_set_vf_macvlan(adapter, vf, index,
-                                             (unsigned char *)(&msgbuf[1]));
-               if (retval == -ENOSPC)
-                       e_warn(drv, "VF %d has requested a MACVLAN filter "
-                                   "but there is no space for it\n", vf);
+               retval = ixgbe_set_vf_macvlan_msg(adapter, msgbuf, vf);
+               break;
+       case IXGBE_VF_API_NEGOTIATE:
+               retval = ixgbe_negotiate_vf_api(adapter, msgbuf, vf);
+               break;
+       case IXGBE_VF_GET_QUEUES:
+               retval = ixgbe_get_vf_queues(adapter, msgbuf, vf);
                break;
        default:
                e_err(drv, "Unhandled Msg %8.8x\n", msgbuf[0]);
@@ -692,7 +878,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
 
        msgbuf[0] |= IXGBE_VT_MSGTYPE_CTS;
 
-       ixgbe_write_mbx(hw, msgbuf, 1, vf);
+       ixgbe_write_mbx(hw, msgbuf, mbx_size, vf);
 
        return retval;
 }
@@ -783,7 +969,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
                err = ixgbe_set_vf_vlan(adapter, true, vlan, vf);
                if (err)
                        goto out;
-               ixgbe_set_vmvir(adapter, vlan | (qos << VLAN_PRIO_SHIFT), vf);
+               ixgbe_set_vmvir(adapter, vlan, qos, vf);
                ixgbe_set_vmolr(hw, vf, false);
                if (adapter->vfinfo[vf].spoofchk_enabled)
                        hw->mac.ops.set_vlan_anti_spoofing(hw, true, vf);
@@ -803,7 +989,7 @@ int ixgbe_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos)
        } else {
                err = ixgbe_set_vf_vlan(adapter, false,
                                        adapter->vfinfo[vf].pf_vlan, vf);
-               ixgbe_set_vmvir(adapter, vlan, vf);
+               ixgbe_clear_vmvir(adapter, vf);
                ixgbe_set_vmolr(hw, vf, true);
                hw->mac.ops.set_vlan_anti_spoofing(hw, false, vf);
                if (adapter->vfinfo[vf].vlan_count)
index 0722f33680926e9c8e79a0592708cfc0c42806e2..9cd8a13711d321546f4ff7107714dfde2fbf490c 100644 (file)
@@ -56,6 +56,7 @@
 #define IXGBE_SUBDEV_ID_82599_SFP        0x11A9
 #define IXGBE_SUBDEV_ID_82599_RNDC       0x1F72
 #define IXGBE_SUBDEV_ID_82599_560FLR     0x17D0
+#define IXGBE_SUBDEV_ID_82599_ECNA_DP    0x0470
 #define IXGBE_DEV_ID_82599_SFP_EM        0x1507
 #define IXGBE_DEV_ID_82599_SFP_SF2       0x154D
 #define IXGBE_DEV_ID_82599EN_SFP         0x1557
@@ -1833,15 +1834,6 @@ enum {
 /* Number of 100 microseconds we wait for PCI Express master disable */
 #define IXGBE_PCI_MASTER_DISABLE_TIMEOUT 800
 
-/* Check whether address is multicast.  This is little-endian specific check.*/
-#define IXGBE_IS_MULTICAST(Address) \
-                (bool)(((u8 *)(Address))[0] & ((u8)0x01))
-
-/* Check whether an address is broadcast. */
-#define IXGBE_IS_BROADCAST(Address)                      \
-                ((((u8 *)(Address))[0] == ((u8)0xff)) && \
-                (((u8 *)(Address))[1] == ((u8)0xff)))
-
 /* RAH */
 #define IXGBE_RAH_VIND_MASK     0x003C0000
 #define IXGBE_RAH_VIND_SHIFT    18
@@ -1962,6 +1954,8 @@ enum {
 #define IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP 0x01000000
 #define IXGBE_MRQC_L3L4TXSWEN            0x00008000
 
+#define IXGBE_FWSM_TS_ENABLED  0x1
+
 /* Queue Drop Enable */
 #define IXGBE_QDE_ENABLE     0x00000001
 #define IXGBE_QDE_IDX_MASK   0x00007F00
index de4da5219b71f652363e2d5a6ded7c639e4ff4e4..c73b92993391b5db31d7868481e65b4b1150b403 100644 (file)
@@ -152,7 +152,7 @@ mac_reset_top:
        hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
 
        /* Add the SAN MAC address to the RAR only if it's a valid address */
-       if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+       if (is_valid_ether_addr(hw->mac.san_addr)) {
                hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
                                    hw->mac.san_addr, 0, IXGBE_RAH_AV);
 
index da17ccf5c09db9b8647a724c55d9c98eae4fa94f..3147795bd135b57137105a3b4769d0f34a7c6faf 100644 (file)
 #define IXGBE_DEV_ID_X540_VF            0x1515
 
 #define IXGBE_VF_IRQ_CLEAR_MASK         7
-#define IXGBE_VF_MAX_TX_QUEUES          1
-#define IXGBE_VF_MAX_RX_QUEUES          1
+#define IXGBE_VF_MAX_TX_QUEUES          8
+#define IXGBE_VF_MAX_RX_QUEUES          8
+
+/* DCB define */
+#define IXGBE_VF_MAX_TRAFFIC_CLASS     8
 
 /* Link speed */
 typedef u32 ixgbe_link_speed;
index 4a9c9c285685294df5b5531c689f0e11171056be..fc0af9a3bb35b354e26568af3b68d54c9a3c5018 100644 (file)
@@ -58,7 +58,6 @@ struct ixgbevf_ring {
        struct ixgbevf_ring *next;
        struct net_device *netdev;
        struct device *dev;
-       struct ixgbevf_adapter *adapter;  /* backlink */
        void *desc;                     /* descriptor ring memory */
        dma_addr_t dma;                 /* phys. address of descriptor ring */
        unsigned int size;              /* length in bytes */
@@ -75,6 +74,8 @@ struct ixgbevf_ring {
        u64                     total_bytes;
        u64                     total_packets;
        struct u64_stats_sync   syncp;
+       u64 hw_csum_rx_error;
+       u64 hw_csum_rx_good;
 
        u16 head;
        u16 tail;
@@ -89,8 +90,8 @@ struct ixgbevf_ring {
 /* How many Rx Buffers do we bundle into one write to the hardware ? */
 #define IXGBEVF_RX_BUFFER_WRITE        16      /* Must be power of 2 */
 
-#define MAX_RX_QUEUES 1
-#define MAX_TX_QUEUES 1
+#define MAX_RX_QUEUES IXGBE_VF_MAX_RX_QUEUES
+#define MAX_TX_QUEUES IXGBE_VF_MAX_TX_QUEUES
 
 #define IXGBEVF_DEFAULT_TXD   1024
 #define IXGBEVF_DEFAULT_RXD   512
@@ -101,10 +102,10 @@ struct ixgbevf_ring {
 
 /* Supported Rx Buffer Sizes */
 #define IXGBEVF_RXBUFFER_256   256    /* Used for packet split */
-#define IXGBEVF_RXBUFFER_3K    3072
-#define IXGBEVF_RXBUFFER_7K    7168
-#define IXGBEVF_RXBUFFER_15K   15360
-#define IXGBEVF_MAX_RXBUFFER   16384  /* largest size for single descriptor */
+#define IXGBEVF_RXBUFFER_2K    2048
+#define IXGBEVF_RXBUFFER_4K    4096
+#define IXGBEVF_RXBUFFER_8K    8192
+#define IXGBEVF_RXBUFFER_10K   10240
 
 #define IXGBEVF_RX_HDR_SIZE IXGBEVF_RXBUFFER_256
 
@@ -229,6 +230,7 @@ struct ixgbevf_adapter {
         */
        u32 flags;
 #define IXGBE_FLAG_IN_WATCHDOG_TASK             (u32)(1)
+#define IXGBE_FLAG_IN_NETPOLL                   (u32)(1 << 1)
 
        /* OS defined structs */
        struct net_device *netdev;
index de1ad506665d6a33c223c8a73fbada54f39df832..257357ae66c365169d6130306d9180789965c98e 100644 (file)
@@ -58,7 +58,7 @@ const char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
        "Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
 
-#define DRV_VERSION "2.6.0-k"
+#define DRV_VERSION "2.7.12-k"
 const char ixgbevf_driver_version[] = DRV_VERSION;
 static char ixgbevf_copyright[] =
        "Copyright (c) 2009 - 2012 Intel Corporation.";
@@ -99,6 +99,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
 /* forward decls */
 static void ixgbevf_set_itr(struct ixgbevf_q_vector *q_vector);
+static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter);
 
 static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
                                           struct ixgbevf_ring *rx_ring,
@@ -120,7 +121,6 @@ static inline void ixgbevf_release_rx_desc(struct ixgbe_hw *hw,
  * @direction: 0 for Rx, 1 for Tx, -1 for other causes
  * @queue: queue to map the corresponding interrupt to
  * @msix_vector: the vector to map to the corresponding queue
- *
  */
 static void ixgbevf_set_ivar(struct ixgbevf_adapter *adapter, s8 direction,
                             u8 queue, u8 msix_vector)
@@ -287,17 +287,19 @@ static void ixgbevf_receive_skb(struct ixgbevf_q_vector *q_vector,
        if (is_vlan && test_bit(tag & VLAN_VID_MASK, adapter->active_vlans))
                __vlan_hwaccel_put_tag(skb, tag);
 
-       napi_gro_receive(&q_vector->napi, skb);
+       if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL))
+               napi_gro_receive(&q_vector->napi, skb);
+       else
+               netif_rx(skb);
 }
 
 /**
  * ixgbevf_rx_checksum - indicate in skb if hw indicated a good cksum
- * @adapter: address of board private structure
+ * @ring: pointer to Rx descriptor ring structure
  * @status_err: hardware indication of status of receive
  * @skb: skb currently being received and modified
  **/
-static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
-                                      struct ixgbevf_ring *ring,
+static inline void ixgbevf_rx_checksum(struct ixgbevf_ring *ring,
                                       u32 status_err, struct sk_buff *skb)
 {
        skb_checksum_none_assert(skb);
@@ -309,7 +311,7 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
        /* if IP and error */
        if ((status_err & IXGBE_RXD_STAT_IPCS) &&
            (status_err & IXGBE_RXDADV_ERR_IPE)) {
-               adapter->hw_csum_rx_error++;
+               ring->hw_csum_rx_error++;
                return;
        }
 
@@ -317,13 +319,13 @@ static inline void ixgbevf_rx_checksum(struct ixgbevf_adapter *adapter,
                return;
 
        if (status_err & IXGBE_RXDADV_ERR_TCPE) {
-               adapter->hw_csum_rx_error++;
+               ring->hw_csum_rx_error++;
                return;
        }
 
        /* It must be a TCP or UDP packet with a valid checksum */
        skb->ip_summed = CHECKSUM_UNNECESSARY;
-       adapter->hw_csum_rx_good++;
+       ring->hw_csum_rx_good++;
 }
 
 /**
@@ -337,15 +339,16 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
        struct pci_dev *pdev = adapter->pdev;
        union ixgbe_adv_rx_desc *rx_desc;
        struct ixgbevf_rx_buffer *bi;
-       struct sk_buff *skb;
        unsigned int i = rx_ring->next_to_use;
 
        bi = &rx_ring->rx_buffer_info[i];
 
        while (cleaned_count--) {
                rx_desc = IXGBEVF_RX_DESC(rx_ring, i);
-               skb = bi->skb;
-               if (!skb) {
+
+               if (!bi->skb) {
+                       struct sk_buff *skb;
+
                        skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
                                                        rx_ring->rx_buf_len);
                        if (!skb) {
@@ -353,11 +356,16 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
                                goto no_buffers;
                        }
                        bi->skb = skb;
-               }
-               if (!bi->dma) {
+
                        bi->dma = dma_map_single(&pdev->dev, skb->data,
                                                 rx_ring->rx_buf_len,
                                                 DMA_FROM_DEVICE);
+                       if (dma_mapping_error(&pdev->dev, bi->dma)) {
+                               dev_kfree_skb(skb);
+                               bi->skb = NULL;
+                               dev_err(&pdev->dev, "RX DMA map failed\n");
+                               break;
+                       }
                }
                rx_desc->read.pkt_addr = cpu_to_le64(bi->dma);
 
@@ -370,7 +378,6 @@ static void ixgbevf_alloc_rx_buffers(struct ixgbevf_adapter *adapter,
 no_buffers:
        if (rx_ring->next_to_use != i) {
                rx_ring->next_to_use = i;
-
                ixgbevf_release_rx_desc(&adapter->hw, rx_ring, i);
        }
 }
@@ -454,7 +461,7 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
                        goto next_desc;
                }
 
-               ixgbevf_rx_checksum(adapter, rx_ring, staterr, skb);
+               ixgbevf_rx_checksum(rx_ring, staterr, skb);
 
                /* probably a little skewed due to removing CRC */
                total_rx_bytes += skb->len;
@@ -471,6 +478,16 @@ static bool ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
                }
                skb->protocol = eth_type_trans(skb, rx_ring->netdev);
 
+               /* Workaround hardware that can't do proper VEPA multicast
+                * source pruning.
+                */
+               if ((skb->pkt_type & (PACKET_BROADCAST | PACKET_MULTICAST)) &&
+                   !(compare_ether_addr(adapter->netdev->dev_addr,
+                                       eth_hdr(skb)->h_source))) {
+                       dev_kfree_skb_irq(skb);
+                       goto next_desc;
+               }
+
                ixgbevf_receive_skb(q_vector, skb, staterr, rx_desc);
 
 next_desc:
@@ -533,9 +550,11 @@ static int ixgbevf_poll(struct napi_struct *napi, int budget)
        else
                per_ring_budget = budget;
 
+       adapter->flags |= IXGBE_FLAG_IN_NETPOLL;
        ixgbevf_for_each_ring(ring, q_vector->rx)
                clean_complete &= ixgbevf_clean_rx_irq(q_vector, ring,
                                                       per_ring_budget);
+       adapter->flags &= ~IXGBE_FLAG_IN_NETPOLL;
 
        /* If all work not completed, return budget and keep polling */
        if (!clean_complete)
@@ -743,7 +762,6 @@ static irqreturn_t ixgbevf_msix_other(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-
 /**
  * ixgbevf_msix_clean_rings - single unshared vector rx clean (all queues)
  * @irq: unused
@@ -1065,20 +1083,20 @@ static void ixgbevf_set_rx_buffer_len(struct ixgbevf_adapter *adapter)
        max_frame += VLAN_HLEN;
 
        /*
-        * Make best use of allocation by using all but 1K of a
-        * power of 2 allocation that will be used for skb->head.
+        * Allocate buffer sizes that fit well into 32K and
+        * take into account max frame size of 9.5K
         */
        if ((hw->mac.type == ixgbe_mac_X540_vf) &&
            (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE))
                rx_buf_len = MAXIMUM_ETHERNET_VLAN_SIZE;
-       else if (max_frame <= IXGBEVF_RXBUFFER_3K)
-               rx_buf_len = IXGBEVF_RXBUFFER_3K;
-       else if (max_frame <= IXGBEVF_RXBUFFER_7K)
-               rx_buf_len = IXGBEVF_RXBUFFER_7K;
-       else if (max_frame <= IXGBEVF_RXBUFFER_15K)
-               rx_buf_len = IXGBEVF_RXBUFFER_15K;
+       else if (max_frame <= IXGBEVF_RXBUFFER_2K)
+               rx_buf_len = IXGBEVF_RXBUFFER_2K;
+       else if (max_frame <= IXGBEVF_RXBUFFER_4K)
+               rx_buf_len = IXGBEVF_RXBUFFER_4K;
+       else if (max_frame <= IXGBEVF_RXBUFFER_8K)
+               rx_buf_len = IXGBEVF_RXBUFFER_8K;
        else
-               rx_buf_len = IXGBEVF_MAX_RXBUFFER;
+               rx_buf_len = IXGBEVF_RXBUFFER_10K;
 
        for (i = 0; i < adapter->num_rx_queues; i++)
                adapter->rx_ring[i].rx_buf_len = rx_buf_len;
@@ -1128,15 +1146,12 @@ static int ixgbevf_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
        struct ixgbe_hw *hw = &adapter->hw;
        int err;
 
-       if (!hw->mac.ops.set_vfta)
-               return -EOPNOTSUPP;
-
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        /* add VID to filter table */
        err = hw->mac.ops.set_vfta(hw, vid, 0, true);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        /* translate error return types so error makes sense */
        if (err == IXGBE_ERR_MBX)
@@ -1156,13 +1171,12 @@ static int ixgbevf_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
        struct ixgbe_hw *hw = &adapter->hw;
        int err = -EOPNOTSUPP;
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        /* remove VID from filter table */
-       if (hw->mac.ops.set_vfta)
-               err = hw->mac.ops.set_vfta(hw, vid, 0, false);
+       err = hw->mac.ops.set_vfta(hw, vid, 0, false);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        clear_bit(vid, adapter->active_vlans);
 
@@ -1206,27 +1220,27 @@ static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
 }
 
 /**
- * ixgbevf_set_rx_mode - Multicast set
+ * ixgbevf_set_rx_mode - Multicast and unicast set
  * @netdev: network interface device structure
  *
  * The set_rx_method entry point is called whenever the multicast address
- * list or the network interface flags are updated.  This routine is
- * responsible for configuring the hardware for proper multicast mode.
+ * list, unicast address list or the network interface flags are updated.
+ * This routine is responsible for configuring the hardware for proper
+ * multicast mode and configuring requested unicast filters.
  **/
 static void ixgbevf_set_rx_mode(struct net_device *netdev)
 {
        struct ixgbevf_adapter *adapter = netdev_priv(netdev);
        struct ixgbe_hw *hw = &adapter->hw;
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        /* reprogram multicast list */
-       if (hw->mac.ops.update_mc_addr_list)
-               hw->mac.ops.update_mc_addr_list(hw, netdev);
+       hw->mac.ops.update_mc_addr_list(hw, netdev);
 
        ixgbevf_write_uc_addr_list(netdev);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 }
 
 static void ixgbevf_napi_enable_all(struct ixgbevf_adapter *adapter)
@@ -1290,8 +1304,8 @@ static inline void ixgbevf_rx_desc_queue_enable(struct ixgbevf_adapter *adapter,
                       "not set within the polling period\n", rxr);
        }
 
-       ixgbevf_release_rx_desc(&adapter->hw, &adapter->rx_ring[rxr],
-                               (adapter->rx_ring[rxr].count - 1));
+       ixgbevf_release_rx_desc(hw, &adapter->rx_ring[rxr],
+                               adapter->rx_ring[rxr].count - 1);
 }
 
 static void ixgbevf_save_reset_stats(struct ixgbevf_adapter *adapter)
@@ -1335,11 +1349,12 @@ static void ixgbevf_init_last_counter_stats(struct ixgbevf_adapter *adapter)
 static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       int api[] = { ixgbe_mbox_api_10,
+       int api[] = { ixgbe_mbox_api_11,
+                     ixgbe_mbox_api_10,
                      ixgbe_mbox_api_unknown };
        int err = 0, idx = 0;
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
        while (api[idx] != ixgbe_mbox_api_unknown) {
                err = ixgbevf_negotiate_api_version(hw, api[idx]);
@@ -1348,7 +1363,7 @@ static void ixgbevf_negotiate_api(struct ixgbevf_adapter *adapter)
                idx++;
        }
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 }
 
 static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
@@ -1389,16 +1404,14 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
 
        ixgbevf_configure_msix(adapter);
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
-       if (hw->mac.ops.set_rar) {
-               if (is_valid_ether_addr(hw->mac.addr))
-                       hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
-               else
-                       hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0);
-       }
+       if (is_valid_ether_addr(hw->mac.addr))
+               hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
+       else
+               hw->mac.ops.set_rar(hw, 0, hw->mac.perm_addr, 0);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        clear_bit(__IXGBEVF_DOWN, &adapter->state);
        ixgbevf_napi_enable_all(adapter);
@@ -1413,12 +1426,87 @@ static void ixgbevf_up_complete(struct ixgbevf_adapter *adapter)
        mod_timer(&adapter->watchdog_timer, jiffies);
 }
 
+static int ixgbevf_reset_queues(struct ixgbevf_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       struct ixgbevf_ring *rx_ring;
+       unsigned int def_q = 0;
+       unsigned int num_tcs = 0;
+       unsigned int num_rx_queues = 1;
+       int err, i;
+
+       spin_lock_bh(&adapter->mbx_lock);
+
+       /* fetch queue configuration from the PF */
+       err = ixgbevf_get_queues(hw, &num_tcs, &def_q);
+
+       spin_unlock_bh(&adapter->mbx_lock);
+
+       if (err)
+               return err;
+
+       if (num_tcs > 1) {
+               /* update default Tx ring register index */
+               adapter->tx_ring[0].reg_idx = def_q;
+
+               /* we need as many queues as traffic classes */
+               num_rx_queues = num_tcs;
+       }
+
+       /* nothing to do if we have the correct number of queues */
+       if (adapter->num_rx_queues == num_rx_queues)
+               return 0;
+
+       /* allocate new rings */
+       rx_ring = kcalloc(num_rx_queues,
+                         sizeof(struct ixgbevf_ring), GFP_KERNEL);
+       if (!rx_ring)
+               return -ENOMEM;
+
+       /* setup ring fields */
+       for (i = 0; i < num_rx_queues; i++) {
+               rx_ring[i].count = adapter->rx_ring_count;
+               rx_ring[i].queue_index = i;
+               rx_ring[i].reg_idx = i;
+               rx_ring[i].dev = &adapter->pdev->dev;
+               rx_ring[i].netdev = adapter->netdev;
+
+               /* allocate resources on the ring */
+               err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]);
+               if (err) {
+                       while (i) {
+                               i--;
+                               ixgbevf_free_rx_resources(adapter, &rx_ring[i]);
+                       }
+                       kfree(rx_ring);
+                       return err;
+               }
+       }
+
+       /* free the existing rings and queues */
+       ixgbevf_free_all_rx_resources(adapter);
+       adapter->num_rx_queues = 0;
+       kfree(adapter->rx_ring);
+
+       /* move new rings into position on the adapter struct */
+       adapter->rx_ring = rx_ring;
+       adapter->num_rx_queues = num_rx_queues;
+
+       /* reset ring to vector mapping */
+       ixgbevf_reset_q_vectors(adapter);
+       ixgbevf_map_rings_to_vectors(adapter);
+
+       return 0;
+}
+
 void ixgbevf_up(struct ixgbevf_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
 
        ixgbevf_negotiate_api(adapter);
 
+       ixgbevf_reset_queues(adapter);
+
        ixgbevf_configure(adapter);
 
        ixgbevf_up_complete(adapter);
@@ -1497,7 +1585,6 @@ static void ixgbevf_clean_tx_ring(struct ixgbevf_adapter *adapter,
                return;
 
        /* Free all the Tx ring sk_buffs */
-
        for (i = 0; i < tx_ring->count; i++) {
                tx_buffer_info = &tx_ring->tx_buffer_info[i];
                ixgbevf_unmap_and_free_tx_resource(tx_ring, tx_buffer_info);
@@ -1593,13 +1680,6 @@ void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter)
        while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state))
                msleep(1);
 
-       /*
-        * Check if PF is up before re-init.  If not then skip until
-        * later when the PF is up and ready to service requests from
-        * the VF via mailbox.  If the VF is up and running then the
-        * watchdog task will continue to schedule reset tasks until
-        * the PF is up and running.
-        */
        ixgbevf_down(adapter);
        ixgbevf_up(adapter);
 
@@ -1611,15 +1691,11 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        struct net_device *netdev = adapter->netdev;
 
-       spin_lock(&adapter->mbx_lock);
-
        if (hw->mac.ops.reset_hw(hw))
                hw_dbg(hw, "PF still resetting\n");
        else
                hw->mac.ops.init_hw(hw);
 
-       spin_unlock(&adapter->mbx_lock);
-
        if (is_valid_ether_addr(adapter->hw.mac.addr)) {
                memcpy(netdev->dev_addr, adapter->hw.mac.addr,
                       netdev->addr_len);
@@ -1628,10 +1704,11 @@ void ixgbevf_reset(struct ixgbevf_adapter *adapter)
        }
 }
 
-static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
-                                        int vectors)
+static int ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
+                                       int vectors)
 {
-       int err, vector_threshold;
+       int err = 0;
+       int vector_threshold;
 
        /* We'll want at least 2 (vector_threshold):
         * 1) TxQ[0] + RxQ[0] handler
@@ -1647,21 +1724,18 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
        while (vectors >= vector_threshold) {
                err = pci_enable_msix(adapter->pdev, adapter->msix_entries,
                                      vectors);
-               if (!err) /* Success in acquiring all requested vectors. */
+               if (!err || err < 0) /* Success or a nasty failure. */
                        break;
-               else if (err < 0)
-                       vectors = 0; /* Nasty failure, quit now */
                else /* err == number of vectors we should try again with */
                        vectors = err;
        }
 
-       if (vectors < vector_threshold) {
-               /* Can't allocate enough MSI-X interrupts?  Oh well.
-                * This just means we'll go with either a single MSI
-                * vector or fall back to legacy interrupts.
-                */
-               hw_dbg(&adapter->hw,
-                      "Unable to allocate MSI-X interrupts\n");
+       if (vectors < vector_threshold)
+               err = -ENOMEM;
+
+       if (err) {
+               dev_err(&adapter->pdev->dev,
+                       "Unable to allocate MSI-X interrupts\n");
                kfree(adapter->msix_entries);
                adapter->msix_entries = NULL;
        } else {
@@ -1672,6 +1746,8 @@ static void ixgbevf_acquire_msix_vectors(struct ixgbevf_adapter *adapter,
                 */
                adapter->num_msix_vectors = vectors;
        }
+
+       return err;
 }
 
 /**
@@ -1717,6 +1793,7 @@ static int ixgbevf_alloc_queues(struct ixgbevf_adapter *adapter)
        for (i = 0; i < adapter->num_tx_queues; i++) {
                adapter->tx_ring[i].count = adapter->tx_ring_count;
                adapter->tx_ring[i].queue_index = i;
+               /* reg_idx may be remapped later by DCB config */
                adapter->tx_ring[i].reg_idx = i;
                adapter->tx_ring[i].dev = &adapter->pdev->dev;
                adapter->tx_ring[i].netdev = adapter->netdev;
@@ -1774,7 +1851,9 @@ static int ixgbevf_set_interrupt_capability(struct ixgbevf_adapter *adapter)
        for (vector = 0; vector < v_budget; vector++)
                adapter->msix_entries[vector].entry = vector;
 
-       ixgbevf_acquire_msix_vectors(adapter, v_budget);
+       err = ixgbevf_acquire_msix_vectors(adapter, v_budget);
+       if (err)
+               goto out;
 
        err = netif_set_real_num_tx_queues(netdev, adapter->num_tx_queues);
        if (err)
@@ -1834,18 +1913,13 @@ err_out:
  **/
 static void ixgbevf_free_q_vectors(struct ixgbevf_adapter *adapter)
 {
-       int q_idx, num_q_vectors;
-       int napi_vectors;
-
-       num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
-       napi_vectors = adapter->num_rx_queues;
+       int q_idx, num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
 
        for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
                struct ixgbevf_q_vector *q_vector = adapter->q_vector[q_idx];
 
                adapter->q_vector[q_idx] = NULL;
-               if (q_idx < napi_vectors)
-                       netif_napi_del(&q_vector->napi);
+               netif_napi_del(&q_vector->napi);
                kfree(q_vector);
        }
 }
@@ -1935,7 +2009,7 @@ static void ixgbevf_clear_interrupt_scheme(struct ixgbevf_adapter *adapter)
  * Fields are initialized based on PCI device information and
  * OS network device settings (MTU size).
  **/
-static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
+static int ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
        struct pci_dev *pdev = adapter->pdev;
@@ -1950,8 +2024,11 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
        hw->subsystem_device_id = pdev->subsystem_device;
 
        hw->mbx.ops.init_params(hw);
-       hw->mac.max_tx_queues = MAX_TX_QUEUES;
-       hw->mac.max_rx_queues = MAX_RX_QUEUES;
+
+       /* assume legacy case in which PF would only give VF 2 queues */
+       hw->mac.max_tx_queues = 2;
+       hw->mac.max_rx_queues = 2;
+
        err = hw->mac.ops.reset_hw(hw);
        if (err) {
                dev_info(&pdev->dev,
@@ -1966,7 +2043,7 @@ static int __devinit ixgbevf_sw_init(struct ixgbevf_adapter *adapter)
                        goto out;
                }
                memcpy(adapter->netdev->dev_addr, adapter->hw.mac.addr,
-                       adapter->netdev->addr_len);
+                      adapter->netdev->addr_len);
        }
 
        /* lock to protect mailbox accesses */
@@ -2016,6 +2093,7 @@ out:
 void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
+       int i;
 
        UPDATE_VF_COUNTER_32bit(IXGBE_VFGPRC, adapter->stats.last_vfgprc,
                                adapter->stats.vfgprc);
@@ -2029,6 +2107,15 @@ void ixgbevf_update_stats(struct ixgbevf_adapter *adapter)
                                adapter->stats.vfgotc);
        UPDATE_VF_COUNTER_32bit(IXGBE_VFMPRC, adapter->stats.last_vfmprc,
                                adapter->stats.vfmprc);
+
+       for (i = 0;  i  < adapter->num_rx_queues;  i++) {
+               adapter->hw_csum_rx_error +=
+                       adapter->rx_ring[i].hw_csum_rx_error;
+               adapter->hw_csum_rx_good +=
+                       adapter->rx_ring[i].hw_csum_rx_good;
+               adapter->rx_ring[i].hw_csum_rx_error = 0;
+               adapter->rx_ring[i].hw_csum_rx_good = 0;
+       }
 }
 
 /**
@@ -2103,6 +2190,7 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
        struct ixgbe_hw *hw = &adapter->hw;
        u32 link_speed = adapter->link_speed;
        bool link_up = adapter->link_up;
+       s32 need_reset;
 
        adapter->flags |= IXGBE_FLAG_IN_WATCHDOG_TASK;
 
@@ -2110,29 +2198,19 @@ static void ixgbevf_watchdog_task(struct work_struct *work)
         * Always check the link on the watchdog because we have
         * no LSC interrupt
         */
-       if (hw->mac.ops.check_link) {
-               s32 need_reset;
-
-               spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
-               need_reset = hw->mac.ops.check_link(hw, &link_speed,
-                                                   &link_up, false);
+       need_reset = hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
 
-               spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
-               if (need_reset) {
-                       adapter->link_up = link_up;
-                       adapter->link_speed = link_speed;
-                       netif_carrier_off(netdev);
-                       netif_tx_stop_all_queues(netdev);
-                       schedule_work(&adapter->reset_task);
-                       goto pf_has_reset;
-               }
-       } else {
-               /* always assume link is up, if no check link
-                * function */
-               link_speed = IXGBE_LINK_SPEED_10GB_FULL;
-               link_up = true;
+       if (need_reset) {
+               adapter->link_up = link_up;
+               adapter->link_speed = link_speed;
+               netif_carrier_off(netdev);
+               netif_tx_stop_all_queues(netdev);
+               schedule_work(&adapter->reset_task);
+               goto pf_has_reset;
        }
        adapter->link_up = link_up;
        adapter->link_speed = link_speed;
@@ -2377,6 +2455,63 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter)
                                                  &adapter->rx_ring[i]);
 }
 
+static int ixgbevf_setup_queues(struct ixgbevf_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       struct ixgbevf_ring *rx_ring;
+       unsigned int def_q = 0;
+       unsigned int num_tcs = 0;
+       unsigned int num_rx_queues = 1;
+       int err, i;
+
+       spin_lock_bh(&adapter->mbx_lock);
+
+       /* fetch queue configuration from the PF */
+       err = ixgbevf_get_queues(hw, &num_tcs, &def_q);
+
+       spin_unlock_bh(&adapter->mbx_lock);
+
+       if (err)
+               return err;
+
+       if (num_tcs > 1) {
+               /* update default Tx ring register index */
+               adapter->tx_ring[0].reg_idx = def_q;
+
+               /* we need as many queues as traffic classes */
+               num_rx_queues = num_tcs;
+       }
+
+       /* nothing to do if we have the correct number of queues */
+       if (adapter->num_rx_queues == num_rx_queues)
+               return 0;
+
+       /* allocate new rings */
+       rx_ring = kcalloc(num_rx_queues,
+                         sizeof(struct ixgbevf_ring), GFP_KERNEL);
+       if (!rx_ring)
+               return -ENOMEM;
+
+       /* setup ring fields */
+       for (i = 0; i < num_rx_queues; i++) {
+               rx_ring[i].count = adapter->rx_ring_count;
+               rx_ring[i].queue_index = i;
+               rx_ring[i].reg_idx = i;
+               rx_ring[i].dev = &adapter->pdev->dev;
+               rx_ring[i].netdev = adapter->netdev;
+       }
+
+       /* free the existing ring and queues */
+       adapter->num_rx_queues = 0;
+       kfree(adapter->rx_ring);
+
+       /* move new rings into position on the adapter struct */
+       adapter->rx_ring = rx_ring;
+       adapter->num_rx_queues = num_rx_queues;
+
+       return 0;
+}
+
 /**
  * ixgbevf_open - Called when a network interface is made active
  * @netdev: network interface device structure
@@ -2413,6 +2548,11 @@ static int ixgbevf_open(struct net_device *netdev)
 
        ixgbevf_negotiate_api(adapter);
 
+       /* setup queue reg_idx and Rx queue count */
+       err = ixgbevf_setup_queues(adapter);
+       if (err)
+               goto err_setup_queues;
+
        /* allocate transmit descriptors */
        err = ixgbevf_setup_all_tx_resources(adapter);
        if (err)
@@ -2451,6 +2591,7 @@ err_setup_rx:
        ixgbevf_free_all_rx_resources(adapter);
 err_setup_tx:
        ixgbevf_free_all_tx_resources(adapter);
+err_setup_queues:
        ixgbevf_reset(adapter);
 
 err_setup_reset:
@@ -2562,9 +2703,6 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
 static bool ixgbevf_tx_csum(struct ixgbevf_ring *tx_ring,
                            struct sk_buff *skb, u32 tx_flags)
 {
-
-
-
        u32 vlan_macip_lens = 0;
        u32 mss_l4len_idx = 0;
        u32 type_tucmd = 0;
@@ -2678,10 +2816,10 @@ static int ixgbevf_tx_map(struct ixgbevf_ring *tx_ring,
                        tx_buffer_info->dma =
                                skb_frag_dma_map(tx_ring->dev, frag,
                                                 offset, size, DMA_TO_DEVICE);
-                       tx_buffer_info->mapped_as_page = true;
                        if (dma_mapping_error(tx_ring->dev,
                                              tx_buffer_info->dma))
                                goto dma_error;
+                       tx_buffer_info->mapped_as_page = true;
                        tx_buffer_info->next_to_watch = i;
 
                        len -= size;
@@ -2754,7 +2892,6 @@ static void ixgbevf_tx_queue(struct ixgbevf_ring *tx_ring, int tx_flags,
                olinfo_status |= (1 << IXGBE_ADVTXD_IDX_SHIFT);
                if (tx_flags & IXGBE_TX_FLAGS_IPV4)
                        olinfo_status |= IXGBE_ADVTXD_POPTS_IXSM;
-
        }
 
        /*
@@ -2823,6 +2960,11 @@ static int ixgbevf_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 #if PAGE_SIZE > IXGBE_MAX_DATA_PER_TXD
        unsigned short f;
 #endif
+       u8 *dst_mac = skb_header_pointer(skb, 0, 0, NULL);
+       if (!dst_mac || is_link_local_ether_addr(dst_mac)) {
+               dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
 
        tx_ring = &adapter->tx_ring[r_idx];
 
@@ -2902,12 +3044,11 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p)
        memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
        memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len);
 
-       spin_lock(&adapter->mbx_lock);
+       spin_lock_bh(&adapter->mbx_lock);
 
-       if (hw->mac.ops.set_rar)
-               hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
+       hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0);
 
-       spin_unlock(&adapter->mbx_lock);
+       spin_unlock_bh(&adapter->mbx_lock);
 
        return 0;
 }
@@ -2925,8 +3066,15 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
        int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
        int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
 
-       if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+       switch (adapter->hw.api_version) {
+       case ixgbe_mbox_api_11:
                max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
+               break;
+       default:
+               if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+                       max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
+               break;
+       }
 
        /* MTU < 68 is an error and causes problems on some kernels */
        if ((new_mtu < 68) || (max_frame > max_possible_frame))
@@ -3094,8 +3242,7 @@ static void ixgbevf_assign_netdev_ops(struct net_device *dev)
  * The OS initialization, configuring of the adapter private structure,
  * and a hardware reset occur.
  **/
-static int __devinit ixgbevf_probe(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct ixgbevf_adapter *adapter = NULL;
@@ -3223,10 +3370,6 @@ static int __devinit ixgbevf_probe(struct pci_dev *pdev,
        if (err)
                goto err_sw_init;
 
-       /* pick up the PCI bus settings for reporting later */
-       if (hw->mac.ops.get_bus_info)
-               hw->mac.ops.get_bus_info(hw);
-
        strcpy(netdev->name, "eth%d");
 
        err = register_netdev(netdev);
@@ -3270,7 +3413,7 @@ err_dma:
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  **/
-static void __devexit ixgbevf_remove(struct pci_dev *pdev)
+static void ixgbevf_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct ixgbevf_adapter *adapter = netdev_priv(netdev);
@@ -3384,7 +3527,7 @@ static struct pci_driver ixgbevf_driver = {
        .name     = ixgbevf_driver_name,
        .id_table = ixgbevf_pci_tbl,
        .probe    = ixgbevf_probe,
-       .remove   = __devexit_p(ixgbevf_remove),
+       .remove   = ixgbevf_remove,
 #ifdef CONFIG_PM
        /* Power Management Hooks */
        .suspend  = ixgbevf_suspend,
index 946ce86f337f702701f10133faa8c71b099d81c3..0bc30058ff82010c81bcc7c15906f2d962e0f4a8 100644 (file)
@@ -85,6 +85,7 @@
 enum ixgbe_pfvf_api_rev {
        ixgbe_mbox_api_10,      /* API version 1.0, linux/freebsd VF driver */
        ixgbe_mbox_api_20,      /* API version 2.0, solaris Phase1 VF driver */
+       ixgbe_mbox_api_11,      /* API version 1.1, linux/freebsd VF driver */
        /* This value should always be last */
        ixgbe_mbox_api_unknown, /* indicates that API version is not known */
 };
@@ -100,6 +101,15 @@ enum ixgbe_pfvf_api_rev {
 #define IXGBE_VF_SET_MACVLAN   0x06 /* VF requests PF for unicast filter */
 #define IXGBE_VF_API_NEGOTIATE 0x08 /* negotiate API version */
 
+/* mailbox API, version 1.1 VF requests */
+#define IXGBE_VF_GET_QUEUE     0x09 /* get queue configuration */
+
+/* GET_QUEUES return data indices within the mailbox */
+#define IXGBE_VF_TX_QUEUES     1       /* number of Tx queues supported */
+#define IXGBE_VF_RX_QUEUES     2       /* number of Rx queues supported */
+#define IXGBE_VF_TRANS_VLAN    3       /* Indication of port vlan */
+#define IXGBE_VF_DEF_QUEUE     4       /* Default queue offset */
+
 /* length of permanent address message returned from PF */
 #define IXGBE_VF_PERMADDR_MSG_LEN 4
 /* word in permanent address message with the current multicast type */
index 0c7447e6fcc84a3a42044b11d0f85fbe3f2d0904..0c94557b53df9b656dafd2e1a96f56c3803c8288 100644 (file)
@@ -331,6 +331,9 @@ static s32 ixgbevf_update_mc_addr_list_vf(struct ixgbe_hw *hw,
        netdev_for_each_mc_addr(ha, netdev) {
                if (i == cnt)
                        break;
+               if (is_link_local_ether_addr(ha->addr))
+                       continue;
+
                vector_list[i++] = ixgbevf_mta_vector(hw, ha->addr);
        }
 
@@ -513,6 +516,64 @@ int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api)
        return err;
 }
 
+int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
+                      unsigned int *default_tc)
+{
+       int err;
+       u32 msg[5];
+
+       /* do nothing if API doesn't support ixgbevf_get_queues */
+       switch (hw->api_version) {
+       case ixgbe_mbox_api_11:
+               break;
+       default:
+               return 0;
+       }
+
+       /* Fetch queue configuration from the PF */
+       msg[0] = IXGBE_VF_GET_QUEUE;
+       msg[1] = msg[2] = msg[3] = msg[4] = 0;
+       err = hw->mbx.ops.write_posted(hw, msg, 5);
+
+       if (!err)
+               err = hw->mbx.ops.read_posted(hw, msg, 5);
+
+       if (!err) {
+               msg[0] &= ~IXGBE_VT_MSGTYPE_CTS;
+
+               /*
+                * if we we didn't get an ACK there must have been
+                * some sort of mailbox error so we should treat it
+                * as such
+                */
+               if (msg[0] != (IXGBE_VF_GET_QUEUE | IXGBE_VT_MSGTYPE_ACK))
+                       return IXGBE_ERR_MBX;
+
+               /* record and validate values from message */
+               hw->mac.max_tx_queues = msg[IXGBE_VF_TX_QUEUES];
+               if (hw->mac.max_tx_queues == 0 ||
+                   hw->mac.max_tx_queues > IXGBE_VF_MAX_TX_QUEUES)
+                       hw->mac.max_tx_queues = IXGBE_VF_MAX_TX_QUEUES;
+
+               hw->mac.max_rx_queues = msg[IXGBE_VF_RX_QUEUES];
+               if (hw->mac.max_rx_queues == 0 ||
+                   hw->mac.max_rx_queues > IXGBE_VF_MAX_RX_QUEUES)
+                       hw->mac.max_rx_queues = IXGBE_VF_MAX_RX_QUEUES;
+
+               *num_tcs = msg[IXGBE_VF_TRANS_VLAN];
+               /* in case of unknown state assume we cannot tag frames */
+               if (*num_tcs > hw->mac.max_rx_queues)
+                       *num_tcs = 1;
+
+               *default_tc = msg[IXGBE_VF_DEF_QUEUE];
+               /* default to queue 0 on out-of-bounds queue number */
+               if (*default_tc >= hw->mac.max_tx_queues)
+                       *default_tc = 0;
+       }
+
+       return err;
+}
+
 static const struct ixgbe_mac_operations ixgbevf_mac_ops = {
        .init_hw             = ixgbevf_init_hw_vf,
        .reset_hw            = ixgbevf_reset_hw_vf,
index 47f11a584d8c04f9f4deaeecc643729362ea6917..7b1f502d171606366c06c767a65eb7ead6add2aa 100644 (file)
@@ -174,5 +174,7 @@ struct ixgbevf_info {
 
 void ixgbevf_rlpml_set_vf(struct ixgbe_hw *hw, u16 max_size);
 int ixgbevf_negotiate_api_version(struct ixgbe_hw *hw, int api);
+int ixgbevf_get_queues(struct ixgbe_hw *hw, unsigned int *num_tcs,
+                      unsigned int *default_tc);
 #endif /* __IXGBE_VF_H__ */
 
index f8064df10cc4ca1d1c6bcf05b42858ae5c9071fc..0519afa413d22714b88e355f1cea862f11650cba 100644 (file)
@@ -1860,10 +1860,14 @@ jme_open(struct net_device *netdev)
        jme_clear_pm(jme);
        JME_NAPI_ENABLE(jme);
 
-       tasklet_enable(&jme->linkch_task);
-       tasklet_enable(&jme->txclean_task);
-       tasklet_hi_enable(&jme->rxclean_task);
-       tasklet_hi_enable(&jme->rxempty_task);
+       tasklet_init(&jme->linkch_task, jme_link_change_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet,
+                    (unsigned long) jme);
 
        rc = jme_request_irq(jme);
        if (rc)
@@ -1948,10 +1952,10 @@ jme_close(struct net_device *netdev)
 
        JME_NAPI_DISABLE(jme);
 
-       tasklet_disable(&jme->linkch_task);
-       tasklet_disable(&jme->txclean_task);
-       tasklet_disable(&jme->rxclean_task);
-       tasklet_disable(&jme->rxempty_task);
+       tasklet_kill(&jme->linkch_task);
+       tasklet_kill(&jme->txclean_task);
+       tasklet_kill(&jme->rxclean_task);
+       tasklet_kill(&jme->rxempty_task);
 
        jme_disable_rx_engine(jme);
        jme_disable_tx_engine(jme);
@@ -2961,7 +2965,7 @@ static const struct net_device_ops jme_netdev_ops = {
 #endif
 };
 
-static int __devinit
+static int
 jme_init_one(struct pci_dev *pdev,
             const struct pci_device_id *ent)
 {
@@ -3079,22 +3083,6 @@ jme_init_one(struct pci_dev *pdev,
        tasklet_init(&jme->pcc_task,
                     jme_pcc_tasklet,
                     (unsigned long) jme);
-       tasklet_init(&jme->linkch_task,
-                    jme_link_change_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->txclean_task,
-                    jme_tx_clean_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->rxclean_task,
-                    jme_rx_clean_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->rxempty_task,
-                    jme_rx_empty_tasklet,
-                    (unsigned long) jme);
-       tasklet_disable_nosync(&jme->linkch_task);
-       tasklet_disable_nosync(&jme->txclean_task);
-       tasklet_disable_nosync(&jme->rxclean_task);
-       tasklet_disable_nosync(&jme->rxempty_task);
        jme->dpi.cur = PCC_P1;
 
        jme->reg_ghc = 0;
@@ -3215,7 +3203,7 @@ err_out:
        return rc;
 }
 
-static void __devexit
+static void
 jme_remove_one(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3330,7 +3318,7 @@ static struct pci_driver jme_driver = {
        .name           = DRV_NAME,
        .id_table       = jme_pci_tbl,
        .probe          = jme_init_one,
-       .remove         = __devexit_p(jme_remove_one),
+       .remove         = jme_remove_one,
        .shutdown       = jme_shutdown,
        .driver.pm      = JME_PM_OPS,
 };
index 003c5bc7189f7ef0138a46f96f10f64b52154d5c..c124e67a1a1ca72599d8fe81f449f32f69480f4f 100644 (file)
@@ -774,7 +774,7 @@ err_out:
        return err;
 }
 
-static int __devexit
+static int
 ltq_etop_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
@@ -789,7 +789,7 @@ ltq_etop_remove(struct platform_device *pdev)
 }
 
 static struct platform_driver ltq_mii_driver = {
-       .remove = __devexit_p(ltq_etop_remove),
+       .remove = ltq_etop_remove,
        .driver = {
                .name = "ltq_etop",
                .owner = THIS_MODULE,
index 59489722e898aa1e517959855c7c7561f858ba65..10d678d3dd018bf40d4ca857459de4c81cd438d6 100644 (file)
@@ -1131,7 +1131,7 @@ static int pxa168_eth_open(struct net_device *dev)
        err = request_irq(dev->irq, pxa168_eth_int_handler,
                          IRQF_DISABLED, dev->name, dev);
        if (err) {
-               dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n");
+               dev_err(&dev->dev, "can't assign irq\n");
                return -EAGAIN;
        }
        pep->rx_resource_err = 0;
@@ -1201,9 +1201,8 @@ static int pxa168_eth_change_mtu(struct net_device *dev, int mtu)
         */
        pxa168_eth_stop(dev);
        if (pxa168_eth_open(dev)) {
-               dev_printk(KERN_ERR, &dev->dev,
-                          "fatal error on re-opening device after "
-                          "MTU change\n");
+               dev_err(&dev->dev,
+                       "fatal error on re-opening device after MTU change\n");
        }
 
        return 0;
index 9b9c2ac5c4c214d65366782c05d6406a1859cb17..5544a1fe2f948f5e64ab2c38e00df0aa82255efa 100644 (file)
@@ -3860,7 +3860,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
        return dev;
 }
 
-static void __devinit skge_show_addr(struct net_device *dev)
+static void skge_show_addr(struct net_device *dev)
 {
        const struct skge_port *skge = netdev_priv(dev);
 
@@ -3869,8 +3869,7 @@ static void __devinit skge_show_addr(struct net_device *dev)
 
 static int only_32bit_dma;
 
-static int __devinit skge_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev, *dev1;
        struct skge_hw *hw;
@@ -4012,7 +4011,7 @@ err_out:
        return err;
 }
 
-static void __devexit skge_remove(struct pci_dev *pdev)
+static void skge_remove(struct pci_dev *pdev)
 {
        struct skge_hw *hw  = pci_get_drvdata(pdev);
        struct net_device *dev0, *dev1;
@@ -4026,7 +4025,7 @@ static void __devexit skge_remove(struct pci_dev *pdev)
        dev0 = hw->dev[0];
        unregister_netdev(dev0);
 
-       tasklet_disable(&hw->phy_task);
+       tasklet_kill(&hw->phy_task);
 
        spin_lock_irq(&hw->hw_lock);
        hw->intr_mask = 0;
@@ -4142,7 +4141,7 @@ static struct pci_driver skge_driver = {
        .name =         DRV_NAME,
        .id_table =     skge_id_table,
        .probe =        skge_probe,
-       .remove =       __devexit_p(skge_remove),
+       .remove =       skge_remove,
        .shutdown =     skge_shutdown,
        .driver.pm =    SKGE_PM_OPS,
 };
index 78946feab4a2de4c187138d02c01418cf8b4fb6f..3269eb38cc576924a958354b9e664b1a92b26dd2 100644 (file)
@@ -3140,7 +3140,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk)
 }
 
 
-static int __devinit sky2_init(struct sky2_hw *hw)
+static int sky2_init(struct sky2_hw *hw)
 {
        u8 t8;
 
@@ -4741,9 +4741,8 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
 };
 
 /* Initialize network device */
-static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
-                                                    unsigned port,
-                                                    int highmem, int wol)
+static struct net_device *sky2_init_netdev(struct sky2_hw *hw, unsigned port,
+                                          int highmem, int wol)
 {
        struct sky2_port *sky2;
        struct net_device *dev = alloc_etherdev(sizeof(*sky2));
@@ -4807,7 +4806,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
        return dev;
 }
 
-static void __devinit sky2_show_addr(struct net_device *dev)
+static void sky2_show_addr(struct net_device *dev)
 {
        const struct sky2_port *sky2 = netdev_priv(dev);
 
@@ -4815,7 +4814,7 @@ static void __devinit sky2_show_addr(struct net_device *dev)
 }
 
 /* Handle software interrupt used during MSI test */
-static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
+static irqreturn_t sky2_test_intr(int irq, void *dev_id)
 {
        struct sky2_hw *hw = dev_id;
        u32 status = sky2_read32(hw, B0_Y2_SP_ISRC2);
@@ -4834,7 +4833,7 @@ static irqreturn_t __devinit sky2_test_intr(int irq, void *dev_id)
 }
 
 /* Test interrupt path by forcing a a software IRQ */
-static int __devinit sky2_test_msi(struct sky2_hw *hw)
+static int sky2_test_msi(struct sky2_hw *hw)
 {
        struct pci_dev *pdev = hw->pdev;
        int err;
@@ -4896,8 +4895,7 @@ static const char *sky2_name(u8 chipid, char *buf, int sz)
        return buf;
 }
 
-static int __devinit sky2_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev, *dev1;
        struct sky2_hw *hw;
@@ -4919,13 +4917,13 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
        err = pci_read_config_dword(pdev, PCI_DEV_REG2, &reg);
        if (err) {
                dev_err(&pdev->dev, "PCI read config failed\n");
-               goto err_out;
+               goto err_out_disable;
        }
 
        if (~reg == 0) {
                dev_err(&pdev->dev, "PCI configuration read error\n");
                err = -EIO;
-               goto err_out;
+               goto err_out_disable;
        }
 
        err = pci_request_regions(pdev, DRV_NAME);
@@ -5012,10 +5010,11 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
 
        if (!disable_msi && pci_enable_msi(pdev) == 0) {
                err = sky2_test_msi(hw);
-               if (err == -EOPNOTSUPP)
+               if (err) {
                        pci_disable_msi(pdev);
-               else if (err)
-                       goto err_out_free_netdev;
+                       if (err != -EOPNOTSUPP)
+                               goto err_out_free_netdev;
+               }
        }
 
        err = register_netdev(dev);
@@ -5063,10 +5062,10 @@ err_out_unregister_dev1:
 err_out_free_dev1:
        free_netdev(dev1);
 err_out_unregister:
-       if (hw->flags & SKY2_HW_USE_MSI)
-               pci_disable_msi(pdev);
        unregister_netdev(dev);
 err_out_free_netdev:
+       if (hw->flags & SKY2_HW_USE_MSI)
+               pci_disable_msi(pdev);
        free_netdev(dev);
 err_out_free_pci:
        pci_free_consistent(pdev, hw->st_size * sizeof(struct sky2_status_le),
@@ -5086,7 +5085,7 @@ err_out:
        return err;
 }
 
-static void __devexit sky2_remove(struct pci_dev *pdev)
+static void sky2_remove(struct pci_dev *pdev)
 {
        struct sky2_hw *hw = pci_get_drvdata(pdev);
        int i;
@@ -5207,7 +5206,7 @@ static struct pci_driver sky2_driver = {
        .name = DRV_NAME,
        .id_table = sky2_id_table,
        .probe = sky2_probe,
-       .remove = __devexit_p(sky2_remove),
+       .remove = sky2_remove,
        .shutdown = sky2_shutdown,
        .driver.pm = SKY2_PM_OPS,
 };
index d8099a7903d3d7bd2fbb5fd627bf822016cc09f4..bcdbc14aeff0d40b4514b777fd7b4d27541cfc9f 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_MELLANOX
        bool "Mellanox devices"
        default y
-       depends on PCI && INET
+       depends on PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
index 5f027f95cc8422fe6887cf41b42c2572b6f809e9..eb520ab640143b918615ceae86a8f5de36bd23b7 100644 (file)
@@ -4,9 +4,8 @@
 
 config MLX4_EN
        tristate "Mellanox Technologies 10Gbit Ethernet support"
-       depends on PCI && INET
+       depends on PCI
        select MLX4_CORE
-       select INET_LRO
        ---help---
          This driver supports Mellanox Technologies ConnectX Ethernet
          devices.
index 5d36795877cb48ef90cd8ea5fac1c11ca05e30d0..b799ab12a2918bb7f0c5b8bdc0d5db70ecaf4392 100644 (file)
@@ -237,7 +237,7 @@ static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,
        if (err)
                return err;
 
-       memcpy(priv->maxrate, tmp, sizeof(*priv->maxrate));
+       memcpy(priv->maxrate, tmp, sizeof(priv->maxrate));
 
        return 0;
 }
index 9d0b88eea02bfcc549d259a0a4ca6ff06ebe4308..4aaa7c3ad22f50b3bc94444ebd00003f69bdec25 100644 (file)
 #define EN_ETHTOOL_SHORT_MASK cpu_to_be16(0xffff)
 #define EN_ETHTOOL_WORD_MASK  cpu_to_be32(0xffffffff)
 
+static int mlx4_en_moderation_update(struct mlx4_en_priv *priv)
+{
+       int i;
+       int err = 0;
+
+       for (i = 0; i < priv->tx_ring_num; i++) {
+               priv->tx_cq[i].moder_cnt = priv->tx_frames;
+               priv->tx_cq[i].moder_time = priv->tx_usecs;
+               err = mlx4_en_set_cq_moder(priv, &priv->tx_cq[i]);
+               if (err)
+                       return err;
+       }
+
+       if (priv->adaptive_rx_coal)
+               return 0;
+
+       for (i = 0; i < priv->rx_ring_num; i++) {
+               priv->rx_cq[i].moder_cnt = priv->rx_frames;
+               priv->rx_cq[i].moder_time = priv->rx_usecs;
+               priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
+               err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
+               if (err)
+                       return err;
+       }
+
+       return err;
+}
+
 static void
 mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
 {
@@ -381,7 +409,6 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
                              struct ethtool_coalesce *coal)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
-       int err, i;
 
        priv->rx_frames = (coal->rx_max_coalesced_frames ==
                           MLX4_EN_AUTO_CONF) ?
@@ -397,14 +424,6 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
            coal->tx_max_coalesced_frames != priv->tx_frames) {
                priv->tx_usecs = coal->tx_coalesce_usecs;
                priv->tx_frames = coal->tx_max_coalesced_frames;
-               for (i = 0; i < priv->tx_ring_num; i++) {
-                       priv->tx_cq[i].moder_cnt = priv->tx_frames;
-                       priv->tx_cq[i].moder_time = priv->tx_usecs;
-                       if (mlx4_en_set_cq_moder(priv, &priv->tx_cq[i])) {
-                               en_warn(priv, "Failed changing moderation "
-                                             "for TX cq %d\n", i);
-                       }
-               }
        }
 
        /* Set adaptive coalescing params */
@@ -414,18 +433,8 @@ static int mlx4_en_set_coalesce(struct net_device *dev,
        priv->rx_usecs_high = coal->rx_coalesce_usecs_high;
        priv->sample_interval = coal->rate_sample_interval;
        priv->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
-       if (priv->adaptive_rx_coal)
-               return 0;
 
-       for (i = 0; i < priv->rx_ring_num; i++) {
-               priv->rx_cq[i].moder_cnt = priv->rx_frames;
-               priv->rx_cq[i].moder_time = priv->rx_usecs;
-               priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
-               err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
-               if (err)
-                       return err;
-       }
-       return 0;
+       return mlx4_en_moderation_update(priv);
 }
 
 static int mlx4_en_set_pauseparam(struct net_device *dev,
@@ -466,7 +475,6 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
        u32 rx_size, tx_size;
        int port_up = 0;
        int err = 0;
-       int i;
 
        if (param->rx_jumbo_pending || param->rx_mini_pending)
                return -EINVAL;
@@ -505,14 +513,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
                        en_err(priv, "Failed starting port\n");
        }
 
-       for (i = 0; i < priv->rx_ring_num; i++) {
-               priv->rx_cq[i].moder_cnt = priv->rx_frames;
-               priv->rx_cq[i].moder_time = priv->rx_usecs;
-               priv->last_moder_time[i] = MLX4_EN_AUTO_CONF;
-               err = mlx4_en_set_cq_moder(priv, &priv->rx_cq[i]);
-               if (err)
-                       goto out;
-       }
+       err = mlx4_en_moderation_update(priv);
 
 out:
        mutex_unlock(&mdev->state_lock);
@@ -998,6 +999,73 @@ static int mlx4_en_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
        return err;
 }
 
+static void mlx4_en_get_channels(struct net_device *dev,
+                                struct ethtool_channels *channel)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+
+       memset(channel, 0, sizeof(*channel));
+
+       channel->max_rx = MAX_RX_RINGS;
+       channel->max_tx = MLX4_EN_MAX_TX_RING_P_UP;
+
+       channel->rx_count = priv->rx_ring_num;
+       channel->tx_count = priv->tx_ring_num / MLX4_EN_NUM_UP;
+}
+
+static int mlx4_en_set_channels(struct net_device *dev,
+                               struct ethtool_channels *channel)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       struct mlx4_en_dev *mdev = priv->mdev;
+       int port_up;
+       int err = 0;
+
+       if (channel->other_count || channel->combined_count ||
+           channel->tx_count > MLX4_EN_MAX_TX_RING_P_UP ||
+           channel->rx_count > MAX_RX_RINGS ||
+           !channel->tx_count || !channel->rx_count)
+               return -EINVAL;
+
+       mutex_lock(&mdev->state_lock);
+       if (priv->port_up) {
+               port_up = 1;
+               mlx4_en_stop_port(dev);
+       }
+
+       mlx4_en_free_resources(priv);
+
+       priv->num_tx_rings_p_up = channel->tx_count;
+       priv->tx_ring_num = channel->tx_count * MLX4_EN_NUM_UP;
+       priv->rx_ring_num = channel->rx_count;
+
+       err = mlx4_en_alloc_resources(priv);
+       if (err) {
+               en_err(priv, "Failed reallocating port resources\n");
+               goto out;
+       }
+
+       netif_set_real_num_tx_queues(dev, priv->tx_ring_num);
+       netif_set_real_num_rx_queues(dev, priv->rx_ring_num);
+
+       mlx4_en_setup_tc(dev, MLX4_EN_NUM_UP);
+
+       en_warn(priv, "Using %d TX rings\n", priv->tx_ring_num);
+       en_warn(priv, "Using %d RX rings\n", priv->rx_ring_num);
+
+       if (port_up) {
+               err = mlx4_en_start_port(dev);
+               if (err)
+                       en_err(priv, "Failed starting port\n");
+       }
+
+       err = mlx4_en_moderation_update(priv);
+
+out:
+       mutex_unlock(&mdev->state_lock);
+       return err;
+}
+
 const struct ethtool_ops mlx4_en_ethtool_ops = {
        .get_drvinfo = mlx4_en_get_drvinfo,
        .get_settings = mlx4_en_get_settings,
@@ -1022,6 +1090,8 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
        .get_rxfh_indir_size = mlx4_en_get_rxfh_indir_size,
        .get_rxfh_indir = mlx4_en_get_rxfh_indir,
        .set_rxfh_indir = mlx4_en_set_rxfh_indir,
+       .get_channels = mlx4_en_get_channels,
+       .set_channels = mlx4_en_set_channels,
 };
 
 
index a52922ed85c12e06a07caab7e4ea8977b53d8135..3a2b8c65642dd7566ffbccfbbcc0f479ee3d49f2 100644 (file)
@@ -250,7 +250,7 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
                                rounddown_pow_of_two(max_t(int, MIN_RX_RINGS,
                                                           min_t(int,
                                                                 dev->caps.num_comp_vectors,
-                                                                MAX_RX_RINGS)));
+                                                                DEF_RX_RINGS)));
                } else {
                        mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
                                min_t(int, dev->caps.comp_pool/
index edd9cb8d3e1d8f09cc1715ddee967b5fa58181fd..7d1287f81a31037ef3bc1bd9802500ca3ffcc629 100644 (file)
 #include "mlx4_en.h"
 #include "en_port.h"
 
-static int mlx4_en_setup_tc(struct net_device *dev, u8 up)
+int mlx4_en_setup_tc(struct net_device *dev, u8 up)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        int i;
-       unsigned int q, offset = 0;
+       unsigned int offset = 0;
 
        if (up && up != MLX4_EN_NUM_UP)
                return -EINVAL;
@@ -59,10 +59,9 @@ static int mlx4_en_setup_tc(struct net_device *dev, u8 up)
        netdev_set_num_tc(dev, up);
 
        /* Partition Tx queues evenly amongst UP's */
-       q = priv->tx_ring_num / up;
        for (i = 0; i < up; i++) {
-               netdev_set_tc_queue(dev, i, q, offset);
-               offset += q;
+               netdev_set_tc_queue(dev, i, priv->num_tx_rings_p_up, offset);
+               offset += priv->num_tx_rings_p_up;
        }
 
        return 0;
@@ -870,7 +869,7 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
        /* If we haven't received a specific coalescing setting
         * (module param), we set the moderation parameters as follows:
         * - moder_cnt is set to the number of mtu sized packets to
-        *   satisfy our coelsing target.
+        *   satisfy our coalescing target.
         * - moder_time is set to a fixed value.
         */
        priv->rx_frames = MLX4_EN_RX_COAL_TARGET;
@@ -1114,7 +1113,7 @@ int mlx4_en_start_port(struct net_device *dev)
                /* Configure ring */
                tx_ring = &priv->tx_ring[i];
                err = mlx4_en_activate_tx_ring(priv, tx_ring, cq->mcq.cqn,
-                       i / priv->mdev->profile.num_tx_rings_p_up);
+                       i / priv->num_tx_rings_p_up);
                if (err) {
                        en_err(priv, "Failed allocating Tx ring\n");
                        mlx4_en_deactivate_cq(priv, cq);
@@ -1564,10 +1563,13 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        int err;
 
        dev = alloc_etherdev_mqs(sizeof(struct mlx4_en_priv),
-           prof->tx_ring_num, prof->rx_ring_num);
+                                MAX_TX_RINGS, MAX_RX_RINGS);
        if (dev == NULL)
                return -ENOMEM;
 
+       netif_set_real_num_tx_queues(dev, prof->tx_ring_num);
+       netif_set_real_num_rx_queues(dev, prof->rx_ring_num);
+
        SET_NETDEV_DEV(dev, &mdev->dev->pdev->dev);
        dev->dev_id =  port - 1;
 
@@ -1586,15 +1588,17 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        priv->flags = prof->flags;
        priv->ctrl_flags = cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE |
                        MLX4_WQE_CTRL_SOLICITED);
+       priv->num_tx_rings_p_up = mdev->profile.num_tx_rings_p_up;
        priv->tx_ring_num = prof->tx_ring_num;
-       priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring) *
-                       priv->tx_ring_num, GFP_KERNEL);
+
+       priv->tx_ring = kzalloc(sizeof(struct mlx4_en_tx_ring) * MAX_TX_RINGS,
+                               GFP_KERNEL);
        if (!priv->tx_ring) {
                err = -ENOMEM;
                goto out;
        }
-       priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * priv->tx_ring_num,
-                       GFP_KERNEL);
+       priv->tx_cq = kzalloc(sizeof(struct mlx4_en_cq) * MAX_RX_RINGS,
+                             GFP_KERNEL);
        if (!priv->tx_cq) {
                err = -ENOMEM;
                goto out;
index 5aba5ecdf1e28157fadf44072c87a4a98511d249..f76c9671f3628c22bbb1280316b8f4eb57c71c3e 100644 (file)
@@ -630,7 +630,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                        if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
                            (cqe->checksum == cpu_to_be16(0xffff))) {
                                ring->csum_ok++;
-                               /* This packet is eligible for LRO if it is:
+                               /* This packet is eligible for GRO if it is:
                                 * - DIX Ethernet (type interpretation)
                                 * - TCP/IP (v4)
                                 * - without IP options
@@ -667,7 +667,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                                        goto next;
                                }
 
-                               /* LRO not possible, complete processing here */
+                               /* GRO not possible, complete processing here */
                                ip_summed = CHECKSUM_UNNECESSARY;
                        } else {
                                ip_summed = CHECKSUM_NONE;
@@ -710,11 +710,8 @@ next:
                ++cq->mcq.cons_index;
                index = (cq->mcq.cons_index) & ring->size_mask;
                cqe = &cq->buf[index];
-               if (++polled == budget) {
-                       /* We are here because we reached the NAPI budget -
-                        * flush only pending LRO sessions */
+               if (++polled == budget)
                        goto out;
-               }
        }
 
 out:
index c10e3a6de09f042a02be933d8aa1ca928207fe6d..1f571d009155de6f96335179a744f5c695b8e20e 100644 (file)
@@ -143,7 +143,6 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
                mlx4_bf_free(mdev->dev, &ring->bf);
        mlx4_qp_remove(mdev->dev, &ring->qp);
        mlx4_qp_free(mdev->dev, &ring->qp);
-       mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
        mlx4_en_unmap_buffer(&ring->wqres.buf);
        mlx4_free_hwq_res(mdev->dev, &ring->wqres, ring->buf_size);
        kfree(ring->bounce_buf);
@@ -524,7 +523,7 @@ static void build_inline_wqe(struct mlx4_en_tx_desc *tx_desc, struct sk_buff *sk
 u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
-       u16 rings_p_up = priv->mdev->profile.num_tx_rings_p_up;
+       u16 rings_p_up = priv->num_tx_rings_p_up;
        u8 up = 0;
 
        if (dev->num_tc)
@@ -712,7 +711,7 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
        if (bounce)
                tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
 
-       if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) {
+       if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tx_tag_present(skb)) {
                *(__be32 *) (&tx_desc->ctrl.vlan_tag) |= cpu_to_be32(ring->doorbell_qpn);
                op_own |= htonl((bf_index & 0xffff) << 8);
                /* Ensure new descirptor hits memory
index 51c764901ad257bce17199496d895f788a647f8b..b84a88bc44dc2a5e7391ca7bc7116344dd63a97f 100644 (file)
@@ -329,9 +329,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
        ctx = &priv->mfunc.master.slave_state[slave];
        spin_lock_irqsave(&ctx->lock, flags);
 
-       mlx4_dbg(dev, "%s: slave: %d, current state: %d new event :%d\n",
-                __func__, slave, cur_state, event);
-
        switch (cur_state) {
        case SLAVE_PORT_DOWN:
                if (MLX4_PORT_STATE_DEV_EVENT_PORT_UP == event)
@@ -366,9 +363,6 @@ int set_and_calc_slave_port_state(struct mlx4_dev *dev, int slave,
                        goto out;
        }
        ret = mlx4_get_slave_port_state(dev, slave, port);
-       mlx4_dbg(dev, "%s: slave: %d, current state: %d new event"
-                " :%d gen_event: %d\n",
-                __func__, slave, cur_state, event, *gen_event);
 
 out:
        spin_unlock_irqrestore(&ctx->lock, flags);
@@ -843,6 +837,18 @@ static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
        return priv->eq_table.uar_map[index] + 0x800 + 8 * (eq->eqn % 4);
 }
 
+static void mlx4_unmap_uar(struct mlx4_dev *dev)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       int i;
+
+       for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
+               if (priv->eq_table.uar_map[i]) {
+                       iounmap(priv->eq_table.uar_map[i]);
+                       priv->eq_table.uar_map[i] = NULL;
+               }
+}
+
 static int mlx4_create_eq(struct mlx4_dev *dev, int nent,
                          u8 intr, struct mlx4_eq *eq)
 {
@@ -1207,6 +1213,7 @@ err_out_unmap:
        mlx4_free_irqs(dev);
 
 err_out_bitmap:
+       mlx4_unmap_uar(dev);
        mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
 
 err_out_free:
@@ -1231,10 +1238,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
        if (!mlx4_is_slave(dev))
                mlx4_unmap_clr_int(dev);
 
-       for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
-               if (priv->eq_table.uar_map[i])
-                       iounmap(priv->eq_table.uar_map[i]);
-
+       mlx4_unmap_uar(dev);
        mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
 
        kfree(priv->eq_table.uar_map);
index 80df2ab0177c398122725a85c82133788b711198..200cc0ec805226506623a90e501f0db527a1dd41 100644 (file)
@@ -98,7 +98,7 @@ MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
 #define HCA_GLOBAL_CAP_MASK            0
 #define PF_CONTEXT_BEHAVIOUR_MASK      0
 
-static char mlx4_version[] __devinitdata =
+static char mlx4_version[] =
        DRV_NAME ": Mellanox ConnectX core driver v"
        DRV_VERSION " (" DRV_RELDATE ")\n";
 
@@ -1405,7 +1405,10 @@ unmap_bf:
        unmap_bf_area(dev);
 
 err_close:
-       mlx4_close_hca(dev);
+       if (mlx4_is_slave(dev))
+               mlx4_slave_exit(dev);
+       else
+               mlx4_CLOSE_HCA(dev, 0);
 
 err_free_icm:
        if (!mlx4_is_slave(dev))
@@ -2221,8 +2224,7 @@ err_disable_pdev:
        return err;
 }
 
-static int __devinit mlx4_init_one(struct pci_dev *pdev,
-                                  const struct pci_device_id *id)
+static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        printk_once(KERN_INFO "%s", mlx4_version);
 
@@ -2388,7 +2390,7 @@ static struct pci_driver mlx4_driver = {
        .name           = DRV_NAME,
        .id_table       = mlx4_pci_table,
        .probe          = mlx4_init_one,
-       .remove         = __devexit_p(mlx4_remove_one),
+       .remove         = mlx4_remove_one,
        .err_handler    = &mlx4_err_handler,
 };
 
index 9d27e42264e2b64aea3827d760c409ab3de0c301..334ec483480ba657da74487a03c15c2f011f1257 100644 (file)
@@ -67,7 +67,8 @@
 
 #define MLX4_EN_PAGE_SHIFT     12
 #define MLX4_EN_PAGE_SIZE      (1 << MLX4_EN_PAGE_SHIFT)
-#define MAX_RX_RINGS           16
+#define DEF_RX_RINGS           16
+#define MAX_RX_RINGS           128
 #define MIN_RX_RINGS           4
 #define TXBB_SIZE              64
 #define HEADROOM               (2048 / TXBB_SIZE + 1)
@@ -95,8 +96,6 @@
 #define MLX4_EN_ALLOC_SIZE     PAGE_ALIGN(16384)
 #define MLX4_EN_ALLOC_ORDER    get_order(MLX4_EN_ALLOC_SIZE)
 
-#define MLX4_EN_MAX_LRO_DESCRIPTORS    32
-
 /* Receive fragment sizes; we use at most 4 fragments (for 9600 byte MTU
  * and 4K allocations) */
 enum {
@@ -120,13 +119,15 @@ enum {
 #define MLX4_EN_NUM_UP                 8
 #define MLX4_EN_DEF_TX_RING_SIZE       512
 #define MLX4_EN_DEF_RX_RING_SIZE       1024
+#define MAX_TX_RINGS                   (MLX4_EN_MAX_TX_RING_P_UP * \
+                                        MLX4_EN_NUM_UP)
 
 /* Target number of packets to coalesce with interrupt moderation */
 #define MLX4_EN_RX_COAL_TARGET 44
 #define MLX4_EN_RX_COAL_TIME   0x10
 
 #define MLX4_EN_TX_COAL_PKTS   16
-#define MLX4_EN_TX_COAL_TIME   0x80
+#define MLX4_EN_TX_COAL_TIME   0x10
 
 #define MLX4_EN_RX_RATE_LOW            400000
 #define MLX4_EN_RX_COAL_TIME_LOW       0
@@ -290,21 +291,6 @@ struct mlx4_en_rx_ring {
        unsigned long csum_none;
 };
 
-
-static inline int mlx4_en_can_lro(__be16 status)
-{
-       return (status & cpu_to_be16(MLX4_CQE_STATUS_IPV4       |
-                                    MLX4_CQE_STATUS_IPV4F      |
-                                    MLX4_CQE_STATUS_IPV6       |
-                                    MLX4_CQE_STATUS_IPV4OPT    |
-                                    MLX4_CQE_STATUS_TCP        |
-                                    MLX4_CQE_STATUS_UDP        |
-                                    MLX4_CQE_STATUS_IPOK)) ==
-               cpu_to_be16(MLX4_CQE_STATUS_IPV4 |
-                           MLX4_CQE_STATUS_IPOK |
-                           MLX4_CQE_STATUS_TCP);
-}
-
 struct mlx4_en_cq {
        struct mlx4_cq          mcq;
        struct mlx4_hwq_resources wqres;
@@ -493,6 +479,7 @@ struct mlx4_en_priv {
        u32 flags;
 #define MLX4_EN_FLAG_PROMISC   0x1
 #define MLX4_EN_FLAG_MC_PROMISC        0x2
+       u8 num_tx_rings_p_up;
        u32 tx_ring_num;
        u32 rx_ring_num;
        u32 rx_skb_size;
@@ -613,6 +600,8 @@ int mlx4_en_QUERY_PORT(struct mlx4_en_dev *mdev, u8 port);
 extern const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops;
 #endif
 
+int mlx4_en_setup_tc(struct net_device *dev, u8 up);
+
 #ifdef CONFIG_RFS_ACCEL
 void mlx4_en_cleanup_filters(struct mlx4_en_priv *priv,
                             struct mlx4_en_rx_ring *rx_ring);
index 926c911c0ac4b184d9d0f3fa70632b5ed84cb33b..b05705f50f0fae529e3f728471280ea4a1a1d753 100644 (file)
@@ -330,9 +330,6 @@ static void update_pkey_index(struct mlx4_dev *dev, int slave,
 
        new_index = priv->virt2phys_pkey[slave][port - 1][orig_index];
        *(u8 *)(inbox->buf + 35) = new_index;
-
-       mlx4_dbg(dev, "port = %d, orig pkey index = %d, "
-                "new pkey index = %d\n", port, orig_index, new_index);
 }
 
 static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
@@ -351,9 +348,6 @@ static void update_gid(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *inbox,
                if (optpar & MLX4_QP_OPTPAR_ALT_ADDR_PATH)
                        qp_ctx->alt_path.mgid_index = slave & 0x7F;
        }
-
-       mlx4_dbg(dev, "slave %d, new gid index: 0x%x ",
-               slave, qp_ctx->pri_path.mgid_index);
 }
 
 static int mpt_mask(struct mlx4_dev *dev)
index dccae1d1743a6241679d2ece28528736404b59e6..07a6ebc47c929bdf6aabdfedf23fd20901226921 100644 (file)
@@ -1249,9 +1249,6 @@ ks8695_open(struct net_device *ndev)
        struct ks8695_priv *ksp = netdev_priv(ndev);
        int ret;
 
-       if (!is_valid_ether_addr(ndev->dev_addr))
-               return -EADDRNOTAVAIL;
-
        ks8695_reset(ksp);
 
        ks8695_update_mac(ksp);
@@ -1277,7 +1274,7 @@ ks8695_open(struct net_device *ndev)
  *     This initialises the LAN switch in the KS8695 to a known-good
  *     set of defaults.
  */
-static void __devinit
+static void
 ks8695_init_switch(struct ks8695_priv *ksp)
 {
        u32 ctrl;
@@ -1305,7 +1302,7 @@ ks8695_init_switch(struct ks8695_priv *ksp)
  *     This initialises a KS8695's WAN phy to sensible values for
  *     autonegotiation etc.
  */
-static void __devinit
+static void
 ks8695_init_wan_phy(struct ks8695_priv *ksp)
 {
        u32 ctrl;
@@ -1349,7 +1346,7 @@ static const struct net_device_ops ks8695_netdev_ops = {
  *     wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
  *     port.
  */
-static int __devinit
+static int
 ks8695_probe(struct platform_device *pdev)
 {
        struct ks8695_priv *ksp;
@@ -1597,7 +1594,7 @@ ks8695_drv_resume(struct platform_device *pdev)
  *
  *     This unregisters and releases a KS8695 ethernet device.
  */
-static int __devexit
+static int
 ks8695_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
@@ -1620,7 +1617,7 @@ static struct platform_driver ks8695_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ks8695_probe,
-       .remove         = __devexit_p(ks8695_drv_remove),
+       .remove         = ks8695_drv_remove,
        .suspend        = ks8695_drv_suspend,
        .resume         = ks8695_drv_resume,
 };
index 24fb049ac2f28fd7f3c71559fdb3f96559eba495..b71eb39ab4483e6d6bd7021d42bdf620f0977a9d 100644 (file)
@@ -1141,7 +1141,7 @@ static const struct ethtool_ops ks8842_ethtool_ops = {
        .get_link               = ethtool_op_get_link,
 };
 
-static int __devinit ks8842_probe(struct platform_device *pdev)
+static int ks8842_probe(struct platform_device *pdev)
 {
        int err = -ENOMEM;
        struct resource *iomem;
@@ -1240,7 +1240,7 @@ err_mem_region:
        return err;
 }
 
-static int __devexit ks8842_remove(struct platform_device *pdev)
+static int ks8842_remove(struct platform_device *pdev)
 {
        struct net_device *netdev = platform_get_drvdata(pdev);
        struct ks8842_adapter *adapter = netdev_priv(netdev);
@@ -1262,7 +1262,7 @@ static struct platform_driver ks8842_platform_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = ks8842_probe,
-       .remove         = __devexit_p(ks8842_remove),
+       .remove         = ks8842_remove,
 };
 
 module_platform_driver(ks8842_platform_driver);
index 1540ebeb86695903ac81d458bd2450436385bd49..286816a4e7833c27e2e994a400be44f968c4c354 100644 (file)
@@ -1415,7 +1415,7 @@ static int ks8851_resume(struct spi_device *spi)
 #define ks8851_resume NULL
 #endif
 
-static int __devinit ks8851_probe(struct spi_device *spi)
+static int ks8851_probe(struct spi_device *spi)
 {
        struct net_device *ndev;
        struct ks8851_net *ks;
@@ -1534,7 +1534,7 @@ err_irq:
        return ret;
 }
 
-static int __devexit ks8851_remove(struct spi_device *spi)
+static int ks8851_remove(struct spi_device *spi)
 {
        struct ks8851_net *priv = dev_get_drvdata(&spi->dev);
 
@@ -1554,7 +1554,7 @@ static struct spi_driver ks8851_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ks8851_probe,
-       .remove = __devexit_p(ks8851_remove),
+       .remove = ks8851_remove,
        .suspend = ks8851_suspend,
        .resume = ks8851_resume,
 };
index 38529edfe350842abf6e9613de00c9fe4b1b534f..ef8f9f92e5476daf73be7e7e3bbbb774695260af 100644 (file)
@@ -1506,7 +1506,7 @@ static int ks_hw_init(struct ks_net *ks)
 }
 
 
-static int __devinit ks8851_probe(struct platform_device *pdev)
+static int ks8851_probe(struct platform_device *pdev)
 {
        int err = -ENOMEM;
        struct resource *io_d, *io_c;
@@ -1641,7 +1641,7 @@ err_mem_region:
        return err;
 }
 
-static int __devexit ks8851_remove(struct platform_device *pdev)
+static int ks8851_remove(struct platform_device *pdev)
 {
        struct net_device *netdev = platform_get_drvdata(pdev);
        struct ks_net *ks = netdev_priv(netdev);
@@ -1663,7 +1663,7 @@ static struct platform_driver ks8851_platform_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ks8851_probe,
-       .remove = __devexit_p(ks8851_remove),
+       .remove = ks8851_remove,
 };
 
 module_platform_driver(ks8851_platform_driver);
index 318fee91c79dad0eeaa6673bd04adb68e43b6f63..093d594435e136db52fff20587d64f23e92df569 100644 (file)
@@ -1487,7 +1487,7 @@ struct dev_priv {
 #define DRV_VERSION            "1.0.0"
 #define DRV_RELDATE            "Feb 8, 2010"
 
-static char version[] __devinitdata =
+static char version[] =
        "Micrel " DEVICE_NAME " " DRV_VERSION " (" DRV_RELDATE ")";
 
 static u8 DEFAULT_MAC_ADDRESS[] = { 0x00, 0x10, 0xA1, 0x88, 0x42, 0x01 };
@@ -5407,8 +5407,8 @@ static int netdev_close(struct net_device *dev)
                /* Delay for receive task to stop scheduling itself. */
                msleep(2000 / HZ);
 
-               tasklet_disable(&hw_priv->rx_tasklet);
-               tasklet_disable(&hw_priv->tx_tasklet);
+               tasklet_kill(&hw_priv->rx_tasklet);
+               tasklet_kill(&hw_priv->tx_tasklet);
                free_irq(dev->irq, hw_priv->dev);
 
                transmit_cleanup(hw_priv, 0);
@@ -5459,8 +5459,10 @@ static int prepare_hardware(struct net_device *dev)
        rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev);
        if (rc)
                return rc;
-       tasklet_enable(&hw_priv->rx_tasklet);
-       tasklet_enable(&hw_priv->tx_tasklet);
+       tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
+                    (unsigned long) hw_priv);
+       tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
+                    (unsigned long) hw_priv);
 
        hw->promiscuous = 0;
        hw->all_multi = 0;
@@ -6917,8 +6919,7 @@ static void read_other_addr(struct ksz_hw *hw)
 #define PCI_VENDOR_ID_MICREL_KS                0x16c6
 #endif
 
-static int __devinit pcidev_init(struct pci_dev *pdev,
-       const struct pci_device_id *id)
+static int pcidev_init(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct net_device *dev;
        struct dev_priv *priv;
@@ -7033,16 +7034,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev,
        spin_lock_init(&hw_priv->hwlock);
        mutex_init(&hw_priv->lock);
 
-       /* tasklet is enabled. */
-       tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
-               (unsigned long) hw_priv);
-       tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
-               (unsigned long) hw_priv);
-
-       /* tasklet_enable will decrement the atomic counter. */
-       tasklet_disable(&hw_priv->rx_tasklet);
-       tasklet_disable(&hw_priv->tx_tasklet);
-
        for (i = 0; i < TOTAL_PORT_NUM; i++)
                init_waitqueue_head(&hw_priv->counter[i].counter);
 
@@ -7251,18 +7242,7 @@ static struct pci_driver pci_device_driver = {
        .remove         = pcidev_exit
 };
 
-static int __init ksz884x_init_module(void)
-{
-       return pci_register_driver(&pci_device_driver);
-}
-
-static void __exit ksz884x_cleanup_module(void)
-{
-       pci_unregister_driver(&pci_device_driver);
-}
-
-module_init(ksz884x_init_module);
-module_exit(ksz884x_cleanup_module);
+module_pci_driver(pci_device_driver);
 
 MODULE_DESCRIPTION("KSZ8841/2 PCI network driver");
 MODULE_AUTHOR("Tristram Ha <Tristram.Ha@micrel.com>");
index 6118bdad244f272b6cc359ca9306c47fa6dfd7a0..a99456c3dd872a783578e7f78c7a3ff4cb316fad 100644 (file)
@@ -1541,7 +1541,7 @@ static const struct net_device_ops enc28j60_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit enc28j60_probe(struct spi_device *spi)
+static int enc28j60_probe(struct spi_device *spi)
 {
        struct net_device *dev;
        struct enc28j60_net *priv;
@@ -1617,7 +1617,7 @@ error_alloc:
        return ret;
 }
 
-static int __devexit enc28j60_remove(struct spi_device *spi)
+static int enc28j60_remove(struct spi_device *spi)
 {
        struct enc28j60_net *priv = dev_get_drvdata(&spi->dev);
 
@@ -1637,7 +1637,7 @@ static struct spi_driver enc28j60_driver = {
                   .owner = THIS_MODULE,
         },
        .probe = enc28j60_probe,
-       .remove = __devexit_p(enc28j60_remove),
+       .remove = enc28j60_remove,
 };
 
 static int __init enc28j60_init(void)
index 540f0c6fc160d5d1dc4074e2142c1ea8417f7a4e..3932d081fa2106865db2d3689f9fdb74634d3b70 100644 (file)
@@ -23,7 +23,6 @@ config MYRI10GE
        depends on PCI && INET
        select FW_LOADER
        select CRC32
-       select INET_LRO
        ---help---
          This driver supports Myricom Myri-10G Dual Protocol interface in
          Ethernet mode. If the eeprom on your board is not recent enough,
index 83516e3369c90ceda6449d1a86e9b90f20a9b27c..f8408d6e961cb7243b6d2f862701697c47532d49 100644 (file)
@@ -50,7 +50,6 @@
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
 #include <linux/if_vlan.h>
-#include <linux/inet_lro.h>
 #include <linux/dca.h>
 #include <linux/ip.h>
 #include <linux/inet.h>
@@ -96,8 +95,6 @@ MODULE_LICENSE("Dual BSD/GPL");
 
 #define MYRI10GE_EEPROM_STRINGS_SIZE 256
 #define MYRI10GE_MAX_SEND_DESC_TSO ((65536 / 2048) * 2)
-#define MYRI10GE_MAX_LRO_DESCRIPTORS 8
-#define MYRI10GE_LRO_MAX_PKTS 64
 
 #define MYRI10GE_NO_CONFIRM_DATA htonl(0xffffffff)
 #define MYRI10GE_NO_RESPONSE_RESULT 0xffffffff
@@ -165,8 +162,6 @@ struct myri10ge_rx_done {
        dma_addr_t bus;
        int cnt;
        int idx;
-       struct net_lro_mgr lro_mgr;
-       struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS];
 };
 
 struct myri10ge_slice_netstats {
@@ -338,11 +333,6 @@ static int myri10ge_debug = -1;    /* defaults above */
 module_param(myri10ge_debug, int, 0);
 MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)");
 
-static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS;
-module_param(myri10ge_lro_max_pkts, int, S_IRUGO);
-MODULE_PARM_DESC(myri10ge_lro_max_pkts,
-                "Number of LRO packets to be aggregated");
-
 static int myri10ge_fill_thresh = 256;
 module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed");
@@ -1197,36 +1187,6 @@ static inline void myri10ge_vlan_ip_csum(struct sk_buff *skb, __wsum hw_csum)
        }
 }
 
-static inline void
-myri10ge_rx_skb_build(struct sk_buff *skb, u8 * va,
-                     struct skb_frag_struct *rx_frags, int len, int hlen)
-{
-       struct skb_frag_struct *skb_frags;
-
-       skb->len = skb->data_len = len;
-       /* attach the page(s) */
-
-       skb_frags = skb_shinfo(skb)->frags;
-       while (len > 0) {
-               memcpy(skb_frags, rx_frags, sizeof(*skb_frags));
-               len -= skb_frag_size(rx_frags);
-               skb_frags++;
-               rx_frags++;
-               skb_shinfo(skb)->nr_frags++;
-       }
-
-       /* pskb_may_pull is not available in irq context, but
-        * skb_pull() (for ether_pad and eth_type_trans()) requires
-        * the beginning of the packet in skb_headlen(), move it
-        * manually */
-       skb_copy_to_linear_data(skb, va, hlen);
-       skb_shinfo(skb)->frags[0].page_offset += hlen;
-       skb_frag_size_sub(&skb_shinfo(skb)->frags[0], hlen);
-       skb->data_len -= hlen;
-       skb->tail += hlen;
-       skb_pull(skb, MXGEFW_PAD);
-}
-
 static void
 myri10ge_alloc_rx_pages(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx,
                        int bytes, int watchdog)
@@ -1304,18 +1264,50 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev,
        }
 }
 
-#define MYRI10GE_HLEN 64       /* The number of bytes to copy from a
-                                * page into an skb */
+/*
+ * GRO does not support acceleration of tagged vlan frames, and
+ * this NIC does not support vlan tag offload, so we must pop
+ * the tag ourselves to be able to achieve GRO performance that
+ * is comparable to LRO.
+ */
+
+static inline void
+myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb)
+{
+       u8 *va;
+       struct vlan_ethhdr *veh;
+       struct skb_frag_struct *frag;
+       __wsum vsum;
+
+       va = addr;
+       va += MXGEFW_PAD;
+       veh = (struct vlan_ethhdr *)va;
+       if ((dev->features & NETIF_F_HW_VLAN_RX) == NETIF_F_HW_VLAN_RX &&
+           veh->h_vlan_proto == htons(ETH_P_8021Q)) {
+               /* fixup csum if needed */
+               if (skb->ip_summed == CHECKSUM_COMPLETE) {
+                       vsum = csum_partial(va + ETH_HLEN, VLAN_HLEN, 0);
+                       skb->csum = csum_sub(skb->csum, vsum);
+               }
+               /* pop tag */
+               __vlan_hwaccel_put_tag(skb, ntohs(veh->h_vlan_TCI));
+               memmove(va + VLAN_HLEN, va, 2 * ETH_ALEN);
+               skb->len -= VLAN_HLEN;
+               skb->data_len -= VLAN_HLEN;
+               frag = skb_shinfo(skb)->frags;
+               frag->page_offset += VLAN_HLEN;
+               skb_frag_size_set(frag, skb_frag_size(frag) - VLAN_HLEN);
+       }
+}
 
 static inline int
-myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
-                bool lro_enabled)
+myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum)
 {
        struct myri10ge_priv *mgp = ss->mgp;
        struct sk_buff *skb;
-       struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME];
+       struct skb_frag_struct *rx_frags;
        struct myri10ge_rx_buf *rx;
-       int i, idx, hlen, remainder, bytes;
+       int i, idx, remainder, bytes;
        struct pci_dev *pdev = mgp->pdev;
        struct net_device *dev = mgp->dev;
        u8 *va;
@@ -1332,67 +1324,48 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
        idx = rx->cnt & rx->mask;
        va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
        prefetch(va);
+
+       skb = napi_get_frags(&ss->napi);
+       if (unlikely(skb == NULL)) {
+               ss->stats.rx_dropped++;
+               for (i = 0, remainder = len; remainder > 0; i++) {
+                       myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
+                       put_page(rx->info[idx].page);
+                       rx->cnt++;
+                       idx = rx->cnt & rx->mask;
+                       remainder -= MYRI10GE_ALLOC_SIZE;
+               }
+               return 0;
+       }
+       rx_frags = skb_shinfo(skb)->frags;
        /* Fill skb_frag_struct(s) with data from our receive */
        for (i = 0, remainder = len; remainder > 0; i++) {
                myri10ge_unmap_rx_page(pdev, &rx->info[idx], bytes);
-               __skb_frag_set_page(&rx_frags[i], rx->info[idx].page);
-               rx_frags[i].page_offset = rx->info[idx].page_offset;
-               if (remainder < MYRI10GE_ALLOC_SIZE)
-                       skb_frag_size_set(&rx_frags[i], remainder);
-               else
-                       skb_frag_size_set(&rx_frags[i], MYRI10GE_ALLOC_SIZE);
+               skb_fill_page_desc(skb, i, rx->info[idx].page,
+                                  rx->info[idx].page_offset,
+                                  remainder < MYRI10GE_ALLOC_SIZE ?
+                                  remainder : MYRI10GE_ALLOC_SIZE);
                rx->cnt++;
                idx = rx->cnt & rx->mask;
                remainder -= MYRI10GE_ALLOC_SIZE;
        }
 
-       if (lro_enabled) {
-               rx_frags[0].page_offset += MXGEFW_PAD;
-               skb_frag_size_sub(&rx_frags[0], MXGEFW_PAD);
-               len -= MXGEFW_PAD;
-               lro_receive_frags(&ss->rx_done.lro_mgr, rx_frags,
-                                 /* opaque, will come back in get_frag_header */
-                                 len, len,
-                                 (void *)(__force unsigned long)csum, csum);
-
-               return 1;
-       }
-
-       hlen = MYRI10GE_HLEN > len ? len : MYRI10GE_HLEN;
-
-       /* allocate an skb to attach the page(s) to. This is done
-        * after trying LRO, so as to avoid skb allocation overheads */
-
-       skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
-       if (unlikely(skb == NULL)) {
-               ss->stats.rx_dropped++;
-               do {
-                       i--;
-                       __skb_frag_unref(&rx_frags[i]);
-               } while (i != 0);
-               return 0;
-       }
+       /* remove padding */
+       rx_frags[0].page_offset += MXGEFW_PAD;
+       rx_frags[0].size -= MXGEFW_PAD;
+       len -= MXGEFW_PAD;
 
-       /* Attach the pages to the skb, and trim off any padding */
-       myri10ge_rx_skb_build(skb, va, rx_frags, len, hlen);
-       if (skb_frag_size(&skb_shinfo(skb)->frags[0]) <= 0) {
-               skb_frag_unref(skb, 0);
-               skb_shinfo(skb)->nr_frags = 0;
-       } else {
-               skb->truesize += bytes * skb_shinfo(skb)->nr_frags;
+       skb->len = len;
+       skb->data_len = len;
+       skb->truesize += len;
+       if (dev->features & NETIF_F_RXCSUM) {
+               skb->ip_summed = CHECKSUM_COMPLETE;
+               skb->csum = csum;
        }
-       skb->protocol = eth_type_trans(skb, dev);
+       myri10ge_vlan_rx(mgp->dev, va, skb);
        skb_record_rx_queue(skb, ss - &mgp->ss[0]);
 
-       if (dev->features & NETIF_F_RXCSUM) {
-               if ((skb->protocol == htons(ETH_P_IP)) ||
-                   (skb->protocol == htons(ETH_P_IPV6))) {
-                       skb->csum = csum;
-                       skb->ip_summed = CHECKSUM_COMPLETE;
-               } else
-                       myri10ge_vlan_ip_csum(skb, csum);
-       }
-       netif_receive_skb(skb);
+       napi_gro_frags(&ss->napi);
        return 1;
 }
 
@@ -1480,18 +1453,11 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
        u16 length;
        __wsum checksum;
 
-       /*
-        * Prevent compiler from generating more than one ->features memory
-        * access to avoid theoretical race condition with functions that
-        * change NETIF_F_LRO flag at runtime.
-        */
-       bool lro_enabled = !!(ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO);
-
        while (rx_done->entry[idx].length != 0 && work_done < budget) {
                length = ntohs(rx_done->entry[idx].length);
                rx_done->entry[idx].length = 0;
                checksum = csum_unfold(rx_done->entry[idx].checksum);
-               rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled);
+               rx_ok = myri10ge_rx_done(ss, length, checksum);
                rx_packets += rx_ok;
                rx_bytes += rx_ok * (unsigned long)length;
                cnt++;
@@ -1503,9 +1469,6 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget)
        ss->stats.rx_packets += rx_packets;
        ss->stats.rx_bytes += rx_bytes;
 
-       if (lro_enabled)
-               lro_flush_all(&rx_done->lro_mgr);
-
        /* restock receive rings if needed */
        if (ss->rx_small.fill_cnt - ss->rx_small.cnt < myri10ge_fill_thresh)
                myri10ge_alloc_rx_pages(mgp, &ss->rx_small,
@@ -1779,7 +1742,6 @@ static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = {
        "tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done",
        "rx_small_cnt", "rx_big_cnt",
        "wake_queue", "stop_queue", "tx_linearized",
-       "LRO aggregated", "LRO flushed", "LRO avg aggr", "LRO no_desc",
 };
 
 #define MYRI10GE_NET_STATS_LEN      21
@@ -1880,14 +1842,6 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
                data[i++] = (unsigned int)ss->tx.wake_queue;
                data[i++] = (unsigned int)ss->tx.stop_queue;
                data[i++] = (unsigned int)ss->tx.linearized;
-               data[i++] = ss->rx_done.lro_mgr.stats.aggregated;
-               data[i++] = ss->rx_done.lro_mgr.stats.flushed;
-               if (ss->rx_done.lro_mgr.stats.flushed)
-                       data[i++] = ss->rx_done.lro_mgr.stats.aggregated /
-                           ss->rx_done.lro_mgr.stats.flushed;
-               else
-                       data[i++] = 0;
-               data[i++] = ss->rx_done.lro_mgr.stats.no_desc;
        }
 }
 
@@ -1931,7 +1885,7 @@ static int myri10ge_led(struct myri10ge_priv *mgp, int on)
        }
        if (!on)
                pattern = swab32(readl(mgp->sram + pattern_off + 4));
-       writel(htonl(pattern), mgp->sram + pattern_off);
+       writel(swab32(pattern), mgp->sram + pattern_off);
        return 0;
 }
 
@@ -2271,67 +2225,6 @@ static void myri10ge_free_irq(struct myri10ge_priv *mgp)
                pci_disable_msix(pdev);
 }
 
-static int
-myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
-                        void **ip_hdr, void **tcpudp_hdr,
-                        u64 * hdr_flags, void *priv)
-{
-       struct ethhdr *eh;
-       struct vlan_ethhdr *veh;
-       struct iphdr *iph;
-       u8 *va = skb_frag_address(frag);
-       unsigned long ll_hlen;
-       /* passed opaque through lro_receive_frags() */
-       __wsum csum = (__force __wsum) (unsigned long)priv;
-
-       /* find the mac header, aborting if not IPv4 */
-
-       eh = (struct ethhdr *)va;
-       *mac_hdr = eh;
-       ll_hlen = ETH_HLEN;
-       if (eh->h_proto != htons(ETH_P_IP)) {
-               if (eh->h_proto == htons(ETH_P_8021Q)) {
-                       veh = (struct vlan_ethhdr *)va;
-                       if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP))
-                               return -1;
-
-                       ll_hlen += VLAN_HLEN;
-
-                       /*
-                        *  HW checksum starts ETH_HLEN bytes into
-                        *  frame, so we must subtract off the VLAN
-                        *  header's checksum before csum can be used
-                        */
-                       csum = csum_sub(csum, csum_partial(va + ETH_HLEN,
-                                                          VLAN_HLEN, 0));
-               } else {
-                       return -1;
-               }
-       }
-       *hdr_flags = LRO_IPV4;
-
-       iph = (struct iphdr *)(va + ll_hlen);
-       *ip_hdr = iph;
-       if (iph->protocol != IPPROTO_TCP)
-               return -1;
-       if (ip_is_fragment(iph))
-               return -1;
-       *hdr_flags |= LRO_TCP;
-       *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
-
-       /* verify the IP checksum */
-       if (unlikely(ip_fast_csum((u8 *) iph, iph->ihl)))
-               return -1;
-
-       /* verify the  checksum */
-       if (unlikely(csum_tcpudp_magic(iph->saddr, iph->daddr,
-                                      ntohs(iph->tot_len) - (iph->ihl << 2),
-                                      IPPROTO_TCP, csum)))
-               return -1;
-
-       return 0;
-}
-
 static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
 {
        struct myri10ge_cmd cmd;
@@ -2401,8 +2294,7 @@ static int myri10ge_open(struct net_device *dev)
        struct myri10ge_priv *mgp = netdev_priv(dev);
        struct myri10ge_cmd cmd;
        int i, status, big_pow2, slice;
-       u8 *itable;
-       struct net_lro_mgr *lro_mgr;
+       u8 __iomem *itable;
 
        if (mgp->running != MYRI10GE_ETH_STOPPED)
                return -EBUSY;
@@ -2513,19 +2405,6 @@ static int myri10ge_open(struct net_device *dev)
                        goto abort_with_rings;
                }
 
-               lro_mgr = &ss->rx_done.lro_mgr;
-               lro_mgr->dev = dev;
-               lro_mgr->features = LRO_F_NAPI;
-               lro_mgr->ip_summed = CHECKSUM_COMPLETE;
-               lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY;
-               lro_mgr->max_desc = MYRI10GE_MAX_LRO_DESCRIPTORS;
-               lro_mgr->lro_arr = ss->rx_done.lro_desc;
-               lro_mgr->get_frag_header = myri10ge_get_frag_header;
-               lro_mgr->max_aggr = myri10ge_lro_max_pkts;
-               lro_mgr->frag_align_pad = 2;
-               if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
-                       lro_mgr->max_aggr = MAX_SKB_FRAGS;
-
                /* must happen prior to any irq */
                napi_enable(&(ss)->napi);
        }
@@ -2878,7 +2757,7 @@ again:
                                        flags_next |= next_is_first *
                                            MXGEFW_FLAGS_FIRST;
                                        rdma_count |= -(chop | next_is_first);
-                                       rdma_count += chop & !next_is_first;
+                                       rdma_count += chop & ~next_is_first;
                                } else if (likely(cum_len_next >= 0)) { /* header ends */
                                        int small;
 
@@ -3143,15 +3022,6 @@ static int myri10ge_set_mac_address(struct net_device *dev, void *addr)
        return 0;
 }
 
-static netdev_features_t myri10ge_fix_features(struct net_device *dev,
-       netdev_features_t features)
-{
-       if (!(features & NETIF_F_RXCSUM))
-               features &= ~NETIF_F_LRO;
-
-       return features;
-}
-
 static int myri10ge_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct myri10ge_priv *mgp = netdev_priv(dev);
@@ -3878,7 +3748,6 @@ static const struct net_device_ops myri10ge_netdev_ops = {
        .ndo_get_stats64        = myri10ge_get_stats,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = myri10ge_change_mtu,
-       .ndo_fix_features       = myri10ge_fix_features,
        .ndo_set_rx_mode        = myri10ge_set_multicast_list,
        .ndo_set_mac_address    = myri10ge_set_mac_address,
 };
@@ -3967,9 +3836,9 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto abort_with_mtrr;
        }
        hdr_offset =
-           ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc;
+           swab32(readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc;
        ss_offset = hdr_offset + offsetof(struct mcp_gen_header, string_specs);
-       mgp->sram_size = ntohl(__raw_readl(mgp->sram + ss_offset));
+       mgp->sram_size = swab32(readl(mgp->sram + ss_offset));
        if (mgp->sram_size > mgp->board_span ||
            mgp->sram_size <= MYRI10GE_FW_OFFSET) {
                dev_err(&pdev->dev,
@@ -4018,7 +3887,11 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        netdev->netdev_ops = &myri10ge_netdev_ops;
        netdev->mtu = myri10ge_initial_mtu;
-       netdev->hw_features = mgp->features | NETIF_F_LRO | NETIF_F_RXCSUM;
+       netdev->hw_features = mgp->features | NETIF_F_RXCSUM;
+
+       /* fake NETIF_F_HW_VLAN_RX for good GRO performance */
+       netdev->hw_features |= NETIF_F_HW_VLAN_RX;
+
        netdev->features = netdev->hw_features;
 
        if (dac_enabled)
index 3f94ddbf4dc0db10261077a55dd142fcbf8a4eb4..923e640d604cc4f32693e218a20ec0fef4db4fa2 100644 (file)
@@ -900,7 +900,7 @@ static short ibmlana_adapter_ids[] __initdata = {
        0x0000
 };
 
-static char *ibmlana_adapter_names[] __devinitdata = {
+static char *ibmlana_adapter_names[] = {
        "IBM LAN Adapter/A",
        NULL
 };
@@ -916,7 +916,7 @@ static const struct net_device_ops ibmlana_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit ibmlana_init_one(struct device *kdev)
+static int ibmlana_init_one(struct device *kdev)
 {
        struct mca_device *mdev = to_mca_device(kdev);
        struct net_device *dev;
index 95dd39ffb2309d340097946be548e55cf5dadfae..b0b36154636508e9f947c8358140f42fb7cbd1d5 100644 (file)
@@ -117,7 +117,7 @@ static const struct net_device_ops sonic_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __devinit sonic_probe1(struct net_device *dev)
+static int sonic_probe1(struct net_device *dev)
 {
        static unsigned version_printed;
        unsigned int silicon_revision;
@@ -220,7 +220,7 @@ out:
  * Probe for a SONIC ethernet controller on a Mips Jazz board.
  * Actually probing is superfluous but we're paranoid.
  */
-static int __devinit jazz_sonic_probe(struct platform_device *pdev)
+static int jazz_sonic_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct sonic_local *lp;
@@ -270,7 +270,7 @@ MODULE_ALIAS("platform:jazzsonic");
 
 #include "sonic.c"
 
-static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
+static int jazz_sonic_device_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct sonic_local* lp = netdev_priv(dev);
@@ -286,7 +286,7 @@ static int __devexit jazz_sonic_device_remove (struct platform_device *pdev)
 
 static struct platform_driver jazz_sonic_driver = {
        .probe  = jazz_sonic_probe,
-       .remove = __devexit_p(jazz_sonic_device_remove),
+       .remove = jazz_sonic_device_remove,
        .driver = {
                .name   = jazz_sonic_string,
                .owner  = THIS_MODULE,
index b9680ba5a32523df25e453b8d847a785fe35def1..0ffde69c8d015e12db0e5943078b225fbfbd40e1 100644 (file)
@@ -196,7 +196,7 @@ static const struct net_device_ops macsonic_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __devinit macsonic_init(struct net_device *dev)
+static int macsonic_init(struct net_device *dev)
 {
        struct sonic_local* lp = netdev_priv(dev);
 
@@ -245,7 +245,7 @@ static int __devinit macsonic_init(struct net_device *dev)
                           memcmp(mac, "\x00\x80\x19", 3) && \
                           memcmp(mac, "\x00\x05\x02", 3))
 
-static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
+static void mac_onboard_sonic_ethernet_addr(struct net_device *dev)
 {
        struct sonic_local *lp = netdev_priv(dev);
        const int prom_addr = ONBOARD_SONIC_PROM_BASE;
@@ -309,7 +309,7 @@ static void __devinit mac_onboard_sonic_ethernet_addr(struct net_device *dev)
        eth_hw_addr_random(dev);
 }
 
-static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
+static int mac_onboard_sonic_probe(struct net_device *dev)
 {
        struct sonic_local* lp = netdev_priv(dev);
        int sr;
@@ -420,9 +420,8 @@ static int __devinit mac_onboard_sonic_probe(struct net_device *dev)
        return macsonic_init(dev);
 }
 
-static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
-                                               unsigned long prom_addr,
-                                               int id)
+static int mac_nubus_sonic_ethernet_addr(struct net_device *dev,
+                                        unsigned long prom_addr, int id)
 {
        int i;
        for(i = 0; i < 6; i++)
@@ -435,7 +434,7 @@ static int __devinit mac_nubus_sonic_ethernet_addr(struct net_device *dev,
        return 0;
 }
 
-static int __devinit macsonic_ident(struct nubus_dev *ndev)
+static int macsonic_ident(struct nubus_dev *ndev)
 {
        if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
            ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
@@ -460,7 +459,7 @@ static int __devinit macsonic_ident(struct nubus_dev *ndev)
        return -1;
 }
 
-static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
+static int mac_nubus_sonic_probe(struct net_device *dev)
 {
        static int slots;
        struct nubus_dev* ndev = NULL;
@@ -573,7 +572,7 @@ static int __devinit mac_nubus_sonic_probe(struct net_device *dev)
        return macsonic_init(dev);
 }
 
-static int __devinit mac_sonic_probe(struct platform_device *pdev)
+static int mac_sonic_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct sonic_local *lp;
@@ -619,7 +618,7 @@ MODULE_ALIAS("platform:macsonic");
 
 #include "sonic.c"
 
-static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
+static int mac_sonic_device_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct sonic_local* lp = netdev_priv(dev);
@@ -634,7 +633,7 @@ static int __devexit mac_sonic_device_remove (struct platform_device *pdev)
 
 static struct platform_driver mac_sonic_driver = {
        .probe  = mac_sonic_probe,
-       .remove = __devexit_p(mac_sonic_device_remove),
+       .remove = mac_sonic_device_remove,
        .driver = {
                .name   = mac_sonic_string,
                .owner  = THIS_MODULE,
index dbaaa99a0d43fb81f14f7d3a4c6c8b2f3caabd80..f4ad60c97eae4b0f271923694b19dd187416445c 100644 (file)
@@ -127,7 +127,7 @@ static int full_duplex[MAX_UNITS];
 #define NATSEMI_RX_LIMIT       2046    /* maximum supported by hardware */
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
   KERN_INFO DRV_NAME " dp8381x driver, version "
       DRV_VERSION ", " DRV_RELDATE "\n"
   "  originally by Donald Becker <becker@scyld.com>\n"
@@ -242,7 +242,7 @@ static struct {
        const char *name;
        unsigned long flags;
        unsigned int eeprom_size;
-} natsemi_pci_info[] __devinitdata = {
+} natsemi_pci_info[] = {
        { "Aculab E1/T1 PMXc cPCI carrier card", NATSEMI_FLAG_IGNORE_PHY, 128 },
        { "NatSemi DP8381[56]", 0, 24 },
 };
@@ -742,7 +742,7 @@ static void move_int_phy(struct net_device *dev, int addr)
        udelay(1);
 }
 
-static void __devinit natsemi_init_media (struct net_device *dev)
+static void natsemi_init_media(struct net_device *dev)
 {
        struct netdev_private *np = netdev_priv(dev);
        u32 tmp;
@@ -797,8 +797,7 @@ static const struct net_device_ops natsemi_netdev_ops = {
 #endif
 };
 
-static int __devinit natsemi_probe1 (struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct netdev_private *np;
@@ -3214,7 +3213,7 @@ static int netdev_close(struct net_device *dev)
 }
 
 
-static void __devexit natsemi_remove1 (struct pci_dev *pdev)
+static void natsemi_remove1(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        void __iomem * ioaddr = ns_ioaddr(dev);
@@ -3353,7 +3352,7 @@ static struct pci_driver natsemi_driver = {
        .name           = DRV_NAME,
        .id_table       = natsemi_pci_tbl,
        .probe          = natsemi_probe1,
-       .remove         = __devexit_p(natsemi_remove1),
+       .remove         = natsemi_remove1,
 #ifdef CONFIG_PM
        .suspend        = natsemi_suspend,
        .resume         = natsemi_resume,
index d52728b3c436e1d9d2d97ff0746fd7a845be6c4b..77c070de621ee09145ea9c94dca1a8e1c0f9b831 100644 (file)
@@ -1941,8 +1941,8 @@ static const struct net_device_ops netdev_ops = {
        .ndo_tx_timeout         = ns83820_tx_timeout,
 };
 
-static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
-                                     const struct pci_device_id *id)
+static int ns83820_init_one(struct pci_dev *pci_dev,
+                           const struct pci_device_id *id)
 {
        struct net_device *ndev;
        struct ns83820 *dev;
@@ -2241,7 +2241,7 @@ out:
        return err;
 }
 
-static void __devexit ns83820_remove_one(struct pci_dev *pci_dev)
+static void ns83820_remove_one(struct pci_dev *pci_dev)
 {
        struct net_device *ndev = pci_get_drvdata(pci_dev);
        struct ns83820 *dev = PRIV(ndev); /* ok even if NULL */
@@ -2272,7 +2272,7 @@ static struct pci_driver driver = {
        .name           = "ns83820",
        .id_table       = ns83820_pci_tbl,
        .probe          = ns83820_init_one,
-       .remove         = __devexit_p(ns83820_remove_one),
+       .remove         = ns83820_remove_one,
 #if 0  /* FIXME: implement */
        .suspend        = ,
        .resume         = ,
index 7dfe88398d7d3937cd6f308fb6d08b6943ee58d5..5e4748e855f632f198adadda71221306fe6d4bcc 100644 (file)
@@ -249,7 +249,7 @@ out:
  * Actually probing is superfluous but we're paranoid.
  */
 
-int __devinit xtsonic_probe(struct platform_device *pdev)
+int xtsonic_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct sonic_local *lp;
@@ -297,7 +297,7 @@ MODULE_PARM_DESC(sonic_debug, "xtsonic debug level (1-4)");
 
 #include "sonic.c"
 
-static int __devexit xtsonic_device_remove (struct platform_device *pdev)
+static int xtsonic_device_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct sonic_local *lp = netdev_priv(dev);
@@ -314,7 +314,7 @@ static int __devexit xtsonic_device_remove (struct platform_device *pdev)
 
 static struct platform_driver xtsonic_driver = {
        .probe = xtsonic_probe,
-       .remove = __devexit_p(xtsonic_device_remove),
+       .remove = xtsonic_device_remove,
        .driver = {
                .name = xtsonic_string,
        },
index ff26b54bd3fbb79f2220ebd8799f5819f73baba1..87abb4f10c43a4e08d99e5d35a60a9eae158837d 100644 (file)
@@ -32,7 +32,7 @@ config S2IO
 
 config VXGE
        tristate "Exar X3100 Series 10GbE PCIe Server Adapter"
-       depends on PCI && INET
+       depends on PCI
        ---help---
          This driver supports Exar Corp's X3100 Series 10 GbE PCIe
          I/O Virtualized Server Adapter.
index de50547c187d7429c755db17fc4f4242f2599894..7c94c089212f9ffe638b0628ffb1635be407c19c 100644 (file)
@@ -494,7 +494,7 @@ static struct pci_driver s2io_driver = {
        .name = "S2IO",
        .id_table = s2io_tbl,
        .probe = s2io_init_nic,
-       .remove = __devexit_p(s2io_rem_nic),
+       .remove = s2io_rem_nic,
        .err_handler = &s2io_err_handler,
 };
 
@@ -1040,7 +1040,7 @@ static int s2io_verify_pci_mode(struct s2io_nic *nic)
 static int s2io_on_nec_bridge(struct pci_dev *s2io_pdev)
 {
        struct pci_dev *tdev = NULL;
-       while ((tdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, tdev)) != NULL) {
+       for_each_pci_dev(tdev) {
                if (tdev->vendor == NEC_VENID && tdev->device == NEC_DEVID) {
                        if (tdev->bus == s2io_pdev->bus->parent) {
                                pci_dev_put(tdev);
@@ -7702,7 +7702,7 @@ static const struct net_device_ops s2io_netdev_ops = {
  *  returns 0 on success and negative on failure.
  */
 
-static int __devinit
+static int
 s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
 {
        struct s2io_nic *sp;
@@ -8200,7 +8200,7 @@ mem_alloc_failed:
  * from memory.
  */
 
-static void __devexit s2io_rem_nic(struct pci_dev *pdev)
+static void s2io_rem_nic(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct s2io_nic *sp;
@@ -8239,7 +8239,8 @@ static int __init s2io_starter(void)
 
 /**
  * s2io_closer - Cleanup routine for the driver
- * Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
+ * Description: This function is the cleanup routine for the driver. It
+ * unregisters the driver.
  */
 
 static __exit void s2io_closer(void)
index d5596926a1ef5f9735d64012d84679dd7fdde815..d89b6ed82c51ac37d18dda4bfdd9937a0605c7f7 100644 (file)
@@ -1075,9 +1075,8 @@ static inline void SPECIAL_REG_WRITE(u64 val, void __iomem *addr, int order)
 /*
  * Prototype declaration.
  */
-static int __devinit s2io_init_nic(struct pci_dev *pdev,
-                                  const struct pci_device_id *pre);
-static void __devexit s2io_rem_nic(struct pci_dev *pdev);
+static int s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre);
+static void s2io_rem_nic(struct pci_dev *pdev);
 static int init_shared_mem(struct s2io_nic *sp);
 static void free_shared_mem(struct s2io_nic *sp);
 static int init_nic(struct s2io_nic *nic);
index c2e420a84d2247bd928799151d8418f3b664f735..fbe5363cb89c5c04ab4d76224dce4ce096eb691b 100644 (file)
@@ -993,7 +993,7 @@ exit:
  * for the driver, FW version information, and the first mac address for
  * each vpath
  */
-enum vxge_hw_status __devinit
+enum vxge_hw_status
 vxge_hw_device_hw_info_get(void __iomem *bar0,
                           struct vxge_hw_device_hw_info *hw_info)
 {
@@ -1310,7 +1310,7 @@ __vxge_hw_device_config_check(struct vxge_hw_device_config *new_config)
  * When done, the driver allocates sizeof(struct __vxge_hw_device) bytes for HW
  * to enable the latter to perform Titan hardware initialization.
  */
-enum vxge_hw_status __devinit
+enum vxge_hw_status
 vxge_hw_device_initialize(
        struct __vxge_hw_device **devh,
        struct vxge_hw_device_attr *attr,
@@ -2917,7 +2917,7 @@ exit:
  * vxge_hw_device_config_default_get - Initialize device config with defaults.
  * Initialize Titan device config with default values.
  */
-enum vxge_hw_status __devinit
+enum vxge_hw_status
 vxge_hw_device_config_default_get(struct vxge_hw_device_config *device_config)
 {
        u32 i;
index 9e0c1eed5dc5fd6041e8173c1c13c5f835fd34cc..6ce4412fcc1ad90b676965effafa7af65d012648 100644 (file)
@@ -1846,11 +1846,11 @@ struct vxge_hw_vpath_attr {
        struct vxge_hw_fifo_attr        fifo_attr;
 };
 
-enum vxge_hw_status __devinit vxge_hw_device_hw_info_get(
+enum vxge_hw_status vxge_hw_device_hw_info_get(
        void __iomem *bar0,
        struct vxge_hw_device_hw_info *hw_info);
 
-enum vxge_hw_status __devinit vxge_hw_device_config_default_get(
+enum vxge_hw_status vxge_hw_device_config_default_get(
        struct vxge_hw_device_config *device_config);
 
 /**
@@ -1877,7 +1877,7 @@ u16 vxge_hw_device_link_width_get(struct __vxge_hw_device *devh);
 const u8 *
 vxge_hw_device_product_name_get(struct __vxge_hw_device *devh);
 
-enum vxge_hw_status __devinit vxge_hw_device_initialize(
+enum vxge_hw_status vxge_hw_device_initialize(
        struct __vxge_hw_device **devh,
        struct vxge_hw_device_attr *attr,
        struct vxge_hw_device_config *device_config);
index 3e5b7509502c6321b9065e14a39156b547b83878..7c87105ca04999d55d4fea2f5f2adc9d3846a660 100644 (file)
@@ -3371,10 +3371,9 @@ static const struct net_device_ops vxge_netdev_ops = {
 #endif
 };
 
-static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
-                                         struct vxge_config *config,
-                                         int high_dma, int no_of_vpath,
-                                         struct vxgedev **vdev_out)
+static int vxge_device_register(struct __vxge_hw_device *hldev,
+                               struct vxge_config *config, int high_dma,
+                               int no_of_vpath, struct vxgedev **vdev_out)
 {
        struct net_device *ndev;
        enum vxge_hw_status status = VXGE_HW_OK;
@@ -3672,9 +3671,8 @@ static void verify_bandwidth(void)
 /*
  * Vpath configuration
  */
-static int __devinit vxge_config_vpaths(
-                       struct vxge_hw_device_config *device_config,
-                       u64 vpath_mask, struct vxge_config *config_param)
+static int vxge_config_vpaths(struct vxge_hw_device_config *device_config,
+                             u64 vpath_mask, struct vxge_config *config_param)
 {
        int i, no_of_vpaths = 0, default_no_vpath = 0, temp;
        u32 txdl_size, txdl_per_memblock;
@@ -3859,9 +3857,8 @@ static int __devinit vxge_config_vpaths(
 }
 
 /* initialize device configuratrions */
-static void __devinit vxge_device_config_init(
-                               struct vxge_hw_device_config *device_config,
-                               int *intr_type)
+static void vxge_device_config_init(struct vxge_hw_device_config *device_config,
+                                   int *intr_type)
 {
        /* Used for CQRQ/SRQ. */
        device_config->dma_blockpool_initial =
@@ -3912,7 +3909,7 @@ static void __devinit vxge_device_config_init(
                        device_config->rth_it_type);
 }
 
-static void __devinit vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask)
+static void vxge_print_parm(struct vxgedev *vdev, u64 vpath_mask)
 {
        int i;
 
@@ -4269,7 +4266,7 @@ static int vxge_probe_fw_update(struct vxgedev *vdev)
        return ret;
 }
 
-static int __devinit is_sriov_initialized(struct pci_dev *pdev)
+static int is_sriov_initialized(struct pci_dev *pdev)
 {
        int pos;
        u16 ctrl;
@@ -4300,7 +4297,7 @@ static const struct vxge_hw_uld_cbs vxge_callbacks = {
  * returns 0 on success and negative on failure.
  *
  */
-static int __devinit
+static int
 vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
 {
        struct __vxge_hw_device *hldev;
@@ -4764,7 +4761,7 @@ _exit0:
  * Description: This function is called by the Pci subsystem to release a
  * PCI device and free up all resource held up by the device.
  */
-static void __devexit vxge_remove(struct pci_dev *pdev)
+static void vxge_remove(struct pci_dev *pdev)
 {
        struct __vxge_hw_device *hldev;
        struct vxgedev *vdev;
@@ -4809,7 +4806,7 @@ static struct pci_driver vxge_driver = {
        .name = VXGE_DRIVER_NAME,
        .id_table = vxge_id_table,
        .probe = vxge_probe,
-       .remove = __devexit_p(vxge_remove),
+       .remove = vxge_remove,
 #ifdef CONFIG_PM
        .suspend = vxge_pm_suspend,
        .resume = vxge_pm_resume,
index 6893a65ae55f179104381d70dbb6021842e3498a..cbd6a529d0c0d94d130dfb16f8703db6c1139fb4 100644 (file)
@@ -978,7 +978,7 @@ static int w90p910_ether_setup(struct net_device *dev)
        return 0;
 }
 
-static int __devinit w90p910_ether_probe(struct platform_device *pdev)
+static int w90p910_ether_probe(struct platform_device *pdev)
 {
        struct w90p910_ether *ether;
        struct net_device *dev;
@@ -1071,7 +1071,7 @@ failed_free:
        return error;
 }
 
-static int __devexit w90p910_ether_remove(struct platform_device *pdev)
+static int w90p910_ether_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct w90p910_ether *ether = netdev_priv(dev);
@@ -1096,7 +1096,7 @@ static int __devexit w90p910_ether_remove(struct platform_device *pdev)
 
 static struct platform_driver w90p910_ether_driver = {
        .probe          = w90p910_ether_probe,
-       .remove         = __devexit_p(w90p910_ether_remove),
+       .remove         = w90p910_ether_remove,
        .driver         = {
                .name   = "nuc900-emc",
                .owner  = THIS_MODULE,
index 876beceaf2d7154f07d9de46bbb75fba3b1f0c43..653487dc7b52c58d69f42723cd5e572dfddc90a0 100644 (file)
@@ -5520,7 +5520,7 @@ static const struct net_device_ops nv_netdev_ops_optimized = {
 #endif
 };
 
-static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
+static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 {
        struct net_device *dev;
        struct fe_priv *np;
@@ -5995,7 +5995,7 @@ static void nv_restore_mac_addr(struct pci_dev *pci_dev)
               base + NvRegTransmitPoll);
 }
 
-static void __devexit nv_remove(struct pci_dev *pci_dev)
+static void nv_remove(struct pci_dev *pci_dev)
 {
        struct net_device *dev = pci_get_drvdata(pci_dev);
 
@@ -6271,7 +6271,7 @@ static struct pci_driver driver = {
        .name           = DRV_NAME,
        .id_table       = pci_tbl,
        .probe          = nv_probe,
-       .remove         = __devexit_p(nv_remove),
+       .remove         = nv_remove,
        .shutdown       = nv_shutdown,
        .driver.pm      = NV_PM_OPS,
 };
index 53743f7a2ca9604d6f264de3a2e3c727556a0619..3466ca1e8f6c0c11edc26a06b86b83595ed014a0 100644 (file)
@@ -1219,9 +1219,6 @@ static int lpc_eth_open(struct net_device *ndev)
        if (netif_msg_ifup(pldat))
                dev_dbg(&pldat->pdev->dev, "enabling %s\n", ndev->name);
 
-       if (!is_valid_ether_addr(ndev->dev_addr))
-               return -EADDRNOTAVAIL;
-
        __lpc_eth_clock_enable(pldat, true);
 
        /* Reset and initialize */
@@ -1301,6 +1298,7 @@ static const struct net_device_ops lpc_netdev_ops = {
        .ndo_set_rx_mode        = lpc_eth_set_multicast_list,
        .ndo_do_ioctl           = lpc_eth_ioctl,
        .ndo_set_mac_address    = lpc_set_mac_address,
+       .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
 };
 
@@ -1524,6 +1522,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)
                                  pldat->dma_buff_base_p);
        free_irq(ndev->irq, ndev);
        iounmap(pldat->net_base);
+       mdiobus_unregister(pldat->mii_bus);
        mdiobus_free(pldat->mii_bus);
        clk_disable(pldat->clk);
        clk_put(pldat->clk);
@@ -1596,7 +1595,7 @@ MODULE_DEVICE_TABLE(of, lpc_eth_match);
 
 static struct platform_driver lpc_eth_driver = {
        .probe          = lpc_eth_drv_probe,
-       .remove         = __devexit_p(lpc_eth_drv_remove),
+       .remove         = lpc_eth_drv_remove,
 #ifdef CONFIG_PM
        .suspend        = lpc_eth_drv_suspend,
        .resume         = lpc_eth_drv_resume,
index f97719c48516a037db795c9ee0879c526a062037..b5499198e0290dd329e44486c5d54a1db3a1f893 100644 (file)
@@ -1419,7 +1419,7 @@ static const struct net_device_ops octeon_mgmt_ops = {
 #endif
 };
 
-static int __devinit octeon_mgmt_probe(struct platform_device *pdev)
+static int octeon_mgmt_probe(struct platform_device *pdev)
 {
        struct net_device *netdev;
        struct octeon_mgmt *p;
@@ -1559,7 +1559,7 @@ err:
        return result;
 }
 
-static int __devexit octeon_mgmt_remove(struct platform_device *pdev)
+static int octeon_mgmt_remove(struct platform_device *pdev)
 {
        struct net_device *netdev = dev_get_drvdata(&pdev->dev);
 
@@ -1583,7 +1583,7 @@ static struct platform_driver octeon_mgmt_driver = {
                .of_match_table = octeon_mgmt_match,
        },
        .probe          = octeon_mgmt_probe,
-       .remove         = __devexit_p(octeon_mgmt_remove),
+       .remove         = octeon_mgmt_remove,
 };
 
 extern void octeon_mdiobus_force_mod_depencency(void);
index 5296cc8d3cbaaf2dc20994a71a200b2d6e547cb7..34d05bf72b2e0e403e3568d7eb2193535d8fda6c 100644 (file)
@@ -7,6 +7,7 @@ config PCH_GBE
        depends on PCI
        select NET_CORE
        select MII
+       select PTP_1588_CLOCK_PCH
        ---help---
          This is a gigabit ethernet driver for EG20T PCH.
          EG20T PCH is the platform controller hub that is used in Intel's
@@ -20,19 +21,3 @@ config PCH_GBE
          purpose use.
          ML7223/ML7831 is companion chip for Intel Atom E6xx series.
          ML7223/ML7831 is completely compatible for Intel EG20T PCH.
-
-if PCH_GBE
-
-config PCH_PTP
-       bool "PCH PTP clock support"
-       default n
-       depends on EXPERIMENTAL
-       select PPS
-       select PTP_1588_CLOCK
-       select PTP_1588_CLOCK_PCH
-       ---help---
-         Say Y here if you want to use Precision Time Protocol (PTP) in the
-         driver. PTP is a method to precisely synchronize distributed clocks
-         over Ethernet networks.
-
-endif # PCH_GBE
index b07311eaa69386d3cdbad86537da599b5dcaccb7..7fb7e178c74eaacd1af8c1597b02cca0b15676ee 100644 (file)
@@ -649,7 +649,6 @@ extern void pch_gbe_free_tx_resources(struct pch_gbe_adapter *adapter,
 extern void pch_gbe_free_rx_resources(struct pch_gbe_adapter *adapter,
                                       struct pch_gbe_rx_ring *rx_ring);
 extern void pch_gbe_update_stats(struct pch_gbe_adapter *adapter);
-#ifdef CONFIG_PCH_PTP
 extern u32 pch_ch_control_read(struct pci_dev *pdev);
 extern void pch_ch_control_write(struct pci_dev *pdev, u32 val);
 extern u32 pch_ch_event_read(struct pci_dev *pdev);
@@ -659,7 +658,6 @@ extern u32 pch_src_uuid_hi_read(struct pci_dev *pdev);
 extern u64 pch_rx_snap_read(struct pci_dev *pdev);
 extern u64 pch_tx_snap_read(struct pci_dev *pdev);
 extern int pch_set_station_address(u8 *addr, struct pci_dev *pdev);
-#endif
 
 /* pch_gbe_param.c */
 extern void pch_gbe_check_options(struct pch_gbe_adapter *adapter);
index b2a94d02a5217db7638164962d59b16f8def20ad..39ab4d09faaa2eb500748466ba6ab0fbe4074ac9 100644 (file)
 #include "pch_gbe.h"
 #include "pch_gbe_api.h"
 #include <linux/module.h>
-#ifdef CONFIG_PCH_PTP
 #include <linux/net_tstamp.h>
 #include <linux/ptp_classify.h>
-#endif
 
 #define DRV_VERSION     "1.01"
 const char pch_driver_version[] = DRV_VERSION;
@@ -98,7 +96,6 @@ const char pch_driver_version[] = DRV_VERSION;
 
 #define PCH_GBE_INT_DISABLE_ALL                0
 
-#ifdef CONFIG_PCH_PTP
 /* Macros for ieee1588 */
 /* 0x40 Time Synchronization Channel Control Register Bits */
 #define MASTER_MODE   (1<<0)
@@ -113,7 +110,6 @@ const char pch_driver_version[] = DRV_VERSION;
 
 #define PTP_L4_MULTICAST_SA "01:00:5e:00:01:81"
 #define PTP_L2_MULTICAST_SA "01:1b:19:00:00:00"
-#endif
 
 static unsigned int copybreak __read_mostly = PCH_GBE_COPYBREAK_DEFAULT;
 
@@ -122,7 +118,6 @@ static void pch_gbe_mdio_write(struct net_device *netdev, int addr, int reg,
                               int data);
 static void pch_gbe_set_multi(struct net_device *netdev);
 
-#ifdef CONFIG_PCH_PTP
 static struct sock_filter ptp_filter[] = {
        PTP_FILTER
 };
@@ -291,7 +286,6 @@ static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 
        return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
 }
-#endif
 
 inline void pch_gbe_mac_load_mac_addr(struct pch_gbe_hw *hw)
 {
@@ -338,26 +332,6 @@ static void pch_gbe_wait_clr_bit(void *reg, u32 bit)
                pr_err("Error: busy bit is not cleared\n");
 }
 
-/**
- * pch_gbe_wait_clr_bit_irq - Wait to clear a bit for interrupt context
- * @reg:       Pointer of register
- * @busy:      Busy bit
- */
-static int pch_gbe_wait_clr_bit_irq(void *reg, u32 bit)
-{
-       u32 tmp;
-       int ret = -1;
-       /* wait busy */
-       tmp = 20;
-       while ((ioread32(reg) & bit) && --tmp)
-               udelay(5);
-       if (!tmp)
-               pr_err("Error: busy bit is not cleared\n");
-       else
-               ret = 0;
-       return ret;
-}
-
 /**
  * pch_gbe_mac_mar_set - Set MAC address register
  * @hw:            Pointer to the HW structure
@@ -409,15 +383,20 @@ static void pch_gbe_mac_reset_hw(struct pch_gbe_hw *hw)
        return;
 }
 
-static void pch_gbe_mac_reset_rx(struct pch_gbe_hw *hw)
+static void pch_gbe_disable_mac_rx(struct pch_gbe_hw *hw)
 {
-       /* Read the MAC addresses. and store to the private data */
-       pch_gbe_mac_read_mac_addr(hw);
-       iowrite32(PCH_GBE_RX_RST, &hw->reg->RESET);
-       pch_gbe_wait_clr_bit_irq(&hw->reg->RESET, PCH_GBE_RX_RST);
-       /* Setup the MAC addresses */
-       pch_gbe_mac_mar_set(hw, hw->mac.addr, 0);
-       return;
+       u32 rctl;
+       /* Disables Receive MAC */
+       rctl = ioread32(&hw->reg->MAC_RX_EN);
+       iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+}
+
+static void pch_gbe_enable_mac_rx(struct pch_gbe_hw *hw)
+{
+       u32 rctl;
+       /* Enables Receive MAC */
+       rctl = ioread32(&hw->reg->MAC_RX_EN);
+       iowrite32((rctl | PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
 }
 
 /**
@@ -913,7 +892,7 @@ static void pch_gbe_setup_rctl(struct pch_gbe_adapter *adapter)
 static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
 {
        struct pch_gbe_hw *hw = &adapter->hw;
-       u32 rdba, rdlen, rctl, rxdma;
+       u32 rdba, rdlen, rxdma;
 
        pr_debug("dma adr = 0x%08llx  size = 0x%08x\n",
                 (unsigned long long)adapter->rx_ring->dma,
@@ -921,9 +900,7 @@ static void pch_gbe_configure_rx(struct pch_gbe_adapter *adapter)
 
        pch_gbe_mac_force_mac_fc(hw);
 
-       /* Disables Receive MAC */
-       rctl = ioread32(&hw->reg->MAC_RX_EN);
-       iowrite32((rctl & ~PCH_GBE_MRE_MAC_RX_EN), &hw->reg->MAC_RX_EN);
+       pch_gbe_disable_mac_rx(hw);
 
        /* Disables Receive DMA */
        rxdma = ioread32(&hw->reg->DMA_CTRL);
@@ -1261,9 +1238,7 @@ static void pch_gbe_tx_queue(struct pch_gbe_adapter *adapter,
                  (int)sizeof(struct pch_gbe_tx_desc) * ring_num,
                  &hw->reg->TX_DSC_SW_P);
 
-#ifdef CONFIG_PCH_PTP
        pch_tx_timestamp(adapter, skb);
-#endif
 
        dev_kfree_skb_any(skb);
 }
@@ -1316,38 +1291,17 @@ void pch_gbe_update_stats(struct pch_gbe_adapter *adapter)
        spin_unlock_irqrestore(&adapter->stats_lock, flags);
 }
 
-static void pch_gbe_stop_receive(struct pch_gbe_adapter *adapter)
+static void pch_gbe_disable_dma_rx(struct pch_gbe_hw *hw)
 {
-       struct pch_gbe_hw *hw = &adapter->hw;
        u32 rxdma;
-       u16 value;
-       int ret;
 
        /* Disable Receive DMA */
        rxdma = ioread32(&hw->reg->DMA_CTRL);
        rxdma &= ~PCH_GBE_RX_DMA_EN;
        iowrite32(rxdma, &hw->reg->DMA_CTRL);
-       /* Wait Rx DMA BUS is IDLE */
-       ret = pch_gbe_wait_clr_bit_irq(&hw->reg->RX_DMA_ST, PCH_GBE_IDLE_CHECK);
-       if (ret) {
-               /* Disable Bus master */
-               pci_read_config_word(adapter->pdev, PCI_COMMAND, &value);
-               value &= ~PCI_COMMAND_MASTER;
-               pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
-               /* Stop Receive */
-               pch_gbe_mac_reset_rx(hw);
-               /* Enable Bus master */
-               value |= PCI_COMMAND_MASTER;
-               pci_write_config_word(adapter->pdev, PCI_COMMAND, value);
-       } else {
-               /* Stop Receive */
-               pch_gbe_mac_reset_rx(hw);
-       }
-       /* reprogram multicast address register after reset */
-       pch_gbe_set_multi(adapter->netdev);
 }
 
-static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
+static void pch_gbe_enable_dma_rx(struct pch_gbe_hw *hw)
 {
        u32 rxdma;
 
@@ -1355,9 +1309,6 @@ static void pch_gbe_start_receive(struct pch_gbe_hw *hw)
        rxdma = ioread32(&hw->reg->DMA_CTRL);
        rxdma |= PCH_GBE_RX_DMA_EN;
        iowrite32(rxdma, &hw->reg->DMA_CTRL);
-       /* Enables Receive */
-       iowrite32(PCH_GBE_MRE_MAC_RX_EN, &hw->reg->MAC_RX_EN);
-       return;
 }
 
 /**
@@ -1393,7 +1344,7 @@ static irqreturn_t pch_gbe_intr(int irq, void *data)
                        int_en = ioread32(&hw->reg->INT_EN);
                        iowrite32((int_en & ~PCH_GBE_INT_RX_FIFO_ERR),
                                  &hw->reg->INT_EN);
-                       pch_gbe_stop_receive(adapter);
+                       pch_gbe_disable_dma_rx(&adapter->hw);
                        int_st |= ioread32(&hw->reg->INT_ST);
                        int_st = int_st & ioread32(&hw->reg->INT_EN);
                }
@@ -1771,9 +1722,7 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter,
                        /* Write meta date of skb */
                        skb_put(skb, length);
 
-#ifdef CONFIG_PCH_PTP
                        pch_rx_timestamp(adapter, skb);
-#endif
 
                        skb->protocol = eth_type_trans(skb, netdev);
                        if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
@@ -1971,12 +1920,12 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
        struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
-       int err;
+       int err = -EINVAL;
 
        /* Ensure we have a valid MAC */
        if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
                pr_err("Error: Invalid MAC address\n");
-               return -EINVAL;
+               goto out;
        }
 
        /* hardware has been reset, we need to reload some things */
@@ -1989,18 +1938,19 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
 
        err = pch_gbe_request_irq(adapter);
        if (err) {
-               pr_err("Error: can't bring device up\n");
-               return err;
+               pr_err("Error: can't bring device up - irq request failed\n");
+               goto out;
        }
        err = pch_gbe_alloc_rx_buffers_pool(adapter, rx_ring, rx_ring->count);
        if (err) {
-               pr_err("Error: can't bring device up\n");
-               return err;
+               pr_err("Error: can't bring device up - alloc rx buffers pool failed\n");
+               goto freeirq;
        }
        pch_gbe_alloc_tx_buffers(adapter, tx_ring);
        pch_gbe_alloc_rx_buffers(adapter, rx_ring, rx_ring->count);
        adapter->tx_queue_len = netdev->tx_queue_len;
-       pch_gbe_start_receive(&adapter->hw);
+       pch_gbe_enable_dma_rx(&adapter->hw);
+       pch_gbe_enable_mac_rx(&adapter->hw);
 
        mod_timer(&adapter->watchdog_timer, jiffies);
 
@@ -2009,6 +1959,11 @@ int pch_gbe_up(struct pch_gbe_adapter *adapter)
        netif_start_queue(adapter->netdev);
 
        return 0;
+
+freeirq:
+       pch_gbe_free_irq(adapter);
+out:
+       return err;
 }
 
 /**
@@ -2369,10 +2324,8 @@ static int pch_gbe_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 
        pr_debug("cmd : 0x%04x\n", cmd);
 
-#ifdef CONFIG_PCH_PTP
        if (cmd == SIOCSHWTSTAMP)
                return hwtstamp_ioctl(netdev, ifr, cmd);
-#endif
 
        return generic_mii_ioctl(&adapter->mii, if_mii(ifr), cmd, NULL);
 }
@@ -2405,7 +2358,6 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
        int work_done = 0;
        bool poll_end_flag = false;
        bool cleaned = false;
-       u32 int_en;
 
        pr_debug("budget : %d\n", budget);
 
@@ -2422,19 +2374,13 @@ static int pch_gbe_napi_poll(struct napi_struct *napi, int budget)
 
        if (poll_end_flag) {
                napi_complete(napi);
-               if (adapter->rx_stop_flag) {
-                       adapter->rx_stop_flag = false;
-                       pch_gbe_start_receive(&adapter->hw);
-               }
                pch_gbe_irq_enable(adapter);
-       } else
-               if (adapter->rx_stop_flag) {
-                       adapter->rx_stop_flag = false;
-                       pch_gbe_start_receive(&adapter->hw);
-                       int_en = ioread32(&adapter->hw.reg->INT_EN);
-                       iowrite32((int_en | PCH_GBE_INT_RX_FIFO_ERR),
-                               &adapter->hw.reg->INT_EN);
-               }
+       }
+
+       if (adapter->rx_stop_flag) {
+               adapter->rx_stop_flag = false;
+               pch_gbe_enable_dma_rx(&adapter->hw);
+       }
 
        pr_debug("poll_end_flag : %d  work_done : %d  budget : %d\n",
                 poll_end_flag, work_done, budget);
@@ -2665,14 +2611,12 @@ static int pch_gbe_probe(struct pci_dev *pdev,
                goto err_free_netdev;
        }
 
-#ifdef CONFIG_PCH_PTP
        adapter->ptp_pdev = pci_get_bus_and_slot(adapter->pdev->bus->number,
                                               PCI_DEVFN(12, 4));
        if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
                pr_err("Bad ptp filter\n");
                return -EINVAL;
        }
-#endif
 
        netdev->netdev_ops = &pch_gbe_netdev_ops;
        netdev->watchdog_timeo = PCH_GBE_WATCHDOG_PERIOD;
index c2367158350ec8680da96b1ff8ecfd1099debd18..bf829ee30077ac0b4716f6ca04101669aea549af 100644 (file)
@@ -166,7 +166,7 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #include <asm/unaligned.h>
 #include <asm/cache.h>
 
-static const char version[] __devinitconst =
+static const char version[] =
 KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "  Written by Donald Becker\n"
 "   Some modifications by Eric kasten <kasten@nscl.msu.edu>\n"
 "   Further modifications by Keith Underwood <keithu@parl.clemson.edu>\n";
@@ -576,8 +576,8 @@ static const struct net_device_ops hamachi_netdev_ops = {
 };
 
 
-static int __devinit hamachi_init_one (struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int hamachi_init_one(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        struct hamachi_private *hmp;
        int option, i, rx_int_var, tx_int_var, boguscnt;
@@ -791,7 +791,7 @@ err_out:
        return ret;
 }
 
-static int __devinit read_eeprom(void __iomem *ioaddr, int location)
+static int read_eeprom(void __iomem *ioaddr, int location)
 {
        int bogus_cnt = 1000;
 
@@ -1894,7 +1894,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 }
 
 
-static void __devexit hamachi_remove_one (struct pci_dev *pdev)
+static void hamachi_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -1923,7 +1923,7 @@ static struct pci_driver hamachi_driver = {
        .name           = DRV_NAME,
        .id_table       = hamachi_pci_tbl,
        .probe          = hamachi_init_one,
-       .remove         = __devexit_p(hamachi_remove_one),
+       .remove         = hamachi_remove_one,
 };
 
 static int __init hamachi_init (void)
index 04e622fd468d89acdaa758b4492434730fea0e0c..fbaed4fa72fa01798ec058b2381c9af381839eab 100644 (file)
@@ -106,7 +106,7 @@ static int gx_fix;
 #include <asm/io.h>
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
   KERN_INFO DRV_NAME ".c:v1.05  1/09/2001  Written by Donald Becker <becker@scyld.com>\n"
   "  (unofficial 2.4.x port, " DRV_VERSION ", " DRV_RELDATE ")\n";
 
@@ -367,8 +367,8 @@ static const struct net_device_ops netdev_ops = {
        .ndo_tx_timeout         = yellowfin_tx_timeout,
 };
 
-static int __devinit yellowfin_init_one(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent)
+static int yellowfin_init_one(struct pci_dev *pdev,
+                             const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct yellowfin_private *np;
@@ -522,7 +522,7 @@ err_out_free_netdev:
        return -ENODEV;
 }
 
-static int __devinit read_eeprom(void __iomem *ioaddr, int location)
+static int read_eeprom(void __iomem *ioaddr, int location)
 {
        int bogus_cnt = 10000;          /* Typical 33Mhz: 1050 ticks */
 
@@ -1372,7 +1372,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 }
 
 
-static void __devexit yellowfin_remove_one (struct pci_dev *pdev)
+static void yellowfin_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct yellowfin_private *np;
@@ -1399,7 +1399,7 @@ static struct pci_driver yellowfin_driver = {
        .name           = DRV_NAME,
        .id_table       = yellowfin_pci_tbl,
        .probe          = yellowfin_init_one,
-       .remove         = __devexit_p(yellowfin_remove_one),
+       .remove         = yellowfin_remove_one,
 };
 
 
index 6fa74d530e44d390ce87946b8327a476e5a728e5..0be5844d637266035299014f85b8b1058944cd43 100644 (file)
@@ -1727,7 +1727,7 @@ static const struct net_device_ops pasemi_netdev_ops = {
 #endif
 };
 
-static int __devinit
+static int
 pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
@@ -1849,7 +1849,7 @@ out_disable_device:
 
 }
 
-static void __devexit pasemi_mac_remove(struct pci_dev *pdev)
+static void pasemi_mac_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct pasemi_mac *mac;
@@ -1884,7 +1884,7 @@ static struct pci_driver pasemi_mac_driver = {
        .name           = "pasemi_mac",
        .id_table       = pasemi_mac_pci_tbl,
        .probe          = pasemi_mac_probe,
-       .remove         = __devexit_p(pasemi_mac_remove),
+       .remove         = pasemi_mac_remove,
 };
 
 static void __exit pasemi_mac_cleanup_module(void)
index 10468e7932dd5ae54947279dda6345e45f16df8e..4ca2c196c98a1e79a77434e7ba56c14c2e98801c 100644 (file)
@@ -218,7 +218,7 @@ skip:
                        check_sfp_module = netif_running(dev) &&
                                adapter->has_link_events;
                } else {
-                       ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
+                       ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
                        ecmd->advertising |=
                                (ADVERTISED_TP | ADVERTISED_Autoneg);
                        ecmd->port = PORT_TP;
@@ -381,7 +381,7 @@ static u32 netxen_nic_test_link(struct net_device *dev)
 
 static int
 netxen_nic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
-                     u8 * bytes)
+                     u8 *bytes)
 {
        struct netxen_adapter *adapter = netdev_priv(dev);
        int offset;
@@ -488,6 +488,8 @@ netxen_nic_get_pauseparam(struct net_device *dev,
        __u32 val;
        int port = adapter->physical_port;
 
+       pause->autoneg = 0;
+
        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
                if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
                        return;
@@ -496,19 +498,19 @@ netxen_nic_get_pauseparam(struct net_device *dev,
                pause->rx_pause = netxen_gb_get_rx_flowctl(val);
                val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
                switch (port) {
-                       case 0:
-                               pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
-                               break;
-                       case 1:
-                               pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
-                               break;
-                       case 2:
-                               pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
-                               break;
-                       case 3:
-                       default:
-                               pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
-                               break;
+               case 0:
+                       pause->tx_pause = !(netxen_gb_get_gb0_mask(val));
+                       break;
+               case 1:
+                       pause->tx_pause = !(netxen_gb_get_gb1_mask(val));
+                       break;
+               case 2:
+                       pause->tx_pause = !(netxen_gb_get_gb2_mask(val));
+                       break;
+               case 3:
+               default:
+                       pause->tx_pause = !(netxen_gb_get_gb3_mask(val));
+                       break;
                }
        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
                if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS))
@@ -532,6 +534,11 @@ netxen_nic_set_pauseparam(struct net_device *dev,
        struct netxen_adapter *adapter = netdev_priv(dev);
        __u32 val;
        int port = adapter->physical_port;
+
+       /* not supported */
+       if (pause->autoneg)
+               return -EINVAL;
+
        /* read mode */
        if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
                if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS))
@@ -549,31 +556,31 @@ netxen_nic_set_pauseparam(struct net_device *dev,
                /* set autoneg */
                val = NXRD32(adapter, NETXEN_NIU_GB_PAUSE_CTL);
                switch (port) {
-                       case 0:
-                               if (pause->tx_pause)
-                                       netxen_gb_unset_gb0_mask(val);
-                               else
-                                       netxen_gb_set_gb0_mask(val);
-                               break;
-                       case 1:
-                               if (pause->tx_pause)
-                                       netxen_gb_unset_gb1_mask(val);
-                               else
-                                       netxen_gb_set_gb1_mask(val);
-                               break;
-                       case 2:
-                               if (pause->tx_pause)
-                                       netxen_gb_unset_gb2_mask(val);
-                               else
-                                       netxen_gb_set_gb2_mask(val);
-                               break;
-                       case 3:
-                       default:
-                               if (pause->tx_pause)
-                                       netxen_gb_unset_gb3_mask(val);
-                               else
-                                       netxen_gb_set_gb3_mask(val);
-                               break;
+               case 0:
+                       if (pause->tx_pause)
+                               netxen_gb_unset_gb0_mask(val);
+                       else
+                               netxen_gb_set_gb0_mask(val);
+                       break;
+               case 1:
+                       if (pause->tx_pause)
+                               netxen_gb_unset_gb1_mask(val);
+                       else
+                               netxen_gb_set_gb1_mask(val);
+                       break;
+               case 2:
+                       if (pause->tx_pause)
+                               netxen_gb_unset_gb2_mask(val);
+                       else
+                               netxen_gb_set_gb2_mask(val);
+                       break;
+               case 3:
+               default:
+                       if (pause->tx_pause)
+                               netxen_gb_unset_gb3_mask(val);
+                       else
+                               netxen_gb_set_gb3_mask(val);
+                       break;
                }
                NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val);
        } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) {
@@ -636,7 +643,7 @@ static int netxen_get_sset_count(struct net_device *dev, int sset)
 
 static void
 netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
-                    u64 * data)
+                    u64 *data)
 {
        memset(data, 0, sizeof(uint64_t) * NETXEN_NIC_TEST_LEN);
        if ((data[0] = netxen_nic_reg_test(dev)))
@@ -647,7 +654,7 @@ netxen_nic_diag_test(struct net_device *dev, struct ethtool_test *eth_test,
 }
 
 static void
-netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 {
        int index;
 
@@ -668,7 +675,7 @@ netxen_nic_get_strings(struct net_device *dev, u32 stringset, u8 * data)
 
 static void
 netxen_nic_get_ethtool_stats(struct net_device *dev,
-                            struct ethtool_stats *stats, u64 * data)
+                            struct ethtool_stats *stats, u64 *data)
 {
        struct netxen_adapter *adapter = netdev_priv(dev);
        int index;
index df450616ab37a2547dbd728e8b0d26c7e4f394b4..6098fd4adfeb89ef5ed9c15407799ddbdcf02e7a 100644 (file)
@@ -60,9 +60,9 @@ static int auto_fw_reset = AUTO_FW_RESET_ENABLED;
 module_param(auto_fw_reset, int, 0644);
 MODULE_PARM_DESC(auto_fw_reset,"Auto firmware reset (0=disabled, 1=enabled");
 
-static int __devinit netxen_nic_probe(struct pci_dev *pdev,
+static int netxen_nic_probe(struct pci_dev *pdev,
                const struct pci_device_id *ent);
-static void __devexit netxen_nic_remove(struct pci_dev *pdev);
+static void netxen_nic_remove(struct pci_dev *pdev);
 static int netxen_nic_open(struct net_device *netdev);
 static int netxen_nic_close(struct net_device *netdev);
 static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *,
@@ -1397,7 +1397,7 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
 }
 #endif
 
-static int __devinit
+static int
 netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev = NULL;
@@ -1569,7 +1569,7 @@ void netxen_cleanup_minidump(struct netxen_adapter *adapter)
        }
 }
 
-static void __devexit netxen_nic_remove(struct pci_dev *pdev)
+static void netxen_nic_remove(struct pci_dev *pdev)
 {
        struct netxen_adapter *adapter;
        struct net_device *netdev;
@@ -3350,7 +3350,7 @@ static struct pci_driver netxen_driver = {
        .name = netxen_nic_driver_name,
        .id_table = netxen_pci_tbl,
        .probe = netxen_nic_probe,
-       .remove = __devexit_p(netxen_nic_remove),
+       .remove = netxen_nic_remove,
 #ifdef CONFIG_PM
        .suspend = netxen_nic_suspend,
        .resume = netxen_nic_resume,
index df09b1cb742fb211f639e0e6a16d658a768cf7d6..67a679aaf29adf949a2b8dfa79e230b308807615 100644 (file)
@@ -1920,7 +1920,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
 {
        struct ql_tx_buf_cb *tx_cb;
        int i;
-       int retval = 0;
 
        if (mac_rsp->flags & OB_MAC_IOCB_RSP_S) {
                netdev_warn(qdev->ndev,
@@ -1935,7 +1934,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
                           "Frame too short to be legal, frame not sent\n");
 
                qdev->ndev->stats.tx_errors++;
-               retval = -EIO;
                goto frame_not_sent;
        }
 
@@ -1944,7 +1942,6 @@ static void ql_process_mac_tx_intr(struct ql3_adapter *qdev,
                           mac_rsp->transaction_id);
 
                qdev->ndev->stats.tx_errors++;
-               retval = -EIO;
                goto invalid_seg_count;
        }
 
@@ -2525,6 +2522,13 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
        qdev->req_q_size =
            (u32) (NUM_REQ_Q_ENTRIES * sizeof(struct ob_mac_iocb_req));
 
+       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
+
+       /* The barrier is required to ensure request and response queue
+        * addr writes to the registers.
+        */
+       wmb();
+
        qdev->req_q_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 (size_t) qdev->req_q_size,
@@ -2536,8 +2540,6 @@ static int ql_alloc_net_req_rsp_queues(struct ql3_adapter *qdev)
                return -ENOMEM;
        }
 
-       qdev->rsp_q_size = NUM_RSP_Q_ENTRIES * sizeof(struct net_rsp_iocb);
-
        qdev->rsp_q_virt_addr =
            pci_alloc_consistent(qdev->pdev,
                                 (size_t) qdev->rsp_q_size,
@@ -3767,8 +3769,8 @@ static const struct net_device_ops ql3xxx_netdev_ops = {
        .ndo_tx_timeout         = ql3xxx_tx_timeout,
 };
 
-static int __devinit ql3xxx_probe(struct pci_dev *pdev,
-                                 const struct pci_device_id *pci_entry)
+static int ql3xxx_probe(struct pci_dev *pdev,
+                       const struct pci_device_id *pci_entry)
 {
        struct net_device *ndev = NULL;
        struct ql3_adapter *qdev = NULL;
@@ -3923,7 +3925,7 @@ err_out:
        return err;
 }
 
-static void __devexit ql3xxx_remove(struct pci_dev *pdev)
+static void ql3xxx_remove(struct pci_dev *pdev)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
        struct ql3_adapter *qdev = netdev_priv(ndev);
@@ -3950,18 +3952,7 @@ static struct pci_driver ql3xxx_driver = {
        .name = DRV_NAME,
        .id_table = ql3xxx_pci_tbl,
        .probe = ql3xxx_probe,
-       .remove = __devexit_p(ql3xxx_remove),
+       .remove = ql3xxx_remove,
 };
 
-static int __init ql3xxx_init_module(void)
-{
-       return pci_register_driver(&ql3xxx_driver);
-}
-
-static void __exit ql3xxx_exit(void)
-{
-       pci_unregister_driver(&ql3xxx_driver);
-}
-
-module_init(ql3xxx_init_module);
-module_exit(ql3xxx_exit);
+module_pci_driver(ql3xxx_driver);
index ddba83ef3f4468ddc5471b3b04ddeb314c0d4c7f..c4b8ced8382989ac539ea9458f74082f0e735866 100644 (file)
@@ -5,4 +5,5 @@
 obj-$(CONFIG_QLCNIC) := qlcnic.o
 
 qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \
-       qlcnic_ethtool.o qlcnic_ctx.o
+       qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \
+       qlcnic_sysfs.o qlcnic_minidump.o
index eaa1db9fec32ccbd8fad0b2e501b78f38a741138..537902479689a85f7fac4a260d2827e760fd7485 100644 (file)
 #define QLCNIC_CT_DEFAULT_RX_BUF_LEN   2048
 #define QLCNIC_LRO_BUFFER_EXTRA                2048
 
-/* Opcodes to be used with the commands */
-#define TX_ETHER_PKT   0x01
-#define TX_TCP_PKT     0x02
-#define TX_UDP_PKT     0x03
-#define TX_IP_PKT      0x04
-#define TX_TCP_LSO     0x05
-#define TX_TCP_LSO6    0x06
-#define TX_TCPV6_PKT   0x0b
-#define TX_UDPV6_PKT   0x0c
-
 /* Tx defines */
 #define QLCNIC_MAX_FRAGS_PER_TX        14
 #define MAX_TSO_HEADER_DESC    2
  * Added fileds of tcpHdrSize and ipHdrSize, The driver needs to do it only when
  * we are doing LSO (above the 1500 size packet) only.
  */
-
-#define FLAGS_VLAN_TAGGED      0x10
-#define FLAGS_VLAN_OOB         0x40
-
-#define qlcnic_set_tx_vlan_tci(cmd_desc, v)    \
-       (cmd_desc)->vlan_TCI = cpu_to_le16(v);
-#define qlcnic_set_cmd_desc_port(cmd_desc, var)        \
-       ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
-#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var)       \
-       ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
-
-#define qlcnic_set_tx_port(_desc, _port) \
-       ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
-
-#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
-       ((_desc)->flags_opcode |= \
-       cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
-
-#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
-       ((_desc)->nfrags__length = \
-       cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)))
-
 struct cmd_desc_type0 {
        u8 tcp_hdr_offset;      /* For LSO only */
        u8 ip_hdr_offset;       /* For LSO only */
@@ -203,65 +171,6 @@ struct rcv_desc {
        __le64 addr_buffer;
 } __packed;
 
-/* opcode field in status_desc */
-#define QLCNIC_SYN_OFFLOAD     0x03
-#define QLCNIC_RXPKT_DESC      0x04
-#define QLCNIC_OLD_RXPKT_DESC  0x3f
-#define QLCNIC_RESPONSE_DESC   0x05
-#define QLCNIC_LRO_DESC        0x12
-
-/* for status field in status_desc */
-#define STATUS_CKSUM_LOOP      0
-#define STATUS_CKSUM_OK                2
-
-/* owner bits of status_desc */
-#define STATUS_OWNER_HOST      (0x1ULL << 56)
-#define STATUS_OWNER_PHANTOM   (0x2ULL << 56)
-
-/* Status descriptor:
-   0-3 port, 4-7 status, 8-11 type, 12-27 total_length
-   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
-   53-55 desc_cnt, 56-57 owner, 58-63 opcode
- */
-#define qlcnic_get_sts_port(sts_data)  \
-       ((sts_data) & 0x0F)
-#define qlcnic_get_sts_status(sts_data)        \
-       (((sts_data) >> 4) & 0x0F)
-#define qlcnic_get_sts_type(sts_data)  \
-       (((sts_data) >> 8) & 0x0F)
-#define qlcnic_get_sts_totallength(sts_data)   \
-       (((sts_data) >> 12) & 0xFFFF)
-#define qlcnic_get_sts_refhandle(sts_data)     \
-       (((sts_data) >> 28) & 0xFFFF)
-#define qlcnic_get_sts_prot(sts_data)  \
-       (((sts_data) >> 44) & 0x0F)
-#define qlcnic_get_sts_pkt_offset(sts_data)    \
-       (((sts_data) >> 48) & 0x1F)
-#define qlcnic_get_sts_desc_cnt(sts_data)      \
-       (((sts_data) >> 53) & 0x7)
-#define qlcnic_get_sts_opcode(sts_data)        \
-       (((sts_data) >> 58) & 0x03F)
-
-#define qlcnic_get_lro_sts_refhandle(sts_data)         \
-       ((sts_data) & 0x0FFFF)
-#define qlcnic_get_lro_sts_length(sts_data)    \
-       (((sts_data) >> 16) & 0x0FFFF)
-#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data)     \
-       (((sts_data) >> 32) & 0x0FF)
-#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data)     \
-       (((sts_data) >> 40) & 0x0FF)
-#define qlcnic_get_lro_sts_timestamp(sts_data) \
-       (((sts_data) >> 48) & 0x1)
-#define qlcnic_get_lro_sts_type(sts_data)      \
-       (((sts_data) >> 49) & 0x7)
-#define qlcnic_get_lro_sts_push_flag(sts_data)         \
-       (((sts_data) >> 52) & 0x1)
-#define qlcnic_get_lro_sts_seq_number(sts_data)                \
-       ((sts_data) & 0x0FFFFFFFF)
-#define qlcnic_get_lro_sts_mss(sts_data1)              \
-       ((sts_data1 >> 32) & 0x0FFFF)
-
-
 struct status_desc {
        __le64 status_desc_data[2];
 } __attribute__ ((aligned(16)));
@@ -280,16 +189,16 @@ struct status_desc {
 #define QLCNIC_UNI_FIRMWARE_IDX_OFF    29
 
 struct uni_table_desc{
-       u32     findex;
-       u32     num_entries;
-       u32     entry_size;
-       u32     reserved[5];
+       __le32  findex;
+       __le32  num_entries;
+       __le32  entry_size;
+       __le32  reserved[5];
 };
 
 struct uni_data_desc{
-       u32     findex;
-       u32     size;
-       u32     reserved[5];
+       __le32  findex;
+       __le32  size;
+       __le32  reserved[5];
 };
 
 /* Flash Defines and Structures */
@@ -416,19 +325,19 @@ struct qlcnic_nic_intr_coalesce {
 };
 
 struct qlcnic_dump_template_hdr {
-       __le32  type;
-       __le32  offset;
-       __le32  size;
-       __le32  cap_mask;
-       __le32  num_entries;
-       __le32  version;
-       __le32  timestamp;
-       __le32  checksum;
-       __le32  drv_cap_mask;
-       __le32  sys_info[3];
-       __le32  saved_state[16];
-       __le32  cap_sizes[8];
-       __le32  rsvd[0];
+       u32     type;
+       u32     offset;
+       u32     size;
+       u32     cap_mask;
+       u32     num_entries;
+       u32     version;
+       u32     timestamp;
+       u32     checksum;
+       u32     drv_cap_mask;
+       u32     sys_info[3];
+       u32     saved_state[16];
+       u32     cap_sizes[8];
+       u32     rsvd[0];
 };
 
 struct qlcnic_fw_dump {
@@ -456,11 +365,41 @@ struct qlcnic_hardware_context {
        u8 pci_func;
        u8 linkup;
        u8 loopback_state;
+       u8 beacon_state;
+       u8 has_link_events;
+       u8 fw_type;
+       u8 physical_port;
+       u8 reset_context;
+       u8 msix_supported;
+       u8 max_mac_filters;
+       u8 mc_enabled;
+       u8 max_mc_count;
+       u8 diag_test;
+       u8 num_msix;
+       u8 nic_mode;
+       char diag_cnt;
+
        u16 port_type;
        u16 board_type;
 
-       u8 beacon_state;
+       u16 link_speed;
+       u16 link_duplex;
+       u16 link_autoneg;
+       u16 module_type;
 
+       u16 op_mode;
+       u16 switch_mode;
+       u16 max_tx_ques;
+       u16 max_rx_ques;
+       u16 max_mtu;
+       u32 msg_enable;
+       u16 act_pci_func;
+
+       u32 capabilities;
+       u32 temp;
+       u32 int_vec_bit;
+       u32 fw_hal_version;
+       struct qlcnic_hardware_ops *hw_ops;
        struct qlcnic_nic_intr_coalesce coal;
        struct qlcnic_fw_dump fw_dump;
 };
@@ -521,6 +460,7 @@ struct qlcnic_host_sds_ring {
 } ____cacheline_internodealigned_in_smp;
 
 struct qlcnic_host_tx_ring {
+       u16 ctx_id;
        u32 producer;
        u32 sw_consumer;
        u32 num_desc;
@@ -985,6 +925,7 @@ struct qlcnic_adapter {
        unsigned long state;
        u32 flags;
 
+       int max_drv_tx_rings;
        u16 num_txd;
        u16 num_rxd;
        u16 num_jumbo_rxd;
@@ -993,57 +934,28 @@ struct qlcnic_adapter {
 
        u8 max_rds_rings;
        u8 max_sds_rings;
-       u8 msix_supported;
        u8 portnum;
-       u8 physical_port;
-       u8 reset_context;
 
-       u8 mc_enabled;
-       u8 max_mc_count;
        u8 fw_wait_cnt;
        u8 fw_fail_cnt;
        u8 tx_timeo_cnt;
        u8 need_fw_reset;
 
-       u8 has_link_events;
-       u8 fw_type;
-       u16 tx_context_id;
        u16 is_up;
-
-       u16 link_speed;
-       u16 link_duplex;
-       u16 link_autoneg;
-       u16 module_type;
-
-       u16 op_mode;
-       u16 switch_mode;
-       u16 max_tx_ques;
-       u16 max_rx_ques;
-       u16 max_mtu;
        u16 pvid;
 
-       u32 fw_hal_version;
-       u32 capabilities;
        u32 irq;
-       u32 temp;
-
-       u32 int_vec_bit;
        u32 heartbeat;
 
-       u8 max_mac_filters;
        u8 dev_state;
-       u8 diag_test;
-       char diag_cnt;
        u8 reset_ack_timeo;
        u8 dev_init_timeo;
-       u16 msg_enable;
 
        u8 mac_addr[ETH_ALEN];
 
        u64 dev_rst_time;
        u8 mac_learn;
        unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)];
-
        struct qlcnic_npar_info *npars;
        struct qlcnic_eswitch *eswitch;
        struct qlcnic_nic_template *nic_ops;
@@ -1057,24 +969,22 @@ struct qlcnic_adapter {
        void __iomem    *isr_int_vec;
 
        struct msix_entry *msix_entries;
-
        struct delayed_work fw_work;
 
-
        struct qlcnic_filter_hash fhash;
 
        spinlock_t tx_clean_lock;
        spinlock_t mac_learn_lock;
-       __le32 file_prd_off;    /*File fw product offset*/
+       u32 file_prd_off;       /*File fw product offset*/
        u32 fw_version;
        const struct firmware *fw;
 };
 
-struct qlcnic_info {
+struct qlcnic_info_le {
        __le16  pci_func;
-       __le16  op_mode; /* 1 = Priv, 2 = NP, 3 = NP passthru */
+       __le16  op_mode;        /* 1 = Priv, 2 = NP, 3 = NP passthru */
        __le16  phys_port;
-       __le16  switch_mode; /* 0 = disabled, 1 = int, 2 = ext */
+       __le16  switch_mode;    /* 0 = disabled, 1 = int, 2 = ext */
 
        __le32  capabilities;
        u8      max_mac_filters;
@@ -1088,13 +998,28 @@ struct qlcnic_info {
        u8      reserved2[104];
 } __packed;
 
-struct qlcnic_pci_info {
-       __le16  id; /* pci function id */
-       __le16  active; /* 1 = Enabled */
-       __le16  type; /* 1 = NIC, 2 = FCoE, 3 = iSCSI */
-       __le16  default_port; /* default port number */
+struct qlcnic_info {
+       u16     pci_func;
+       u16     op_mode;
+       u16     phys_port;
+       u16     switch_mode;
+       u32     capabilities;
+       u8      max_mac_filters;
+       u8      reserved1;
+       u16     max_mtu;
+       u16     max_tx_ques;
+       u16     max_rx_ques;
+       u16     min_tx_bw;
+       u16     max_tx_bw;
+};
+
+struct qlcnic_pci_info_le {
+       __le16  id;             /* pci function id */
+       __le16  active;         /* 1 = Enabled */
+       __le16  type;           /* 1 = NIC, 2 = FCoE, 3 = iSCSI */
+       __le16  default_port;   /* default port number */
 
-       __le16  tx_min_bw; /* Multiple of 100mbpc */
+       __le16  tx_min_bw;      /* Multiple of 100mbpc */
        __le16  tx_max_bw;
        __le16  reserved1[2];
 
@@ -1102,6 +1027,16 @@ struct qlcnic_pci_info {
        u8      reserved2[106];
 } __packed;
 
+struct qlcnic_pci_info {
+       u16     id;
+       u16     active;
+       u16     type;
+       u16     default_port;
+       u16     tx_min_bw;
+       u16     tx_max_bw;
+       u8      mac[ETH_ALEN];
+};
+
 struct qlcnic_npar_info {
        u16     pvid;
        u16     min_bw;
@@ -1116,6 +1051,7 @@ struct qlcnic_npar_info {
        u8      mac_anti_spoof;
        u8      promisc_mode;
        u8      offload_flags;
+       u8      pci_func;
 };
 
 struct qlcnic_eswitch {
@@ -1208,7 +1144,7 @@ do {      \
                        (VAL1) += (VAL2); \
 } while (0)
 
-struct qlcnic_mac_statistics{
+struct qlcnic_mac_statistics_le {
        __le64  mac_tx_frames;
        __le64  mac_tx_bytes;
        __le64  mac_tx_mcast_pkts;
@@ -1248,7 +1184,45 @@ struct qlcnic_mac_statistics{
        __le64  mac_align_error;
 } __packed;
 
-struct __qlcnic_esw_statistics {
+struct qlcnic_mac_statistics {
+       u64     mac_tx_frames;
+       u64     mac_tx_bytes;
+       u64     mac_tx_mcast_pkts;
+       u64     mac_tx_bcast_pkts;
+       u64     mac_tx_pause_cnt;
+       u64     mac_tx_ctrl_pkt;
+       u64     mac_tx_lt_64b_pkts;
+       u64     mac_tx_lt_127b_pkts;
+       u64     mac_tx_lt_255b_pkts;
+       u64     mac_tx_lt_511b_pkts;
+       u64     mac_tx_lt_1023b_pkts;
+       u64     mac_tx_lt_1518b_pkts;
+       u64     mac_tx_gt_1518b_pkts;
+       u64     rsvd1[3];
+       u64     mac_rx_frames;
+       u64     mac_rx_bytes;
+       u64     mac_rx_mcast_pkts;
+       u64     mac_rx_bcast_pkts;
+       u64     mac_rx_pause_cnt;
+       u64     mac_rx_ctrl_pkt;
+       u64     mac_rx_lt_64b_pkts;
+       u64     mac_rx_lt_127b_pkts;
+       u64     mac_rx_lt_255b_pkts;
+       u64     mac_rx_lt_511b_pkts;
+       u64     mac_rx_lt_1023b_pkts;
+       u64     mac_rx_lt_1518b_pkts;
+       u64     mac_rx_gt_1518b_pkts;
+       u64     rsvd2[3];
+       u64     mac_rx_length_error;
+       u64     mac_rx_length_small;
+       u64     mac_rx_length_large;
+       u64     mac_rx_jabber;
+       u64     mac_rx_dropped;
+       u64     mac_rx_crc_error;
+       u64     mac_align_error;
+};
+
+struct qlcnic_esw_stats_le {
        __le16 context_id;
        __le16 version;
        __le16 size;
@@ -1263,147 +1237,27 @@ struct __qlcnic_esw_statistics {
        __le64 rsvd[3];
 } __packed;
 
+struct __qlcnic_esw_statistics {
+       u16     context_id;
+       u16     version;
+       u16     size;
+       u16     unused;
+       u64     unicast_frames;
+       u64     multicast_frames;
+       u64     broadcast_frames;
+       u64     dropped_frames;
+       u64     errors;
+       u64     local_frames;
+       u64     numbytes;
+       u64     rsvd[3];
+};
+
 struct qlcnic_esw_statistics {
        struct __qlcnic_esw_statistics rx;
        struct __qlcnic_esw_statistics tx;
 };
 
-struct qlcnic_common_entry_hdr {
-       __le32  type;
-       __le32  offset;
-       __le32  cap_size;
-       u8      mask;
-       u8      rsvd[2];
-       u8      flags;
-} __packed;
-
-struct __crb {
-       __le32  addr;
-       u8      stride;
-       u8      rsvd1[3];
-       __le32  data_size;
-       __le32  no_ops;
-       __le32  rsvd2[4];
-} __packed;
-
-struct __ctrl {
-       __le32  addr;
-       u8      stride;
-       u8      index_a;
-       __le16  timeout;
-       __le32  data_size;
-       __le32  no_ops;
-       u8      opcode;
-       u8      index_v;
-       u8      shl_val;
-       u8      shr_val;
-       __le32  val1;
-       __le32  val2;
-       __le32  val3;
-} __packed;
-
-struct __cache {
-       __le32  addr;
-       __le16  stride;
-       __le16  init_tag_val;
-       __le32  size;
-       __le32  no_ops;
-       __le32  ctrl_addr;
-       __le32  ctrl_val;
-       __le32  read_addr;
-       u8      read_addr_stride;
-       u8      read_addr_num;
-       u8      rsvd1[2];
-} __packed;
-
-struct __ocm {
-       u8      rsvd[8];
-       __le32  size;
-       __le32  no_ops;
-       u8      rsvd1[8];
-       __le32  read_addr;
-       __le32  read_addr_stride;
-} __packed;
-
-struct __mem {
-       u8      rsvd[24];
-       __le32  addr;
-       __le32  size;
-} __packed;
-
-struct __mux {
-       __le32  addr;
-       u8      rsvd[4];
-       __le32  size;
-       __le32  no_ops;
-       __le32  val;
-       __le32  val_stride;
-       __le32  read_addr;
-       u8      rsvd2[4];
-} __packed;
-
-struct __queue {
-       __le32  sel_addr;
-       __le16  stride;
-       u8      rsvd[2];
-       __le32  size;
-       __le32  no_ops;
-       u8      rsvd2[8];
-       __le32  read_addr;
-       u8      read_addr_stride;
-       u8      read_addr_cnt;
-       u8      rsvd3[2];
-} __packed;
-
-struct qlcnic_dump_entry {
-       struct qlcnic_common_entry_hdr hdr;
-       union {
-               struct __crb    crb;
-               struct __cache  cache;
-               struct __ocm    ocm;
-               struct __mem    mem;
-               struct __mux    mux;
-               struct __queue  que;
-               struct __ctrl   ctrl;
-       } region;
-} __packed;
-
-enum op_codes {
-       QLCNIC_DUMP_NOP         = 0,
-       QLCNIC_DUMP_READ_CRB    = 1,
-       QLCNIC_DUMP_READ_MUX    = 2,
-       QLCNIC_DUMP_QUEUE       = 3,
-       QLCNIC_DUMP_BRD_CONFIG  = 4,
-       QLCNIC_DUMP_READ_OCM    = 6,
-       QLCNIC_DUMP_PEG_REG     = 7,
-       QLCNIC_DUMP_L1_DTAG     = 8,
-       QLCNIC_DUMP_L1_ITAG     = 9,
-       QLCNIC_DUMP_L1_DATA     = 11,
-       QLCNIC_DUMP_L1_INST     = 12,
-       QLCNIC_DUMP_L2_DTAG     = 21,
-       QLCNIC_DUMP_L2_ITAG     = 22,
-       QLCNIC_DUMP_L2_DATA     = 23,
-       QLCNIC_DUMP_L2_INST     = 24,
-       QLCNIC_DUMP_READ_ROM    = 71,
-       QLCNIC_DUMP_READ_MEM    = 72,
-       QLCNIC_DUMP_READ_CTRL   = 98,
-       QLCNIC_DUMP_TLHDR       = 99,
-       QLCNIC_DUMP_RDEND       = 255
-};
-
-#define QLCNIC_DUMP_WCRB       BIT_0
-#define QLCNIC_DUMP_RWCRB      BIT_1
-#define QLCNIC_DUMP_ANDCRB     BIT_2
-#define QLCNIC_DUMP_ORCRB      BIT_3
-#define QLCNIC_DUMP_POLLCRB    BIT_4
-#define QLCNIC_DUMP_RD_SAVE    BIT_5
-#define QLCNIC_DUMP_WRT_SAVED  BIT_6
-#define QLCNIC_DUMP_MOD_SAVE_ST        BIT_7
-#define QLCNIC_DUMP_SKIP       BIT_7
-
-#define QLCNIC_DUMP_MASK_MIN           3
 #define QLCNIC_DUMP_MASK_DEF           0x1f
-#define QLCNIC_DUMP_MASK_MAX           0xff
 #define QLCNIC_FORCE_FW_DUMP_KEY       0xdeadfeed
 #define QLCNIC_ENABLE_FW_DUMP          0xaddfeed
 #define QLCNIC_DISABLE_FW_DUMP         0xbadfeed
@@ -1411,12 +1265,6 @@ enum op_codes {
 #define QLCNIC_SET_QUIESCENT           0xadd00010
 #define QLCNIC_RESET_QUIESCENT         0xadd00020
 
-struct qlcnic_dump_operations {
-       enum op_codes opcode;
-       u32 (*handler)(struct qlcnic_adapter *,
-                       struct qlcnic_dump_entry *, u32 *);
-};
-
 struct _cdrp_cmd {
        u32 cmd;
        u32 arg1;
@@ -1432,7 +1280,7 @@ struct qlcnic_cmd_args {
 int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
 int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config);
 
-u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off);
+int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off);
 int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data);
 int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data);
 int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data);
@@ -1474,6 +1322,8 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
 #define __QLCNIC_MAX_LED_RATE  0xf
 #define __QLCNIC_MAX_LED_STATE 0x2
 
+#define MAX_CTL_CHECK 1000
+
 int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
 int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
 int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
@@ -1496,7 +1346,7 @@ int qlcnic_rom_fast_read_words(struct qlcnic_adapter *adapter, int addr,
 int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter);
 void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter);
 
-void __iomem *qlcnic_get_ioaddr(struct qlcnic_adapter *, u32);
+void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *, u32);
 
 int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter);
 void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter);
@@ -1530,9 +1380,8 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features);
 int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable);
 int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
 int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
-void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_tx_ring *tx_ring);
-void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
+void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *);
+void qlcnic_fetch_mac(u32, u32, u8, u8 *);
 void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
 void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
 int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
@@ -1571,12 +1420,32 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
 int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *);
 extern int qlcnic_config_tso;
 
+int qlcnic_napi_add(struct qlcnic_adapter *, struct net_device *);
+void qlcnic_napi_del(struct qlcnic_adapter *adapter);
+void qlcnic_napi_enable(struct qlcnic_adapter *adapter);
+void qlcnic_napi_disable(struct qlcnic_adapter *adapter);
+int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int);
+void qlcnic_free_sds_rings(struct qlcnic_recv_context *);
+void qlcnic_free_tx_rings(struct qlcnic_adapter *);
+int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *);
+
+void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
+void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
+void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
+void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
+int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
+int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
+void qlcnic_set_vlan_config(struct qlcnic_adapter *,
+                           struct qlcnic_esw_func_cfg *);
+void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *,
+                                     struct qlcnic_esw_func_cfg *);
+
 /*
  * QLOGIC Board information
  */
 
 #define QLCNIC_MAX_BOARD_NAME_LEN 100
-struct qlcnic_brdinfo {
+struct qlcnic_board_info {
        unsigned short  vendor;
        unsigned short  device;
        unsigned short  sub_vendor;
@@ -1584,30 +1453,6 @@ struct qlcnic_brdinfo {
        char short_name[QLCNIC_MAX_BOARD_NAME_LEN];
 };
 
-static const struct qlcnic_brdinfo qlcnic_boards[] = {
-       {0x1077, 0x8020, 0x1077, 0x203,
-               "8200 Series Single Port 10GbE Converged Network Adapter "
-               "(TCP/IP Networking)"},
-       {0x1077, 0x8020, 0x1077, 0x207,
-               "8200 Series Dual Port 10GbE Converged Network Adapter "
-               "(TCP/IP Networking)"},
-       {0x1077, 0x8020, 0x1077, 0x20b,
-               "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
-       {0x1077, 0x8020, 0x1077, 0x20c,
-               "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
-       {0x1077, 0x8020, 0x1077, 0x20f,
-               "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
-       {0x1077, 0x8020, 0x103c, 0x3733,
-               "NC523SFP 10Gb 2-port Server Adapter"},
-       {0x1077, 0x8020, 0x103c, 0x3346,
-               "CN1000Q Dual Port Converged Network Adapter"},
-       {0x1077, 0x8020, 0x1077, 0x210,
-               "QME8242-k 10GbE Dual Port Mezzanine Card"},
-       {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
-};
-
-#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)
-
 static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
 {
        if (likely(tx_ring->producer < tx_ring->sw_consumer))
@@ -1617,6 +1462,21 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
                                tx_ring->producer;
 }
 
+static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
+{
+       writel(0, sds_ring->crb_intr_mask);
+}
+
+static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
+{
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
+
+       writel(0x1, sds_ring->crb_intr_mask);
+
+       if (!QLCNIC_IS_MSI_FAMILY(adapter))
+               writel(0xfbff, adapter->tgt_mask_reg);
+}
+
 extern const struct ethtool_ops qlcnic_ethtool_ops;
 extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
 
@@ -1627,10 +1487,17 @@ struct qlcnic_nic_template {
 };
 
 #define QLCDB(adapter, lvl, _fmt, _args...) do {       \
-       if (NETIF_MSG_##lvl & adapter->msg_enable)      \
+       if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \
                printk(KERN_INFO "%s: %s: " _fmt,       \
                         dev_name(&adapter->pdev->dev), \
                        __func__, ##_args);             \
        } while (0)
 
+#define PCI_DEVICE_ID_QLOGIC_QLE824X   0x8020
+static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter)
+{
+       unsigned short device = adapter->pdev->device;
+       return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false;
+}
+
 #endif                         /* __QLCNIC_H_ */
index 2a179d087207e4375afb0d66f712043a10417786..58f094ca052e088c521a94059a92349d2533b1eb 100644 (file)
@@ -7,6 +7,18 @@
 
 #include "qlcnic.h"
 
+static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
+{
+       int i;
+
+       for (i = 0; i < adapter->ahw->act_pci_func; i++) {
+               if (adapter->npars[i].pci_func == pci_func)
+                       return i;
+       }
+
+       return -1;
+}
+
 static u32
 qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
 {
@@ -35,7 +47,7 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
        struct qlcnic_hardware_context *ahw = adapter->ahw;
 
        signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw->pci_func,
-               adapter->fw_hal_version);
+                                              adapter->ahw->fw_hal_version);
 
        /* Acquire semaphore before accessing CRB */
        if (qlcnic_api_lock(adapter)) {
@@ -103,7 +115,7 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd)
 
 }
 
-static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
+static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size)
 {
        uint64_t sum = 0;
        int count = temp_size / sizeof(uint32_t);
@@ -117,9 +129,9 @@ static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size)
 int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
 {
        int err, i;
-       u16 temp_size;
        void *tmp_addr;
-       u32 version, csum, *template, *tmp_buf;
+       u32 temp_size, version, csum, *template;
+       __le32 *tmp_buf;
        struct qlcnic_cmd_args cmd;
        struct qlcnic_hardware_context *ahw;
        struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl;
@@ -163,13 +175,6 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
                goto error;
        }
        tmp_tmpl = tmp_addr;
-       csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size);
-       if (csum) {
-               dev_err(&adapter->pdev->dev,
-                       "Template header checksum validation failed\n");
-               err = -EIO;
-               goto error;
-       }
        ahw->fw_dump.tmpl_hdr = vzalloc(temp_size);
        if (!ahw->fw_dump.tmpl_hdr) {
                err = -EIO;
@@ -180,6 +185,14 @@ int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
        for (i = 0; i < temp_size/sizeof(u32); i++)
                *template++ = __le32_to_cpu(*tmp_buf++);
 
+       csum = qlcnic_temp_checksum((u32 *)ahw->fw_dump.tmpl_hdr, temp_size);
+       if (csum) {
+               dev_err(&adapter->pdev->dev,
+                       "Template header checksum validation failed\n");
+               err = -EIO;
+               goto error;
+       }
+
        tmpl_hdr = ahw->fw_dump.tmpl_hdr;
        tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF;
        ahw->fw_dump.enable = 1;
@@ -231,6 +244,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
        size_t rq_size, rsp_size;
        u32 cap, reg, val, reg2;
        int err;
+       u16 temp;
 
        struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
 
@@ -267,8 +281,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
        if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
                cap |= QLCNIC_CAP0_LRO_MSS;
 
-       prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx,
-                                                        msix_handler);
+       temp = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler);
+       prq->valid_field_offset = cpu_to_le16(temp);
        prq->txrx_sds_binding = nsds_rings - 1;
 
        prq->capabilities[0] = cpu_to_le32(cap);
@@ -453,8 +467,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
                temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
                tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
 
-               adapter->tx_context_id =
-                       le16_to_cpu(prsp->context_id);
+               adapter->tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
        } else {
                dev_err(&adapter->pdev->dev,
                        "Failed to create tx ctx in firmware%d\n", err);
@@ -476,7 +489,7 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter)
        struct qlcnic_cmd_args cmd;
 
        memset(&cmd, 0, sizeof(cmd));
-       cmd.req.arg1 = adapter->tx_context_id;
+       cmd.req.arg1 = adapter->tx_ring->ctx_id;
        cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET;
        cmd.req.arg3 = 0;
        cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX;
@@ -671,7 +684,7 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
        err = cmd.rsp.cmd;
 
        if (err == QLCNIC_RCODE_SUCCESS)
-               qlcnic_fetch_mac(adapter, cmd.rsp.arg1, cmd.rsp.arg2, 0, mac);
+               qlcnic_fetch_mac(cmd.rsp.arg1, cmd.rsp.arg2, 0, mac);
        else {
                dev_err(&adapter->pdev->dev,
                        "Failed to get mac address%d\n", err);
@@ -687,10 +700,10 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
 {
        int     err;
        dma_addr_t nic_dma_t;
-       struct qlcnic_info *nic_info;
+       struct qlcnic_info_le *nic_info;
        void *nic_info_addr;
        struct qlcnic_cmd_args cmd;
-       size_t  nic_size = sizeof(struct qlcnic_info);
+       size_t  nic_size = sizeof(struct qlcnic_info_le);
 
        nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
                                &nic_dma_t, GFP_KERNEL);
@@ -745,10 +758,10 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
        dma_addr_t nic_dma_t;
        void *nic_info_addr;
        struct qlcnic_cmd_args cmd;
-       struct qlcnic_info *nic_info;
-       size_t nic_size = sizeof(struct qlcnic_info);
+       struct qlcnic_info_le *nic_info;
+       size_t nic_size = sizeof(struct qlcnic_info_le);
 
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
                return err;
 
        nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
@@ -796,9 +809,9 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
        int err = 0, i;
        struct qlcnic_cmd_args cmd;
        dma_addr_t pci_info_dma_t;
-       struct qlcnic_pci_info *npar;
+       struct qlcnic_pci_info_le *npar;
        void *pci_info_addr;
-       size_t npar_size = sizeof(struct qlcnic_pci_info);
+       size_t npar_size = sizeof(struct qlcnic_pci_info_le);
        size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC;
 
        pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
@@ -816,11 +829,14 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
        qlcnic_issue_cmd(adapter, &cmd);
        err = cmd.rsp.cmd;
 
+       adapter->ahw->act_pci_func = 0;
        if (err == QLCNIC_RCODE_SUCCESS) {
                for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) {
                        pci_info->id = le16_to_cpu(npar->id);
                        pci_info->active = le16_to_cpu(npar->active);
                        pci_info->type = le16_to_cpu(npar->type);
+                       if (pci_info->type == QLCNIC_TYPE_NIC)
+                               adapter->ahw->act_pci_func++;
                        pci_info->default_port =
                                le16_to_cpu(npar->default_port);
                        pci_info->tx_min_bw =
@@ -848,8 +864,8 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
        u32 arg1;
        struct qlcnic_cmd_args cmd;
 
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC ||
-               !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC ||
+           !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE))
                return err;
 
        arg1 = id | (enable_mirroring ? BIT_4 : 0);
@@ -877,8 +893,8 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
 int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
                const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) {
 
-       size_t stats_size = sizeof(struct __qlcnic_esw_statistics);
-       struct __qlcnic_esw_statistics *stats;
+       size_t stats_size = sizeof(struct qlcnic_esw_stats_le);
+       struct qlcnic_esw_stats_le *stats;
        dma_addr_t stats_dma_t;
        void *stats_addr;
        u32 arg1;
@@ -888,8 +904,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
        if (esw_stats == NULL)
                return -ENOMEM;
 
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC &&
-           func != adapter->ahw->pci_func) {
+       if ((adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) &&
+           (func != adapter->ahw->pci_func)) {
                dev_err(&adapter->pdev->dev,
                        "Not privilege to query stats for func=%d", func);
                return -EIO;
@@ -939,9 +955,9 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
 int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
                struct qlcnic_mac_statistics *mac_stats)
 {
-       struct qlcnic_mac_statistics *stats;
+       struct qlcnic_mac_statistics_le *stats;
        struct qlcnic_cmd_args cmd;
-       size_t stats_size = sizeof(struct qlcnic_mac_statistics);
+       size_t stats_size = sizeof(struct qlcnic_mac_statistics_le);
        dma_addr_t stats_dma_t;
        void *stats_addr;
        int err;
@@ -1000,7 +1016,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
 
        if (esw_stats == NULL)
                return -ENOMEM;
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
                return -EIO;
        if (adapter->npars == NULL)
                return -EIO;
@@ -1015,12 +1031,13 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
        esw_stats->numbytes = QLCNIC_STATS_NOT_AVAIL;
        esw_stats->context_id = eswitch;
 
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+       for (i = 0; i < adapter->ahw->act_pci_func; i++) {
                if (adapter->npars[i].phy_port != eswitch)
                        continue;
 
                memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics));
-               if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats))
+               if (qlcnic_get_port_stats(adapter, adapter->npars[i].pci_func,
+                                         rx_tx, &port_stats))
                        continue;
 
                esw_stats->size = port_stats.size;
@@ -1051,7 +1068,7 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
        u32 arg1;
        struct qlcnic_cmd_args cmd;
 
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
                return -EIO;
 
        if (func_esw == QLCNIC_STATS_PORT) {
@@ -1119,15 +1136,18 @@ op_type = 1 for port vlan_id
 int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
                struct qlcnic_esw_func_cfg *esw_cfg)
 {
-       int err = -EIO;
+       int err = -EIO, index;
        u32 arg1, arg2 = 0;
        struct qlcnic_cmd_args cmd;
        u8 pci_func;
 
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC)
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
                return err;
        pci_func = esw_cfg->pci_func;
-       arg1 = (adapter->npars[pci_func].phy_port & BIT_0);
+       index = qlcnic_is_valid_nic_func(adapter, pci_func);
+       if (index < 0)
+               return err;
+       arg1 = (adapter->npars[index].phy_port & BIT_0);
        arg1 |= (pci_func << 8);
 
        if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
@@ -1139,7 +1159,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
        case QLCNIC_PORT_DEFAULTS:
                arg1 |= (BIT_4 | BIT_6 | BIT_7);
                arg2 |= (BIT_0 | BIT_1);
-               if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+               if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
                        arg2 |= (BIT_2 | BIT_3);
                if (!(esw_cfg->discard_tagged))
                        arg1 &= ~BIT_4;
@@ -1191,11 +1211,17 @@ qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
                        struct qlcnic_esw_func_cfg *esw_cfg)
 {
        u32 arg1, arg2;
+       int index;
        u8 phy_port;
-       if (adapter->op_mode == QLCNIC_MGMT_FUNC)
-               phy_port = adapter->npars[esw_cfg->pci_func].phy_port;
-       else
-               phy_port = adapter->physical_port;
+
+       if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
+               index = qlcnic_is_valid_nic_func(adapter, esw_cfg->pci_func);
+               if (index < 0)
+                       return -EIO;
+               phy_port = adapter->npars[index].phy_port;
+       } else {
+               phy_port = adapter->ahw->physical_port;
+       }
        arg1 = phy_port;
        arg1 |= (esw_cfg->pci_func << 8);
        if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2))
index 9e9e78a5c4d7e1721a6542908eada4dd04084011..74b98110c5b45c6549d63c9ab76f36f040b9e340 100644 (file)
@@ -208,9 +208,9 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                                     ADVERTISED_1000baseT_Half |
                                     ADVERTISED_1000baseT_Full);
 
-               ethtool_cmd_speed_set(ecmd, adapter->link_speed);
-               ecmd->duplex = adapter->link_duplex;
-               ecmd->autoneg = adapter->link_autoneg;
+               ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed);
+               ecmd->duplex = adapter->ahw->link_duplex;
+               ecmd->autoneg = adapter->ahw->link_autoneg;
 
        } else if (adapter->ahw->port_type == QLCNIC_XGBE) {
                u32 val;
@@ -224,10 +224,10 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                        ecmd->advertising = ADVERTISED_10000baseT_Full;
                }
 
-               if (netif_running(dev) && adapter->has_link_events) {
-                       ethtool_cmd_speed_set(ecmd, adapter->link_speed);
-                       ecmd->autoneg = adapter->link_autoneg;
-                       ecmd->duplex = adapter->link_duplex;
+               if (netif_running(dev) && adapter->ahw->has_link_events) {
+                       ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed);
+                       ecmd->autoneg = adapter->ahw->link_autoneg;
+                       ecmd->duplex = adapter->ahw->link_duplex;
                        goto skip;
                }
 
@@ -238,7 +238,7 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
                return -EIO;
 
 skip:
-       ecmd->phy_address = adapter->physical_port;
+       ecmd->phy_address = adapter->ahw->physical_port;
        ecmd->transceiver = XCVR_EXTERNAL;
 
        switch (adapter->ahw->board_type) {
@@ -254,7 +254,7 @@ skip:
                ecmd->supported |= SUPPORTED_TP;
                ecmd->advertising |= ADVERTISED_TP;
                ecmd->port = PORT_TP;
-               ecmd->autoneg =  adapter->link_autoneg;
+               ecmd->autoneg =  adapter->ahw->link_autoneg;
                break;
        case QLCNIC_BRDTYPE_P3P_IMEZ:
        case QLCNIC_BRDTYPE_P3P_XG_LOM:
@@ -270,7 +270,7 @@ skip:
                ecmd->advertising |= ADVERTISED_TP;
                ecmd->supported |= SUPPORTED_TP;
                check_sfp_module = netif_running(dev) &&
-                       adapter->has_link_events;
+                                  adapter->ahw->has_link_events;
        case QLCNIC_BRDTYPE_P3P_10G_XFP:
                ecmd->supported |= SUPPORTED_FIBRE;
                ecmd->advertising |= ADVERTISED_FIBRE;
@@ -285,7 +285,7 @@ skip:
                                (ADVERTISED_FIBRE | ADVERTISED_TP);
                        ecmd->port = PORT_FIBRE;
                        check_sfp_module = netif_running(dev) &&
-                               adapter->has_link_events;
+                                          adapter->ahw->has_link_events;
                } else {
                        ecmd->autoneg = AUTONEG_ENABLE;
                        ecmd->supported |= (SUPPORTED_TP | SUPPORTED_Autoneg);
@@ -301,7 +301,7 @@ skip:
        }
 
        if (check_sfp_module) {
-               switch (adapter->module_type) {
+               switch (adapter->ahw->module_type) {
                case LINKEVENT_MODULE_OPTICAL_UNKNOWN:
                case LINKEVENT_MODULE_OPTICAL_SRLR:
                case LINKEVENT_MODULE_OPTICAL_LRM:
@@ -359,9 +359,9 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
        else if (ret)
                return -EIO;
 
-       adapter->link_speed = ethtool_cmd_speed(ecmd);
-       adapter->link_duplex = ecmd->duplex;
-       adapter->link_autoneg = ecmd->autoneg;
+       adapter->ahw->link_speed = ethtool_cmd_speed(ecmd);
+       adapter->ahw->link_duplex = ecmd->duplex;
+       adapter->ahw->link_autoneg = ecmd->autoneg;
 
        if (!netif_running(dev))
                return 0;
@@ -508,14 +508,15 @@ qlcnic_set_ringparam(struct net_device *dev,
 static void qlcnic_get_channels(struct net_device *dev,
                struct ethtool_channels *channel)
 {
+       int min;
        struct qlcnic_adapter *adapter = netdev_priv(dev);
 
-       channel->max_rx = rounddown_pow_of_two(min_t(int,
-                       adapter->max_rx_ques, num_online_cpus()));
-       channel->max_tx = adapter->max_tx_ques;
+       min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus());
+       channel->max_rx = rounddown_pow_of_two(min);
+       channel->max_tx = adapter->ahw->max_tx_ques;
 
        channel->rx_count = adapter->max_sds_rings;
-       channel->tx_count = adapter->max_tx_ques;
+       channel->tx_count = adapter->ahw->max_tx_ques;
 }
 
 static int qlcnic_set_channels(struct net_device *dev,
@@ -543,7 +544,7 @@ qlcnic_get_pauseparam(struct net_device *netdev,
                          struct ethtool_pauseparam *pause)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
-       int port = adapter->physical_port;
+       int port = adapter->ahw->physical_port;
        __u32 val;
 
        if (adapter->ahw->port_type == QLCNIC_GBE) {
@@ -588,7 +589,7 @@ qlcnic_set_pauseparam(struct net_device *netdev,
                          struct ethtool_pauseparam *pause)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
-       int port = adapter->physical_port;
+       int port = adapter->ahw->physical_port;
        __u32 val;
 
        /* read mode */
@@ -703,7 +704,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
        if (ret)
                goto clear_it;
 
-       adapter->diag_cnt = 0;
+       adapter->ahw->diag_cnt = 0;
        memset(&cmd, 0, sizeof(cmd));
        cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
        cmd.req.arg1 = adapter->ahw->pci_func;
@@ -715,7 +716,7 @@ static int qlcnic_irq_test(struct net_device *netdev)
 
        msleep(10);
 
-       ret = !adapter->diag_cnt;
+       ret = !adapter->ahw->diag_cnt;
 
 done:
        qlcnic_diag_free_res(netdev, max_sds_rings);
@@ -761,7 +762,7 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
                qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
                skb_put(skb, QLCNIC_ILB_PKT_SIZE);
 
-               adapter->diag_cnt = 0;
+               adapter->ahw->diag_cnt = 0;
                qlcnic_xmit_frame(skb, adapter->netdev);
 
                loop = 0;
@@ -770,11 +771,11 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
                        qlcnic_process_rcv_ring_diag(sds_ring);
                        if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP)
                                break;
-               } while (!adapter->diag_cnt);
+               } while (!adapter->ahw->diag_cnt);
 
                dev_kfree_skb_any(skb);
 
-               if (!adapter->diag_cnt)
+               if (!adapter->ahw->diag_cnt)
                        QLCDB(adapter, DRV,
                        "LB Test: packet #%d was not received\n", i + 1);
                else
@@ -800,14 +801,15 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
        int loop = 0;
        int ret;
 
-       if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
+       if (!(adapter->ahw->capabilities &
+             QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) {
                netdev_info(netdev, "Firmware is not loopback test capable\n");
                return -EOPNOTSUPP;
        }
 
        QLCDB(adapter, DRV, "%s loopback test in progress\n",
                   mode == QLCNIC_ILB_MODE ? "internal" : "external");
-       if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+       if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
                netdev_warn(netdev, "Loopback test not supported for non "
                                "privilege function\n");
                return 0;
@@ -826,7 +828,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
        if (ret)
                goto free_res;
 
-       adapter->diag_cnt = 0;
+       adapter->ahw->diag_cnt = 0;
        do {
                msleep(500);
                qlcnic_process_rcv_ring_diag(sds_ring);
@@ -835,8 +837,8 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
                                " configure request\n");
                        ret = -QLCNIC_FW_NOT_RESPOND;
                        goto free_res;
-               } else if (adapter->diag_cnt) {
-                       ret = adapter->diag_cnt;
+               } else if (adapter->ahw->diag_cnt) {
+                       ret = adapter->ahw->diag_cnt;
                        goto free_res;
                }
        } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state));
@@ -1028,7 +1030,7 @@ static int qlcnic_set_led(struct net_device *dev,
        int max_sds_rings = adapter->max_sds_rings;
        int err = -EIO, active = 1;
 
-       if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+       if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
                netdev_warn(dev, "LED test not supported for non "
                                "privilege function\n");
                return -EOPNOTSUPP;
@@ -1207,14 +1209,14 @@ static u32 qlcnic_get_msglevel(struct net_device *netdev)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
-       return adapter->msg_enable;
+       return adapter->ahw->msg_enable;
 }
 
 static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl)
 {
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
-       adapter->msg_enable = msglvl;
+       adapter->ahw->msg_enable = msglvl;
 }
 
 static int
@@ -1247,7 +1249,8 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump,
                        void *buffer)
 {
        int i, copy_sz;
-       u32 *hdr_ptr, *data;
+       u32 *hdr_ptr;
+       __le32 *data;
        struct qlcnic_adapter *adapter = netdev_priv(netdev);
        struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
 
index 28a6b28192e302227a9b02552c0acef56e6ea560..49cc1ac4f0573b446a7a8c1228cf09760fa3f266 100644 (file)
@@ -792,22 +792,6 @@ static const u32 MIU_TEST_READ_DATA[] = {
 #define QLCNIC_FLASH_SEM2_ULK  0x0013C014
 #define QLCNIC_FLASH_LOCK_ID   0x001B2100
 
-#define QLCNIC_RD_DUMP_REG(addr, bar0, data) do {                      \
-       writel((addr & 0xFFFF0000), (void *) (bar0 +                    \
-               QLCNIC_FW_DUMP_REG1));                                  \
-       readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1));                   \
-       *data = readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 +            \
-               LSW(addr)));                                            \
-} while (0)
-
-#define QLCNIC_WR_DUMP_REG(addr, bar0, data) do {                      \
-       writel((addr & 0xFFFF0000), (void *) (bar0 +                    \
-               QLCNIC_FW_DUMP_REG1));                                  \
-       readl((void *) (bar0 + QLCNIC_FW_DUMP_REG1));                   \
-       writel(data, (void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr)));\
-       readl((void *) (bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr)));       \
-} while (0)
-
 /* PCI function operational mode */
 enum {
        QLCNIC_MGMT_FUNC        = 0,
@@ -832,55 +816,63 @@ enum {
 #define LSD(x)  ((uint32_t)((uint64_t)(x)))
 #define MSD(x)  ((uint32_t)((((uint64_t)(x)) >> 16) >> 16))
 
+#define QLCNIC_MS_CTRL                 0x41000090
+#define QLCNIC_MS_ADDR_LO              0x41000094
+#define QLCNIC_MS_ADDR_HI              0x41000098
+#define QLCNIC_MS_WRTDATA_LO           0x410000A0
+#define QLCNIC_MS_WRTDATA_HI           0x410000A4
+#define QLCNIC_MS_WRTDATA_ULO          0x410000B0
+#define QLCNIC_MS_WRTDATA_UHI          0x410000B4
+#define QLCNIC_MS_RDDATA_LO            0x410000A8
+#define QLCNIC_MS_RDDATA_HI            0x410000AC
+#define QLCNIC_MS_RDDATA_ULO           0x410000B8
+#define QLCNIC_MS_RDDATA_UHI           0x410000BC
+
+#define QLCNIC_TA_WRITE_ENABLE (TA_CTL_ENABLE | TA_CTL_WRITE)
+#define QLCNIC_TA_WRITE_START  (TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE)
+#define QLCNIC_TA_START_ENABLE (TA_CTL_START | TA_CTL_ENABLE)
+
 #define        QLCNIC_LEGACY_INTR_CONFIG                                       \
 {                                                                      \
        {                                                               \
                .int_vec_bit    =       PCIX_INT_VECTOR_BIT_F0,         \
                .tgt_status_reg =       ISR_INT_TARGET_STATUS,          \
-               .tgt_mask_reg   =       ISR_INT_TARGET_MASK,            \
-               .pci_int_reg    =       ISR_MSI_INT_TRIGGER(0) },       \
+               .tgt_mask_reg   =       ISR_INT_TARGET_MASK, },         \
                                                                        \
        {                                                               \
                .int_vec_bit    =       PCIX_INT_VECTOR_BIT_F1,         \
                .tgt_status_reg =       ISR_INT_TARGET_STATUS_F1,       \
-               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F1,         \
-               .pci_int_reg    =       ISR_MSI_INT_TRIGGER(1) },       \
+               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F1, },      \
                                                                        \
        {                                                               \
                .int_vec_bit    =       PCIX_INT_VECTOR_BIT_F2,         \
                .tgt_status_reg =       ISR_INT_TARGET_STATUS_F2,       \
-               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F2,         \
-               .pci_int_reg    =       ISR_MSI_INT_TRIGGER(2) },       \
+               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F2, },      \
                                                                        \
        {                                                               \
                .int_vec_bit    =       PCIX_INT_VECTOR_BIT_F3,         \
                .tgt_status_reg =       ISR_INT_TARGET_STATUS_F3,       \
-               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F3,         \
-               .pci_int_reg    =       ISR_MSI_INT_TRIGGER(3) },       \
+               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F3, },      \
                                                                        \
        {                                                               \
                .int_vec_bit    =       PCIX_INT_VECTOR_BIT_F4,         \
                .tgt_status_reg =       ISR_INT_TARGET_STATUS_F4,       \
-               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F4,         \
-               .pci_int_reg    =       ISR_MSI_INT_TRIGGER(4) },       \
+               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F4, },      \
                                                                        \
        {                                                               \
                .int_vec_bit    =       PCIX_INT_VECTOR_BIT_F5,         \
                .tgt_status_reg =       ISR_INT_TARGET_STATUS_F5,       \
-               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F5,         \
-               .pci_int_reg    =       ISR_MSI_INT_TRIGGER(5) },       \
+               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F5, },      \
                                                                        \
        {                                                               \
                .int_vec_bit    =       PCIX_INT_VECTOR_BIT_F6,         \
                .tgt_status_reg =       ISR_INT_TARGET_STATUS_F6,       \
-               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F6,         \
-               .pci_int_reg    =       ISR_MSI_INT_TRIGGER(6) },       \
+               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F6, },      \
                                                                        \
        {                                                               \
                .int_vec_bit    =       PCIX_INT_VECTOR_BIT_F7,         \
                .tgt_status_reg =       ISR_INT_TARGET_STATUS_F7,       \
-               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F7,         \
-               .pci_int_reg    =       ISR_MSI_INT_TRIGGER(7) },       \
+               .tgt_mask_reg   =       ISR_INT_TARGET_MASK_F7, },      \
 }
 
 /* NIU REGS */
index 2a0c9dc48eb38a5a3a85a06145ae12ce3db84309..fc48e000f35f62ab46c071a4e401ff61f176fce2 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "qlcnic.h"
+#include "qlcnic_hdr.h"
 
 #include <linux/slab.h>
 #include <net/ip.h>
 #define CRB_HI(off)    ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000))
 #define CRB_INDIRECT_2M        (0x1e0000UL)
 
+struct qlcnic_ms_reg_ctrl {
+       u32 ocm_window;
+       u32 control;
+       u32 hi;
+       u32 low;
+       u32 rd[4];
+       u32 wd[4];
+       u64 off;
+};
 
 #ifndef readq
 static inline u64 readq(void __iomem *addr)
@@ -266,10 +276,44 @@ static const unsigned crb_hub_agt[64] = {
        0,
 };
 
+static const u32 msi_tgt_status[8] = {
+       ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
+       ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3,
+       ISR_INT_TARGET_STATUS_F4, ISR_INT_TARGET_STATUS_F5,
+       ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
+};
+
 /*  PCI Windowing for DDR regions.  */
 
 #define QLCNIC_PCIE_SEM_TIMEOUT        10000
 
+static void qlcnic_read_window_reg(u32 addr, void __iomem *bar0, u32 *data)
+{
+       u32 dest;
+       void __iomem *val;
+
+       dest = addr & 0xFFFF0000;
+       val = bar0 + QLCNIC_FW_DUMP_REG1;
+       writel(dest, val);
+       readl(val);
+       val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+       *data = readl(val);
+}
+
+static void qlcnic_write_window_reg(u32 addr, void __iomem *bar0, u32 data)
+{
+       u32 dest;
+       void __iomem *val;
+
+       dest = addr & 0xFFFF0000;
+       val = bar0 + QLCNIC_FW_DUMP_REG1;
+       writel(dest, val);
+       readl(val);
+       val = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+       writel(data, val);
+       readl(val);
+}
+
 int
 qlcnic_pcie_sem_lock(struct qlcnic_adapter *adapter, int sem, u32 id_reg)
 {
@@ -300,6 +344,23 @@ qlcnic_pcie_sem_unlock(struct qlcnic_adapter *adapter, int sem)
        QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem)));
 }
 
+static int qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr)
+{
+       u32 data;
+
+       if (qlcnic_82xx_check(adapter))
+               qlcnic_read_window_reg(addr, adapter->ahw->pci_base0, &data);
+       else
+               return -EIO;
+       return data;
+}
+
+static void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data)
+{
+       if (qlcnic_82xx_check(adapter))
+               qlcnic_write_window_reg(addr, adapter->ahw->pci_base0, data);
+}
+
 static int
 qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
                struct cmd_desc_type0 *cmd_desc_arr, int nr_desc)
@@ -350,7 +411,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
 
        tx_ring->producer = producer;
 
-       qlcnic_update_cmd_producer(adapter, tx_ring);
+       qlcnic_update_cmd_producer(tx_ring);
 
        __netif_tx_unlock_bh(tx_ring->txq);
 
@@ -434,7 +495,7 @@ void qlcnic_set_multi(struct net_device *netdev)
        }
 
        if ((netdev->flags & IFF_ALLMULTI) ||
-           (netdev_mc_count(netdev) > adapter->max_mc_count)) {
+           (netdev_mc_count(netdev) > adapter->ahw->max_mc_count)) {
                mode = VPORT_MISS_MODE_ACCEPT_MULTI;
                goto send_fw_cmd;
        }
@@ -540,7 +601,7 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
        }
 }
 
-int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
+static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
 {
        struct qlcnic_nic_req req;
        int rv;
@@ -863,9 +924,8 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features)
  *      0 if no window access is needed. 'off' is set to 2M addr
  * In: 'off' is offset from base in 128M pci map
  */
-static int
-qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
-               ulong off, void __iomem **addr)
+static int qlcnic_pci_get_crb_addr_2M(struct qlcnic_hardware_context *ahw,
+                                     ulong off, void __iomem **addr)
 {
        const struct crb_128M_2M_sub_block_map *m;
 
@@ -880,7 +940,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
        m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)];
 
        if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) {
-               *addr = adapter->ahw->pci_base0 + m->start_2M +
+               *addr = ahw->pci_base0 + m->start_2M +
                        (off - m->start_128M);
                return 0;
        }
@@ -888,7 +948,7 @@ qlcnic_pci_get_crb_addr_2M(struct qlcnic_adapter *adapter,
        /*
         * Not in direct map, use crb window
         */
-       *addr = adapter->ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
+       *addr = ahw->pci_base0 + CRB_INDIRECT_2M + (off & MASK(16));
        return 1;
 }
 
@@ -929,7 +989,7 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
        int rv;
        void __iomem *addr = NULL;
 
-       rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr);
+       rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
 
        if (rv == 0) {
                writel(data, addr);
@@ -954,15 +1014,14 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
        return -EIO;
 }
 
-u32
-qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
+int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
 {
        unsigned long flags;
        int rv;
        u32 data = -1;
        void __iomem *addr = NULL;
 
-       rv = qlcnic_pci_get_crb_addr_2M(adapter, off, &addr);
+       rv = qlcnic_pci_get_crb_addr_2M(adapter->ahw, off, &addr);
 
        if (rv == 0)
                return readl(addr);
@@ -985,46 +1044,28 @@ qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
 }
 
 
-void __iomem *
-qlcnic_get_ioaddr(struct qlcnic_adapter *adapter, u32 offset)
+void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw,
+                               u32 offset)
 {
        void __iomem *addr = NULL;
 
-       WARN_ON(qlcnic_pci_get_crb_addr_2M(adapter, offset, &addr));
+       WARN_ON(qlcnic_pci_get_crb_addr_2M(ahw, offset, &addr));
 
        return addr;
 }
 
-
-static int
-qlcnic_pci_set_window_2M(struct qlcnic_adapter *adapter,
-               u64 addr, u32 *start)
-{
-       u32 window;
-
-       window = OCM_WIN_P3P(addr);
-
-       writel(window, adapter->ahw->ocm_win_crb);
-       /* read back to flush */
-       readl(adapter->ahw->ocm_win_crb);
-
-       *start = QLCNIC_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr);
-       return 0;
-}
-
-static int
-qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off,
-               u64 *data, int op)
+static int qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter,
+                                       u32 window, u64 off, u64 *data, int op)
 {
        void __iomem *addr;
-       int ret;
        u32 start;
 
        mutex_lock(&adapter->ahw->mem_lock);
 
-       ret = qlcnic_pci_set_window_2M(adapter, off, &start);
-       if (ret != 0)
-               goto unlock;
+       writel(window, adapter->ahw->ocm_win_crb);
+       /* read back to flush */
+       readl(adapter->ahw->ocm_win_crb);
+       start = QLCNIC_PCI_OCM0_2M + off;
 
        addr = adapter->ahw->pci_base0 + start;
 
@@ -1033,10 +1074,12 @@ qlcnic_pci_mem_access_direct(struct qlcnic_adapter *adapter, u64 off,
        else            /* write */
                writeq(*data, addr);
 
-unlock:
-       mutex_unlock(&adapter->ahw->mem_lock);
+       /* Set window to 0 */
+       writel(0, adapter->ahw->ocm_win_crb);
+       readl(adapter->ahw->ocm_win_crb);
 
-       return ret;
+       mutex_unlock(&adapter->ahw->mem_lock);
+       return 0;
 }
 
 void
@@ -1061,54 +1104,74 @@ qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
        mutex_unlock(&adapter->ahw->mem_lock);
 }
 
-#define MAX_CTL_CHECK   1000
 
-int
-qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter,
-               u64 off, u64 data)
+
+/* Set MS memory control data for different adapters */
+static void qlcnic_set_ms_controls(struct qlcnic_adapter *adapter, u64 off,
+                                  struct qlcnic_ms_reg_ctrl *ms)
+{
+       ms->control = QLCNIC_MS_CTRL;
+       ms->low = QLCNIC_MS_ADDR_LO;
+       ms->hi = QLCNIC_MS_ADDR_HI;
+       if (off & 0xf) {
+               ms->wd[0] = QLCNIC_MS_WRTDATA_LO;
+               ms->rd[0] = QLCNIC_MS_RDDATA_LO;
+               ms->wd[1] = QLCNIC_MS_WRTDATA_HI;
+               ms->rd[1] = QLCNIC_MS_RDDATA_HI;
+               ms->wd[2] = QLCNIC_MS_WRTDATA_ULO;
+               ms->wd[3] = QLCNIC_MS_WRTDATA_UHI;
+               ms->rd[2] = QLCNIC_MS_RDDATA_ULO;
+               ms->rd[3] = QLCNIC_MS_RDDATA_UHI;
+       } else {
+               ms->wd[0] = QLCNIC_MS_WRTDATA_ULO;
+               ms->rd[0] = QLCNIC_MS_RDDATA_ULO;
+               ms->wd[1] = QLCNIC_MS_WRTDATA_UHI;
+               ms->rd[1] = QLCNIC_MS_RDDATA_UHI;
+               ms->wd[2] = QLCNIC_MS_WRTDATA_LO;
+               ms->wd[3] = QLCNIC_MS_WRTDATA_HI;
+               ms->rd[2] = QLCNIC_MS_RDDATA_LO;
+               ms->rd[3] = QLCNIC_MS_RDDATA_HI;
+       }
+
+       ms->ocm_window = OCM_WIN_P3P(off);
+       ms->off = GET_MEM_OFFS_2M(off);
+}
+
+int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *adapter, u64 off, u64 data)
 {
-       int i, j, ret;
+       int j, ret = 0;
        u32 temp, off8;
-       void __iomem *mem_crb;
+       struct qlcnic_ms_reg_ctrl ms;
 
        /* Only 64-bit aligned access */
        if (off & 7)
                return -EIO;
 
-       /* P3 onward, test agent base for MIU and SIU is same */
-       if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
-                               QLCNIC_ADDR_QDR_NET_MAX)) {
-               mem_crb = qlcnic_get_ioaddr(adapter,
-                               QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE);
-               goto correct;
-       }
+       memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
+       if (!(ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
+                           QLCNIC_ADDR_QDR_NET_MAX) ||
+             ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
+                           QLCNIC_ADDR_DDR_NET_MAX)))
+               return -EIO;
 
-       if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) {
-               mem_crb = qlcnic_get_ioaddr(adapter,
-                               QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE);
-               goto correct;
-       }
+       qlcnic_set_ms_controls(adapter, off, &ms);
 
        if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
-               return qlcnic_pci_mem_access_direct(adapter, off, &data, 1);
-
-       return -EIO;
+               return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
+                                                   ms.off, &data, 1);
 
-correct:
        off8 = off & ~0xf;
 
        mutex_lock(&adapter->ahw->mem_lock);
 
-       writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
-       writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
+       qlcnic_ind_wr(adapter, ms.low, off8);
+       qlcnic_ind_wr(adapter, ms.hi, 0);
 
-       i = 0;
-       writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
-       writel((TA_CTL_START | TA_CTL_ENABLE),
-                       (mem_crb + TEST_AGT_CTRL));
+       qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
+       qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_START_ENABLE);
 
        for (j = 0; j < MAX_CTL_CHECK; j++) {
-               temp = readl(mem_crb + TEST_AGT_CTRL);
+               temp = qlcnic_ind_rd(adapter, ms.control);
                if ((temp & TA_CTL_BUSY) == 0)
                        break;
        }
@@ -1118,24 +1181,18 @@ correct:
                goto done;
        }
 
-       i = (off & 0xf) ? 0 : 2;
-       writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i)),
-                       mem_crb + MIU_TEST_AGT_WRDATA(i));
-       writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i+1)),
-                       mem_crb + MIU_TEST_AGT_WRDATA(i+1));
-       i = (off & 0xf) ? 2 : 0;
-
-       writel(data & 0xffffffff,
-                       mem_crb + MIU_TEST_AGT_WRDATA(i));
-       writel((data >> 32) & 0xffffffff,
-                       mem_crb + MIU_TEST_AGT_WRDATA(i+1));
+       /* This is the modify part of read-modify-write */
+       qlcnic_ind_wr(adapter, ms.wd[0], qlcnic_ind_rd(adapter, ms.rd[0]));
+       qlcnic_ind_wr(adapter, ms.wd[1], qlcnic_ind_rd(adapter, ms.rd[1]));
+       /* This is the write part of read-modify-write */
+       qlcnic_ind_wr(adapter, ms.wd[2], data & 0xffffffff);
+       qlcnic_ind_wr(adapter, ms.wd[3], (data >> 32) & 0xffffffff);
 
-       writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL));
-       writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE),
-                       (mem_crb + TEST_AGT_CTRL));
+       qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_WRITE_ENABLE);
+       qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_WRITE_START);
 
        for (j = 0; j < MAX_CTL_CHECK; j++) {
-               temp = readl(mem_crb + TEST_AGT_CTRL);
+               temp = qlcnic_ind_rd(adapter, ms.control);
                if ((temp & TA_CTL_BUSY) == 0)
                        break;
        }
@@ -1154,52 +1211,41 @@ done:
        return ret;
 }
 
-int
-qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter,
-               u64 off, u64 *data)
+int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data)
 {
        int j, ret;
        u32 temp, off8;
        u64 val;
-       void __iomem *mem_crb;
+       struct qlcnic_ms_reg_ctrl ms;
 
        /* Only 64-bit aligned access */
        if (off & 7)
                return -EIO;
+       if (!(ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
+                           QLCNIC_ADDR_QDR_NET_MAX) ||
+             ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET,
+                           QLCNIC_ADDR_DDR_NET_MAX)))
+               return -EIO;
 
-       /* P3 onward, test agent base for MIU and SIU is same */
-       if (ADDR_IN_RANGE(off, QLCNIC_ADDR_QDR_NET,
-                               QLCNIC_ADDR_QDR_NET_MAX)) {
-               mem_crb = qlcnic_get_ioaddr(adapter,
-                               QLCNIC_CRB_QDR_NET+MIU_TEST_AGT_BASE);
-               goto correct;
-       }
-
-       if (ADDR_IN_RANGE(off, QLCNIC_ADDR_DDR_NET, QLCNIC_ADDR_DDR_NET_MAX)) {
-               mem_crb = qlcnic_get_ioaddr(adapter,
-                               QLCNIC_CRB_DDR_NET+MIU_TEST_AGT_BASE);
-               goto correct;
-       }
+       memset(&ms, 0, sizeof(struct qlcnic_ms_reg_ctrl));
+       qlcnic_set_ms_controls(adapter, off, &ms);
 
-       if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX)) {
-               return qlcnic_pci_mem_access_direct(adapter,
-                               off, data, 0);
-       }
+       if (ADDR_IN_RANGE(off, QLCNIC_ADDR_OCM0, QLCNIC_ADDR_OCM0_MAX))
+               return qlcnic_pci_mem_access_direct(adapter, ms.ocm_window,
+                                                   ms.off, data, 0);
 
-       return -EIO;
+       mutex_lock(&adapter->ahw->mem_lock);
 
-correct:
        off8 = off & ~0xf;
 
-       mutex_lock(&adapter->ahw->mem_lock);
+       qlcnic_ind_wr(adapter, ms.low, off8);
+       qlcnic_ind_wr(adapter, ms.hi, 0);
 
-       writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO));
-       writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI));
-       writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL));
-       writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL));
+       qlcnic_ind_wr(adapter, ms.control, TA_CTL_ENABLE);
+       qlcnic_ind_wr(adapter, ms.control, QLCNIC_TA_START_ENABLE);
 
        for (j = 0; j < MAX_CTL_CHECK; j++) {
-               temp = readl(mem_crb + TEST_AGT_CTRL);
+               temp = qlcnic_ind_rd(adapter, ms.control);
                if ((temp & TA_CTL_BUSY) == 0)
                        break;
        }
@@ -1210,13 +1256,10 @@ correct:
                                        "failed to read through agent\n");
                ret = -EIO;
        } else {
-               off8 = MIU_TEST_AGT_RDDATA_LO;
-               if (off & 0xf)
-                       off8 = MIU_TEST_AGT_RDDATA_UPPER_LO;
 
-               temp = readl(mem_crb + off8 + 4);
+               temp = qlcnic_ind_rd(adapter, ms.rd[3]);
                val = (u64)temp << 32;
-               val |= readl(mem_crb + off8);
+               val |= qlcnic_ind_rd(adapter, ms.rd[2]);
                *data = val;
                ret = 0;
        }
@@ -1320,469 +1363,3 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
 
        return rv;
 }
-
-/* FW dump related functions */
-static u32
-qlcnic_dump_crb(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-               u32 *buffer)
-{
-       int i;
-       u32 addr, data;
-       struct __crb *crb = &entry->region.crb;
-       void __iomem *base = adapter->ahw->pci_base0;
-
-       addr = crb->addr;
-
-       for (i = 0; i < crb->no_ops; i++) {
-               QLCNIC_RD_DUMP_REG(addr, base, &data);
-               *buffer++ = cpu_to_le32(addr);
-               *buffer++ = cpu_to_le32(data);
-               addr += crb->stride;
-       }
-       return crb->no_ops * 2 * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
-       struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-       int i, k, timeout = 0;
-       void __iomem *base = adapter->ahw->pci_base0;
-       u32 addr, data;
-       u8 opcode, no_ops;
-       struct __ctrl *ctr = &entry->region.ctrl;
-       struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
-
-       addr = ctr->addr;
-       no_ops = ctr->no_ops;
-
-       for (i = 0; i < no_ops; i++) {
-               k = 0;
-               opcode = 0;
-               for (k = 0; k < 8; k++) {
-                       if (!(ctr->opcode & (1 << k)))
-                               continue;
-                       switch (1 << k) {
-                       case QLCNIC_DUMP_WCRB:
-                               QLCNIC_WR_DUMP_REG(addr, base, ctr->val1);
-                               break;
-                       case QLCNIC_DUMP_RWCRB:
-                               QLCNIC_RD_DUMP_REG(addr, base, &data);
-                               QLCNIC_WR_DUMP_REG(addr, base, data);
-                               break;
-                       case QLCNIC_DUMP_ANDCRB:
-                               QLCNIC_RD_DUMP_REG(addr, base, &data);
-                               QLCNIC_WR_DUMP_REG(addr, base,
-                                       (data & ctr->val2));
-                               break;
-                       case QLCNIC_DUMP_ORCRB:
-                               QLCNIC_RD_DUMP_REG(addr, base, &data);
-                               QLCNIC_WR_DUMP_REG(addr, base,
-                                       (data | ctr->val3));
-                               break;
-                       case QLCNIC_DUMP_POLLCRB:
-                               while (timeout <= ctr->timeout) {
-                                       QLCNIC_RD_DUMP_REG(addr, base, &data);
-                                       if ((data & ctr->val2) == ctr->val1)
-                                               break;
-                                       msleep(1);
-                                       timeout++;
-                               }
-                               if (timeout > ctr->timeout) {
-                                       dev_info(&adapter->pdev->dev,
-                                       "Timed out, aborting poll CRB\n");
-                                       return -EINVAL;
-                               }
-                               break;
-                       case QLCNIC_DUMP_RD_SAVE:
-                               if (ctr->index_a)
-                                       addr = t_hdr->saved_state[ctr->index_a];
-                               QLCNIC_RD_DUMP_REG(addr, base, &data);
-                               t_hdr->saved_state[ctr->index_v] = data;
-                               break;
-                       case QLCNIC_DUMP_WRT_SAVED:
-                               if (ctr->index_v)
-                                       data = t_hdr->saved_state[ctr->index_v];
-                               else
-                                       data = ctr->val1;
-                               if (ctr->index_a)
-                                       addr = t_hdr->saved_state[ctr->index_a];
-                               QLCNIC_WR_DUMP_REG(addr, base, data);
-                               break;
-                       case QLCNIC_DUMP_MOD_SAVE_ST:
-                               data = t_hdr->saved_state[ctr->index_v];
-                               data <<= ctr->shl_val;
-                               data >>= ctr->shr_val;
-                               if (ctr->val2)
-                                       data &= ctr->val2;
-                               data |= ctr->val3;
-                               data += ctr->val1;
-                               t_hdr->saved_state[ctr->index_v] = data;
-                               break;
-                       default:
-                               dev_info(&adapter->pdev->dev,
-                                       "Unknown opcode\n");
-                               break;
-                       }
-               }
-               addr += ctr->stride;
-       }
-       return 0;
-}
-
-static u32
-qlcnic_dump_mux(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-       u32 *buffer)
-{
-       int loop;
-       u32 val, data = 0;
-       struct __mux *mux = &entry->region.mux;
-       void __iomem *base = adapter->ahw->pci_base0;
-
-       val = mux->val;
-       for (loop = 0; loop < mux->no_ops; loop++) {
-               QLCNIC_WR_DUMP_REG(mux->addr, base, val);
-               QLCNIC_RD_DUMP_REG(mux->read_addr, base, &data);
-               *buffer++ = cpu_to_le32(val);
-               *buffer++ = cpu_to_le32(data);
-               val += mux->val_stride;
-       }
-       return 2 * mux->no_ops * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_que(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-       u32 *buffer)
-{
-       int i, loop;
-       u32 cnt, addr, data, que_id = 0;
-       void __iomem *base = adapter->ahw->pci_base0;
-       struct __queue *que = &entry->region.que;
-
-       addr = que->read_addr;
-       cnt = que->read_addr_cnt;
-
-       for (loop = 0; loop < que->no_ops; loop++) {
-               QLCNIC_WR_DUMP_REG(que->sel_addr, base, que_id);
-               addr = que->read_addr;
-               for (i = 0; i < cnt; i++) {
-                       QLCNIC_RD_DUMP_REG(addr, base, &data);
-                       *buffer++ = cpu_to_le32(data);
-                       addr += que->read_addr_stride;
-               }
-               que_id += que->stride;
-       }
-       return que->no_ops * cnt * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_ocm(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-       u32 *buffer)
-{
-       int i;
-       u32 data;
-       void __iomem *addr;
-       struct __ocm *ocm = &entry->region.ocm;
-
-       addr = adapter->ahw->pci_base0 + ocm->read_addr;
-       for (i = 0; i < ocm->no_ops; i++) {
-               data = readl(addr);
-               *buffer++ = cpu_to_le32(data);
-               addr += ocm->read_addr_stride;
-       }
-       return ocm->no_ops * sizeof(u32);
-}
-
-static u32
-qlcnic_read_rom(struct qlcnic_adapter *adapter, struct qlcnic_dump_entry *entry,
-       u32 *buffer)
-{
-       int i, count = 0;
-       u32 fl_addr, size, val, lck_val, addr;
-       struct __mem *rom = &entry->region.mem;
-       void __iomem *base = adapter->ahw->pci_base0;
-
-       fl_addr = rom->addr;
-       size = rom->size/4;
-lock_try:
-       lck_val = readl(base + QLCNIC_FLASH_SEM2_LK);
-       if (!lck_val && count < MAX_CTL_CHECK) {
-               msleep(10);
-               count++;
-               goto lock_try;
-       }
-       writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID));
-       for (i = 0; i < size; i++) {
-               addr = fl_addr & 0xFFFF0000;
-               QLCNIC_WR_DUMP_REG(FLASH_ROM_WINDOW, base, addr);
-               addr = LSW(fl_addr) + FLASH_ROM_DATA;
-               QLCNIC_RD_DUMP_REG(addr, base, &val);
-               fl_addr += 4;
-               *buffer++ = cpu_to_le32(val);
-       }
-       readl(base + QLCNIC_FLASH_SEM2_ULK);
-       return rom->size;
-}
-
-static u32
-qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,
-       struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-       int i;
-       u32 cnt, val, data, addr;
-       void __iomem *base = adapter->ahw->pci_base0;
-       struct __cache *l1 = &entry->region.cache;
-
-       val = l1->init_tag_val;
-
-       for (i = 0; i < l1->no_ops; i++) {
-               QLCNIC_WR_DUMP_REG(l1->addr, base, val);
-               QLCNIC_WR_DUMP_REG(l1->ctrl_addr, base, LSW(l1->ctrl_val));
-               addr = l1->read_addr;
-               cnt = l1->read_addr_num;
-               while (cnt) {
-                       QLCNIC_RD_DUMP_REG(addr, base, &data);
-                       *buffer++ = cpu_to_le32(data);
-                       addr += l1->read_addr_stride;
-                       cnt--;
-               }
-               val += l1->stride;
-       }
-       return l1->no_ops * l1->read_addr_num * sizeof(u32);
-}
-
-static u32
-qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
-       struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-       int i;
-       u32 cnt, val, data, addr;
-       u8 poll_mask, poll_to, time_out = 0;
-       void __iomem *base = adapter->ahw->pci_base0;
-       struct __cache *l2 = &entry->region.cache;
-
-       val = l2->init_tag_val;
-       poll_mask = LSB(MSW(l2->ctrl_val));
-       poll_to = MSB(MSW(l2->ctrl_val));
-
-       for (i = 0; i < l2->no_ops; i++) {
-               QLCNIC_WR_DUMP_REG(l2->addr, base, val);
-               if (LSW(l2->ctrl_val))
-                       QLCNIC_WR_DUMP_REG(l2->ctrl_addr, base,
-                               LSW(l2->ctrl_val));
-               if (!poll_mask)
-                       goto skip_poll;
-               do {
-                       QLCNIC_RD_DUMP_REG(l2->ctrl_addr, base, &data);
-                       if (!(data & poll_mask))
-                               break;
-                       msleep(1);
-                       time_out++;
-               } while (time_out <= poll_to);
-
-               if (time_out > poll_to) {
-                       dev_err(&adapter->pdev->dev,
-                               "Timeout exceeded in %s, aborting dump\n",
-                               __func__);
-                       return -EINVAL;
-               }
-skip_poll:
-               addr = l2->read_addr;
-               cnt = l2->read_addr_num;
-               while (cnt) {
-                       QLCNIC_RD_DUMP_REG(addr, base, &data);
-                       *buffer++ = cpu_to_le32(data);
-                       addr += l2->read_addr_stride;
-                       cnt--;
-               }
-               val += l2->stride;
-       }
-       return l2->no_ops * l2->read_addr_num * sizeof(u32);
-}
-
-static u32
-qlcnic_read_memory(struct qlcnic_adapter *adapter,
-       struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-       u32 addr, data, test, ret = 0;
-       int i, reg_read;
-       struct __mem *mem = &entry->region.mem;
-       void __iomem *base = adapter->ahw->pci_base0;
-
-       reg_read = mem->size;
-       addr = mem->addr;
-       /* check for data size of multiple of 16 and 16 byte alignment */
-       if ((addr & 0xf) || (reg_read%16)) {
-               dev_info(&adapter->pdev->dev,
-                       "Unaligned memory addr:0x%x size:0x%x\n",
-                       addr, reg_read);
-               return -EINVAL;
-       }
-
-       mutex_lock(&adapter->ahw->mem_lock);
-
-       while (reg_read != 0) {
-               QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_LO, base, addr);
-               QLCNIC_WR_DUMP_REG(MIU_TEST_ADDR_HI, base, 0);
-               QLCNIC_WR_DUMP_REG(MIU_TEST_CTR, base,
-                       TA_CTL_ENABLE | TA_CTL_START);
-
-               for (i = 0; i < MAX_CTL_CHECK; i++) {
-                       QLCNIC_RD_DUMP_REG(MIU_TEST_CTR, base, &test);
-                       if (!(test & TA_CTL_BUSY))
-                               break;
-               }
-               if (i == MAX_CTL_CHECK) {
-                       if (printk_ratelimit()) {
-                               dev_err(&adapter->pdev->dev,
-                                       "failed to read through agent\n");
-                               ret = -EINVAL;
-                               goto out;
-                       }
-               }
-               for (i = 0; i < 4; i++) {
-                       QLCNIC_RD_DUMP_REG(MIU_TEST_READ_DATA[i], base, &data);
-                       *buffer++ = cpu_to_le32(data);
-               }
-               addr += 16;
-               reg_read -= 16;
-               ret += 16;
-       }
-out:
-       mutex_unlock(&adapter->ahw->mem_lock);
-       return mem->size;
-}
-
-static u32
-qlcnic_dump_nop(struct qlcnic_adapter *adapter,
-       struct qlcnic_dump_entry *entry, u32 *buffer)
-{
-       entry->hdr.flags |= QLCNIC_DUMP_SKIP;
-       return 0;
-}
-
-struct qlcnic_dump_operations fw_dump_ops[] = {
-       { QLCNIC_DUMP_NOP, qlcnic_dump_nop },
-       { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
-       { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
-       { QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
-       { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom },
-       { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
-       { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
-       { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
-       { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
-       { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
-       { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
-       { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
-       { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
-       { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
-       { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
-       { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom },
-       { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
-       { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
-       { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
-       { QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
-};
-
-/* Walk the template and collect dump for each entry in the dump template */
-static int
-qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
-       u32 size)
-{
-       int ret = 1;
-       if (size != entry->hdr.cap_size) {
-               dev_info(dev,
-               "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
-               entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
-               dev_info(dev, "Aborting further dump capture\n");
-               ret = 0;
-       }
-       return ret;
-}
-
-int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
-{
-       u32 *buffer;
-       char mesg[64];
-       char *msg[] = {mesg, NULL};
-       int i, k, ops_cnt, ops_index, dump_size = 0;
-       u32 entry_offset, dump, no_entries, buf_offset = 0;
-       struct qlcnic_dump_entry *entry;
-       struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
-       struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
-
-       if (fw_dump->clr) {
-               dev_info(&adapter->pdev->dev,
-                       "Previous dump not cleared, not capturing dump\n");
-               return -EIO;
-       }
-       /* Calculate the size for dump data area only */
-       for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
-               if (i & tmpl_hdr->drv_cap_mask)
-                       dump_size += tmpl_hdr->cap_sizes[k];
-       if (!dump_size)
-               return -EIO;
-
-       fw_dump->data = vzalloc(dump_size);
-       if (!fw_dump->data) {
-               dev_info(&adapter->pdev->dev,
-                       "Unable to allocate (%d KB) for fw dump\n",
-                       dump_size/1024);
-               return -ENOMEM;
-       }
-       buffer = fw_dump->data;
-       fw_dump->size = dump_size;
-       no_entries = tmpl_hdr->num_entries;
-       ops_cnt = ARRAY_SIZE(fw_dump_ops);
-       entry_offset = tmpl_hdr->offset;
-       tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
-       tmpl_hdr->sys_info[1] = adapter->fw_version;
-
-       for (i = 0; i < no_entries; i++) {
-               entry = (void *)tmpl_hdr + entry_offset;
-               if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
-                       entry->hdr.flags |= QLCNIC_DUMP_SKIP;
-                       entry_offset += entry->hdr.offset;
-                       continue;
-               }
-               /* Find the handler for this entry */
-               ops_index = 0;
-               while (ops_index < ops_cnt) {
-                       if (entry->hdr.type == fw_dump_ops[ops_index].opcode)
-                               break;
-                       ops_index++;
-               }
-               if (ops_index == ops_cnt) {
-                       dev_info(&adapter->pdev->dev,
-                               "Invalid entry type %d, exiting dump\n",
-                               entry->hdr.type);
-                       goto error;
-               }
-               /* Collect dump for this entry */
-               dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
-               if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry,
-                       dump))
-                       entry->hdr.flags |= QLCNIC_DUMP_SKIP;
-               buf_offset += entry->hdr.cap_size;
-               entry_offset += entry->hdr.offset;
-               buffer = fw_dump->data + buf_offset;
-       }
-       if (dump_size != buf_offset) {
-               dev_info(&adapter->pdev->dev,
-                       "Captured(%d) and expected size(%d) do not match\n",
-                       buf_offset, dump_size);
-               goto error;
-       } else {
-               fw_dump->clr = 1;
-               snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
-                       adapter->netdev->name);
-               dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n",
-                       fw_dump->size);
-               /* Send a udev event to notify availability of FW dump */
-               kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
-               return 0;
-       }
-error:
-       vfree(fw_dump->data);
-       return -EINVAL;
-}
index 0bcda9c51e9bcbc42abde3c0130f00371613389e..de79cde233def0a88f9bab32e2bfab295f7d785b 100644 (file)
@@ -25,10 +25,6 @@ static unsigned int crb_addr_xform[QLCNIC_MAX_CRB_XFORM];
 
 #define QLCNIC_ADDR_ERROR (0xffffffff)
 
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_rds_ring *rds_ring);
-
 static int
 qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
 
@@ -250,7 +246,8 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter)
                        rds_ring->dma_size =
                                QLCNIC_P3P_RX_JUMBO_BUF_MAX_LEN;
 
-                       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+                       if (adapter->ahw->capabilities &
+                           QLCNIC_FW_CAPABILITY_HW_LRO)
                                rds_ring->dma_size += QLCNIC_LRO_BUFFER_EXTRA;
 
                        rds_ring->skb_size =
@@ -659,7 +656,7 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) {
                        "Not an Ethernet NIC func=%u\n", val);
                return -EIO;
        }
-       adapter->physical_port = (val >> 2);
+       adapter->ahw->physical_port = (val >> 2);
        if (qlcnic_rom_fast_read(adapter, QLCNIC_ROM_DEV_INIT_TIMEOUT, &timeo))
                timeo = QLCNIC_INIT_TIMEOUT_SECS;
 
@@ -778,15 +775,15 @@ qlcnic_has_mn(struct qlcnic_adapter *adapter)
 static
 struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section)
 {
-       u32 i;
+       u32 i, entries;
        struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
-       __le32 entries = cpu_to_le32(directory->num_entries);
+       entries = le32_to_cpu(directory->num_entries);
 
        for (i = 0; i < entries; i++) {
 
-               __le32 offs = cpu_to_le32(directory->findex) +
-                               (i * cpu_to_le32(directory->entry_size));
-               __le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8));
+               u32 offs = le32_to_cpu(directory->findex) +
+                          i * le32_to_cpu(directory->entry_size);
+               u32 tab_type = le32_to_cpu(*((__le32 *)&unirom[offs] + 8));
 
                if (tab_type == section)
                        return (struct uni_table_desc *) &unirom[offs];
@@ -802,17 +799,16 @@ qlcnic_validate_header(struct qlcnic_adapter *adapter)
 {
        const u8 *unirom = adapter->fw->data;
        struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
-       __le32 fw_file_size = adapter->fw->size;
-       __le32 entries;
-       __le32 entry_size;
-       __le32 tab_size;
+       u32 entries, entry_size, tab_size, fw_file_size;
+
+       fw_file_size = adapter->fw->size;
 
        if (fw_file_size < FILEHEADER_SIZE)
                return -EINVAL;
 
-       entries = cpu_to_le32(directory->num_entries);
-       entry_size = cpu_to_le32(directory->entry_size);
-       tab_size = cpu_to_le32(directory->findex) + (entries * entry_size);
+       entries = le32_to_cpu(directory->num_entries);
+       entry_size = le32_to_cpu(directory->entry_size);
+       tab_size = le32_to_cpu(directory->findex) + (entries * entry_size);
 
        if (fw_file_size < tab_size)
                return -EINVAL;
@@ -825,29 +821,29 @@ qlcnic_validate_bootld(struct qlcnic_adapter *adapter)
 {
        struct uni_table_desc *tab_desc;
        struct uni_data_desc *descr;
+       u32 offs, tab_size, data_size, idx;
        const u8 *unirom = adapter->fw->data;
-       int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
-                               QLCNIC_UNI_BOOTLD_IDX_OFF));
-       __le32 offs;
-       __le32 tab_size;
-       __le32 data_size;
+       __le32 temp;
 
+       temp = *((__le32 *)&unirom[adapter->file_prd_off] +
+                QLCNIC_UNI_BOOTLD_IDX_OFF);
+       idx = le32_to_cpu(temp);
        tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD);
 
        if (!tab_desc)
                return -EINVAL;
 
-       tab_size = cpu_to_le32(tab_desc->findex) +
-                       (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
+       tab_size = le32_to_cpu(tab_desc->findex) +
+                  le32_to_cpu(tab_desc->entry_size) * (idx + 1);
 
        if (adapter->fw->size < tab_size)
                return -EINVAL;
 
-       offs = cpu_to_le32(tab_desc->findex) +
-               (cpu_to_le32(tab_desc->entry_size) * (idx));
+       offs = le32_to_cpu(tab_desc->findex) +
+              le32_to_cpu(tab_desc->entry_size) * idx;
        descr = (struct uni_data_desc *)&unirom[offs];
 
-       data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
+       data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
 
        if (adapter->fw->size < data_size)
                return -EINVAL;
@@ -861,27 +857,27 @@ qlcnic_validate_fw(struct qlcnic_adapter *adapter)
        struct uni_table_desc *tab_desc;
        struct uni_data_desc *descr;
        const u8 *unirom = adapter->fw->data;
-       int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
-                               QLCNIC_UNI_FIRMWARE_IDX_OFF));
-       __le32 offs;
-       __le32 tab_size;
-       __le32 data_size;
+       u32 offs, tab_size, data_size, idx;
+       __le32 temp;
 
+       temp = *((__le32 *)&unirom[adapter->file_prd_off] +
+                QLCNIC_UNI_FIRMWARE_IDX_OFF);
+       idx = le32_to_cpu(temp);
        tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW);
 
        if (!tab_desc)
                return -EINVAL;
 
-       tab_size = cpu_to_le32(tab_desc->findex) +
-                       (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
+       tab_size = le32_to_cpu(tab_desc->findex) +
+                  le32_to_cpu(tab_desc->entry_size) * (idx + 1);
 
        if (adapter->fw->size < tab_size)
                return -EINVAL;
 
-       offs = cpu_to_le32(tab_desc->findex) +
-               (cpu_to_le32(tab_desc->entry_size) * (idx));
+       offs = le32_to_cpu(tab_desc->findex) +
+              le32_to_cpu(tab_desc->entry_size) * idx;
        descr = (struct uni_data_desc *)&unirom[offs];
-       data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
+       data_size = le32_to_cpu(descr->findex) + le32_to_cpu(descr->size);
 
        if (adapter->fw->size < data_size)
                return -EINVAL;
@@ -895,19 +891,17 @@ qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
        struct uni_table_desc *ptab_descr;
        const u8 *unirom = adapter->fw->data;
        int mn_present = qlcnic_has_mn(adapter);
-       __le32 entries;
-       __le32 entry_size;
-       __le32 tab_size;
-       u32 i;
+       u32 entries, entry_size, tab_size, i;
+       __le32 temp;
 
        ptab_descr = qlcnic_get_table_desc(unirom,
                                QLCNIC_UNI_DIR_SECT_PRODUCT_TBL);
        if (!ptab_descr)
                return -EINVAL;
 
-       entries = cpu_to_le32(ptab_descr->num_entries);
-       entry_size = cpu_to_le32(ptab_descr->entry_size);
-       tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size);
+       entries = le32_to_cpu(ptab_descr->num_entries);
+       entry_size = le32_to_cpu(ptab_descr->entry_size);
+       tab_size = le32_to_cpu(ptab_descr->findex) + (entries * entry_size);
 
        if (adapter->fw->size < tab_size)
                return -EINVAL;
@@ -915,16 +909,16 @@ qlcnic_validate_product_offs(struct qlcnic_adapter *adapter)
 nomn:
        for (i = 0; i < entries; i++) {
 
-               __le32 flags, file_chiprev, offs;
+               u32 flags, file_chiprev, offs;
                u8 chiprev = adapter->ahw->revision_id;
                u32 flagbit;
 
-               offs = cpu_to_le32(ptab_descr->findex) +
-                               (i * cpu_to_le32(ptab_descr->entry_size));
-               flags = cpu_to_le32(*((int *)&unirom[offs] +
-                                               QLCNIC_UNI_FLAGS_OFF));
-               file_chiprev = cpu_to_le32(*((int *)&unirom[offs] +
-                                               QLCNIC_UNI_CHIP_REV_OFF));
+               offs = le32_to_cpu(ptab_descr->findex) +
+                      i * le32_to_cpu(ptab_descr->entry_size);
+               temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_FLAGS_OFF);
+               flags = le32_to_cpu(temp);
+               temp = *((__le32 *)&unirom[offs] + QLCNIC_UNI_CHIP_REV_OFF);
+               file_chiprev = le32_to_cpu(temp);
 
                flagbit = mn_present ? 1 : 2;
 
@@ -976,18 +970,20 @@ struct uni_data_desc *qlcnic_get_data_desc(struct qlcnic_adapter *adapter,
                        u32 section, u32 idx_offset)
 {
        const u8 *unirom = adapter->fw->data;
-       int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
-                                                               idx_offset));
        struct uni_table_desc *tab_desc;
-       __le32 offs;
+       u32 offs, idx;
+       __le32 temp;
+
+       temp = *((__le32 *)&unirom[adapter->file_prd_off] + idx_offset);
+       idx = le32_to_cpu(temp);
 
        tab_desc = qlcnic_get_table_desc(unirom, section);
 
        if (tab_desc == NULL)
                return NULL;
 
-       offs = cpu_to_le32(tab_desc->findex) +
-                       (cpu_to_le32(tab_desc->entry_size) * idx);
+       offs = le32_to_cpu(tab_desc->findex) +
+              le32_to_cpu(tab_desc->entry_size) * idx;
 
        return (struct uni_data_desc *)&unirom[offs];
 }
@@ -996,11 +992,13 @@ static u8 *
 qlcnic_get_bootld_offs(struct qlcnic_adapter *adapter)
 {
        u32 offs = QLCNIC_BOOTLD_START;
+       struct uni_data_desc *data_desc;
 
-       if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
-               offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
-                                       QLCNIC_UNI_DIR_SECT_BOOTLD,
-                                       QLCNIC_UNI_BOOTLD_IDX_OFF))->findex);
+       data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_BOOTLD,
+                                        QLCNIC_UNI_BOOTLD_IDX_OFF);
+
+       if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+               offs = le32_to_cpu(data_desc->findex);
 
        return (u8 *)&adapter->fw->data[offs];
 }
@@ -1009,43 +1007,48 @@ static u8 *
 qlcnic_get_fw_offs(struct qlcnic_adapter *adapter)
 {
        u32 offs = QLCNIC_IMAGE_START;
+       struct uni_data_desc *data_desc;
 
-       if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
-               offs = cpu_to_le32((qlcnic_get_data_desc(adapter,
-                                       QLCNIC_UNI_DIR_SECT_FW,
-                                       QLCNIC_UNI_FIRMWARE_IDX_OFF))->findex);
+       data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
+                                        QLCNIC_UNI_FIRMWARE_IDX_OFF);
+       if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+               offs = le32_to_cpu(data_desc->findex);
 
        return (u8 *)&adapter->fw->data[offs];
 }
 
-static __le32
-qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_fw_size(struct qlcnic_adapter *adapter)
 {
-       if (adapter->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
-               return cpu_to_le32((qlcnic_get_data_desc(adapter,
-                                       QLCNIC_UNI_DIR_SECT_FW,
-                                       QLCNIC_UNI_FIRMWARE_IDX_OFF))->size);
+       struct uni_data_desc *data_desc;
+       const u8 *unirom = adapter->fw->data;
+
+       data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
+                                        QLCNIC_UNI_FIRMWARE_IDX_OFF);
+
+       if (adapter->ahw->fw_type == QLCNIC_UNIFIED_ROMIMAGE)
+               return le32_to_cpu(data_desc->size);
        else
-               return cpu_to_le32(
-                       *(u32 *)&adapter->fw->data[QLCNIC_FW_SIZE_OFFSET]);
+               return le32_to_cpu(*(__le32 *)&unirom[QLCNIC_FW_SIZE_OFFSET]);
 }
 
-static __le32
-qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
 {
        struct uni_data_desc *fw_data_desc;
        const struct firmware *fw = adapter->fw;
-       __le32 major, minor, sub;
+       u32 major, minor, sub;
+       __le32 version_offset;
        const u8 *ver_str;
        int i, ret;
 
-       if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
-               return cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET]);
+       if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
+               version_offset = *(__le32 *)&fw->data[QLCNIC_FW_VERSION_OFFSET];
+               return le32_to_cpu(version_offset);
+       }
 
        fw_data_desc = qlcnic_get_data_desc(adapter, QLCNIC_UNI_DIR_SECT_FW,
                        QLCNIC_UNI_FIRMWARE_IDX_OFF);
-       ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) +
-               cpu_to_le32(fw_data_desc->size) - 17;
+       ver_str = fw->data + le32_to_cpu(fw_data_desc->findex) +
+                 le32_to_cpu(fw_data_desc->size) - 17;
 
        for (i = 0; i < 12; i++) {
                if (!strncmp(&ver_str[i], "REV=", 4)) {
@@ -1061,18 +1064,20 @@ qlcnic_get_fw_version(struct qlcnic_adapter *adapter)
        return 0;
 }
 
-static __le32
-qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
+static u32 qlcnic_get_bios_version(struct qlcnic_adapter *adapter)
 {
        const struct firmware *fw = adapter->fw;
-       __le32 bios_ver, prd_off = adapter->file_prd_off;
+       u32 bios_ver, prd_off = adapter->file_prd_off;
+       u8 *version_offset;
+       __le32 temp;
 
-       if (adapter->fw_type != QLCNIC_UNIFIED_ROMIMAGE)
-               return cpu_to_le32(
-                       *(u32 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET]);
+       if (adapter->ahw->fw_type != QLCNIC_UNIFIED_ROMIMAGE) {
+               version_offset = (u8 *)&fw->data[QLCNIC_BIOS_VERSION_OFFSET];
+               return le32_to_cpu(*(__le32 *)version_offset);
+       }
 
-       bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off])
-                               + QLCNIC_UNI_BIOS_VERSION_OFF));
+       temp = *((__le32 *)(&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF);
+       bios_ver = le32_to_cpu(temp);
 
        return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24);
 }
@@ -1131,24 +1136,24 @@ static const char *fw_name[] = {
 int
 qlcnic_load_firmware(struct qlcnic_adapter *adapter)
 {
-       u64 *ptr64;
+       __le64 *ptr64;
        u32 i, flashaddr, size;
        const struct firmware *fw = adapter->fw;
        struct pci_dev *pdev = adapter->pdev;
 
        dev_info(&pdev->dev, "loading firmware from %s\n",
-                       fw_name[adapter->fw_type]);
+                fw_name[adapter->ahw->fw_type]);
 
        if (fw) {
-               __le64 data;
+               u64 data;
 
                size = (QLCNIC_IMAGE_START - QLCNIC_BOOTLD_START) / 8;
 
-               ptr64 = (u64 *)qlcnic_get_bootld_offs(adapter);
+               ptr64 = (__le64 *)qlcnic_get_bootld_offs(adapter);
                flashaddr = QLCNIC_BOOTLD_START;
 
                for (i = 0; i < size; i++) {
-                       data = cpu_to_le64(ptr64[i]);
+                       data = le64_to_cpu(ptr64[i]);
 
                        if (qlcnic_pci_mem_write_2M(adapter, flashaddr, data))
                                return -EIO;
@@ -1156,13 +1161,13 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
                        flashaddr += 8;
                }
 
-               size = (__force u32)qlcnic_get_fw_size(adapter) / 8;
+               size = qlcnic_get_fw_size(adapter) / 8;
 
-               ptr64 = (u64 *)qlcnic_get_fw_offs(adapter);
+               ptr64 = (__le64 *)qlcnic_get_fw_offs(adapter);
                flashaddr = QLCNIC_IMAGE_START;
 
                for (i = 0; i < size; i++) {
-                       data = cpu_to_le64(ptr64[i]);
+                       data = le64_to_cpu(ptr64[i]);
 
                        if (qlcnic_pci_mem_write_2M(adapter,
                                                flashaddr, data))
@@ -1171,9 +1176,9 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
                        flashaddr += 8;
                }
 
-               size = (__force u32)qlcnic_get_fw_size(adapter) % 8;
+               size = qlcnic_get_fw_size(adapter) % 8;
                if (size) {
-                       data = cpu_to_le64(ptr64[i]);
+                       data = le64_to_cpu(ptr64[i]);
 
                        if (qlcnic_pci_mem_write_2M(adapter,
                                                flashaddr, data))
@@ -1225,11 +1230,11 @@ qlcnic_load_firmware(struct qlcnic_adapter *adapter)
 static int
 qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
 {
-       __le32 val;
+       u32 val;
        u32 ver, bios, min_size;
        struct pci_dev *pdev = adapter->pdev;
        const struct firmware *fw = adapter->fw;
-       u8 fw_type = adapter->fw_type;
+       u8 fw_type = adapter->ahw->fw_type;
 
        if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) {
                if (qlcnic_validate_unified_romimage(adapter))
@@ -1237,8 +1242,8 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
 
                min_size = QLCNIC_UNI_FW_MIN_SIZE;
        } else {
-               val = cpu_to_le32(*(u32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
-               if ((__force u32)val != QLCNIC_BDINFO_MAGIC)
+               val = le32_to_cpu(*(__le32 *)&fw->data[QLCNIC_FW_MAGIC_OFFSET]);
+               if (val != QLCNIC_BDINFO_MAGIC)
                        return -EINVAL;
 
                min_size = QLCNIC_FW_MIN_SIZE;
@@ -1259,7 +1264,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter)
 
        val = qlcnic_get_bios_version(adapter);
        qlcnic_rom_fast_read(adapter, QLCNIC_BIOS_VERSION_OFFSET, (int *)&bios);
-       if ((__force u32)val != bios) {
+       if (val != bios) {
                dev_err(&pdev->dev, "%s: firmware bios is incompatible\n",
                                fw_name[fw_type]);
                return -EINVAL;
@@ -1274,7 +1279,7 @@ qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
 {
        u8 fw_type;
 
-       switch (adapter->fw_type) {
+       switch (adapter->ahw->fw_type) {
        case QLCNIC_UNKNOWN_ROMIMAGE:
                fw_type = QLCNIC_UNIFIED_ROMIMAGE;
                break;
@@ -1285,7 +1290,7 @@ qlcnic_get_next_fwtype(struct qlcnic_adapter *adapter)
                break;
        }
 
-       adapter->fw_type = fw_type;
+       adapter->ahw->fw_type = fw_type;
 }
 
 
@@ -1295,16 +1300,17 @@ void qlcnic_request_firmware(struct qlcnic_adapter *adapter)
        struct pci_dev *pdev = adapter->pdev;
        int rc;
 
-       adapter->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
+       adapter->ahw->fw_type = QLCNIC_UNKNOWN_ROMIMAGE;
 
 next:
        qlcnic_get_next_fwtype(adapter);
 
-       if (adapter->fw_type == QLCNIC_FLASH_ROMIMAGE) {
+       if (adapter->ahw->fw_type == QLCNIC_FLASH_ROMIMAGE) {
                adapter->fw = NULL;
        } else {
                rc = request_firmware(&adapter->fw,
-                               fw_name[adapter->fw_type], &pdev->dev);
+                                     fw_name[adapter->ahw->fw_type],
+                                     &pdev->dev);
                if (rc != 0)
                        goto next;
 
@@ -1324,633 +1330,3 @@ qlcnic_release_firmware(struct qlcnic_adapter *adapter)
        release_firmware(adapter->fw);
        adapter->fw = NULL;
 }
-
-static void
-qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
-                               struct qlcnic_fw_msg *msg)
-{
-       u32 cable_OUI;
-       u16 cable_len;
-       u16 link_speed;
-       u8  link_status, module, duplex, autoneg;
-       u8 lb_status = 0;
-       struct net_device *netdev = adapter->netdev;
-
-       adapter->has_link_events = 1;
-
-       cable_OUI = msg->body[1] & 0xffffffff;
-       cable_len = (msg->body[1] >> 32) & 0xffff;
-       link_speed = (msg->body[1] >> 48) & 0xffff;
-
-       link_status = msg->body[2] & 0xff;
-       duplex = (msg->body[2] >> 16) & 0xff;
-       autoneg = (msg->body[2] >> 24) & 0xff;
-       lb_status = (msg->body[2] >> 32) & 0x3;
-
-       module = (msg->body[2] >> 8) & 0xff;
-       if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
-               dev_info(&netdev->dev, "unsupported cable: OUI 0x%x, "
-                               "length %d\n", cable_OUI, cable_len);
-       else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
-               dev_info(&netdev->dev, "unsupported cable length %d\n",
-                               cable_len);
-
-       if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
-           lb_status == QLCNIC_ELB_MODE))
-               adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
-
-       qlcnic_advert_link_change(adapter, link_status);
-
-       if (duplex == LINKEVENT_FULL_DUPLEX)
-               adapter->link_duplex = DUPLEX_FULL;
-       else
-               adapter->link_duplex = DUPLEX_HALF;
-
-       adapter->module_type = module;
-       adapter->link_autoneg = autoneg;
-
-       if (link_status) {
-               adapter->link_speed = link_speed;
-       } else {
-               adapter->link_speed = SPEED_UNKNOWN;
-               adapter->link_duplex = DUPLEX_UNKNOWN;
-       }
-}
-
-static void
-qlcnic_handle_fw_message(int desc_cnt, int index,
-               struct qlcnic_host_sds_ring *sds_ring)
-{
-       struct qlcnic_fw_msg msg;
-       struct status_desc *desc;
-       struct qlcnic_adapter *adapter;
-       struct device *dev;
-       int i = 0, opcode, ret;
-
-       while (desc_cnt > 0 && i < 8) {
-               desc = &sds_ring->desc_head[index];
-               msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
-               msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
-
-               index = get_next_index(index, sds_ring->num_desc);
-               desc_cnt--;
-       }
-
-       adapter = sds_ring->adapter;
-       dev = &adapter->pdev->dev;
-       opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
-
-       switch (opcode) {
-       case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
-               qlcnic_handle_linkevent(adapter, &msg);
-               break;
-       case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
-               ret = (u32)(msg.body[1]);
-               switch (ret) {
-               case 0:
-                       adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
-                       break;
-               case 1:
-                       dev_info(dev, "loopback already in progress\n");
-                       adapter->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
-                       break;
-               case 2:
-                       dev_info(dev, "loopback cable is not connected\n");
-                       adapter->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
-                       break;
-               default:
-                       dev_info(dev, "loopback configure request failed,"
-                                       " ret %x\n", ret);
-                       adapter->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
-                       break;
-               }
-               break;
-       default:
-               break;
-       }
-}
-
-static int
-qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_rds_ring *rds_ring,
-               struct qlcnic_rx_buffer *buffer)
-{
-       struct sk_buff *skb;
-       dma_addr_t dma;
-       struct pci_dev *pdev = adapter->pdev;
-
-       skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
-       if (!skb) {
-               adapter->stats.skb_alloc_failure++;
-               return -ENOMEM;
-       }
-
-       skb_reserve(skb, NET_IP_ALIGN);
-
-       dma = pci_map_single(pdev, skb->data,
-                       rds_ring->dma_size, PCI_DMA_FROMDEVICE);
-
-       if (pci_dma_mapping_error(pdev, dma)) {
-               adapter->stats.rx_dma_map_error++;
-               dev_kfree_skb_any(skb);
-               return -ENOMEM;
-       }
-
-       buffer->skb = skb;
-       buffer->dma = dma;
-
-       return 0;
-}
-
-static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_rds_ring *rds_ring, u16 index, u16 cksum)
-{
-       struct qlcnic_rx_buffer *buffer;
-       struct sk_buff *skb;
-
-       buffer = &rds_ring->rx_buf_arr[index];
-
-       if (unlikely(buffer->skb == NULL)) {
-               WARN_ON(1);
-               return NULL;
-       }
-
-       pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
-                       PCI_DMA_FROMDEVICE);
-
-       skb = buffer->skb;
-
-       if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
-           (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
-               adapter->stats.csummed++;
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-       } else {
-               skb_checksum_none_assert(skb);
-       }
-
-       buffer->skb = NULL;
-
-       return skb;
-}
-
-static inline int
-qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter, struct sk_buff *skb,
-                       u16 *vlan_tag)
-{
-       struct ethhdr *eth_hdr;
-
-       if (!__vlan_get_tag(skb, vlan_tag)) {
-               eth_hdr = (struct ethhdr *) skb->data;
-               memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
-               skb_pull(skb, VLAN_HLEN);
-       }
-       if (!adapter->pvid)
-               return 0;
-
-       if (*vlan_tag == adapter->pvid) {
-               /* Outer vlan tag. Packet should follow non-vlan path */
-               *vlan_tag = 0xffff;
-               return 0;
-       }
-       if (adapter->flags & QLCNIC_TAGGING_ENABLED)
-               return 0;
-
-       return -EINVAL;
-}
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_rcv(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_sds_ring *sds_ring,
-               int ring, u64 sts_data0)
-{
-       struct net_device *netdev = adapter->netdev;
-       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-       struct qlcnic_rx_buffer *buffer;
-       struct sk_buff *skb;
-       struct qlcnic_host_rds_ring *rds_ring;
-       int index, length, cksum, pkt_offset;
-       u16 vid = 0xffff;
-
-       if (unlikely(ring >= adapter->max_rds_rings))
-               return NULL;
-
-       rds_ring = &recv_ctx->rds_rings[ring];
-
-       index = qlcnic_get_sts_refhandle(sts_data0);
-       if (unlikely(index >= rds_ring->num_desc))
-               return NULL;
-
-       buffer = &rds_ring->rx_buf_arr[index];
-
-       length = qlcnic_get_sts_totallength(sts_data0);
-       cksum  = qlcnic_get_sts_status(sts_data0);
-       pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
-       skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
-       if (!skb)
-               return buffer;
-
-       if (length > rds_ring->skb_size)
-               skb_put(skb, rds_ring->skb_size);
-       else
-               skb_put(skb, length);
-
-       if (pkt_offset)
-               skb_pull(skb, pkt_offset);
-
-       if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
-               adapter->stats.rxdropped++;
-               dev_kfree_skb(skb);
-               return buffer;
-       }
-
-       skb->protocol = eth_type_trans(skb, netdev);
-
-       if (vid != 0xffff)
-               __vlan_hwaccel_put_tag(skb, vid);
-
-       napi_gro_receive(&sds_ring->napi, skb);
-
-       adapter->stats.rx_pkts++;
-       adapter->stats.rxbytes += length;
-
-       return buffer;
-}
-
-#define QLC_TCP_HDR_SIZE            20
-#define QLC_TCP_TS_OPTION_SIZE      12
-#define QLC_TCP_TS_HDR_SIZE         (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
-
-static struct qlcnic_rx_buffer *
-qlcnic_process_lro(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_sds_ring *sds_ring,
-               int ring, u64 sts_data0, u64 sts_data1)
-{
-       struct net_device *netdev = adapter->netdev;
-       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-       struct qlcnic_rx_buffer *buffer;
-       struct sk_buff *skb;
-       struct qlcnic_host_rds_ring *rds_ring;
-       struct iphdr *iph;
-       struct tcphdr *th;
-       bool push, timestamp;
-       int l2_hdr_offset, l4_hdr_offset;
-       int index;
-       u16 lro_length, length, data_offset;
-       u32 seq_number;
-       u16 vid = 0xffff;
-
-       if (unlikely(ring > adapter->max_rds_rings))
-               return NULL;
-
-       rds_ring = &recv_ctx->rds_rings[ring];
-
-       index = qlcnic_get_lro_sts_refhandle(sts_data0);
-       if (unlikely(index > rds_ring->num_desc))
-               return NULL;
-
-       buffer = &rds_ring->rx_buf_arr[index];
-
-       timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
-       lro_length = qlcnic_get_lro_sts_length(sts_data0);
-       l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
-       l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
-       push = qlcnic_get_lro_sts_push_flag(sts_data0);
-       seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
-
-       skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
-       if (!skb)
-               return buffer;
-
-       if (timestamp)
-               data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
-       else
-               data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
-
-       skb_put(skb, lro_length + data_offset);
-
-       skb_pull(skb, l2_hdr_offset);
-
-       if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
-               adapter->stats.rxdropped++;
-               dev_kfree_skb(skb);
-               return buffer;
-       }
-
-       skb->protocol = eth_type_trans(skb, netdev);
-
-       iph = (struct iphdr *)skb->data;
-       th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
-
-       length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
-       iph->tot_len = htons(length);
-       iph->check = 0;
-       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-       th->psh = push;
-       th->seq = htonl(seq_number);
-
-       length = skb->len;
-
-       if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
-               skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
-
-       if (vid != 0xffff)
-               __vlan_hwaccel_put_tag(skb, vid);
-       netif_receive_skb(skb);
-
-       adapter->stats.lro_pkts++;
-       adapter->stats.lrobytes += length;
-
-       return buffer;
-}
-
-int
-qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
-{
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-       struct list_head *cur;
-       struct status_desc *desc;
-       struct qlcnic_rx_buffer *rxbuf;
-       u64 sts_data0, sts_data1;
-
-       int count = 0;
-       int opcode, ring, desc_cnt;
-       u32 consumer = sds_ring->consumer;
-
-       while (count < max) {
-               desc = &sds_ring->desc_head[consumer];
-               sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
-               if (!(sts_data0 & STATUS_OWNER_HOST))
-                       break;
-
-               desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
-               opcode = qlcnic_get_sts_opcode(sts_data0);
-
-               switch (opcode) {
-               case QLCNIC_RXPKT_DESC:
-               case QLCNIC_OLD_RXPKT_DESC:
-               case QLCNIC_SYN_OFFLOAD:
-                       ring = qlcnic_get_sts_type(sts_data0);
-                       rxbuf = qlcnic_process_rcv(adapter, sds_ring,
-                                       ring, sts_data0);
-                       break;
-               case QLCNIC_LRO_DESC:
-                       ring = qlcnic_get_lro_sts_type(sts_data0);
-                       sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
-                       rxbuf = qlcnic_process_lro(adapter, sds_ring,
-                                       ring, sts_data0, sts_data1);
-                       break;
-               case QLCNIC_RESPONSE_DESC:
-                       qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
-               default:
-                       goto skip;
-               }
-
-               WARN_ON(desc_cnt > 1);
-
-               if (likely(rxbuf))
-                       list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
-               else
-                       adapter->stats.null_rxbuf++;
-
-skip:
-               for (; desc_cnt > 0; desc_cnt--) {
-                       desc = &sds_ring->desc_head[consumer];
-                       desc->status_desc_data[0] =
-                               cpu_to_le64(STATUS_OWNER_PHANTOM);
-                       consumer = get_next_index(consumer, sds_ring->num_desc);
-               }
-               count++;
-       }
-
-       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
-               struct qlcnic_host_rds_ring *rds_ring =
-                       &adapter->recv_ctx->rds_rings[ring];
-
-               if (!list_empty(&sds_ring->free_list[ring])) {
-                       list_for_each(cur, &sds_ring->free_list[ring]) {
-                               rxbuf = list_entry(cur,
-                                               struct qlcnic_rx_buffer, list);
-                               qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
-                       }
-                       spin_lock(&rds_ring->lock);
-                       list_splice_tail_init(&sds_ring->free_list[ring],
-                                               &rds_ring->free_list);
-                       spin_unlock(&rds_ring->lock);
-               }
-
-               qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
-       }
-
-       if (count) {
-               sds_ring->consumer = consumer;
-               writel(consumer, sds_ring->crb_sts_consumer);
-       }
-
-       return count;
-}
-
-void
-qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
-       struct qlcnic_host_rds_ring *rds_ring)
-{
-       struct rcv_desc *pdesc;
-       struct qlcnic_rx_buffer *buffer;
-       int count = 0;
-       u32 producer;
-       struct list_head *head;
-
-       producer = rds_ring->producer;
-
-       head = &rds_ring->free_list;
-       while (!list_empty(head)) {
-
-               buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
-
-               if (!buffer->skb) {
-                       if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
-                               break;
-               }
-
-               count++;
-               list_del(&buffer->list);
-
-               /* make a rcv descriptor  */
-               pdesc = &rds_ring->desc_head[producer];
-               pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-               pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
-               pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
-
-               producer = get_next_index(producer, rds_ring->num_desc);
-       }
-
-       if (count) {
-               rds_ring->producer = producer;
-               writel((producer-1) & (rds_ring->num_desc-1),
-                               rds_ring->crb_rcv_producer);
-       }
-}
-
-static void
-qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_rds_ring *rds_ring)
-{
-       struct rcv_desc *pdesc;
-       struct qlcnic_rx_buffer *buffer;
-       int  count = 0;
-       uint32_t producer;
-       struct list_head *head;
-
-       if (!spin_trylock(&rds_ring->lock))
-               return;
-
-       producer = rds_ring->producer;
-
-       head = &rds_ring->free_list;
-       while (!list_empty(head)) {
-
-               buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
-
-               if (!buffer->skb) {
-                       if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
-                               break;
-               }
-
-               count++;
-               list_del(&buffer->list);
-
-               /* make a rcv descriptor  */
-               pdesc = &rds_ring->desc_head[producer];
-               pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
-               pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
-               pdesc->addr_buffer = cpu_to_le64(buffer->dma);
-
-               producer = get_next_index(producer, rds_ring->num_desc);
-       }
-
-       if (count) {
-               rds_ring->producer = producer;
-               writel((producer - 1) & (rds_ring->num_desc - 1),
-                               rds_ring->crb_rcv_producer);
-       }
-       spin_unlock(&rds_ring->lock);
-}
-
-static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
-{
-       int i;
-       unsigned char *data = skb->data;
-
-       printk(KERN_INFO "\n");
-       for (i = 0; i < skb->len; i++) {
-               QLCDB(adapter, DRV, "%02x ", data[i]);
-               if ((i & 0x0f) == 8)
-                       printk(KERN_INFO "\n");
-       }
-}
-
-void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_sds_ring *sds_ring,
-               int ring, u64 sts_data0)
-{
-       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-       struct sk_buff *skb;
-       struct qlcnic_host_rds_ring *rds_ring;
-       int index, length, cksum, pkt_offset;
-
-       if (unlikely(ring >= adapter->max_rds_rings))
-               return;
-
-       rds_ring = &recv_ctx->rds_rings[ring];
-
-       index = qlcnic_get_sts_refhandle(sts_data0);
-       length = qlcnic_get_sts_totallength(sts_data0);
-       if (unlikely(index >= rds_ring->num_desc))
-               return;
-
-       cksum  = qlcnic_get_sts_status(sts_data0);
-       pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
-
-       skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
-       if (!skb)
-               return;
-
-       if (length > rds_ring->skb_size)
-               skb_put(skb, rds_ring->skb_size);
-       else
-               skb_put(skb, length);
-
-       if (pkt_offset)
-               skb_pull(skb, pkt_offset);
-
-       if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
-               adapter->diag_cnt++;
-       else
-               dump_skb(skb, adapter);
-
-       dev_kfree_skb_any(skb);
-       adapter->stats.rx_pkts++;
-       adapter->stats.rxbytes += length;
-
-       return;
-}
-
-void
-qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
-{
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-       struct status_desc *desc;
-       u64 sts_data0;
-       int ring, opcode, desc_cnt;
-
-       u32 consumer = sds_ring->consumer;
-
-       desc = &sds_ring->desc_head[consumer];
-       sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
-
-       if (!(sts_data0 & STATUS_OWNER_HOST))
-               return;
-
-       desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
-       opcode = qlcnic_get_sts_opcode(sts_data0);
-       switch (opcode) {
-       case QLCNIC_RESPONSE_DESC:
-               qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
-               break;
-       default:
-               ring = qlcnic_get_sts_type(sts_data0);
-               qlcnic_process_rcv_diag(adapter, sds_ring, ring, sts_data0);
-               break;
-       }
-
-       for (; desc_cnt > 0; desc_cnt--) {
-               desc = &sds_ring->desc_head[consumer];
-               desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
-               consumer = get_next_index(consumer, sds_ring->num_desc);
-       }
-
-       sds_ring->consumer = consumer;
-       writel(consumer, sds_ring->crb_sts_consumer);
-}
-
-void
-qlcnic_fetch_mac(struct qlcnic_adapter *adapter, u32 off1, u32 off2,
-                       u8 alt_mac, u8 *mac)
-{
-       u32 mac_low, mac_high;
-       int i;
-
-       mac_low = off1;
-       mac_high = off2;
-
-       if (alt_mac) {
-               mac_low |= (mac_low >> 16) | (mac_high << 16);
-               mac_high >>= 16;
-       }
-
-       for (i = 0; i < 2; i++)
-               mac[i] = (u8)(mac_high >> ((1 - i) * 8));
-       for (i = 2; i < 6; i++)
-               mac[i] = (u8)(mac_low >> ((5 - i) * 8));
-}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c
new file mode 100644 (file)
index 0000000..6f82812
--- /dev/null
@@ -0,0 +1,1309 @@
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+
+#include "qlcnic.h"
+
+#define QLCNIC_MAC_HASH(MAC)\
+       ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
+
+#define TX_ETHER_PKT   0x01
+#define TX_TCP_PKT     0x02
+#define TX_UDP_PKT     0x03
+#define TX_IP_PKT      0x04
+#define TX_TCP_LSO     0x05
+#define TX_TCP_LSO6    0x06
+#define TX_TCPV6_PKT   0x0b
+#define TX_UDPV6_PKT   0x0c
+#define FLAGS_VLAN_TAGGED      0x10
+#define FLAGS_VLAN_OOB         0x40
+
+#define qlcnic_set_tx_vlan_tci(cmd_desc, v)    \
+       (cmd_desc)->vlan_TCI = cpu_to_le16(v);
+#define qlcnic_set_cmd_desc_port(cmd_desc, var)        \
+       ((cmd_desc)->port_ctxid |= ((var) & 0x0F))
+#define qlcnic_set_cmd_desc_ctxid(cmd_desc, var)       \
+       ((cmd_desc)->port_ctxid |= ((var) << 4 & 0xF0))
+
+#define qlcnic_set_tx_port(_desc, _port) \
+       ((_desc)->port_ctxid = ((_port) & 0xf) | (((_port) << 4) & 0xf0))
+
+#define qlcnic_set_tx_flags_opcode(_desc, _flags, _opcode) \
+       ((_desc)->flags_opcode |= \
+       cpu_to_le16(((_flags) & 0x7f) | (((_opcode) & 0x3f) << 7)))
+
+#define qlcnic_set_tx_frags_len(_desc, _frags, _len) \
+       ((_desc)->nfrags__length = \
+       cpu_to_le32(((_frags) & 0xff) | (((_len) & 0xffffff) << 8)))
+
+/* owner bits of status_desc */
+#define STATUS_OWNER_HOST      (0x1ULL << 56)
+#define STATUS_OWNER_PHANTOM   (0x2ULL << 56)
+
+/* Status descriptor:
+   0-3 port, 4-7 status, 8-11 type, 12-27 total_length
+   28-43 reference_handle, 44-47 protocol, 48-52 pkt_offset
+   53-55 desc_cnt, 56-57 owner, 58-63 opcode
+ */
+#define qlcnic_get_sts_port(sts_data)  \
+       ((sts_data) & 0x0F)
+#define qlcnic_get_sts_status(sts_data)        \
+       (((sts_data) >> 4) & 0x0F)
+#define qlcnic_get_sts_type(sts_data)  \
+       (((sts_data) >> 8) & 0x0F)
+#define qlcnic_get_sts_totallength(sts_data)   \
+       (((sts_data) >> 12) & 0xFFFF)
+#define qlcnic_get_sts_refhandle(sts_data)     \
+       (((sts_data) >> 28) & 0xFFFF)
+#define qlcnic_get_sts_prot(sts_data)  \
+       (((sts_data) >> 44) & 0x0F)
+#define qlcnic_get_sts_pkt_offset(sts_data)    \
+       (((sts_data) >> 48) & 0x1F)
+#define qlcnic_get_sts_desc_cnt(sts_data)      \
+       (((sts_data) >> 53) & 0x7)
+#define qlcnic_get_sts_opcode(sts_data)        \
+       (((sts_data) >> 58) & 0x03F)
+
+#define qlcnic_get_lro_sts_refhandle(sts_data)         \
+       ((sts_data) & 0x07FFF)
+#define qlcnic_get_lro_sts_length(sts_data)    \
+       (((sts_data) >> 16) & 0x0FFFF)
+#define qlcnic_get_lro_sts_l2_hdr_offset(sts_data)     \
+       (((sts_data) >> 32) & 0x0FF)
+#define qlcnic_get_lro_sts_l4_hdr_offset(sts_data)     \
+       (((sts_data) >> 40) & 0x0FF)
+#define qlcnic_get_lro_sts_timestamp(sts_data) \
+       (((sts_data) >> 48) & 0x1)
+#define qlcnic_get_lro_sts_type(sts_data)      \
+       (((sts_data) >> 49) & 0x7)
+#define qlcnic_get_lro_sts_push_flag(sts_data)         \
+       (((sts_data) >> 52) & 0x1)
+#define qlcnic_get_lro_sts_seq_number(sts_data)                \
+       ((sts_data) & 0x0FFFFFFFF)
+#define qlcnic_get_lro_sts_mss(sts_data1)              \
+       ((sts_data1 >> 32) & 0x0FFFF)
+
+/* opcode field in status_desc */
+#define QLCNIC_SYN_OFFLOAD     0x03
+#define QLCNIC_RXPKT_DESC      0x04
+#define QLCNIC_OLD_RXPKT_DESC  0x3f
+#define QLCNIC_RESPONSE_DESC   0x05
+#define QLCNIC_LRO_DESC        0x12
+
+/* for status field in status_desc */
+#define STATUS_CKSUM_LOOP      0
+#define STATUS_CKSUM_OK                2
+
+static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
+                                u64 uaddr, __le16 vlan_id,
+                                struct qlcnic_host_tx_ring *tx_ring)
+{
+       struct cmd_desc_type0 *hwdesc;
+       struct qlcnic_nic_req *req;
+       struct qlcnic_mac_req *mac_req;
+       struct qlcnic_vlan_req *vlan_req;
+       u32 producer;
+       u64 word;
+
+       producer = tx_ring->producer;
+       hwdesc = &tx_ring->desc_head[tx_ring->producer];
+
+       req = (struct qlcnic_nic_req *)hwdesc;
+       memset(req, 0, sizeof(struct qlcnic_nic_req));
+       req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
+
+       word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
+       req->req_hdr = cpu_to_le64(word);
+
+       mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
+       mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
+       memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+
+       vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
+       vlan_req->vlan_id = vlan_id;
+
+       tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
+       smp_mb();
+}
+
+static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
+                              struct qlcnic_host_tx_ring *tx_ring,
+                              struct cmd_desc_type0 *first_desc,
+                              struct sk_buff *skb)
+{
+       struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+       struct qlcnic_filter *fil, *tmp_fil;
+       struct hlist_node *tmp_hnode, *n;
+       struct hlist_head *head;
+       u64 src_addr = 0;
+       __le16 vlan_id = 0;
+       u8 hindex;
+
+       if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
+               return;
+
+       if (adapter->fhash.fnum >= adapter->fhash.fmax)
+               return;
+
+       /* Only NPAR capable devices support vlan based learning*/
+       if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+               vlan_id = first_desc->vlan_TCI;
+       memcpy(&src_addr, phdr->h_source, ETH_ALEN);
+       hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
+       head = &(adapter->fhash.fhead[hindex]);
+
+       hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+               if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
+                           tmp_fil->vlan_id == vlan_id) {
+
+                       if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
+                               qlcnic_change_filter(adapter, src_addr, vlan_id,
+                                                    tx_ring);
+                       tmp_fil->ftime = jiffies;
+                       return;
+               }
+       }
+
+       fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
+       if (!fil)
+               return;
+
+       qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+
+       fil->ftime = jiffies;
+       fil->vlan_id = vlan_id;
+       memcpy(fil->faddr, &src_addr, ETH_ALEN);
+
+       spin_lock(&adapter->mac_learn_lock);
+
+       hlist_add_head(&(fil->fnode), head);
+       adapter->fhash.fnum++;
+
+       spin_unlock(&adapter->mac_learn_lock);
+}
+
+static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
+                        struct cmd_desc_type0 *first_desc, struct sk_buff *skb)
+{
+       u8 l4proto, opcode = 0, hdr_len = 0;
+       u16 flags = 0, vlan_tci = 0;
+       int copied, offset, copy_len, size;
+       struct cmd_desc_type0 *hwdesc;
+       struct vlan_ethhdr *vh;
+       struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+       u16 protocol = ntohs(skb->protocol);
+       u32 producer = tx_ring->producer;
+
+       if (protocol == ETH_P_8021Q) {
+               vh = (struct vlan_ethhdr *)skb->data;
+               flags = FLAGS_VLAN_TAGGED;
+               vlan_tci = ntohs(vh->h_vlan_TCI);
+               protocol = ntohs(vh->h_vlan_encapsulated_proto);
+       } else if (vlan_tx_tag_present(skb)) {
+               flags = FLAGS_VLAN_OOB;
+               vlan_tci = vlan_tx_tag_get(skb);
+       }
+       if (unlikely(adapter->pvid)) {
+               if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
+                       return -EIO;
+               if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
+                       goto set_flags;
+
+               flags = FLAGS_VLAN_OOB;
+               vlan_tci = adapter->pvid;
+       }
+set_flags:
+       qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
+       qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+
+       if (*(skb->data) & BIT_0) {
+               flags |= BIT_0;
+               memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
+       }
+       opcode = TX_ETHER_PKT;
+       if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
+           skb_shinfo(skb)->gso_size > 0) {
+               hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
+               first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
+               first_desc->total_hdr_length = hdr_len;
+               opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
+
+               /* For LSO, we need to copy the MAC/IP/TCP headers into
+               * the descriptor ring */
+               copied = 0;
+               offset = 2;
+
+               if (flags & FLAGS_VLAN_OOB) {
+                       first_desc->total_hdr_length += VLAN_HLEN;
+                       first_desc->tcp_hdr_offset = VLAN_HLEN;
+                       first_desc->ip_hdr_offset = VLAN_HLEN;
+
+                       /* Only in case of TSO on vlan device */
+                       flags |= FLAGS_VLAN_TAGGED;
+
+                       /* Create a TSO vlan header template for firmware */
+                       hwdesc = &tx_ring->desc_head[producer];
+                       tx_ring->cmd_buf_arr[producer].skb = NULL;
+
+                       copy_len = min((int)sizeof(struct cmd_desc_type0) -
+                                      offset, hdr_len + VLAN_HLEN);
+
+                       vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
+                       skb_copy_from_linear_data(skb, vh, 12);
+                       vh->h_vlan_proto = htons(ETH_P_8021Q);
+                       vh->h_vlan_TCI = htons(vlan_tci);
+
+                       skb_copy_from_linear_data_offset(skb, 12,
+                                                        (char *)vh + 16,
+                                                        copy_len - 16);
+                       copied = copy_len - VLAN_HLEN;
+                       offset = 0;
+                       producer = get_next_index(producer, tx_ring->num_desc);
+               }
+
+               while (copied < hdr_len) {
+                       size = (int)sizeof(struct cmd_desc_type0) - offset;
+                       copy_len = min(size, (hdr_len - copied));
+                       hwdesc = &tx_ring->desc_head[producer];
+                       tx_ring->cmd_buf_arr[producer].skb = NULL;
+                       skb_copy_from_linear_data_offset(skb, copied,
+                                                        (char *)hwdesc +
+                                                        offset, copy_len);
+                       copied += copy_len;
+                       offset = 0;
+                       producer = get_next_index(producer, tx_ring->num_desc);
+               }
+
+               tx_ring->producer = producer;
+               smp_mb();
+               adapter->stats.lso_frames++;
+
+       } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               if (protocol == ETH_P_IP) {
+                       l4proto = ip_hdr(skb)->protocol;
+
+                       if (l4proto == IPPROTO_TCP)
+                               opcode = TX_TCP_PKT;
+                       else if (l4proto == IPPROTO_UDP)
+                               opcode = TX_UDP_PKT;
+               } else if (protocol == ETH_P_IPV6) {
+                       l4proto = ipv6_hdr(skb)->nexthdr;
+
+                       if (l4proto == IPPROTO_TCP)
+                               opcode = TX_TCPV6_PKT;
+                       else if (l4proto == IPPROTO_UDP)
+                               opcode = TX_UDPV6_PKT;
+               }
+       }
+       first_desc->tcp_hdr_offset += skb_transport_offset(skb);
+       first_desc->ip_hdr_offset += skb_network_offset(skb);
+       qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+
+       return 0;
+}
+
+static int qlcnic_map_tx_skb(struct pci_dev *pdev, struct sk_buff *skb,
+                            struct qlcnic_cmd_buffer *pbuf)
+{
+       struct qlcnic_skb_frag *nf;
+       struct skb_frag_struct *frag;
+       int i, nr_frags;
+       dma_addr_t map;
+
+       nr_frags = skb_shinfo(skb)->nr_frags;
+       nf = &pbuf->frag_array[0];
+
+       map = pci_map_single(pdev, skb->data, skb_headlen(skb),
+                            PCI_DMA_TODEVICE);
+       if (pci_dma_mapping_error(pdev, map))
+               goto out_err;
+
+       nf->dma = map;
+       nf->length = skb_headlen(skb);
+
+       for (i = 0; i < nr_frags; i++) {
+               frag = &skb_shinfo(skb)->frags[i];
+               nf = &pbuf->frag_array[i+1];
+               map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
+                                      DMA_TO_DEVICE);
+               if (dma_mapping_error(&pdev->dev, map))
+                       goto unwind;
+
+               nf->dma = map;
+               nf->length = skb_frag_size(frag);
+       }
+
+       return 0;
+
+unwind:
+       while (--i >= 0) {
+               nf = &pbuf->frag_array[i+1];
+               pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+       }
+
+       nf = &pbuf->frag_array[0];
+       pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+
+out_err:
+       return -ENOMEM;
+}
+
+static void qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
+                                struct qlcnic_cmd_buffer *pbuf)
+{
+       struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
+       int i, nr_frags = skb_shinfo(skb)->nr_frags;
+
+       for (i = 0; i < nr_frags; i++) {
+               nf = &pbuf->frag_array[i+1];
+               pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+       }
+
+       nf = &pbuf->frag_array[0];
+       pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+       pbuf->skb = NULL;
+}
+
+static inline void qlcnic_clear_cmddesc(u64 *desc)
+{
+       desc[0] = 0ULL;
+       desc[2] = 0ULL;
+       desc[7] = 0ULL;
+}
+
+netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+{
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+       struct qlcnic_cmd_buffer *pbuf;
+       struct qlcnic_skb_frag *buffrag;
+       struct cmd_desc_type0 *hwdesc, *first_desc;
+       struct pci_dev *pdev;
+       struct ethhdr *phdr;
+       int i, k, frag_count, delta = 0;
+       u32 producer, num_txd;
+
+       num_txd = tx_ring->num_desc;
+
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+               netif_stop_queue(netdev);
+               return NETDEV_TX_BUSY;
+       }
+
+       if (adapter->flags & QLCNIC_MACSPOOF) {
+               phdr = (struct ethhdr *)skb->data;
+               if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
+                       goto drop_packet;
+       }
+
+       frag_count = skb_shinfo(skb)->nr_frags + 1;
+       /* 14 frags supported for normal packet and
+        * 32 frags supported for TSO packet
+        */
+       if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
+               for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
+                       delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
+
+               if (!__pskb_pull_tail(skb, delta))
+                       goto drop_packet;
+
+               frag_count = 1 + skb_shinfo(skb)->nr_frags;
+       }
+
+       if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
+               netif_stop_queue(netdev);
+               if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
+                       netif_start_queue(netdev);
+               } else {
+                       adapter->stats.xmit_off++;
+                       return NETDEV_TX_BUSY;
+               }
+       }
+
+       producer = tx_ring->producer;
+       pbuf = &tx_ring->cmd_buf_arr[producer];
+       pdev = adapter->pdev;
+       first_desc = &tx_ring->desc_head[producer];
+       hwdesc = &tx_ring->desc_head[producer];
+       qlcnic_clear_cmddesc((u64 *)hwdesc);
+
+       if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
+               adapter->stats.tx_dma_map_error++;
+               goto drop_packet;
+       }
+
+       pbuf->skb = skb;
+       pbuf->frag_count = frag_count;
+
+       qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
+       qlcnic_set_tx_port(first_desc, adapter->portnum);
+
+       for (i = 0; i < frag_count; i++) {
+               k = i % 4;
+
+               if ((k == 0) && (i > 0)) {
+                       /* move to next desc.*/
+                       producer = get_next_index(producer, num_txd);
+                       hwdesc = &tx_ring->desc_head[producer];
+                       qlcnic_clear_cmddesc((u64 *)hwdesc);
+                       tx_ring->cmd_buf_arr[producer].skb = NULL;
+               }
+
+               buffrag = &pbuf->frag_array[i];
+               hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
+               switch (k) {
+               case 0:
+                       hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
+                       break;
+               case 1:
+                       hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
+                       break;
+               case 2:
+                       hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
+                       break;
+               case 3:
+                       hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
+                       break;
+               }
+       }
+
+       tx_ring->producer = get_next_index(producer, num_txd);
+       smp_mb();
+
+       if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
+               goto unwind_buff;
+
+       if (adapter->mac_learn)
+               qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
+
+       adapter->stats.txbytes += skb->len;
+       adapter->stats.xmitcalled++;
+
+       qlcnic_update_cmd_producer(tx_ring);
+
+       return NETDEV_TX_OK;
+
+unwind_buff:
+       qlcnic_unmap_buffers(pdev, skb, pbuf);
+drop_packet:
+       adapter->stats.txdropped++;
+       dev_kfree_skb_any(skb);
+       return NETDEV_TX_OK;
+}
+
+void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
+{
+       struct net_device *netdev = adapter->netdev;
+
+       if (adapter->ahw->linkup && !linkup) {
+               netdev_info(netdev, "NIC Link is down\n");
+               adapter->ahw->linkup = 0;
+               if (netif_running(netdev)) {
+                       netif_carrier_off(netdev);
+                       netif_stop_queue(netdev);
+               }
+       } else if (!adapter->ahw->linkup && linkup) {
+               netdev_info(netdev, "NIC Link is up\n");
+               adapter->ahw->linkup = 1;
+               if (netif_running(netdev)) {
+                       netif_carrier_on(netdev);
+                       netif_wake_queue(netdev);
+               }
+       }
+}
+
+static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter,
+                              struct qlcnic_host_rds_ring *rds_ring,
+                              struct qlcnic_rx_buffer *buffer)
+{
+       struct sk_buff *skb;
+       dma_addr_t dma;
+       struct pci_dev *pdev = adapter->pdev;
+
+       skb = netdev_alloc_skb(adapter->netdev, rds_ring->skb_size);
+       if (!skb) {
+               adapter->stats.skb_alloc_failure++;
+               return -ENOMEM;
+       }
+
+       skb_reserve(skb, NET_IP_ALIGN);
+       dma = pci_map_single(pdev, skb->data, rds_ring->dma_size,
+                            PCI_DMA_FROMDEVICE);
+
+       if (pci_dma_mapping_error(pdev, dma)) {
+               adapter->stats.rx_dma_map_error++;
+               dev_kfree_skb_any(skb);
+               return -ENOMEM;
+       }
+
+       buffer->skb = skb;
+       buffer->dma = dma;
+
+       return 0;
+}
+
+static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
+                                        struct qlcnic_host_rds_ring *rds_ring)
+{
+       struct rcv_desc *pdesc;
+       struct qlcnic_rx_buffer *buffer;
+       int  count = 0;
+       uint32_t producer;
+       struct list_head *head;
+
+       if (!spin_trylock(&rds_ring->lock))
+               return;
+
+       producer = rds_ring->producer;
+       head = &rds_ring->free_list;
+
+       while (!list_empty(head)) {
+               buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
+
+               if (!buffer->skb) {
+                       if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
+                               break;
+               }
+
+               count++;
+               list_del(&buffer->list);
+
+               /* make a rcv descriptor  */
+               pdesc = &rds_ring->desc_head[producer];
+               pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+               pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+               pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+               producer = get_next_index(producer, rds_ring->num_desc);
+       }
+
+       if (count) {
+               rds_ring->producer = producer;
+               writel((producer - 1) & (rds_ring->num_desc - 1),
+                      rds_ring->crb_rcv_producer);
+       }
+
+       spin_unlock(&rds_ring->lock);
+}
+
+static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
+{
+       u32 sw_consumer, hw_consumer;
+       int i, done, count = 0;
+       struct qlcnic_cmd_buffer *buffer;
+       struct pci_dev *pdev = adapter->pdev;
+       struct net_device *netdev = adapter->netdev;
+       struct qlcnic_skb_frag *frag;
+       struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
+
+       if (!spin_trylock(&adapter->tx_clean_lock))
+               return 1;
+
+       sw_consumer = tx_ring->sw_consumer;
+       hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+
+       while (sw_consumer != hw_consumer) {
+               buffer = &tx_ring->cmd_buf_arr[sw_consumer];
+               if (buffer->skb) {
+                       frag = &buffer->frag_array[0];
+                       pci_unmap_single(pdev, frag->dma, frag->length,
+                                        PCI_DMA_TODEVICE);
+                       frag->dma = 0ULL;
+                       for (i = 1; i < buffer->frag_count; i++) {
+                               frag++;
+                               pci_unmap_page(pdev, frag->dma, frag->length,
+                                              PCI_DMA_TODEVICE);
+                               frag->dma = 0ULL;
+                       }
+
+                       adapter->stats.xmitfinished++;
+                       dev_kfree_skb_any(buffer->skb);
+                       buffer->skb = NULL;
+               }
+
+               sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
+               if (++count >= MAX_STATUS_HANDLE)
+                       break;
+       }
+
+       if (count && netif_running(netdev)) {
+               tx_ring->sw_consumer = sw_consumer;
+
+               smp_mb();
+
+               if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
+                       if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
+                               netif_wake_queue(netdev);
+                               adapter->stats.xmit_on++;
+                       }
+               }
+               adapter->tx_timeo_cnt = 0;
+       }
+       /*
+        * If everything is freed up to consumer then check if the ring is full
+        * If the ring is full then check if more needs to be freed and
+        * schedule the call back again.
+        *
+        * This happens when there are 2 CPUs. One could be freeing and the
+        * other filling it. If the ring is full when we get out of here and
+        * the card has already interrupted the host then the host can miss the
+        * interrupt.
+        *
+        * There is still a possible race condition and the host could miss an
+        * interrupt. The card has to take care of this.
+        */
+       hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
+       done = (sw_consumer == hw_consumer);
+
+       spin_unlock(&adapter->tx_clean_lock);
+
+       return done;
+}
+
+static int qlcnic_poll(struct napi_struct *napi, int budget)
+{
+       struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_adapter *adapter;
+       int tx_complete, work_done;
+
+       sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
+       adapter = sds_ring->adapter;
+
+       tx_complete = qlcnic_process_cmd_ring(adapter);
+       work_done = qlcnic_process_rcv_ring(sds_ring, budget);
+
+       if ((work_done < budget) && tx_complete) {
+               napi_complete(&sds_ring->napi);
+               if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+                       qlcnic_enable_int(sds_ring);
+       }
+
+       return work_done;
+}
+
+static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
+{
+       struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_adapter *adapter;
+       int work_done;
+
+       sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi);
+       adapter = sds_ring->adapter;
+
+       work_done = qlcnic_process_rcv_ring(sds_ring, budget);
+
+       if (work_done < budget) {
+               napi_complete(&sds_ring->napi);
+               if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
+                       qlcnic_enable_int(sds_ring);
+       }
+
+       return work_done;
+}
+
+static void qlcnic_handle_linkevent(struct qlcnic_adapter *adapter,
+                                   struct qlcnic_fw_msg *msg)
+{
+       u32 cable_OUI;
+       u16 cable_len, link_speed;
+       u8  link_status, module, duplex, autoneg, lb_status = 0;
+       struct net_device *netdev = adapter->netdev;
+
+       adapter->ahw->has_link_events = 1;
+
+       cable_OUI = msg->body[1] & 0xffffffff;
+       cable_len = (msg->body[1] >> 32) & 0xffff;
+       link_speed = (msg->body[1] >> 48) & 0xffff;
+
+       link_status = msg->body[2] & 0xff;
+       duplex = (msg->body[2] >> 16) & 0xff;
+       autoneg = (msg->body[2] >> 24) & 0xff;
+       lb_status = (msg->body[2] >> 32) & 0x3;
+
+       module = (msg->body[2] >> 8) & 0xff;
+       if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE)
+               dev_info(&netdev->dev,
+                        "unsupported cable: OUI 0x%x, length %d\n",
+                        cable_OUI, cable_len);
+       else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN)
+               dev_info(&netdev->dev, "unsupported cable length %d\n",
+                        cable_len);
+
+       if (!link_status && (lb_status == QLCNIC_ILB_MODE ||
+           lb_status == QLCNIC_ELB_MODE))
+               adapter->ahw->loopback_state |= QLCNIC_LINKEVENT;
+
+       qlcnic_advert_link_change(adapter, link_status);
+
+       if (duplex == LINKEVENT_FULL_DUPLEX)
+               adapter->ahw->link_duplex = DUPLEX_FULL;
+       else
+               adapter->ahw->link_duplex = DUPLEX_HALF;
+
+       adapter->ahw->module_type = module;
+       adapter->ahw->link_autoneg = autoneg;
+
+       if (link_status) {
+               adapter->ahw->link_speed = link_speed;
+       } else {
+               adapter->ahw->link_speed = SPEED_UNKNOWN;
+               adapter->ahw->link_duplex = DUPLEX_UNKNOWN;
+       }
+}
+
+static void qlcnic_handle_fw_message(int desc_cnt, int index,
+                                    struct qlcnic_host_sds_ring *sds_ring)
+{
+       struct qlcnic_fw_msg msg;
+       struct status_desc *desc;
+       struct qlcnic_adapter *adapter;
+       struct device *dev;
+       int i = 0, opcode, ret;
+
+       while (desc_cnt > 0 && i < 8) {
+               desc = &sds_ring->desc_head[index];
+               msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]);
+               msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]);
+
+               index = get_next_index(index, sds_ring->num_desc);
+               desc_cnt--;
+       }
+
+       adapter = sds_ring->adapter;
+       dev = &adapter->pdev->dev;
+       opcode = qlcnic_get_nic_msg_opcode(msg.body[0]);
+
+       switch (opcode) {
+       case QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE:
+               qlcnic_handle_linkevent(adapter, &msg);
+               break;
+       case QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK:
+               ret = (u32)(msg.body[1]);
+               switch (ret) {
+               case 0:
+                       adapter->ahw->loopback_state |= QLCNIC_LB_RESPONSE;
+                       break;
+               case 1:
+                       dev_info(dev, "loopback already in progress\n");
+                       adapter->ahw->diag_cnt = -QLCNIC_TEST_IN_PROGRESS;
+                       break;
+               case 2:
+                       dev_info(dev, "loopback cable is not connected\n");
+                       adapter->ahw->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN;
+                       break;
+               default:
+                       dev_info(dev,
+                                "loopback configure request failed, err %x\n",
+                                ret);
+                       adapter->ahw->diag_cnt = -QLCNIC_UNDEFINED_ERROR;
+                       break;
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+static struct sk_buff *
+qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
+                    struct qlcnic_host_rds_ring *rds_ring, u16 index,
+                    u16 cksum)
+{
+       struct qlcnic_rx_buffer *buffer;
+       struct sk_buff *skb;
+
+       buffer = &rds_ring->rx_buf_arr[index];
+
+       if (unlikely(buffer->skb == NULL)) {
+               WARN_ON(1);
+               return NULL;
+       }
+
+       pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size,
+                        PCI_DMA_FROMDEVICE);
+
+       skb = buffer->skb;
+
+       if (likely((adapter->netdev->features & NETIF_F_RXCSUM) &&
+                  (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) {
+               adapter->stats.csummed++;
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+       } else {
+               skb_checksum_none_assert(skb);
+       }
+
+       buffer->skb = NULL;
+
+       return skb;
+}
+
+static inline int qlcnic_check_rx_tagging(struct qlcnic_adapter *adapter,
+                                         struct sk_buff *skb, u16 *vlan_tag)
+{
+       struct ethhdr *eth_hdr;
+
+       if (!__vlan_get_tag(skb, vlan_tag)) {
+               eth_hdr = (struct ethhdr *)skb->data;
+               memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2);
+               skb_pull(skb, VLAN_HLEN);
+       }
+       if (!adapter->pvid)
+               return 0;
+
+       if (*vlan_tag == adapter->pvid) {
+               /* Outer vlan tag. Packet should follow non-vlan path */
+               *vlan_tag = 0xffff;
+               return 0;
+       }
+       if (adapter->flags & QLCNIC_TAGGING_ENABLED)
+               return 0;
+
+       return -EINVAL;
+}
+
+static struct qlcnic_rx_buffer *
+qlcnic_process_rcv(struct qlcnic_adapter *adapter,
+                  struct qlcnic_host_sds_ring *sds_ring, int ring,
+                  u64 sts_data0)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+       struct qlcnic_rx_buffer *buffer;
+       struct sk_buff *skb;
+       struct qlcnic_host_rds_ring *rds_ring;
+       int index, length, cksum, pkt_offset;
+       u16 vid = 0xffff;
+
+       if (unlikely(ring >= adapter->max_rds_rings))
+               return NULL;
+
+       rds_ring = &recv_ctx->rds_rings[ring];
+
+       index = qlcnic_get_sts_refhandle(sts_data0);
+       if (unlikely(index >= rds_ring->num_desc))
+               return NULL;
+
+       buffer = &rds_ring->rx_buf_arr[index];
+       length = qlcnic_get_sts_totallength(sts_data0);
+       cksum  = qlcnic_get_sts_status(sts_data0);
+       pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+       skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+       if (!skb)
+               return buffer;
+
+       if (length > rds_ring->skb_size)
+               skb_put(skb, rds_ring->skb_size);
+       else
+               skb_put(skb, length);
+
+       if (pkt_offset)
+               skb_pull(skb, pkt_offset);
+
+       if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+               adapter->stats.rxdropped++;
+               dev_kfree_skb(skb);
+               return buffer;
+       }
+
+       skb->protocol = eth_type_trans(skb, netdev);
+
+       if (vid != 0xffff)
+               __vlan_hwaccel_put_tag(skb, vid);
+
+       napi_gro_receive(&sds_ring->napi, skb);
+
+       adapter->stats.rx_pkts++;
+       adapter->stats.rxbytes += length;
+
+       return buffer;
+}
+
+#define QLC_TCP_HDR_SIZE            20
+#define QLC_TCP_TS_OPTION_SIZE      12
+#define QLC_TCP_TS_HDR_SIZE         (QLC_TCP_HDR_SIZE + QLC_TCP_TS_OPTION_SIZE)
+
+static struct qlcnic_rx_buffer *
+qlcnic_process_lro(struct qlcnic_adapter *adapter,
+                  int ring, u64 sts_data0, u64 sts_data1)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+       struct qlcnic_rx_buffer *buffer;
+       struct sk_buff *skb;
+       struct qlcnic_host_rds_ring *rds_ring;
+       struct iphdr *iph;
+       struct tcphdr *th;
+       bool push, timestamp;
+       int index, l2_hdr_offset, l4_hdr_offset;
+       u16 lro_length, length, data_offset, vid = 0xffff;
+       u32 seq_number;
+
+       if (unlikely(ring > adapter->max_rds_rings))
+               return NULL;
+
+       rds_ring = &recv_ctx->rds_rings[ring];
+
+       index = qlcnic_get_lro_sts_refhandle(sts_data0);
+       if (unlikely(index > rds_ring->num_desc))
+               return NULL;
+
+       buffer = &rds_ring->rx_buf_arr[index];
+
+       timestamp = qlcnic_get_lro_sts_timestamp(sts_data0);
+       lro_length = qlcnic_get_lro_sts_length(sts_data0);
+       l2_hdr_offset = qlcnic_get_lro_sts_l2_hdr_offset(sts_data0);
+       l4_hdr_offset = qlcnic_get_lro_sts_l4_hdr_offset(sts_data0);
+       push = qlcnic_get_lro_sts_push_flag(sts_data0);
+       seq_number = qlcnic_get_lro_sts_seq_number(sts_data1);
+
+       skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK);
+       if (!skb)
+               return buffer;
+
+       if (timestamp)
+               data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE;
+       else
+               data_offset = l4_hdr_offset + QLC_TCP_HDR_SIZE;
+
+       skb_put(skb, lro_length + data_offset);
+       skb_pull(skb, l2_hdr_offset);
+
+       if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) {
+               adapter->stats.rxdropped++;
+               dev_kfree_skb(skb);
+               return buffer;
+       }
+
+       skb->protocol = eth_type_trans(skb, netdev);
+       iph = (struct iphdr *)skb->data;
+       th = (struct tcphdr *)(skb->data + (iph->ihl << 2));
+       length = (iph->ihl << 2) + (th->doff << 2) + lro_length;
+       iph->tot_len = htons(length);
+       iph->check = 0;
+       iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+       th->psh = push;
+       th->seq = htonl(seq_number);
+       length = skb->len;
+
+       if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP)
+               skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1);
+
+       if (vid != 0xffff)
+               __vlan_hwaccel_put_tag(skb, vid);
+       netif_receive_skb(skb);
+
+       adapter->stats.lro_pkts++;
+       adapter->stats.lrobytes += length;
+
+       return buffer;
+}
+
+int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max)
+{
+       struct qlcnic_host_rds_ring *rds_ring;
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
+       struct list_head *cur;
+       struct status_desc *desc;
+       struct qlcnic_rx_buffer *rxbuf;
+       u64 sts_data0, sts_data1;
+       __le64 owner_phantom = cpu_to_le64(STATUS_OWNER_PHANTOM);
+       int opcode, ring, desc_cnt, count = 0;
+       u32 consumer = sds_ring->consumer;
+
+       while (count < max) {
+               desc = &sds_ring->desc_head[consumer];
+               sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+               if (!(sts_data0 & STATUS_OWNER_HOST))
+                       break;
+
+               desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+               opcode = qlcnic_get_sts_opcode(sts_data0);
+
+               switch (opcode) {
+               case QLCNIC_RXPKT_DESC:
+               case QLCNIC_OLD_RXPKT_DESC:
+               case QLCNIC_SYN_OFFLOAD:
+                       ring = qlcnic_get_sts_type(sts_data0);
+                       rxbuf = qlcnic_process_rcv(adapter, sds_ring, ring,
+                                                  sts_data0);
+                       break;
+               case QLCNIC_LRO_DESC:
+                       ring = qlcnic_get_lro_sts_type(sts_data0);
+                       sts_data1 = le64_to_cpu(desc->status_desc_data[1]);
+                       rxbuf = qlcnic_process_lro(adapter, ring, sts_data0,
+                                                  sts_data1);
+                       break;
+               case QLCNIC_RESPONSE_DESC:
+                       qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+               default:
+                       goto skip;
+               }
+
+               WARN_ON(desc_cnt > 1);
+
+               if (likely(rxbuf))
+                       list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]);
+               else
+                       adapter->stats.null_rxbuf++;
+
+skip:
+               for (; desc_cnt > 0; desc_cnt--) {
+                       desc = &sds_ring->desc_head[consumer];
+                       desc->status_desc_data[0] = owner_phantom;
+                       consumer = get_next_index(consumer, sds_ring->num_desc);
+               }
+               count++;
+       }
+
+       for (ring = 0; ring < adapter->max_rds_rings; ring++) {
+               rds_ring = &adapter->recv_ctx->rds_rings[ring];
+
+               if (!list_empty(&sds_ring->free_list[ring])) {
+                       list_for_each(cur, &sds_ring->free_list[ring]) {
+                               rxbuf = list_entry(cur, struct qlcnic_rx_buffer,
+                                                  list);
+                               qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf);
+                       }
+                       spin_lock(&rds_ring->lock);
+                       list_splice_tail_init(&sds_ring->free_list[ring],
+                                             &rds_ring->free_list);
+                       spin_unlock(&rds_ring->lock);
+               }
+
+               qlcnic_post_rx_buffers_nodb(adapter, rds_ring);
+       }
+
+       if (count) {
+               sds_ring->consumer = consumer;
+               writel(consumer, sds_ring->crb_sts_consumer);
+       }
+
+       return count;
+}
+
+void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
+                           struct qlcnic_host_rds_ring *rds_ring)
+{
+       struct rcv_desc *pdesc;
+       struct qlcnic_rx_buffer *buffer;
+       int count = 0;
+       u32 producer;
+       struct list_head *head;
+
+       producer = rds_ring->producer;
+       head = &rds_ring->free_list;
+
+       while (!list_empty(head)) {
+
+               buffer = list_entry(head->next, struct qlcnic_rx_buffer, list);
+
+               if (!buffer->skb) {
+                       if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer))
+                               break;
+               }
+
+               count++;
+               list_del(&buffer->list);
+
+               /* make a rcv descriptor  */
+               pdesc = &rds_ring->desc_head[producer];
+               pdesc->addr_buffer = cpu_to_le64(buffer->dma);
+               pdesc->reference_handle = cpu_to_le16(buffer->ref_handle);
+               pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size);
+               producer = get_next_index(producer, rds_ring->num_desc);
+       }
+
+       if (count) {
+               rds_ring->producer = producer;
+               writel((producer-1) & (rds_ring->num_desc-1),
+                      rds_ring->crb_rcv_producer);
+       }
+}
+
+static void dump_skb(struct sk_buff *skb, struct qlcnic_adapter *adapter)
+{
+       int i;
+       unsigned char *data = skb->data;
+
+       pr_info(KERN_INFO "\n");
+       for (i = 0; i < skb->len; i++) {
+               QLCDB(adapter, DRV, "%02x ", data[i]);
+               if ((i & 0x0f) == 8)
+                       pr_info(KERN_INFO "\n");
+       }
+}
+
+static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring,
+                                   u64 sts_data0)
+{
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+       struct sk_buff *skb;
+       struct qlcnic_host_rds_ring *rds_ring;
+       int index, length, cksum, pkt_offset;
+
+       if (unlikely(ring >= adapter->max_rds_rings))
+               return;
+
+       rds_ring = &recv_ctx->rds_rings[ring];
+
+       index = qlcnic_get_sts_refhandle(sts_data0);
+       length = qlcnic_get_sts_totallength(sts_data0);
+       if (unlikely(index >= rds_ring->num_desc))
+               return;
+
+       cksum  = qlcnic_get_sts_status(sts_data0);
+       pkt_offset = qlcnic_get_sts_pkt_offset(sts_data0);
+
+       skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum);
+       if (!skb)
+               return;
+
+       if (length > rds_ring->skb_size)
+               skb_put(skb, rds_ring->skb_size);
+       else
+               skb_put(skb, length);
+
+       if (pkt_offset)
+               skb_pull(skb, pkt_offset);
+
+       if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr))
+               adapter->ahw->diag_cnt++;
+       else
+               dump_skb(skb, adapter);
+
+       dev_kfree_skb_any(skb);
+       adapter->stats.rx_pkts++;
+       adapter->stats.rxbytes += length;
+
+       return;
+}
+
+void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
+{
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
+       struct status_desc *desc;
+       u64 sts_data0;
+       int ring, opcode, desc_cnt;
+
+       u32 consumer = sds_ring->consumer;
+
+       desc = &sds_ring->desc_head[consumer];
+       sts_data0 = le64_to_cpu(desc->status_desc_data[0]);
+
+       if (!(sts_data0 & STATUS_OWNER_HOST))
+               return;
+
+       desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0);
+       opcode = qlcnic_get_sts_opcode(sts_data0);
+       switch (opcode) {
+       case QLCNIC_RESPONSE_DESC:
+               qlcnic_handle_fw_message(desc_cnt, consumer, sds_ring);
+               break;
+       default:
+               ring = qlcnic_get_sts_type(sts_data0);
+               qlcnic_process_rcv_diag(adapter, ring, sts_data0);
+               break;
+       }
+
+       for (; desc_cnt > 0; desc_cnt--) {
+               desc = &sds_ring->desc_head[consumer];
+               desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM);
+               consumer = get_next_index(consumer, sds_ring->num_desc);
+       }
+
+       sds_ring->consumer = consumer;
+       writel(consumer, sds_ring->crb_sts_consumer);
+}
+
+void qlcnic_fetch_mac(u32 off1, u32 off2, u8 alt_mac, u8 *mac)
+{
+       u32 mac_low, mac_high;
+       int i;
+
+       mac_low = off1;
+       mac_high = off2;
+
+       if (alt_mac) {
+               mac_low |= (mac_low >> 16) | (mac_high << 16);
+               mac_high >>= 16;
+       }
+
+       for (i = 0; i < 2; i++)
+               mac[i] = (u8)(mac_high >> ((1 - i) * 8));
+       for (i = 2; i < 6; i++)
+               mac[i] = (u8)(mac_low >> ((5 - i) * 8));
+}
+
+int qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
+{
+       int ring, max_sds_rings;
+       struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+       if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
+               return -ENOMEM;
+
+       max_sds_rings = adapter->max_sds_rings;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+
+               if (ring == max_sds_rings - 1)
+                       netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll,
+                                      QLCNIC_NETDEV_WEIGHT / max_sds_rings);
+               else
+                       netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll,
+                                      QLCNIC_NETDEV_WEIGHT*2);
+       }
+
+       return 0;
+}
+
+void qlcnic_napi_del(struct qlcnic_adapter *adapter)
+{
+       int ring;
+       struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               netif_napi_del(&sds_ring->napi);
+       }
+
+       qlcnic_free_sds_rings(adapter->recv_ctx);
+}
+
+void qlcnic_napi_enable(struct qlcnic_adapter *adapter)
+{
+       int ring;
+       struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+               return;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               napi_enable(&sds_ring->napi);
+               qlcnic_enable_int(sds_ring);
+       }
+}
+
+void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
+{
+       int ring;
+       struct qlcnic_host_sds_ring *sds_ring;
+       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
+
+       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
+               return;
+
+       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
+               sds_ring = &recv_ctx->sds_rings[ring];
+               qlcnic_disable_int(sds_ring);
+               napi_synchronize(&sds_ring->napi);
+               napi_disable(&sds_ring->napi);
+       }
+}
index 24ad17ec7fcde46a6f11491873546f8ffbb3cef2..a7554d9aab0cc2b5a7804fcd3e97ac6b4da01182 100644 (file)
@@ -34,29 +34,28 @@ static int qlcnic_mac_learn;
 module_param(qlcnic_mac_learn, int, 0444);
 MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
 
-static int use_msi = 1;
-module_param(use_msi, int, 0444);
+static int qlcnic_use_msi = 1;
 MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
+module_param_named(use_msi, qlcnic_use_msi, int, 0444);
 
-static int use_msi_x = 1;
-module_param(use_msi_x, int, 0444);
+static int qlcnic_use_msi_x = 1;
 MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
+module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444);
 
-static int auto_fw_reset = 1;
-module_param(auto_fw_reset, int, 0644);
+static int qlcnic_auto_fw_reset = 1;
 MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
+module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644);
 
-static int load_fw_file;
-module_param(load_fw_file, int, 0444);
+static int qlcnic_load_fw_file;
 MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file");
+module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444);
 
 static int qlcnic_config_npars;
 module_param(qlcnic_config_npars, int, 0444);
 MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled");
 
-static int __devinit qlcnic_probe(struct pci_dev *pdev,
-               const struct pci_device_id *ent);
-static void __devexit qlcnic_remove(struct pci_dev *pdev);
+static int qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
+static void qlcnic_remove(struct pci_dev *pdev);
 static int qlcnic_open(struct net_device *netdev);
 static int qlcnic_close(struct net_device *netdev);
 static void qlcnic_tx_timeout(struct net_device *netdev);
@@ -66,17 +65,10 @@ static void qlcnic_fw_poll_work(struct work_struct *work);
 static void qlcnic_schedule_work(struct qlcnic_adapter *adapter,
                work_func_t func, int delay);
 static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter);
-static int qlcnic_poll(struct napi_struct *napi, int budget);
-static int qlcnic_rx_poll(struct napi_struct *napi, int budget);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void qlcnic_poll_controller(struct net_device *netdev);
 #endif
 
-static void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
-static void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
-
 static void qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding);
 static void qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8);
 static int qlcnic_can_start_firmware(struct qlcnic_adapter *adapter);
@@ -92,14 +84,15 @@ static int qlcnic_start_firmware(struct qlcnic_adapter *);
 
 static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
 static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
-static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
-static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
 static int qlcnicvf_start_firmware(struct qlcnic_adapter *);
 static void qlcnic_set_netdev_features(struct qlcnic_adapter *,
                                struct qlcnic_esw_func_cfg *);
 static int qlcnic_vlan_rx_add(struct net_device *, u16);
 static int qlcnic_vlan_rx_del(struct net_device *, u16);
 
+#define QLCNIC_IS_TSO_CAPABLE(adapter) \
+       ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+
 /*  PCI Device ID Table  */
 #define ENTRY(device) \
        {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \
@@ -115,9 +108,7 @@ static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = {
 MODULE_DEVICE_TABLE(pci, qlcnic_pci_tbl);
 
 
-inline void
-qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_tx_ring *tx_ring)
+inline void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *tx_ring)
 {
        writel(tx_ring->producer, tx_ring->crb_cmd_producer);
 }
@@ -129,26 +120,34 @@ static const u32 msi_tgt_status[8] = {
        ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
 };
 
-static const
-struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
-
-static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
-{
-       writel(0, sds_ring->crb_intr_mask);
-}
-
-static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
-{
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
+static const struct qlcnic_board_info qlcnic_boards[] = {
+       {0x1077, 0x8020, 0x1077, 0x203,
+        "8200 Series Single Port 10GbE Converged Network Adapter"
+        "(TCP/IP Networking)"},
+       {0x1077, 0x8020, 0x1077, 0x207,
+        "8200 Series Dual Port 10GbE Converged Network Adapter"
+        "(TCP/IP Networking)"},
+       {0x1077, 0x8020, 0x1077, 0x20b,
+        "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"},
+       {0x1077, 0x8020, 0x1077, 0x20c,
+        "3200 Series Quad Port 1Gb Intelligent Ethernet Adapter"},
+       {0x1077, 0x8020, 0x1077, 0x20f,
+        "3200 Series Single Port 10Gb Intelligent Ethernet Adapter"},
+       {0x1077, 0x8020, 0x103c, 0x3733,
+        "NC523SFP 10Gb 2-port Server Adapter"},
+       {0x1077, 0x8020, 0x103c, 0x3346,
+        "CN1000Q Dual Port Converged Network Adapter"},
+       {0x1077, 0x8020, 0x1077, 0x210,
+        "QME8242-k 10GbE Dual Port Mezzanine Card"},
+       {0x1077, 0x8020, 0x0, 0x0, "cLOM8214 1/10GbE Controller"},
+};
 
-       writel(0x1, sds_ring->crb_intr_mask);
+#define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards)
 
-       if (!QLCNIC_IS_MSI_FAMILY(adapter))
-               writel(0xfbff, adapter->tgt_mask_reg);
-}
+static const
+struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG;
 
-static int
-qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
+int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
 {
        int size = sizeof(struct qlcnic_host_sds_ring) * count;
 
@@ -157,8 +156,7 @@ qlcnic_alloc_sds_rings(struct qlcnic_recv_context *recv_ctx, int count)
        return recv_ctx->sds_rings == NULL;
 }
 
-static void
-qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
+void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
 {
        if (recv_ctx->sds_rings != NULL)
                kfree(recv_ctx->sds_rings);
@@ -166,80 +164,6 @@ qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
        recv_ctx->sds_rings = NULL;
 }
 
-static int
-qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
-{
-       int ring;
-       struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-       if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings))
-               return -ENOMEM;
-
-       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-               sds_ring = &recv_ctx->sds_rings[ring];
-
-               if (ring == adapter->max_sds_rings - 1)
-                       netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll,
-                               QLCNIC_NETDEV_WEIGHT/adapter->max_sds_rings);
-               else
-                       netif_napi_add(netdev, &sds_ring->napi,
-                               qlcnic_rx_poll, QLCNIC_NETDEV_WEIGHT*2);
-       }
-
-       return 0;
-}
-
-static void
-qlcnic_napi_del(struct qlcnic_adapter *adapter)
-{
-       int ring;
-       struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-               sds_ring = &recv_ctx->sds_rings[ring];
-               netif_napi_del(&sds_ring->napi);
-       }
-
-       qlcnic_free_sds_rings(adapter->recv_ctx);
-}
-
-static void
-qlcnic_napi_enable(struct qlcnic_adapter *adapter)
-{
-       int ring;
-       struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
-               return;
-
-       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-               sds_ring = &recv_ctx->sds_rings[ring];
-               napi_enable(&sds_ring->napi);
-               qlcnic_enable_int(sds_ring);
-       }
-}
-
-static void
-qlcnic_napi_disable(struct qlcnic_adapter *adapter)
-{
-       int ring;
-       struct qlcnic_host_sds_ring *sds_ring;
-       struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
-
-       if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC)
-               return;
-
-       for (ring = 0; ring < adapter->max_sds_rings; ring++) {
-               sds_ring = &recv_ctx->sds_rings[ring];
-               qlcnic_disable_int(sds_ring);
-               napi_synchronize(&sds_ring->napi);
-               napi_disable(&sds_ring->napi);
-       }
-}
-
 static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
 {
        memset(&adapter->stats, 0, sizeof(adapter->stats));
@@ -363,7 +287,7 @@ static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
        adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED);
        qlcnic_set_msix_bit(pdev, 0);
 
-       if (adapter->msix_supported) {
+       if (adapter->ahw->msix_supported) {
  enable_msix:
                qlcnic_init_msix_entries(adapter, num_msix);
                err = pci_enable_msix(pdev, adapter->msix_entries, num_msix);
@@ -385,32 +309,31 @@ static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
        return err;
 }
 
-
 static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
 {
+       u32 offset, mask_reg;
        const struct qlcnic_legacy_intr_set *legacy_intrp;
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
        struct pci_dev *pdev = adapter->pdev;
 
-       if (use_msi && !pci_enable_msi(pdev)) {
+       if (qlcnic_use_msi && !pci_enable_msi(pdev)) {
                adapter->flags |= QLCNIC_MSI_ENABLED;
-               adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
-                               msi_tgt_status[adapter->ahw->pci_func]);
+               offset = msi_tgt_status[adapter->ahw->pci_func];
+               adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter->ahw,
+                                                           offset);
                dev_info(&pdev->dev, "using msi interrupts\n");
                adapter->msix_entries[0].vector = pdev->irq;
                return;
        }
 
        legacy_intrp = &legacy_intr[adapter->ahw->pci_func];
-
-       adapter->int_vec_bit = legacy_intrp->int_vec_bit;
-       adapter->tgt_status_reg = qlcnic_get_ioaddr(adapter,
-                       legacy_intrp->tgt_status_reg);
-       adapter->tgt_mask_reg = qlcnic_get_ioaddr(adapter,
-                       legacy_intrp->tgt_mask_reg);
-       adapter->isr_int_vec = qlcnic_get_ioaddr(adapter, ISR_INT_VECTOR);
-
-       adapter->crb_int_state_reg = qlcnic_get_ioaddr(adapter,
-                       ISR_INT_STATE_REG);
+       adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit;
+       offset = legacy_intrp->tgt_status_reg;
+       adapter->tgt_status_reg = qlcnic_get_ioaddr(ahw, offset);
+       mask_reg = legacy_intrp->tgt_mask_reg;
+       adapter->tgt_mask_reg = qlcnic_get_ioaddr(ahw, mask_reg);
+       adapter->isr_int_vec = qlcnic_get_ioaddr(ahw, ISR_INT_VECTOR);
+       adapter->crb_int_state_reg = qlcnic_get_ioaddr(ahw, ISR_INT_STATE_REG);
        dev_info(&pdev->dev, "using legacy interrupts\n");
        adapter->msix_entries[0].vector = pdev->irq;
 }
@@ -420,7 +343,7 @@ qlcnic_setup_intr(struct qlcnic_adapter *adapter)
 {
        int num_msix;
 
-       if (adapter->msix_supported) {
+       if (adapter->ahw->msix_supported) {
                num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
                                QLCNIC_DEF_NUM_STS_DESC_RINGS));
        } else
@@ -448,19 +371,25 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
                iounmap(adapter->ahw->pci_base0);
 }
 
-static int
-qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
+static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_pci_info *pci_info;
-       int i, ret = 0;
+       int i, ret = 0, j = 0;
+       u16 act_pci_func;
        u8 pfn;
 
        pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
        if (!pci_info)
                return -ENOMEM;
 
+       ret = qlcnic_get_pci_info(adapter, pci_info);
+       if (ret)
+               goto err_pci_info;
+
+       act_pci_func = adapter->ahw->act_pci_func;
+
        adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
-                               QLCNIC_MAX_PCI_FUNC, GFP_KERNEL);
+                                act_pci_func, GFP_KERNEL);
        if (!adapter->npars) {
                ret = -ENOMEM;
                goto err_pci_info;
@@ -473,21 +402,25 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
                goto err_npars;
        }
 
-       ret = qlcnic_get_pci_info(adapter, pci_info);
-       if (ret)
-               goto err_eswitch;
-
        for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
                pfn = pci_info[i].id;
+
                if (pfn >= QLCNIC_MAX_PCI_FUNC) {
                        ret = QL_STATUS_INVALID_PARAM;
                        goto err_eswitch;
                }
-               adapter->npars[pfn].active = (u8)pci_info[i].active;
-               adapter->npars[pfn].type = (u8)pci_info[i].type;
-               adapter->npars[pfn].phy_port = (u8)pci_info[i].default_port;
-               adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
-               adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
+
+               if (!pci_info[i].active ||
+                   (pci_info[i].type != QLCNIC_TYPE_NIC))
+                       continue;
+
+               adapter->npars[j].pci_func = pfn;
+               adapter->npars[j].active = (u8)pci_info[i].active;
+               adapter->npars[j].type = (u8)pci_info[i].type;
+               adapter->npars[j].phy_port = (u8)pci_info[i].default_port;
+               adapter->npars[j].min_bw = pci_info[i].tx_min_bw;
+               adapter->npars[j].max_bw = pci_info[i].tx_max_bw;
+               j++;
        }
 
        for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
@@ -515,7 +448,7 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
        u32 ref_count;
        int i, ret = 1;
        u32 data = QLCNIC_MGMT_FUNC;
-       void __iomem *priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE;
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
 
        /* If other drivers are not in use set their privilege level */
        ref_count = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE);
@@ -524,21 +457,20 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter)
                goto err_lock;
 
        if (qlcnic_config_npars) {
-               for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-                       id = i;
-                       if (adapter->npars[i].type != QLCNIC_TYPE_NIC ||
-                               id == adapter->ahw->pci_func)
+               for (i = 0; i < ahw->act_pci_func; i++) {
+                       id = adapter->npars[i].pci_func;
+                       if (id == ahw->pci_func)
                                continue;
                        data |= (qlcnic_config_npars &
                                        QLC_DEV_SET_DRV(0xf, id));
                }
        } else {
-               data = readl(priv_op);
-               data = (data & ~QLC_DEV_SET_DRV(0xf, adapter->ahw->pci_func)) |
+               data = QLCRD32(adapter, QLCNIC_DRV_OP_MODE);
+               data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) |
                        (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC,
-                       adapter->ahw->pci_func));
+                                        ahw->pci_func));
        }
-       writel(data, priv_op);
+       QLCWR32(adapter, QLCNIC_DRV_OP_MODE, data);
        qlcnic_api_unlock(adapter);
 err_lock:
        return ret;
@@ -554,8 +486,8 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
        u32 op_mode, priv_level;
 
        /* Determine FW API version */
-       adapter->fw_hal_version = readl(adapter->ahw->pci_base0 +
-                                       QLCNIC_FW_API);
+       adapter->ahw->fw_hal_version = readl(adapter->ahw->pci_base0 +
+                                            QLCNIC_FW_API);
 
        /* Find PCI function number */
        pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
@@ -573,29 +505,41 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter)
                priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func);
 
        if (priv_level == QLCNIC_NON_PRIV_FUNC) {
-               adapter->op_mode = QLCNIC_NON_PRIV_FUNC;
+               adapter->ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
                dev_info(&adapter->pdev->dev,
                        "HAL Version: %d Non Privileged function\n",
-                       adapter->fw_hal_version);
+                        adapter->ahw->fw_hal_version);
                adapter->nic_ops = &qlcnic_vf_ops;
        } else
                adapter->nic_ops = &qlcnic_ops;
 }
 
-static int
-qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
+#define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL
+static void qlcnic_get_bar_length(u32 dev_id, ulong *bar)
+{
+       switch (dev_id) {
+       case PCI_DEVICE_ID_QLOGIC_QLE824X:
+               *bar = QLCNIC_82XX_BAR0_LENGTH;
+               break;
+       default:
+               *bar = 0;
+       }
+}
+
+static int qlcnic_setup_pci_map(struct pci_dev *pdev,
+                               struct qlcnic_hardware_context *ahw)
 {
+       u32 offset;
        void __iomem *mem_ptr0 = NULL;
        resource_size_t mem_base;
-       unsigned long mem_len, pci_len0 = 0;
-
-       struct pci_dev *pdev = adapter->pdev;
+       unsigned long mem_len, pci_len0 = 0, bar0_len;
 
        /* remap phys address */
        mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */
        mem_len = pci_resource_len(pdev, 0);
 
-       if (mem_len == QLCNIC_PCI_2MB_SIZE) {
+       qlcnic_get_bar_length(pdev->device, &bar0_len);
+       if (mem_len >= bar0_len) {
 
                mem_ptr0 = pci_ioremap_bar(pdev, 0);
                if (mem_ptr0 == NULL) {
@@ -608,20 +552,15 @@ qlcnic_setup_pci_map(struct qlcnic_adapter *adapter)
        }
 
        dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
-
-       adapter->ahw->pci_base0 = mem_ptr0;
-       adapter->ahw->pci_len0 = pci_len0;
-
-       qlcnic_check_vf(adapter);
-
-       adapter->ahw->ocm_win_crb = qlcnic_get_ioaddr(adapter,
-               QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(
-                       adapter->ahw->pci_func)));
+       ahw->pci_base0 = mem_ptr0;
+       ahw->pci_len0 = pci_len0;
+       offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func));
+       qlcnic_get_ioaddr(ahw, offset);
 
        return 0;
 }
 
-static void get_brd_name(struct qlcnic_adapter *adapter, char *name)
+static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name)
 {
        struct pci_dev *pdev = adapter->pdev;
        int i, found = 0;
@@ -659,7 +598,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
 
        adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
 
-       if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC) {
+       if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC) {
                if (fw_dump->tmpl_hdr == NULL ||
                                adapter->fw_version > prev_fw_version) {
                        if (fw_dump->tmpl_hdr)
@@ -691,7 +630,7 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
                adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
        }
 
-       adapter->msix_supported = !!use_msi_x;
+       adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
 
        adapter->num_txd = MAX_CMD_DESCRIPTORS;
 
@@ -704,19 +643,20 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
        int err;
        struct qlcnic_info nic_info;
 
+       memset(&nic_info, 0, sizeof(struct qlcnic_info));
        err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw->pci_func);
        if (err)
                return err;
 
-       adapter->physical_port = (u8)nic_info.phys_port;
-       adapter->switch_mode = nic_info.switch_mode;
-       adapter->max_tx_ques = nic_info.max_tx_ques;
-       adapter->max_rx_ques = nic_info.max_rx_ques;
-       adapter->capabilities = nic_info.capabilities;
-       adapter->max_mac_filters = nic_info.max_mac_filters;
-       adapter->max_mtu = nic_info.max_mtu;
+       adapter->ahw->physical_port = (u8)nic_info.phys_port;
+       adapter->ahw->switch_mode = nic_info.switch_mode;
+       adapter->ahw->max_tx_ques = nic_info.max_tx_ques;
+       adapter->ahw->max_rx_ques = nic_info.max_rx_ques;
+       adapter->ahw->capabilities = nic_info.capabilities;
+       adapter->ahw->max_mac_filters = nic_info.max_mac_filters;
+       adapter->ahw->max_mtu = nic_info.max_mtu;
 
-       if (adapter->capabilities & BIT_6)
+       if (adapter->ahw->capabilities & BIT_6)
                adapter->flags |= QLCNIC_ESWITCH_ENABLED;
        else
                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
@@ -724,9 +664,8 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
        return err;
 }
 
-static void
-qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
-               struct qlcnic_esw_func_cfg *esw_cfg)
+void qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
+                           struct qlcnic_esw_func_cfg *esw_cfg)
 {
        if (esw_cfg->discard_tagged)
                adapter->flags &= ~QLCNIC_TAGGING_ENABLED;
@@ -757,9 +696,8 @@ qlcnic_vlan_rx_del(struct net_device *netdev, u16 vid)
        return 0;
 }
 
-static void
-qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
-               struct qlcnic_esw_func_cfg *esw_cfg)
+void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
+                                     struct qlcnic_esw_func_cfg *esw_cfg)
 {
        adapter->flags &= ~(QLCNIC_MACSPOOF | QLCNIC_MAC_OVERRIDE_DISABLED |
                                QLCNIC_PROMISC_DISABLED);
@@ -776,8 +714,7 @@ qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
        qlcnic_set_netdev_features(adapter, esw_cfg);
 }
 
-static int
-qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
+static int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_esw_func_cfg esw_cfg;
 
@@ -805,7 +742,7 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter,
        vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM |
                        NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER);
 
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
+       if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) {
                features |= (NETIF_F_TSO | NETIF_F_TSO6);
                vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6);
        }
@@ -851,7 +788,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
 
        if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
                if (priv_level == QLCNIC_MGMT_FUNC) {
-                       adapter->op_mode = QLCNIC_MGMT_FUNC;
+                       adapter->ahw->op_mode = QLCNIC_MGMT_FUNC;
                        err = qlcnic_init_pci_info(adapter);
                        if (err)
                                return err;
@@ -859,12 +796,12 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
                        qlcnic_set_function_modes(adapter);
                        dev_info(&adapter->pdev->dev,
                                "HAL Version: %d, Management function\n",
-                               adapter->fw_hal_version);
+                                adapter->ahw->fw_hal_version);
                } else if (priv_level == QLCNIC_PRIV_FUNC) {
-                       adapter->op_mode = QLCNIC_PRIV_FUNC;
+                       adapter->ahw->op_mode = QLCNIC_PRIV_FUNC;
                        dev_info(&adapter->pdev->dev,
                                "HAL Version: %d, Privileged function\n",
-                               adapter->fw_hal_version);
+                                adapter->ahw->fw_hal_version);
                }
        }
 
@@ -873,8 +810,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
        return err;
 }
 
-static int
-qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
+static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
 {
        struct qlcnic_esw_func_cfg esw_cfg;
        struct qlcnic_npar_info *npar;
@@ -883,16 +819,16 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
        if (adapter->need_fw_reset)
                return 0;
 
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-               if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-                       continue;
+       for (i = 0; i < adapter->ahw->act_pci_func; i++) {
                memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
-               esw_cfg.pci_func = i;
-               esw_cfg.offload_flags = BIT_0;
+               esw_cfg.pci_func = adapter->npars[i].pci_func;
                esw_cfg.mac_override = BIT_0;
                esw_cfg.promisc_mode = BIT_0;
-               if (adapter->capabilities  & QLCNIC_FW_CAPABILITY_TSO)
-                       esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+               if (qlcnic_82xx_check(adapter)) {
+                       esw_cfg.offload_flags = BIT_0;
+                       if (QLCNIC_IS_TSO_CAPABLE(adapter))
+                               esw_cfg.offload_flags |= (BIT_1 | BIT_2);
+               }
                if (qlcnic_config_switch_port(adapter, &esw_cfg))
                        return -EIO;
                npar = &adapter->npars[i];
@@ -930,22 +866,24 @@ qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
        return 0;
 }
 
-static int
-qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
+static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
 {
        int i, err;
        struct qlcnic_npar_info *npar;
        struct qlcnic_info nic_info;
+       u8 pci_func;
 
-       if (!adapter->need_fw_reset)
-               return 0;
+       if (qlcnic_82xx_check(adapter))
+               if (!adapter->need_fw_reset)
+                       return 0;
 
        /* Set the NPAR config data after FW reset */
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+       for (i = 0; i < adapter->ahw->act_pci_func; i++) {
                npar = &adapter->npars[i];
-               if (npar->type != QLCNIC_TYPE_NIC)
-                       continue;
-               err = qlcnic_get_nic_info(adapter, &nic_info, i);
+               pci_func = npar->pci_func;
+               memset(&nic_info, 0, sizeof(struct qlcnic_info));
+               err = qlcnic_get_nic_info(adapter,
+                                         &nic_info, pci_func);
                if (err)
                        return err;
                nic_info.min_tx_bw = npar->min_bw;
@@ -956,11 +894,12 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
 
                if (npar->enable_pm) {
                        err = qlcnic_config_port_mirroring(adapter,
-                                                       npar->dest_npar, 1, i);
+                                                          npar->dest_npar, 1,
+                                                          pci_func);
                        if (err)
                                return err;
                }
-               err = qlcnic_reset_eswitch_config(adapter, npar, i);
+               err = qlcnic_reset_eswitch_config(adapter, npar, pci_func);
                if (err)
                        return err;
        }
@@ -972,7 +911,7 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
        u8 npar_opt_timeo = QLCNIC_DEV_NPAR_OPER_TIMEO;
        u32 npar_state;
 
-       if (adapter->op_mode == QLCNIC_MGMT_FUNC)
+       if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
                return 0;
 
        npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
@@ -994,7 +933,7 @@ qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
        int err;
 
        if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
-                   adapter->op_mode != QLCNIC_MGMT_FUNC)
+           adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
                return 0;
 
        err = qlcnic_set_default_offload_settings(adapter);
@@ -1021,14 +960,14 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter)
        else if (!err)
                goto check_fw_status;
 
-       if (load_fw_file)
+       if (qlcnic_load_fw_file)
                qlcnic_request_firmware(adapter);
        else {
                err = qlcnic_check_flash_fw_ver(adapter);
                if (err)
                        goto err_out;
 
-               adapter->fw_type = QLCNIC_FLASH_ROMIMAGE;
+               adapter->ahw->fw_type = QLCNIC_FLASH_ROMIMAGE;
        }
 
        err = qlcnic_need_fw_reset(adapter);
@@ -1089,7 +1028,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
 
-       if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+       if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                handler = qlcnic_tmp_intr;
                if (!QLCNIC_IS_MSI_FAMILY(adapter))
                        flags |= IRQF_SHARED;
@@ -1148,7 +1087,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
        if (qlcnic_set_eswitch_port_config(adapter))
                return -EIO;
 
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
+       if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) {
                capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2);
                if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG)
                        adapter->flags |= QLCNIC_FW_LRO_MSS_CAP;
@@ -1179,7 +1118,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
 
        qlcnic_linkevent_request(adapter, 1);
 
-       adapter->reset_context = 0;
+       adapter->ahw->reset_context = 0;
        set_bit(__QLCNIC_DEV_UP, &adapter->state);
        return 0;
 }
@@ -1312,7 +1251,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
        int ring;
 
        clear_bit(__QLCNIC_DEV_UP, &adapter->state);
-       if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+       if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
                        qlcnic_disable_int(sds_ring);
@@ -1323,7 +1262,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings)
 
        qlcnic_detach(adapter);
 
-       adapter->diag_test = 0;
+       adapter->ahw->diag_test = 0;
        adapter->max_sds_rings = max_sds_rings;
 
        if (qlcnic_attach(adapter))
@@ -1393,7 +1332,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
        qlcnic_detach(adapter);
 
        adapter->max_sds_rings = 1;
-       adapter->diag_test = test;
+       adapter->ahw->diag_test = test;
 
        ret = qlcnic_attach(adapter);
        if (ret) {
@@ -1413,14 +1352,14 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
                qlcnic_post_rx_buffers(adapter, rds_ring);
        }
 
-       if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) {
+       if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) {
                for (ring = 0; ring < adapter->max_sds_rings; ring++) {
                        sds_ring = &adapter->recv_ctx->sds_rings[ring];
                        qlcnic_enable_int(sds_ring);
                }
        }
 
-       if (adapter->diag_test == QLCNIC_LOOPBACK_TEST) {
+       if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) {
                adapter->ahw->loopback_state = 0;
                qlcnic_linkevent_request(adapter, 1);
        }
@@ -1485,14 +1424,14 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter)
 }
 
 static int
-qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
-               struct net_device *netdev, u8 pci_using_dac)
+qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev,
+                   int pci_using_dac)
 {
        int err;
        struct pci_dev *pdev = adapter->pdev;
 
-       adapter->mc_enabled = 0;
-       adapter->max_mc_count = 38;
+       adapter->ahw->mc_enabled = 0;
+       adapter->ahw->max_mc_count = 38;
 
        netdev->netdev_ops         = &qlcnic_netdev_ops;
        netdev->watchdog_timeo     = 5*HZ;
@@ -1504,16 +1443,16 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
        netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
                NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM;
 
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
+       if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO)
                netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6;
-       if (pci_using_dac)
+       if (pci_using_dac == 1)
                netdev->hw_features |= NETIF_F_HIGHDMA;
 
        netdev->vlan_features = netdev->hw_features;
 
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
+       if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX)
                netdev->hw_features |= NETIF_F_HW_VLAN_TX;
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
+       if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO)
                netdev->hw_features |= NETIF_F_LRO;
 
        netdev->features |= netdev->hw_features |
@@ -1530,7 +1469,7 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
        return 0;
 }
 
-static int qlcnic_set_dma_mask(struct pci_dev *pdev, u8 *pci_using_dac)
+static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac)
 {
        if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
                        !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
@@ -1559,15 +1498,14 @@ qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count)
        return -ENOMEM;
 }
 
-static int __devinit
+static int
 qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev = NULL;
        struct qlcnic_adapter *adapter = NULL;
-       int err;
+       int err, pci_using_dac = -1;
        uint8_t revision_id;
-       uint8_t pci_using_dac;
-       char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
+       char board_name[QLCNIC_MAX_BOARD_NAME_LEN];
 
        err = pci_enable_device(pdev);
        if (err)
@@ -1616,9 +1554,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        spin_lock_init(&adapter->tx_clean_lock);
        INIT_LIST_HEAD(&adapter->mac_list);
 
-       err = qlcnic_setup_pci_map(adapter);
+       err = qlcnic_setup_pci_map(pdev, adapter->ahw);
        if (err)
                goto err_out_free_hw;
+       qlcnic_check_vf(adapter);
 
        /* This will be reset for mezz cards  */
        adapter->portnum = adapter->ahw->pci_func;
@@ -1646,16 +1585,15 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                dev_warn(&pdev->dev, "failed to read mac addr\n");
 
        if (adapter->portnum == 0) {
-               get_brd_name(adapter, brd_name);
-
+               qlcnic_get_board_name(adapter, board_name);
                pr_info("%s: %s Board Chip rev 0x%x\n",
-                               module_name(THIS_MODULE),
-                               brd_name, adapter->ahw->revision_id);
+                       module_name(THIS_MODULE),
+                       board_name, adapter->ahw->revision_id);
        }
 
        qlcnic_clear_stats(adapter);
 
-       err = qlcnic_alloc_msix_entries(adapter, adapter->max_rx_ques);
+       err = qlcnic_alloc_msix_entries(adapter, adapter->ahw->max_rx_ques);
        if (err)
                goto err_out_decr_ref;
 
@@ -1667,7 +1605,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        pci_set_drvdata(pdev, adapter);
 
-       qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
+       if (qlcnic_82xx_check(adapter))
+               qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
+                                    FW_POLL_DELAY);
 
        switch (adapter->ahw->port_type) {
        case QLCNIC_GBE:
@@ -1724,7 +1664,7 @@ err_out_maintenance_mode:
        return 0;
 }
 
-static void __devexit qlcnic_remove(struct pci_dev *pdev)
+static void qlcnic_remove(struct pci_dev *pdev)
 {
        struct qlcnic_adapter *adapter;
        struct net_device *netdev;
@@ -1746,7 +1686,8 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
        if (adapter->eswitch != NULL)
                kfree(adapter->eswitch);
 
-       qlcnic_clr_all_drv_state(adapter, 0);
+       if (qlcnic_82xx_check(adapter))
+               qlcnic_clr_all_drv_state(adapter, 0);
 
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 
@@ -1782,7 +1723,8 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
        if (netif_running(netdev))
                qlcnic_down(adapter, netdev);
 
-       qlcnic_clr_all_drv_state(adapter, 0);
+       if (qlcnic_82xx_check(adapter))
+               qlcnic_clr_all_drv_state(adapter, 0);
 
        clear_bit(__QLCNIC_RESETTING, &adapter->state);
 
@@ -1790,9 +1732,11 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
        if (retval)
                return retval;
 
-       if (qlcnic_wol_supported(adapter)) {
-               pci_enable_wake(pdev, PCI_D3cold, 1);
-               pci_enable_wake(pdev, PCI_D3hot, 1);
+       if (qlcnic_82xx_check(adapter)) {
+               if (qlcnic_wol_supported(adapter)) {
+                       pci_enable_wake(pdev, PCI_D3cold, 1);
+                       pci_enable_wake(pdev, PCI_D3hot, 1);
+               }
        }
 
        return 0;
@@ -1927,706 +1871,148 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
        adapter->fhash.fmax = 0;
 }
 
-static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
-               u64 uaddr, __le16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
+static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
 {
-       struct cmd_desc_type0 *hwdesc;
-       struct qlcnic_nic_req *req;
-       struct qlcnic_mac_req *mac_req;
-       struct qlcnic_vlan_req *vlan_req;
-       u32 producer;
-       u64 word;
-
-       producer = tx_ring->producer;
-       hwdesc = &tx_ring->desc_head[tx_ring->producer];
-
-       req = (struct qlcnic_nic_req *)hwdesc;
-       memset(req, 0, sizeof(struct qlcnic_nic_req));
-       req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
-
-       word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
-       req->req_hdr = cpu_to_le64(word);
+       struct net_device *netdev = adapter->netdev;
+       u32 temp_state, temp_val, temp = 0;
+       int rv = 0;
 
-       mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
-       mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
-       memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+       if (qlcnic_82xx_check(adapter))
+               temp = QLCRD32(adapter, CRB_TEMP_STATE);
 
-       vlan_req = (struct qlcnic_vlan_req *)&req->words[1];
-       vlan_req->vlan_id = vlan_id;
+       temp_state = qlcnic_get_temp_state(temp);
+       temp_val = qlcnic_get_temp_val(temp);
 
-       tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
-       smp_mb();
+       if (temp_state == QLCNIC_TEMP_PANIC) {
+               dev_err(&netdev->dev,
+                      "Device temperature %d degrees C exceeds"
+                      " maximum allowed. Hardware has been shut down.\n",
+                      temp_val);
+               rv = 1;
+       } else if (temp_state == QLCNIC_TEMP_WARN) {
+               if (adapter->ahw->temp == QLCNIC_TEMP_NORMAL) {
+                       dev_err(&netdev->dev,
+                              "Device temperature %d degrees C "
+                              "exceeds operating range."
+                              " Immediate action needed.\n",
+                              temp_val);
+               }
+       } else {
+               if (adapter->ahw->temp == QLCNIC_TEMP_WARN) {
+                       dev_info(&netdev->dev,
+                              "Device temperature is now %d degrees C"
+                              " in normal range.\n", temp_val);
+               }
+       }
+       adapter->ahw->temp = temp_state;
+       return rv;
 }
 
-#define QLCNIC_MAC_HASH(MAC)\
-       ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
-
-static void
-qlcnic_send_filter(struct qlcnic_adapter *adapter,
-               struct qlcnic_host_tx_ring *tx_ring,
-               struct cmd_desc_type0 *first_desc,
-               struct sk_buff *skb)
+static void qlcnic_tx_timeout(struct net_device *netdev)
 {
-       struct ethhdr *phdr = (struct ethhdr *)(skb->data);
-       struct qlcnic_filter *fil, *tmp_fil;
-       struct hlist_node *tmp_hnode, *n;
-       struct hlist_head *head;
-       u64 src_addr = 0;
-       __le16 vlan_id = 0;
-       u8 hindex;
-
-       if (ether_addr_equal(phdr->h_source, adapter->mac_addr))
-               return;
-
-       if (adapter->fhash.fnum >= adapter->fhash.fmax)
-               return;
-
-       /* Only NPAR capable devices support vlan based learning*/
-       if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
-               vlan_id = first_desc->vlan_TCI;
-       memcpy(&src_addr, phdr->h_source, ETH_ALEN);
-       hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
-       head = &(adapter->fhash.fhead[hindex]);
-
-       hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
-               if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
-                           tmp_fil->vlan_id == vlan_id) {
-
-                       if (jiffies >
-                           (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
-                               qlcnic_change_filter(adapter, src_addr, vlan_id,
-                                                               tx_ring);
-                       tmp_fil->ftime = jiffies;
-                       return;
-               }
-       }
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
 
-       fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
-       if (!fil)
+       if (test_bit(__QLCNIC_RESETTING, &adapter->state))
                return;
 
-       qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
+       dev_err(&netdev->dev, "transmit timeout, resetting.\n");
 
-       fil->ftime = jiffies;
-       fil->vlan_id = vlan_id;
-       memcpy(fil->faddr, &src_addr, ETH_ALEN);
-       spin_lock(&adapter->mac_learn_lock);
-       hlist_add_head(&(fil->fnode), head);
-       adapter->fhash.fnum++;
-       spin_unlock(&adapter->mac_learn_lock);
+       if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
+               adapter->need_fw_reset = 1;
+       else
+               adapter->ahw->reset_context = 1;
 }
 
-static int
-qlcnic_tx_pkt(struct qlcnic_adapter *adapter,
-               struct cmd_desc_type0 *first_desc,
-               struct sk_buff *skb)
+static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
 {
-       u8 opcode = 0, hdr_len = 0;
-       u16 flags = 0, vlan_tci = 0;
-       int copied, offset, copy_len;
-       struct cmd_desc_type0 *hwdesc;
-       struct vlan_ethhdr *vh;
-       struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-       u16 protocol = ntohs(skb->protocol);
-       u32 producer = tx_ring->producer;
-
-       if (protocol == ETH_P_8021Q) {
-               vh = (struct vlan_ethhdr *)skb->data;
-               flags = FLAGS_VLAN_TAGGED;
-               vlan_tci = vh->h_vlan_TCI;
-               protocol = ntohs(vh->h_vlan_encapsulated_proto);
-       } else if (vlan_tx_tag_present(skb)) {
-               flags = FLAGS_VLAN_OOB;
-               vlan_tci = vlan_tx_tag_get(skb);
-       }
-       if (unlikely(adapter->pvid)) {
-               if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED))
-                       return -EIO;
-               if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED))
-                       goto set_flags;
-
-               flags = FLAGS_VLAN_OOB;
-               vlan_tci = adapter->pvid;
-       }
-set_flags:
-       qlcnic_set_tx_vlan_tci(first_desc, vlan_tci);
-       qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
-
-       if (*(skb->data) & BIT_0) {
-               flags |= BIT_0;
-               memcpy(&first_desc->eth_addr, skb->data, ETH_ALEN);
-       }
-       opcode = TX_ETHER_PKT;
-       if ((adapter->netdev->features & (NETIF_F_TSO | NETIF_F_TSO6)) &&
-                       skb_shinfo(skb)->gso_size > 0) {
-
-               hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-
-               first_desc->mss = cpu_to_le16(skb_shinfo(skb)->gso_size);
-               first_desc->total_hdr_length = hdr_len;
-
-               opcode = (protocol == ETH_P_IPV6) ? TX_TCP_LSO6 : TX_TCP_LSO;
-
-               /* For LSO, we need to copy the MAC/IP/TCP headers into
-               * the descriptor ring */
-               copied = 0;
-               offset = 2;
-
-               if (flags & FLAGS_VLAN_OOB) {
-                       first_desc->total_hdr_length += VLAN_HLEN;
-                       first_desc->tcp_hdr_offset = VLAN_HLEN;
-                       first_desc->ip_hdr_offset = VLAN_HLEN;
-                       /* Only in case of TSO on vlan device */
-                       flags |= FLAGS_VLAN_TAGGED;
-
-                       /* Create a TSO vlan header template for firmware */
-
-                       hwdesc = &tx_ring->desc_head[producer];
-                       tx_ring->cmd_buf_arr[producer].skb = NULL;
-
-                       copy_len = min((int)sizeof(struct cmd_desc_type0) -
-                               offset, hdr_len + VLAN_HLEN);
+       struct qlcnic_adapter *adapter = netdev_priv(netdev);
+       struct net_device_stats *stats = &netdev->stats;
 
-                       vh = (struct vlan_ethhdr *)((char *) hwdesc + 2);
-                       skb_copy_from_linear_data(skb, vh, 12);
-                       vh->h_vlan_proto = htons(ETH_P_8021Q);
-                       vh->h_vlan_TCI = htons(vlan_tci);
+       stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
+       stats->tx_packets = adapter->stats.xmitfinished;
+       stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
+       stats->tx_bytes = adapter->stats.txbytes;
+       stats->rx_dropped = adapter->stats.rxdropped;
+       stats->tx_dropped = adapter->stats.txdropped;
 
-                       skb_copy_from_linear_data_offset(skb, 12,
-                               (char *)vh + 16, copy_len - 16);
+       return stats;
+}
 
-                       copied = copy_len - VLAN_HLEN;
-                       offset = 0;
+static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
+{
+       u32 status;
 
-                       producer = get_next_index(producer, tx_ring->num_desc);
-               }
+       status = readl(adapter->isr_int_vec);
 
-               while (copied < hdr_len) {
+       if (!(status & adapter->ahw->int_vec_bit))
+               return IRQ_NONE;
 
-                       copy_len = min((int)sizeof(struct cmd_desc_type0) -
-                               offset, (hdr_len - copied));
+       /* check interrupt state machine, to be sure */
+       status = readl(adapter->crb_int_state_reg);
+       if (!ISR_LEGACY_INT_TRIGGERED(status))
+               return IRQ_NONE;
 
-                       hwdesc = &tx_ring->desc_head[producer];
-                       tx_ring->cmd_buf_arr[producer].skb = NULL;
+       writel(0xffffffff, adapter->tgt_status_reg);
+       /* read twice to ensure write is flushed */
+       readl(adapter->isr_int_vec);
+       readl(adapter->isr_int_vec);
 
-                       skb_copy_from_linear_data_offset(skb, copied,
-                                (char *) hwdesc + offset, copy_len);
+       return IRQ_HANDLED;
+}
 
-                       copied += copy_len;
-                       offset = 0;
+static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
+{
+       struct qlcnic_host_sds_ring *sds_ring = data;
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
 
-                       producer = get_next_index(producer, tx_ring->num_desc);
-               }
+       if (adapter->flags & QLCNIC_MSIX_ENABLED)
+               goto done;
+       else if (adapter->flags & QLCNIC_MSI_ENABLED) {
+               writel(0xffffffff, adapter->tgt_status_reg);
+               goto done;
+       }
 
-               tx_ring->producer = producer;
-               smp_mb();
-               adapter->stats.lso_frames++;
+       if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
+               return IRQ_NONE;
 
-       } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               u8 l4proto;
+done:
+       adapter->ahw->diag_cnt++;
+       qlcnic_enable_int(sds_ring);
+       return IRQ_HANDLED;
+}
 
-               if (protocol == ETH_P_IP) {
-                       l4proto = ip_hdr(skb)->protocol;
+static irqreturn_t qlcnic_intr(int irq, void *data)
+{
+       struct qlcnic_host_sds_ring *sds_ring = data;
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
 
-                       if (l4proto == IPPROTO_TCP)
-                               opcode = TX_TCP_PKT;
-                       else if (l4proto == IPPROTO_UDP)
-                               opcode = TX_UDP_PKT;
-               } else if (protocol == ETH_P_IPV6) {
-                       l4proto = ipv6_hdr(skb)->nexthdr;
+       if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
+               return IRQ_NONE;
 
-                       if (l4proto == IPPROTO_TCP)
-                               opcode = TX_TCPV6_PKT;
-                       else if (l4proto == IPPROTO_UDP)
-                               opcode = TX_UDPV6_PKT;
-               }
-       }
-       first_desc->tcp_hdr_offset += skb_transport_offset(skb);
-       first_desc->ip_hdr_offset += skb_network_offset(skb);
-       qlcnic_set_tx_flags_opcode(first_desc, flags, opcode);
+       napi_schedule(&sds_ring->napi);
 
-       return 0;
+       return IRQ_HANDLED;
 }
 
-static int
-qlcnic_map_tx_skb(struct pci_dev *pdev,
-               struct sk_buff *skb, struct qlcnic_cmd_buffer *pbuf)
+static irqreturn_t qlcnic_msi_intr(int irq, void *data)
 {
-       struct qlcnic_skb_frag *nf;
-       struct skb_frag_struct *frag;
-       int i, nr_frags;
-       dma_addr_t map;
+       struct qlcnic_host_sds_ring *sds_ring = data;
+       struct qlcnic_adapter *adapter = sds_ring->adapter;
 
-       nr_frags = skb_shinfo(skb)->nr_frags;
-       nf = &pbuf->frag_array[0];
+       /* clear interrupt */
+       writel(0xffffffff, adapter->tgt_status_reg);
 
-       map = pci_map_single(pdev, skb->data,
-                       skb_headlen(skb), PCI_DMA_TODEVICE);
-       if (pci_dma_mapping_error(pdev, map))
-               goto out_err;
+       napi_schedule(&sds_ring->napi);
+       return IRQ_HANDLED;
+}
 
-       nf->dma = map;
-       nf->length = skb_headlen(skb);
+static irqreturn_t qlcnic_msix_intr(int irq, void *data)
+{
+       struct qlcnic_host_sds_ring *sds_ring = data;
 
-       for (i = 0; i < nr_frags; i++) {
-               frag = &skb_shinfo(skb)->frags[i];
-               nf = &pbuf->frag_array[i+1];
-
-               map = skb_frag_dma_map(&pdev->dev, frag, 0, skb_frag_size(frag),
-                                      DMA_TO_DEVICE);
-               if (dma_mapping_error(&pdev->dev, map))
-                       goto unwind;
-
-               nf->dma = map;
-               nf->length = skb_frag_size(frag);
-       }
-
-       return 0;
-
-unwind:
-       while (--i >= 0) {
-               nf = &pbuf->frag_array[i+1];
-               pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
-       }
-
-       nf = &pbuf->frag_array[0];
-       pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
-
-out_err:
-       return -ENOMEM;
-}
-
-static void
-qlcnic_unmap_buffers(struct pci_dev *pdev, struct sk_buff *skb,
-                       struct qlcnic_cmd_buffer *pbuf)
-{
-       struct qlcnic_skb_frag *nf = &pbuf->frag_array[0];
-       int nr_frags = skb_shinfo(skb)->nr_frags;
-       int i;
-
-       for (i = 0; i < nr_frags; i++) {
-               nf = &pbuf->frag_array[i+1];
-               pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
-       }
-
-       nf = &pbuf->frag_array[0];
-       pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
-       pbuf->skb = NULL;
-}
-
-static inline void
-qlcnic_clear_cmddesc(u64 *desc)
-{
-       desc[0] = 0ULL;
-       desc[2] = 0ULL;
-       desc[7] = 0ULL;
-}
-
-netdev_tx_t
-qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
-{
-       struct qlcnic_adapter *adapter = netdev_priv(netdev);
-       struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-       struct qlcnic_cmd_buffer *pbuf;
-       struct qlcnic_skb_frag *buffrag;
-       struct cmd_desc_type0 *hwdesc, *first_desc;
-       struct pci_dev *pdev;
-       struct ethhdr *phdr;
-       int delta = 0;
-       int i, k;
-
-       u32 producer;
-       int frag_count;
-       u32 num_txd = tx_ring->num_desc;
-
-       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
-               netif_stop_queue(netdev);
-               return NETDEV_TX_BUSY;
-       }
-
-       if (adapter->flags & QLCNIC_MACSPOOF) {
-               phdr = (struct ethhdr *)skb->data;
-               if (!ether_addr_equal(phdr->h_source, adapter->mac_addr))
-                       goto drop_packet;
-       }
-
-       frag_count = skb_shinfo(skb)->nr_frags + 1;
-       /* 14 frags supported for normal packet and
-        * 32 frags supported for TSO packet
-        */
-       if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
-
-               for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
-                       delta += skb_frag_size(&skb_shinfo(skb)->frags[i]);
-
-               if (!__pskb_pull_tail(skb, delta))
-                       goto drop_packet;
-
-               frag_count = 1 + skb_shinfo(skb)->nr_frags;
-       }
-
-       if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) {
-               netif_stop_queue(netdev);
-               if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH)
-                       netif_start_queue(netdev);
-               else {
-                       adapter->stats.xmit_off++;
-                       return NETDEV_TX_BUSY;
-               }
-       }
-
-       producer = tx_ring->producer;
-       pbuf = &tx_ring->cmd_buf_arr[producer];
-
-       pdev = adapter->pdev;
-
-       first_desc = hwdesc = &tx_ring->desc_head[producer];
-       qlcnic_clear_cmddesc((u64 *)hwdesc);
-
-       if (qlcnic_map_tx_skb(pdev, skb, pbuf)) {
-               adapter->stats.tx_dma_map_error++;
-               goto drop_packet;
-       }
-
-       pbuf->skb = skb;
-       pbuf->frag_count = frag_count;
-
-       qlcnic_set_tx_frags_len(first_desc, frag_count, skb->len);
-       qlcnic_set_tx_port(first_desc, adapter->portnum);
-
-       for (i = 0; i < frag_count; i++) {
-
-               k = i % 4;
-
-               if ((k == 0) && (i > 0)) {
-                       /* move to next desc.*/
-                       producer = get_next_index(producer, num_txd);
-                       hwdesc = &tx_ring->desc_head[producer];
-                       qlcnic_clear_cmddesc((u64 *)hwdesc);
-                       tx_ring->cmd_buf_arr[producer].skb = NULL;
-               }
-
-               buffrag = &pbuf->frag_array[i];
-
-               hwdesc->buffer_length[k] = cpu_to_le16(buffrag->length);
-               switch (k) {
-               case 0:
-                       hwdesc->addr_buffer1 = cpu_to_le64(buffrag->dma);
-                       break;
-               case 1:
-                       hwdesc->addr_buffer2 = cpu_to_le64(buffrag->dma);
-                       break;
-               case 2:
-                       hwdesc->addr_buffer3 = cpu_to_le64(buffrag->dma);
-                       break;
-               case 3:
-                       hwdesc->addr_buffer4 = cpu_to_le64(buffrag->dma);
-                       break;
-               }
-       }
-
-       tx_ring->producer = get_next_index(producer, num_txd);
-       smp_mb();
-
-       if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb)))
-               goto unwind_buff;
-
-       if (adapter->mac_learn)
-               qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
-
-       adapter->stats.txbytes += skb->len;
-       adapter->stats.xmitcalled++;
-
-       qlcnic_update_cmd_producer(adapter, tx_ring);
-
-       return NETDEV_TX_OK;
-
-unwind_buff:
-       qlcnic_unmap_buffers(pdev, skb, pbuf);
-drop_packet:
-       adapter->stats.txdropped++;
-       dev_kfree_skb_any(skb);
-       return NETDEV_TX_OK;
-}
-
-static int qlcnic_check_temp(struct qlcnic_adapter *adapter)
-{
-       struct net_device *netdev = adapter->netdev;
-       u32 temp, temp_state, temp_val;
-       int rv = 0;
-
-       temp = QLCRD32(adapter, CRB_TEMP_STATE);
-
-       temp_state = qlcnic_get_temp_state(temp);
-       temp_val = qlcnic_get_temp_val(temp);
-
-       if (temp_state == QLCNIC_TEMP_PANIC) {
-               dev_err(&netdev->dev,
-                      "Device temperature %d degrees C exceeds"
-                      " maximum allowed. Hardware has been shut down.\n",
-                      temp_val);
-               rv = 1;
-       } else if (temp_state == QLCNIC_TEMP_WARN) {
-               if (adapter->temp == QLCNIC_TEMP_NORMAL) {
-                       dev_err(&netdev->dev,
-                              "Device temperature %d degrees C "
-                              "exceeds operating range."
-                              " Immediate action needed.\n",
-                              temp_val);
-               }
-       } else {
-               if (adapter->temp == QLCNIC_TEMP_WARN) {
-                       dev_info(&netdev->dev,
-                              "Device temperature is now %d degrees C"
-                              " in normal range.\n", temp_val);
-               }
-       }
-       adapter->temp = temp_state;
-       return rv;
-}
-
-void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup)
-{
-       struct net_device *netdev = adapter->netdev;
-
-       if (adapter->ahw->linkup && !linkup) {
-               netdev_info(netdev, "NIC Link is down\n");
-               adapter->ahw->linkup = 0;
-               if (netif_running(netdev)) {
-                       netif_carrier_off(netdev);
-                       netif_stop_queue(netdev);
-               }
-       } else if (!adapter->ahw->linkup && linkup) {
-               netdev_info(netdev, "NIC Link is up\n");
-               adapter->ahw->linkup = 1;
-               if (netif_running(netdev)) {
-                       netif_carrier_on(netdev);
-                       netif_wake_queue(netdev);
-               }
-       }
-}
-
-static void qlcnic_tx_timeout(struct net_device *netdev)
-{
-       struct qlcnic_adapter *adapter = netdev_priv(netdev);
-
-       if (test_bit(__QLCNIC_RESETTING, &adapter->state))
-               return;
-
-       dev_err(&netdev->dev, "transmit timeout, resetting.\n");
-
-       if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
-               adapter->need_fw_reset = 1;
-       else
-               adapter->reset_context = 1;
-}
-
-static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
-{
-       struct qlcnic_adapter *adapter = netdev_priv(netdev);
-       struct net_device_stats *stats = &netdev->stats;
-
-       stats->rx_packets = adapter->stats.rx_pkts + adapter->stats.lro_pkts;
-       stats->tx_packets = adapter->stats.xmitfinished;
-       stats->rx_bytes = adapter->stats.rxbytes + adapter->stats.lrobytes;
-       stats->tx_bytes = adapter->stats.txbytes;
-       stats->rx_dropped = adapter->stats.rxdropped;
-       stats->tx_dropped = adapter->stats.txdropped;
-
-       return stats;
-}
-
-static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
-{
-       u32 status;
-
-       status = readl(adapter->isr_int_vec);
-
-       if (!(status & adapter->int_vec_bit))
-               return IRQ_NONE;
-
-       /* check interrupt state machine, to be sure */
-       status = readl(adapter->crb_int_state_reg);
-       if (!ISR_LEGACY_INT_TRIGGERED(status))
-               return IRQ_NONE;
-
-       writel(0xffffffff, adapter->tgt_status_reg);
-       /* read twice to ensure write is flushed */
-       readl(adapter->isr_int_vec);
-       readl(adapter->isr_int_vec);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t qlcnic_tmp_intr(int irq, void *data)
-{
-       struct qlcnic_host_sds_ring *sds_ring = data;
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-       if (adapter->flags & QLCNIC_MSIX_ENABLED)
-               goto done;
-       else if (adapter->flags & QLCNIC_MSI_ENABLED) {
-               writel(0xffffffff, adapter->tgt_status_reg);
-               goto done;
-       }
-
-       if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
-               return IRQ_NONE;
-
-done:
-       adapter->diag_cnt++;
-       qlcnic_enable_int(sds_ring);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t qlcnic_intr(int irq, void *data)
-{
-       struct qlcnic_host_sds_ring *sds_ring = data;
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-       if (qlcnic_clear_legacy_intr(adapter) == IRQ_NONE)
-               return IRQ_NONE;
-
-       napi_schedule(&sds_ring->napi);
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t qlcnic_msi_intr(int irq, void *data)
-{
-       struct qlcnic_host_sds_ring *sds_ring = data;
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-       /* clear interrupt */
-       writel(0xffffffff, adapter->tgt_status_reg);
-
-       napi_schedule(&sds_ring->napi);
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t qlcnic_msix_intr(int irq, void *data)
-{
-       struct qlcnic_host_sds_ring *sds_ring = data;
-
-       napi_schedule(&sds_ring->napi);
-       return IRQ_HANDLED;
-}
-
-static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter)
-{
-       u32 sw_consumer, hw_consumer;
-       int count = 0, i;
-       struct qlcnic_cmd_buffer *buffer;
-       struct pci_dev *pdev = adapter->pdev;
-       struct net_device *netdev = adapter->netdev;
-       struct qlcnic_skb_frag *frag;
-       int done;
-       struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
-
-       if (!spin_trylock(&adapter->tx_clean_lock))
-               return 1;
-
-       sw_consumer = tx_ring->sw_consumer;
-       hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
-
-       while (sw_consumer != hw_consumer) {
-               buffer = &tx_ring->cmd_buf_arr[sw_consumer];
-               if (buffer->skb) {
-                       frag = &buffer->frag_array[0];
-                       pci_unmap_single(pdev, frag->dma, frag->length,
-                                        PCI_DMA_TODEVICE);
-                       frag->dma = 0ULL;
-                       for (i = 1; i < buffer->frag_count; i++) {
-                               frag++;
-                               pci_unmap_page(pdev, frag->dma, frag->length,
-                                              PCI_DMA_TODEVICE);
-                               frag->dma = 0ULL;
-                       }
-
-                       adapter->stats.xmitfinished++;
-                       dev_kfree_skb_any(buffer->skb);
-                       buffer->skb = NULL;
-               }
-
-               sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc);
-               if (++count >= MAX_STATUS_HANDLE)
-                       break;
-       }
-
-       if (count && netif_running(netdev)) {
-               tx_ring->sw_consumer = sw_consumer;
-
-               smp_mb();
-
-               if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) {
-                       if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) {
-                               netif_wake_queue(netdev);
-                               adapter->stats.xmit_on++;
-                       }
-               }
-               adapter->tx_timeo_cnt = 0;
-       }
-       /*
-        * If everything is freed up to consumer then check if the ring is full
-        * If the ring is full then check if more needs to be freed and
-        * schedule the call back again.
-        *
-        * This happens when there are 2 CPUs. One could be freeing and the
-        * other filling it. If the ring is full when we get out of here and
-        * the card has already interrupted the host then the host can miss the
-        * interrupt.
-        *
-        * There is still a possible race condition and the host could miss an
-        * interrupt. The card has to take care of this.
-        */
-       hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
-       done = (sw_consumer == hw_consumer);
-       spin_unlock(&adapter->tx_clean_lock);
-
-       return done;
-}
-
-static int qlcnic_poll(struct napi_struct *napi, int budget)
-{
-       struct qlcnic_host_sds_ring *sds_ring =
-               container_of(napi, struct qlcnic_host_sds_ring, napi);
-
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-
-       int tx_complete;
-       int work_done;
-
-       tx_complete = qlcnic_process_cmd_ring(adapter);
-
-       work_done = qlcnic_process_rcv_ring(sds_ring, budget);
-
-       if ((work_done < budget) && tx_complete) {
-               napi_complete(&sds_ring->napi);
-               if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
-                       qlcnic_enable_int(sds_ring);
-       }
-
-       return work_done;
-}
-
-static int qlcnic_rx_poll(struct napi_struct *napi, int budget)
-{
-       struct qlcnic_host_sds_ring *sds_ring =
-               container_of(napi, struct qlcnic_host_sds_ring, napi);
-
-       struct qlcnic_adapter *adapter = sds_ring->adapter;
-       int work_done;
-
-       work_done = qlcnic_process_rcv_ring(sds_ring, budget);
-
-       if (work_done < budget) {
-               napi_complete(&sds_ring->napi);
-               if (test_bit(__QLCNIC_DEV_UP, &adapter->state))
-                       qlcnic_enable_int(sds_ring);
-       }
-
-       return work_done;
-}
+       napi_schedule(&sds_ring->napi);
+       return IRQ_HANDLED;
+}
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
 static void qlcnic_poll_controller(struct net_device *netdev)
@@ -2871,7 +2257,7 @@ qlcnic_fwinit_work(struct work_struct *work)
                return;
        }
 
-       if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
+       if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
                qlcnic_api_unlock(adapter);
                goto wait_npar;
        }
@@ -2987,9 +2373,9 @@ qlcnic_detach_work(struct work_struct *work)
                goto err_ret;
        }
 
-       if (adapter->temp == QLCNIC_TEMP_PANIC) {
+       if (adapter->ahw->temp == QLCNIC_TEMP_PANIC) {
                dev_err(&adapter->pdev->dev, "Detaching the device: temp=%d\n",
-                       adapter->temp);
+                       adapter->ahw->temp);
                goto err_ret;
        }
 
@@ -3114,7 +2500,7 @@ qlcnic_attach_work(struct work_struct *work)
        struct net_device *netdev = adapter->netdev;
        u32 npar_state;
 
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC) {
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) {
                npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE);
                if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO)
                        qlcnic_clr_all_drv_state(adapter, 0);
@@ -3171,7 +2557,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
                if (adapter->need_fw_reset)
                        goto detach;
 
-               if (adapter->reset_context && auto_fw_reset) {
+               if (adapter->ahw->reset_context && qlcnic_auto_fw_reset) {
                        qlcnic_reset_hw_context(adapter);
                        adapter->netdev->trans_start = jiffies;
                }
@@ -3186,7 +2572,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
 
        qlcnic_dev_request_reset(adapter);
 
-       if (auto_fw_reset)
+       if (qlcnic_auto_fw_reset)
                clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
 
        dev_err(&adapter->pdev->dev, "firmware hang detected\n");
@@ -3211,8 +2597,8 @@ detach:
        adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
                QLCNIC_DEV_NEED_RESET;
 
-       if (auto_fw_reset &&
-               !test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) {
+       if (qlcnic_auto_fw_reset && !test_and_set_bit(__QLCNIC_RESETTING,
+                                                     &adapter->state)) {
 
                qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
                QLCDB(adapter, DRV, "fw recovery scheduled.\n");
@@ -3283,7 +2669,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
        if (qlcnic_api_lock(adapter))
                return -EINVAL;
 
-       if (adapter->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
+       if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) {
                adapter->need_fw_reset = 1;
                set_bit(__QLCNIC_START_FW, &adapter->state);
                QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
@@ -3395,96 +2781,9 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
        return err;
 }
 
-static int
-qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
+int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
 {
-       return -EOPNOTSUPP;
-}
-
-static int
-qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
-{
-       return -EOPNOTSUPP;
-}
-
-static ssize_t
-qlcnic_store_bridged_mode(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t len)
-{
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       unsigned long new;
-       int ret = -EINVAL;
-
-       if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG))
-               goto err_out;
-
-       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
-               goto err_out;
-
-       if (strict_strtoul(buf, 2, &new))
-               goto err_out;
-
-       if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
-               ret = len;
-
-err_out:
-       return ret;
-}
-
-static ssize_t
-qlcnic_show_bridged_mode(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       int bridged_mode = 0;
-
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
-               bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
-
-       return sprintf(buf, "%d\n", bridged_mode);
-}
-
-static struct device_attribute dev_attr_bridged_mode = {
-       .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
-       .show = qlcnic_show_bridged_mode,
-       .store = qlcnic_store_bridged_mode,
-};
-
-static ssize_t
-qlcnic_store_diag_mode(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t len)
-{
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       unsigned long new;
-
-       if (strict_strtoul(buf, 2, &new))
-               return -EINVAL;
-
-       if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
-               adapter->flags ^= QLCNIC_DIAG_ENABLED;
-
-       return len;
-}
-
-static ssize_t
-qlcnic_show_diag_mode(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-
-       return sprintf(buf, "%d\n",
-                       !!(adapter->flags & QLCNIC_DIAG_ENABLED));
-}
-
-static struct device_attribute dev_attr_diag_mode = {
-       .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
-       .show = qlcnic_show_diag_mode,
-       .store = qlcnic_store_diag_mode,
-};
-
-int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val)
-{
-       if (!use_msi_x && !use_msi) {
+       if (!qlcnic_use_msi_x && !qlcnic_use_msi) {
                netdev_info(netdev, "no msix or msi support, hence no rss\n");
                return -EINVAL;
        }
@@ -3532,859 +2831,6 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data)
        return err;
 }
 
-static int
-qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, u8 *state,
-                       u8 *rate)
-{
-       *rate = LSB(beacon);
-       *state = MSB(beacon);
-
-       QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
-
-       if (!*state) {
-               *rate = __QLCNIC_MAX_LED_RATE;
-               return 0;
-       } else if (*state > __QLCNIC_MAX_LED_STATE)
-               return -EINVAL;
-
-       if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
-               return -EINVAL;
-
-       return 0;
-}
-
-static ssize_t
-qlcnic_store_beacon(struct device *dev,
-               struct device_attribute *attr, const char *buf, size_t len)
-{
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       int max_sds_rings = adapter->max_sds_rings;
-       u16 beacon;
-       u8 b_state, b_rate;
-       int err;
-
-       if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) {
-               dev_warn(dev, "LED test not supported for non "
-                               "privilege function\n");
-               return -EOPNOTSUPP;
-       }
-
-       if (len != sizeof(u16))
-               return QL_STATUS_INVALID_PARAM;
-
-       memcpy(&beacon, buf, sizeof(u16));
-       err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
-       if (err)
-               return err;
-
-       if (adapter->ahw->beacon_state == b_state)
-               return len;
-
-       rtnl_lock();
-
-       if (!adapter->ahw->beacon_state)
-               if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
-                       rtnl_unlock();
-                       return -EBUSY;
-               }
-
-       if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
-               err = -EIO;
-               goto out;
-       }
-
-       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
-               err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
-               if (err)
-                       goto out;
-               set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
-       }
-
-       err = qlcnic_config_led(adapter, b_state, b_rate);
-
-       if (!err) {
-               err = len;
-               adapter->ahw->beacon_state = b_state;
-       }
-
-       if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
-               qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
-
- out:
-       if (!adapter->ahw->beacon_state)
-               clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
-       rtnl_unlock();
-
-       return err;
-}
-
-static ssize_t
-qlcnic_show_beacon(struct device *dev,
-               struct device_attribute *attr, char *buf)
-{
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-
-       return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
-}
-
-static struct device_attribute dev_attr_beacon = {
-       .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
-       .show = qlcnic_show_beacon,
-       .store = qlcnic_store_beacon,
-};
-
-static int
-qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
-               loff_t offset, size_t size)
-{
-       size_t crb_size = 4;
-
-       if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
-               return -EIO;
-
-       if (offset < QLCNIC_PCI_CRBSPACE) {
-               if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
-                                       QLCNIC_PCI_CAMQM_END))
-                       crb_size = 8;
-               else
-                       return -EINVAL;
-       }
-
-       if ((size != crb_size) || (offset & (crb_size-1)))
-               return  -EINVAL;
-
-       return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
-               struct bin_attribute *attr,
-               char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       u32 data;
-       u64 qmdata;
-       int ret;
-
-       ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
-       if (ret != 0)
-               return ret;
-
-       if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
-               qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
-               memcpy(buf, &qmdata, size);
-       } else {
-               data = QLCRD32(adapter, offset);
-               memcpy(buf, &data, size);
-       }
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
-               struct bin_attribute *attr,
-               char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       u32 data;
-       u64 qmdata;
-       int ret;
-
-       ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
-       if (ret != 0)
-               return ret;
-
-       if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
-               memcpy(&qmdata, buf, size);
-               qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
-       } else {
-               memcpy(&data, buf, size);
-               QLCWR32(adapter, offset, data);
-       }
-       return size;
-}
-
-static int
-qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
-               loff_t offset, size_t size)
-{
-       if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
-               return -EIO;
-
-       if ((size != 8) || (offset & 0x7))
-               return  -EIO;
-
-       return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
-               struct bin_attribute *attr,
-               char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       u64 data;
-       int ret;
-
-       ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
-       if (ret != 0)
-               return ret;
-
-       if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
-               return -EIO;
-
-       memcpy(buf, &data, size);
-
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
-               struct bin_attribute *attr,
-               char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       u64 data;
-       int ret;
-
-       ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
-       if (ret != 0)
-               return ret;
-
-       memcpy(&data, buf, size);
-
-       if (qlcnic_pci_mem_write_2M(adapter, offset, data))
-               return -EIO;
-
-       return size;
-}
-
-static struct bin_attribute bin_attr_crb = {
-       .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
-       .size = 0,
-       .read = qlcnic_sysfs_read_crb,
-       .write = qlcnic_sysfs_write_crb,
-};
-
-static struct bin_attribute bin_attr_mem = {
-       .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
-       .size = 0,
-       .read = qlcnic_sysfs_read_mem,
-       .write = qlcnic_sysfs_write_mem,
-};
-
-static int
-validate_pm_config(struct qlcnic_adapter *adapter,
-                       struct qlcnic_pm_func_cfg *pm_cfg, int count)
-{
-
-       u8 src_pci_func, s_esw_id, d_esw_id;
-       u8 dest_pci_func;
-       int i;
-
-       for (i = 0; i < count; i++) {
-               src_pci_func = pm_cfg[i].pci_func;
-               dest_pci_func = pm_cfg[i].dest_npar;
-               if (src_pci_func >= QLCNIC_MAX_PCI_FUNC
-                               || dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
-                       return QL_STATUS_INVALID_PARAM;
-
-               if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
-                       return QL_STATUS_INVALID_PARAM;
-
-               if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
-                       return QL_STATUS_INVALID_PARAM;
-
-               s_esw_id = adapter->npars[src_pci_func].phy_port;
-               d_esw_id = adapter->npars[dest_pci_func].phy_port;
-
-               if (s_esw_id != d_esw_id)
-                       return QL_STATUS_INVALID_PARAM;
-
-       }
-       return 0;
-
-}
-
-static ssize_t
-qlcnic_sysfs_write_pm_config(struct file *filp, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_pm_func_cfg *pm_cfg;
-       u32 id, action, pci_func;
-       int count, rem, i, ret;
-
-       count   = size / sizeof(struct qlcnic_pm_func_cfg);
-       rem     = size % sizeof(struct qlcnic_pm_func_cfg);
-       if (rem)
-               return QL_STATUS_INVALID_PARAM;
-
-       pm_cfg = (struct qlcnic_pm_func_cfg *) buf;
-
-       ret = validate_pm_config(adapter, pm_cfg, count);
-       if (ret)
-               return ret;
-       for (i = 0; i < count; i++) {
-               pci_func = pm_cfg[i].pci_func;
-               action = !!pm_cfg[i].action;
-               id = adapter->npars[pci_func].phy_port;
-               ret = qlcnic_config_port_mirroring(adapter, id,
-                                               action, pci_func);
-               if (ret)
-                       return ret;
-       }
-
-       for (i = 0; i < count; i++) {
-               pci_func = pm_cfg[i].pci_func;
-               id = adapter->npars[pci_func].phy_port;
-               adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
-               adapter->npars[pci_func].dest_npar = id;
-       }
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_pm_config(struct file *filp, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
-       int i;
-
-       if (size != sizeof(pm_cfg))
-               return QL_STATUS_INVALID_PARAM;
-
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-               if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-                       continue;
-               pm_cfg[i].action = adapter->npars[i].enable_pm;
-               pm_cfg[i].dest_npar = 0;
-               pm_cfg[i].pci_func = i;
-       }
-       memcpy(buf, &pm_cfg, size);
-
-       return size;
-}
-
-static int
-validate_esw_config(struct qlcnic_adapter *adapter,
-       struct qlcnic_esw_func_cfg *esw_cfg, int count)
-{
-       u32 op_mode;
-       u8 pci_func;
-       int i;
-
-       op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
-
-       for (i = 0; i < count; i++) {
-               pci_func = esw_cfg[i].pci_func;
-               if (pci_func >= QLCNIC_MAX_PCI_FUNC)
-                       return QL_STATUS_INVALID_PARAM;
-
-               if (adapter->op_mode == QLCNIC_MGMT_FUNC)
-                       if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
-                               return QL_STATUS_INVALID_PARAM;
-
-               switch (esw_cfg[i].op_mode) {
-               case QLCNIC_PORT_DEFAULTS:
-                       if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
-                                               QLCNIC_NON_PRIV_FUNC) {
-                               if (esw_cfg[i].mac_anti_spoof != 0)
-                                       return QL_STATUS_INVALID_PARAM;
-                               if (esw_cfg[i].mac_override != 1)
-                                       return QL_STATUS_INVALID_PARAM;
-                               if (esw_cfg[i].promisc_mode != 1)
-                                       return QL_STATUS_INVALID_PARAM;
-                       }
-                       break;
-               case QLCNIC_ADD_VLAN:
-                       if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
-                               return QL_STATUS_INVALID_PARAM;
-                       if (!esw_cfg[i].op_type)
-                               return QL_STATUS_INVALID_PARAM;
-                       break;
-               case QLCNIC_DEL_VLAN:
-                       if (!esw_cfg[i].op_type)
-                               return QL_STATUS_INVALID_PARAM;
-                       break;
-               default:
-                       return QL_STATUS_INVALID_PARAM;
-               }
-       }
-       return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_esw_func_cfg *esw_cfg;
-       struct qlcnic_npar_info *npar;
-       int count, rem, i, ret;
-       u8 pci_func, op_mode = 0;
-
-       count   = size / sizeof(struct qlcnic_esw_func_cfg);
-       rem     = size % sizeof(struct qlcnic_esw_func_cfg);
-       if (rem)
-               return QL_STATUS_INVALID_PARAM;
-
-       esw_cfg = (struct qlcnic_esw_func_cfg *) buf;
-       ret = validate_esw_config(adapter, esw_cfg, count);
-       if (ret)
-               return ret;
-
-       for (i = 0; i < count; i++) {
-               if (adapter->op_mode == QLCNIC_MGMT_FUNC)
-                       if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
-                               return QL_STATUS_INVALID_PARAM;
-
-               if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
-                       continue;
-
-               op_mode = esw_cfg[i].op_mode;
-               qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
-               esw_cfg[i].op_mode = op_mode;
-               esw_cfg[i].pci_func = adapter->ahw->pci_func;
-
-               switch (esw_cfg[i].op_mode) {
-               case QLCNIC_PORT_DEFAULTS:
-                       qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
-                       break;
-               case QLCNIC_ADD_VLAN:
-                       qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
-                       break;
-               case QLCNIC_DEL_VLAN:
-                       esw_cfg[i].vlan_id = 0;
-                       qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
-                       break;
-               }
-       }
-
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-               goto out;
-
-       for (i = 0; i < count; i++) {
-               pci_func = esw_cfg[i].pci_func;
-               npar = &adapter->npars[pci_func];
-               switch (esw_cfg[i].op_mode) {
-               case QLCNIC_PORT_DEFAULTS:
-                       npar->promisc_mode = esw_cfg[i].promisc_mode;
-                       npar->mac_override = esw_cfg[i].mac_override;
-                       npar->offload_flags = esw_cfg[i].offload_flags;
-                       npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
-                       npar->discard_tagged = esw_cfg[i].discard_tagged;
-                       break;
-               case QLCNIC_ADD_VLAN:
-                       npar->pvid = esw_cfg[i].vlan_id;
-                       break;
-               case QLCNIC_DEL_VLAN:
-                       npar->pvid = 0;
-                       break;
-               }
-       }
-out:
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_esw_config(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
-       u8 i;
-
-       if (size != sizeof(esw_cfg))
-               return QL_STATUS_INVALID_PARAM;
-
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
-               if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-                       continue;
-               esw_cfg[i].pci_func = i;
-               if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
-                       return QL_STATUS_INVALID_PARAM;
-       }
-       memcpy(buf, &esw_cfg, size);
-
-       return size;
-}
-
-static int
-validate_npar_config(struct qlcnic_adapter *adapter,
-                               struct qlcnic_npar_func_cfg *np_cfg, int count)
-{
-       u8 pci_func, i;
-
-       for (i = 0; i < count; i++) {
-               pci_func = np_cfg[i].pci_func;
-               if (pci_func >= QLCNIC_MAX_PCI_FUNC)
-                       return QL_STATUS_INVALID_PARAM;
-
-               if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
-                       return QL_STATUS_INVALID_PARAM;
-
-               if (!IS_VALID_BW(np_cfg[i].min_bw) ||
-                   !IS_VALID_BW(np_cfg[i].max_bw))
-                       return QL_STATUS_INVALID_PARAM;
-       }
-       return 0;
-}
-
-static ssize_t
-qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_info nic_info;
-       struct qlcnic_npar_func_cfg *np_cfg;
-       int i, count, rem, ret;
-       u8 pci_func;
-
-       count   = size / sizeof(struct qlcnic_npar_func_cfg);
-       rem     = size % sizeof(struct qlcnic_npar_func_cfg);
-       if (rem)
-               return QL_STATUS_INVALID_PARAM;
-
-       np_cfg = (struct qlcnic_npar_func_cfg *) buf;
-       ret = validate_npar_config(adapter, np_cfg, count);
-       if (ret)
-               return ret;
-
-       for (i = 0; i < count ; i++) {
-               pci_func = np_cfg[i].pci_func;
-               ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
-               if (ret)
-                       return ret;
-               nic_info.pci_func = pci_func;
-               nic_info.min_tx_bw = np_cfg[i].min_bw;
-               nic_info.max_tx_bw = np_cfg[i].max_bw;
-               ret = qlcnic_set_nic_info(adapter, &nic_info);
-               if (ret)
-                       return ret;
-               adapter->npars[i].min_bw = nic_info.min_tx_bw;
-               adapter->npars[i].max_bw = nic_info.max_tx_bw;
-       }
-
-       return size;
-
-}
-static ssize_t
-qlcnic_sysfs_read_npar_config(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_info nic_info;
-       struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
-       int i, ret;
-
-       if (size != sizeof(np_cfg))
-               return QL_STATUS_INVALID_PARAM;
-
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
-               if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
-                       continue;
-               ret = qlcnic_get_nic_info(adapter, &nic_info, i);
-               if (ret)
-                       return ret;
-
-               np_cfg[i].pci_func = i;
-               np_cfg[i].op_mode = (u8)nic_info.op_mode;
-               np_cfg[i].port_num = nic_info.phys_port;
-               np_cfg[i].fw_capab = nic_info.capabilities;
-               np_cfg[i].min_bw = nic_info.min_tx_bw ;
-               np_cfg[i].max_bw = nic_info.max_tx_bw;
-               np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
-               np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
-       }
-       memcpy(buf, &np_cfg, size);
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_get_port_stats(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_esw_statistics port_stats;
-       int ret;
-
-       if (size != sizeof(struct qlcnic_esw_statistics))
-               return QL_STATUS_INVALID_PARAM;
-
-       if (offset >= QLCNIC_MAX_PCI_FUNC)
-               return QL_STATUS_INVALID_PARAM;
-
-       memset(&port_stats, 0, size);
-       ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
-                                                               &port_stats.rx);
-       if (ret)
-               return ret;
-
-       ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
-                                                               &port_stats.tx);
-       if (ret)
-               return ret;
-
-       memcpy(buf, &port_stats, size);
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_get_esw_stats(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_esw_statistics esw_stats;
-       int ret;
-
-       if (size != sizeof(struct qlcnic_esw_statistics))
-               return QL_STATUS_INVALID_PARAM;
-
-       if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
-               return QL_STATUS_INVALID_PARAM;
-
-       memset(&esw_stats, 0, size);
-       ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
-                                                               &esw_stats.rx);
-       if (ret)
-               return ret;
-
-       ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
-                                                               &esw_stats.tx);
-       if (ret)
-               return ret;
-
-       memcpy(buf, &esw_stats, size);
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_clear_esw_stats(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       int ret;
-
-       if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
-               return QL_STATUS_INVALID_PARAM;
-
-       ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
-                                               QLCNIC_QUERY_RX_COUNTER);
-       if (ret)
-               return ret;
-
-       ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
-                                               QLCNIC_QUERY_TX_COUNTER);
-       if (ret)
-               return ret;
-
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_clear_port_stats(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       int ret;
-
-       if (offset >= QLCNIC_MAX_PCI_FUNC)
-               return QL_STATUS_INVALID_PARAM;
-
-       ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
-                                               QLCNIC_QUERY_RX_COUNTER);
-       if (ret)
-               return ret;
-
-       ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
-                                               QLCNIC_QUERY_TX_COUNTER);
-       if (ret)
-               return ret;
-
-       return size;
-}
-
-static ssize_t
-qlcnic_sysfs_read_pci_config(struct file *file, struct kobject *kobj,
-       struct bin_attribute *attr, char *buf, loff_t offset, size_t size)
-{
-       struct device *dev = container_of(kobj, struct device, kobj);
-       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
-       struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
-       struct qlcnic_pci_info *pci_info;
-       int i, ret;
-
-       if (size != sizeof(pci_cfg))
-               return QL_STATUS_INVALID_PARAM;
-
-       pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
-       if (!pci_info)
-               return -ENOMEM;
-
-       ret = qlcnic_get_pci_info(adapter, pci_info);
-       if (ret) {
-               kfree(pci_info);
-               return ret;
-       }
-
-       for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
-               pci_cfg[i].pci_func = pci_info[i].id;
-               pci_cfg[i].func_type = pci_info[i].type;
-               pci_cfg[i].port_num = pci_info[i].default_port;
-               pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
-               pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
-               memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
-       }
-       memcpy(buf, &pci_cfg, size);
-       kfree(pci_info);
-       return size;
-}
-static struct bin_attribute bin_attr_npar_config = {
-       .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
-       .size = 0,
-       .read = qlcnic_sysfs_read_npar_config,
-       .write = qlcnic_sysfs_write_npar_config,
-};
-
-static struct bin_attribute bin_attr_pci_config = {
-       .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
-       .size = 0,
-       .read = qlcnic_sysfs_read_pci_config,
-       .write = NULL,
-};
-
-static struct bin_attribute bin_attr_port_stats = {
-       .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
-       .size = 0,
-       .read = qlcnic_sysfs_get_port_stats,
-       .write = qlcnic_sysfs_clear_port_stats,
-};
-
-static struct bin_attribute bin_attr_esw_stats = {
-       .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
-       .size = 0,
-       .read = qlcnic_sysfs_get_esw_stats,
-       .write = qlcnic_sysfs_clear_esw_stats,
-};
-
-static struct bin_attribute bin_attr_esw_config = {
-       .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
-       .size = 0,
-       .read = qlcnic_sysfs_read_esw_config,
-       .write = qlcnic_sysfs_write_esw_config,
-};
-
-static struct bin_attribute bin_attr_pm_config = {
-       .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
-       .size = 0,
-       .read = qlcnic_sysfs_read_pm_config,
-       .write = qlcnic_sysfs_write_pm_config,
-};
-
-static void
-qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
-{
-       struct device *dev = &adapter->pdev->dev;
-
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
-               if (device_create_file(dev, &dev_attr_bridged_mode))
-                       dev_warn(dev,
-                               "failed to create bridged_mode sysfs entry\n");
-}
-
-static void
-qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
-{
-       struct device *dev = &adapter->pdev->dev;
-
-       if (adapter->capabilities & QLCNIC_FW_CAPABILITY_BDG)
-               device_remove_file(dev, &dev_attr_bridged_mode);
-}
-
-static void
-qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
-{
-       struct device *dev = &adapter->pdev->dev;
-       u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-
-       if (device_create_bin_file(dev, &bin_attr_port_stats))
-               dev_info(dev, "failed to create port stats sysfs entry");
-
-       if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
-               return;
-       if (device_create_file(dev, &dev_attr_diag_mode))
-               dev_info(dev, "failed to create diag_mode sysfs entry\n");
-       if (device_create_bin_file(dev, &bin_attr_crb))
-               dev_info(dev, "failed to create crb sysfs entry\n");
-       if (device_create_bin_file(dev, &bin_attr_mem))
-               dev_info(dev, "failed to create mem sysfs entry\n");
-
-       if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
-               return;
-
-       if (device_create_bin_file(dev, &bin_attr_pci_config))
-               dev_info(dev, "failed to create pci config sysfs entry");
-       if (device_create_file(dev, &dev_attr_beacon))
-               dev_info(dev, "failed to create beacon sysfs entry");
-
-       if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
-               return;
-       if (device_create_bin_file(dev, &bin_attr_esw_config))
-               dev_info(dev, "failed to create esw config sysfs entry");
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-               return;
-       if (device_create_bin_file(dev, &bin_attr_npar_config))
-               dev_info(dev, "failed to create npar config sysfs entry");
-       if (device_create_bin_file(dev, &bin_attr_pm_config))
-               dev_info(dev, "failed to create pm config sysfs entry");
-       if (device_create_bin_file(dev, &bin_attr_esw_stats))
-               dev_info(dev, "failed to create eswitch stats sysfs entry");
-}
-
-static void
-qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
-{
-       struct device *dev = &adapter->pdev->dev;
-       u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
-
-       device_remove_bin_file(dev, &bin_attr_port_stats);
-
-       if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
-               return;
-       device_remove_file(dev, &dev_attr_diag_mode);
-       device_remove_bin_file(dev, &bin_attr_crb);
-       device_remove_bin_file(dev, &bin_attr_mem);
-       if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
-               return;
-       device_remove_bin_file(dev, &bin_attr_pci_config);
-       device_remove_file(dev, &dev_attr_beacon);
-       if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
-               return;
-       device_remove_bin_file(dev, &bin_attr_esw_config);
-       if (adapter->op_mode != QLCNIC_MGMT_FUNC)
-               return;
-       device_remove_bin_file(dev, &bin_attr_npar_config);
-       device_remove_bin_file(dev, &bin_attr_pm_config);
-       device_remove_bin_file(dev, &bin_attr_esw_stats);
-}
-
 #ifdef CONFIG_INET
 
 #define is_qlcnic_netdev(dev) (dev->netdev_ops == &qlcnic_netdev_ops)
@@ -4523,7 +2969,7 @@ static void
 qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event)
 { }
 #endif
-static const struct pci_error_handlers qlcnic_err_handler = {
+static struct pci_error_handlers qlcnic_err_handler = {
        .error_detected = qlcnic_io_error_detected,
        .slot_reset = qlcnic_io_slot_reset,
        .resume = qlcnic_io_resume,
@@ -4533,7 +2979,7 @@ static struct pci_driver qlcnic_driver = {
        .name = qlcnic_driver_name,
        .id_table = qlcnic_pci_tbl,
        .probe = qlcnic_probe,
-       .remove = __devexit_p(qlcnic_remove),
+       .remove = qlcnic_remove,
 #ifdef CONFIG_PM
        .suspend = qlcnic_suspend,
        .resume = qlcnic_resume,
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c
new file mode 100644 (file)
index 0000000..12ff292
--- /dev/null
@@ -0,0 +1,629 @@
+#include "qlcnic.h"
+#include "qlcnic_hdr.h"
+
+#include <net/ip.h>
+
+#define QLCNIC_DUMP_WCRB       BIT_0
+#define QLCNIC_DUMP_RWCRB      BIT_1
+#define QLCNIC_DUMP_ANDCRB     BIT_2
+#define QLCNIC_DUMP_ORCRB      BIT_3
+#define QLCNIC_DUMP_POLLCRB    BIT_4
+#define QLCNIC_DUMP_RD_SAVE    BIT_5
+#define QLCNIC_DUMP_WRT_SAVED  BIT_6
+#define QLCNIC_DUMP_MOD_SAVE_ST        BIT_7
+#define QLCNIC_DUMP_SKIP       BIT_7
+
+#define QLCNIC_DUMP_MASK_MAX   0xff
+
+struct qlcnic_common_entry_hdr {
+       u32     type;
+       u32     offset;
+       u32     cap_size;
+       u8      mask;
+       u8      rsvd[2];
+       u8      flags;
+} __packed;
+
+struct __crb {
+       u32     addr;
+       u8      stride;
+       u8      rsvd1[3];
+       u32     data_size;
+       u32     no_ops;
+       u32     rsvd2[4];
+} __packed;
+
+struct __ctrl {
+       u32     addr;
+       u8      stride;
+       u8      index_a;
+       u16     timeout;
+       u32     data_size;
+       u32     no_ops;
+       u8      opcode;
+       u8      index_v;
+       u8      shl_val;
+       u8      shr_val;
+       u32     val1;
+       u32     val2;
+       u32     val3;
+} __packed;
+
+struct __cache {
+       u32     addr;
+       u16     stride;
+       u16     init_tag_val;
+       u32     size;
+       u32     no_ops;
+       u32     ctrl_addr;
+       u32     ctrl_val;
+       u32     read_addr;
+       u8      read_addr_stride;
+       u8      read_addr_num;
+       u8      rsvd1[2];
+} __packed;
+
+struct __ocm {
+       u8      rsvd[8];
+       u32     size;
+       u32     no_ops;
+       u8      rsvd1[8];
+       u32     read_addr;
+       u32     read_addr_stride;
+} __packed;
+
+struct __mem {
+       u8      rsvd[24];
+       u32     addr;
+       u32     size;
+} __packed;
+
+struct __mux {
+       u32     addr;
+       u8      rsvd[4];
+       u32     size;
+       u32     no_ops;
+       u32     val;
+       u32     val_stride;
+       u32     read_addr;
+       u8      rsvd2[4];
+} __packed;
+
+struct __queue {
+       u32     sel_addr;
+       u16     stride;
+       u8      rsvd[2];
+       u32     size;
+       u32     no_ops;
+       u8      rsvd2[8];
+       u32     read_addr;
+       u8      read_addr_stride;
+       u8      read_addr_cnt;
+       u8      rsvd3[2];
+} __packed;
+
+struct qlcnic_dump_entry {
+       struct qlcnic_common_entry_hdr hdr;
+       union {
+               struct __crb    crb;
+               struct __cache  cache;
+               struct __ocm    ocm;
+               struct __mem    mem;
+               struct __mux    mux;
+               struct __queue  que;
+               struct __ctrl   ctrl;
+       } region;
+} __packed;
+
+enum qlcnic_minidump_opcode {
+       QLCNIC_DUMP_NOP         = 0,
+       QLCNIC_DUMP_READ_CRB    = 1,
+       QLCNIC_DUMP_READ_MUX    = 2,
+       QLCNIC_DUMP_QUEUE       = 3,
+       QLCNIC_DUMP_BRD_CONFIG  = 4,
+       QLCNIC_DUMP_READ_OCM    = 6,
+       QLCNIC_DUMP_PEG_REG     = 7,
+       QLCNIC_DUMP_L1_DTAG     = 8,
+       QLCNIC_DUMP_L1_ITAG     = 9,
+       QLCNIC_DUMP_L1_DATA     = 11,
+       QLCNIC_DUMP_L1_INST     = 12,
+       QLCNIC_DUMP_L2_DTAG     = 21,
+       QLCNIC_DUMP_L2_ITAG     = 22,
+       QLCNIC_DUMP_L2_DATA     = 23,
+       QLCNIC_DUMP_L2_INST     = 24,
+       QLCNIC_DUMP_READ_ROM    = 71,
+       QLCNIC_DUMP_READ_MEM    = 72,
+       QLCNIC_DUMP_READ_CTRL   = 98,
+       QLCNIC_DUMP_TLHDR       = 99,
+       QLCNIC_DUMP_RDEND       = 255
+};
+
+struct qlcnic_dump_operations {
+       enum qlcnic_minidump_opcode opcode;
+       u32 (*handler)(struct qlcnic_adapter *, struct qlcnic_dump_entry *,
+                      __le32 *);
+};
+
+static void qlcnic_read_dump_reg(u32 addr, void __iomem *bar0, u32 *data)
+{
+       u32 dest;
+       void __iomem *window_reg;
+
+       dest = addr & 0xFFFF0000;
+       window_reg = bar0 + QLCNIC_FW_DUMP_REG1;
+       writel(dest, window_reg);
+       readl(window_reg);
+       window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+       *data = readl(window_reg);
+}
+
+static void qlcnic_write_dump_reg(u32 addr, void __iomem *bar0, u32 data)
+{
+       u32 dest;
+       void __iomem *window_reg;
+
+       dest = addr & 0xFFFF0000;
+       window_reg = bar0 + QLCNIC_FW_DUMP_REG1;
+       writel(dest, window_reg);
+       readl(window_reg);
+       window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr);
+       writel(data, window_reg);
+       readl(window_reg);
+}
+
+/* FW dump related functions */
+static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter,
+                          struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       int i;
+       u32 addr, data;
+       struct __crb *crb = &entry->region.crb;
+       void __iomem *base = adapter->ahw->pci_base0;
+
+       addr = crb->addr;
+
+       for (i = 0; i < crb->no_ops; i++) {
+               qlcnic_read_dump_reg(addr, base, &data);
+               *buffer++ = cpu_to_le32(addr);
+               *buffer++ = cpu_to_le32(data);
+               addr += crb->stride;
+       }
+       return crb->no_ops * 2 * sizeof(u32);
+}
+
+static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter,
+                           struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       int i, k, timeout = 0;
+       void __iomem *base = adapter->ahw->pci_base0;
+       u32 addr, data;
+       u8 opcode, no_ops;
+       struct __ctrl *ctr = &entry->region.ctrl;
+       struct qlcnic_dump_template_hdr *t_hdr = adapter->ahw->fw_dump.tmpl_hdr;
+
+       addr = ctr->addr;
+       no_ops = ctr->no_ops;
+
+       for (i = 0; i < no_ops; i++) {
+               k = 0;
+               opcode = 0;
+               for (k = 0; k < 8; k++) {
+                       if (!(ctr->opcode & (1 << k)))
+                               continue;
+                       switch (1 << k) {
+                       case QLCNIC_DUMP_WCRB:
+                               qlcnic_write_dump_reg(addr, base, ctr->val1);
+                               break;
+                       case QLCNIC_DUMP_RWCRB:
+                               qlcnic_read_dump_reg(addr, base, &data);
+                               qlcnic_write_dump_reg(addr, base, data);
+                               break;
+                       case QLCNIC_DUMP_ANDCRB:
+                               qlcnic_read_dump_reg(addr, base, &data);
+                               qlcnic_write_dump_reg(addr, base,
+                                                     data & ctr->val2);
+                               break;
+                       case QLCNIC_DUMP_ORCRB:
+                               qlcnic_read_dump_reg(addr, base, &data);
+                               qlcnic_write_dump_reg(addr, base,
+                                                     data | ctr->val3);
+                               break;
+                       case QLCNIC_DUMP_POLLCRB:
+                               while (timeout <= ctr->timeout) {
+                                       qlcnic_read_dump_reg(addr, base, &data);
+                                       if ((data & ctr->val2) == ctr->val1)
+                                               break;
+                                       msleep(1);
+                                       timeout++;
+                               }
+                               if (timeout > ctr->timeout) {
+                                       dev_info(&adapter->pdev->dev,
+                                       "Timed out, aborting poll CRB\n");
+                                       return -EINVAL;
+                               }
+                               break;
+                       case QLCNIC_DUMP_RD_SAVE:
+                               if (ctr->index_a)
+                                       addr = t_hdr->saved_state[ctr->index_a];
+                               qlcnic_read_dump_reg(addr, base, &data);
+                               t_hdr->saved_state[ctr->index_v] = data;
+                               break;
+                       case QLCNIC_DUMP_WRT_SAVED:
+                               if (ctr->index_v)
+                                       data = t_hdr->saved_state[ctr->index_v];
+                               else
+                                       data = ctr->val1;
+                               if (ctr->index_a)
+                                       addr = t_hdr->saved_state[ctr->index_a];
+                               qlcnic_write_dump_reg(addr, base, data);
+                               break;
+                       case QLCNIC_DUMP_MOD_SAVE_ST:
+                               data = t_hdr->saved_state[ctr->index_v];
+                               data <<= ctr->shl_val;
+                               data >>= ctr->shr_val;
+                               if (ctr->val2)
+                                       data &= ctr->val2;
+                               data |= ctr->val3;
+                               data += ctr->val1;
+                               t_hdr->saved_state[ctr->index_v] = data;
+                               break;
+                       default:
+                               dev_info(&adapter->pdev->dev,
+                                        "Unknown opcode\n");
+                               break;
+                       }
+               }
+               addr += ctr->stride;
+       }
+       return 0;
+}
+
+static u32 qlcnic_dump_mux(struct qlcnic_adapter *adapter,
+                          struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       int loop;
+       u32 val, data = 0;
+       struct __mux *mux = &entry->region.mux;
+       void __iomem *base = adapter->ahw->pci_base0;
+
+       val = mux->val;
+       for (loop = 0; loop < mux->no_ops; loop++) {
+               qlcnic_write_dump_reg(mux->addr, base, val);
+               qlcnic_read_dump_reg(mux->read_addr, base, &data);
+               *buffer++ = cpu_to_le32(val);
+               *buffer++ = cpu_to_le32(data);
+               val += mux->val_stride;
+       }
+       return 2 * mux->no_ops * sizeof(u32);
+}
+
+static u32 qlcnic_dump_que(struct qlcnic_adapter *adapter,
+                          struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       int i, loop;
+       u32 cnt, addr, data, que_id = 0;
+       void __iomem *base = adapter->ahw->pci_base0;
+       struct __queue *que = &entry->region.que;
+
+       addr = que->read_addr;
+       cnt = que->read_addr_cnt;
+
+       for (loop = 0; loop < que->no_ops; loop++) {
+               qlcnic_write_dump_reg(que->sel_addr, base, que_id);
+               addr = que->read_addr;
+               for (i = 0; i < cnt; i++) {
+                       qlcnic_read_dump_reg(addr, base, &data);
+                       *buffer++ = cpu_to_le32(data);
+                       addr += que->read_addr_stride;
+               }
+               que_id += que->stride;
+       }
+       return que->no_ops * cnt * sizeof(u32);
+}
+
+static u32 qlcnic_dump_ocm(struct qlcnic_adapter *adapter,
+                          struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       int i;
+       u32 data;
+       void __iomem *addr;
+       struct __ocm *ocm = &entry->region.ocm;
+
+       addr = adapter->ahw->pci_base0 + ocm->read_addr;
+       for (i = 0; i < ocm->no_ops; i++) {
+               data = readl(addr);
+               *buffer++ = cpu_to_le32(data);
+               addr += ocm->read_addr_stride;
+       }
+       return ocm->no_ops * sizeof(u32);
+}
+
+static u32 qlcnic_read_rom(struct qlcnic_adapter *adapter,
+                          struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       int i, count = 0;
+       u32 fl_addr, size, val, lck_val, addr;
+       struct __mem *rom = &entry->region.mem;
+       void __iomem *base = adapter->ahw->pci_base0;
+
+       fl_addr = rom->addr;
+       size = rom->size/4;
+lock_try:
+       lck_val = readl(base + QLCNIC_FLASH_SEM2_LK);
+       if (!lck_val && count < MAX_CTL_CHECK) {
+               msleep(10);
+               count++;
+               goto lock_try;
+       }
+       writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID));
+       for (i = 0; i < size; i++) {
+               addr = fl_addr & 0xFFFF0000;
+               qlcnic_write_dump_reg(FLASH_ROM_WINDOW, base, addr);
+               addr = LSW(fl_addr) + FLASH_ROM_DATA;
+               qlcnic_read_dump_reg(addr, base, &val);
+               fl_addr += 4;
+               *buffer++ = cpu_to_le32(val);
+       }
+       readl(base + QLCNIC_FLASH_SEM2_ULK);
+       return rom->size;
+}
+
+static u32 qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter,
+                               struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       int i;
+       u32 cnt, val, data, addr;
+       void __iomem *base = adapter->ahw->pci_base0;
+       struct __cache *l1 = &entry->region.cache;
+
+       val = l1->init_tag_val;
+
+       for (i = 0; i < l1->no_ops; i++) {
+               qlcnic_write_dump_reg(l1->addr, base, val);
+               qlcnic_write_dump_reg(l1->ctrl_addr, base, LSW(l1->ctrl_val));
+               addr = l1->read_addr;
+               cnt = l1->read_addr_num;
+               while (cnt) {
+                       qlcnic_read_dump_reg(addr, base, &data);
+                       *buffer++ = cpu_to_le32(data);
+                       addr += l1->read_addr_stride;
+                       cnt--;
+               }
+               val += l1->stride;
+       }
+       return l1->no_ops * l1->read_addr_num * sizeof(u32);
+}
+
+static u32 qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter,
+                               struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       int i;
+       u32 cnt, val, data, addr;
+       u8 poll_mask, poll_to, time_out = 0;
+       void __iomem *base = adapter->ahw->pci_base0;
+       struct __cache *l2 = &entry->region.cache;
+
+       val = l2->init_tag_val;
+       poll_mask = LSB(MSW(l2->ctrl_val));
+       poll_to = MSB(MSW(l2->ctrl_val));
+
+       for (i = 0; i < l2->no_ops; i++) {
+               qlcnic_write_dump_reg(l2->addr, base, val);
+               if (LSW(l2->ctrl_val))
+                       qlcnic_write_dump_reg(l2->ctrl_addr, base,
+                                             LSW(l2->ctrl_val));
+               if (!poll_mask)
+                       goto skip_poll;
+               do {
+                       qlcnic_read_dump_reg(l2->ctrl_addr, base, &data);
+                       if (!(data & poll_mask))
+                               break;
+                       msleep(1);
+                       time_out++;
+               } while (time_out <= poll_to);
+
+               if (time_out > poll_to) {
+                       dev_err(&adapter->pdev->dev,
+                               "Timeout exceeded in %s, aborting dump\n",
+                               __func__);
+                       return -EINVAL;
+               }
+skip_poll:
+               addr = l2->read_addr;
+               cnt = l2->read_addr_num;
+               while (cnt) {
+                       qlcnic_read_dump_reg(addr, base, &data);
+                       *buffer++ = cpu_to_le32(data);
+                       addr += l2->read_addr_stride;
+                       cnt--;
+               }
+               val += l2->stride;
+       }
+       return l2->no_ops * l2->read_addr_num * sizeof(u32);
+}
+
+static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter,
+                             struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       u32 addr, data, test, ret = 0;
+       int i, reg_read;
+       struct __mem *mem = &entry->region.mem;
+       void __iomem *base = adapter->ahw->pci_base0;
+
+       reg_read = mem->size;
+       addr = mem->addr;
+       /* check for data size of multiple of 16 and 16 byte alignment */
+       if ((addr & 0xf) || (reg_read%16)) {
+               dev_info(&adapter->pdev->dev,
+                        "Unaligned memory addr:0x%x size:0x%x\n",
+                        addr, reg_read);
+               return -EINVAL;
+       }
+
+       mutex_lock(&adapter->ahw->mem_lock);
+
+       while (reg_read != 0) {
+               qlcnic_write_dump_reg(MIU_TEST_ADDR_LO, base, addr);
+               qlcnic_write_dump_reg(MIU_TEST_ADDR_HI, base, 0);
+               qlcnic_write_dump_reg(MIU_TEST_CTR, base,
+                                     TA_CTL_ENABLE | TA_CTL_START);
+
+               for (i = 0; i < MAX_CTL_CHECK; i++) {
+                       qlcnic_read_dump_reg(MIU_TEST_CTR, base, &test);
+                       if (!(test & TA_CTL_BUSY))
+                               break;
+               }
+               if (i == MAX_CTL_CHECK) {
+                       if (printk_ratelimit()) {
+                               dev_err(&adapter->pdev->dev,
+                                       "failed to read through agent\n");
+                               ret = -EINVAL;
+                               goto out;
+                       }
+               }
+               for (i = 0; i < 4; i++) {
+                       qlcnic_read_dump_reg(MIU_TEST_READ_DATA[i], base,
+                                            &data);
+                       *buffer++ = cpu_to_le32(data);
+               }
+               addr += 16;
+               reg_read -= 16;
+               ret += 16;
+       }
+out:
+       mutex_unlock(&adapter->ahw->mem_lock);
+       return mem->size;
+}
+
+static u32 qlcnic_dump_nop(struct qlcnic_adapter *adapter,
+                          struct qlcnic_dump_entry *entry, __le32 *buffer)
+{
+       entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+       return 0;
+}
+
+static const struct qlcnic_dump_operations fw_dump_ops[] = {
+       { QLCNIC_DUMP_NOP, qlcnic_dump_nop },
+       { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb },
+       { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux },
+       { QLCNIC_DUMP_QUEUE, qlcnic_dump_que },
+       { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom },
+       { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm },
+       { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl },
+       { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache },
+       { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache },
+       { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache },
+       { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache },
+       { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache },
+       { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache },
+       { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache },
+       { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache },
+       { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom },
+       { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory },
+       { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl },
+       { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop },
+       { QLCNIC_DUMP_RDEND, qlcnic_dump_nop },
+};
+
+/* Walk the template and collect dump for each entry in the dump template */
+static int
+qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry,
+                       u32 size)
+{
+       int ret = 1;
+       if (size != entry->hdr.cap_size) {
+               dev_info(dev,
+                        "Invalid dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n",
+               entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size);
+               dev_info(dev, "Aborting further dump capture\n");
+               ret = 0;
+       }
+       return ret;
+}
+
+int qlcnic_dump_fw(struct qlcnic_adapter *adapter)
+{
+       __le32 *buffer;
+       char mesg[64];
+       char *msg[] = {mesg, NULL};
+       int i, k, ops_cnt, ops_index, dump_size = 0;
+       u32 entry_offset, dump, no_entries, buf_offset = 0;
+       struct qlcnic_dump_entry *entry;
+       struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
+       struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr;
+
+       if (fw_dump->clr) {
+               dev_info(&adapter->pdev->dev,
+                        "Previous dump not cleared, not capturing dump\n");
+               return -EIO;
+       }
+       /* Calculate the size for dump data area only */
+       for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++)
+               if (i & tmpl_hdr->drv_cap_mask)
+                       dump_size += tmpl_hdr->cap_sizes[k];
+       if (!dump_size)
+               return -EIO;
+
+       fw_dump->data = vzalloc(dump_size);
+       if (!fw_dump->data) {
+               dev_info(&adapter->pdev->dev,
+                        "Unable to allocate (%d KB) for fw dump\n",
+                        dump_size / 1024);
+               return -ENOMEM;
+       }
+       buffer = fw_dump->data;
+       fw_dump->size = dump_size;
+       no_entries = tmpl_hdr->num_entries;
+       ops_cnt = ARRAY_SIZE(fw_dump_ops);
+       entry_offset = tmpl_hdr->offset;
+       tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION;
+       tmpl_hdr->sys_info[1] = adapter->fw_version;
+
+       for (i = 0; i < no_entries; i++) {
+               entry = (void *)tmpl_hdr + entry_offset;
+               if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) {
+                       entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+                       entry_offset += entry->hdr.offset;
+                       continue;
+               }
+               /* Find the handler for this entry */
+               ops_index = 0;
+               while (ops_index < ops_cnt) {
+                       if (entry->hdr.type == fw_dump_ops[ops_index].opcode)
+                               break;
+                       ops_index++;
+               }
+               if (ops_index == ops_cnt) {
+                       dev_info(&adapter->pdev->dev,
+                                "Invalid entry type %d, exiting dump\n",
+                                entry->hdr.type);
+                       goto error;
+               }
+               /* Collect dump for this entry */
+               dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer);
+               if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry,
+                                                    dump))
+                       entry->hdr.flags |= QLCNIC_DUMP_SKIP;
+               buf_offset += entry->hdr.cap_size;
+               entry_offset += entry->hdr.offset;
+               buffer = fw_dump->data + buf_offset;
+       }
+       if (dump_size != buf_offset) {
+               dev_info(&adapter->pdev->dev,
+                        "Captured(%d) and expected size(%d) do not match\n",
+                        buf_offset, dump_size);
+               goto error;
+       } else {
+               fw_dump->clr = 1;
+               snprintf(mesg, sizeof(mesg), "FW_DUMP=%s",
+                        adapter->netdev->name);
+               dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n",
+                        fw_dump->size);
+               /* Send a udev event to notify availability of FW dump */
+               kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg);
+               return 0;
+       }
+error:
+       vfree(fw_dump->data);
+       return -EINVAL;
+}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
new file mode 100644 (file)
index 0000000..341d37c
--- /dev/null
@@ -0,0 +1,960 @@
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+
+#include "qlcnic.h"
+
+#include <linux/swab.h>
+#include <linux/dma-mapping.h>
+#include <net/ip.h>
+#include <linux/ipv6.h>
+#include <linux/inetdevice.h>
+#include <linux/sysfs.h>
+#include <linux/aer.h>
+#include <linux/log2.h>
+
+int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
+{
+       return -EOPNOTSUPP;
+}
+
+int qlcnicvf_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
+{
+       return -EOPNOTSUPP;
+}
+
+static ssize_t qlcnic_store_bridged_mode(struct device *dev,
+                                        struct device_attribute *attr,
+                                        const char *buf, size_t len)
+{
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       unsigned long new;
+       int ret = -EINVAL;
+
+       if (!(adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG))
+               goto err_out;
+
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
+               goto err_out;
+
+       if (strict_strtoul(buf, 2, &new))
+               goto err_out;
+
+       if (!adapter->nic_ops->config_bridged_mode(adapter, !!new))
+               ret = len;
+
+err_out:
+       return ret;
+}
+
+static ssize_t qlcnic_show_bridged_mode(struct device *dev,
+                                       struct device_attribute *attr,
+                                       char *buf)
+{
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       int bridged_mode = 0;
+
+       if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+               bridged_mode = !!(adapter->flags & QLCNIC_BRIDGE_ENABLED);
+
+       return sprintf(buf, "%d\n", bridged_mode);
+}
+
+static ssize_t qlcnic_store_diag_mode(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t len)
+{
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       unsigned long new;
+
+       if (strict_strtoul(buf, 2, &new))
+               return -EINVAL;
+
+       if (!!new != !!(adapter->flags & QLCNIC_DIAG_ENABLED))
+               adapter->flags ^= QLCNIC_DIAG_ENABLED;
+
+       return len;
+}
+
+static ssize_t qlcnic_show_diag_mode(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n",
+                      !!(adapter->flags & QLCNIC_DIAG_ENABLED));
+}
+
+static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon,
+                                 u8 *state, u8 *rate)
+{
+       *rate = LSB(beacon);
+       *state = MSB(beacon);
+
+       QLCDB(adapter, DRV, "rate %x state %x\n", *rate, *state);
+
+       if (!*state) {
+               *rate = __QLCNIC_MAX_LED_RATE;
+               return 0;
+       } else if (*state > __QLCNIC_MAX_LED_STATE) {
+               return -EINVAL;
+       }
+
+       if ((!*rate) || (*rate > __QLCNIC_MAX_LED_RATE))
+               return -EINVAL;
+
+       return 0;
+}
+
+static ssize_t qlcnic_store_beacon(struct device *dev,
+                                  struct device_attribute *attr,
+                                  const char *buf, size_t len)
+{
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       int max_sds_rings = adapter->max_sds_rings;
+       u16 beacon;
+       u8 b_state, b_rate;
+       int err;
+
+       if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) {
+               dev_warn(dev,
+                        "LED test not supported in non privileged mode\n");
+               return -EOPNOTSUPP;
+       }
+
+       if (len != sizeof(u16))
+               return QL_STATUS_INVALID_PARAM;
+
+       memcpy(&beacon, buf, sizeof(u16));
+       err = qlcnic_validate_beacon(adapter, beacon, &b_state, &b_rate);
+       if (err)
+               return err;
+
+       if (adapter->ahw->beacon_state == b_state)
+               return len;
+
+       rtnl_lock();
+
+       if (!adapter->ahw->beacon_state)
+               if (test_and_set_bit(__QLCNIC_LED_ENABLE, &adapter->state)) {
+                       rtnl_unlock();
+                       return -EBUSY;
+               }
+
+       if (test_bit(__QLCNIC_RESETTING, &adapter->state)) {
+               err = -EIO;
+               goto out;
+       }
+
+       if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) {
+               err = qlcnic_diag_alloc_res(adapter->netdev, QLCNIC_LED_TEST);
+               if (err)
+                       goto out;
+               set_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state);
+       }
+
+       err = qlcnic_config_led(adapter, b_state, b_rate);
+
+       if (!err) {
+               err = len;
+               adapter->ahw->beacon_state = b_state;
+       }
+
+       if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state))
+               qlcnic_diag_free_res(adapter->netdev, max_sds_rings);
+
+ out:
+       if (!adapter->ahw->beacon_state)
+               clear_bit(__QLCNIC_LED_ENABLE, &adapter->state);
+       rtnl_unlock();
+
+       return err;
+}
+
+static ssize_t qlcnic_show_beacon(struct device *dev,
+                                 struct device_attribute *attr, char *buf)
+{
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", adapter->ahw->beacon_state);
+}
+
+static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
+                                    loff_t offset, size_t size)
+{
+       size_t crb_size = 4;
+
+       if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+               return -EIO;
+
+       if (offset < QLCNIC_PCI_CRBSPACE) {
+               if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM,
+                                 QLCNIC_PCI_CAMQM_END))
+                       crb_size = 8;
+               else
+                       return -EINVAL;
+       }
+
+       if ((size != crb_size) || (offset & (crb_size-1)))
+               return  -EINVAL;
+
+       return 0;
+}
+
+static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
+                                    struct bin_attribute *attr, char *buf,
+                                    loff_t offset, size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       u32 data;
+       u64 qmdata;
+       int ret;
+
+       ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
+       if (ret != 0)
+               return ret;
+
+       if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+               qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
+               memcpy(buf, &qmdata, size);
+       } else {
+               data = QLCRD32(adapter, offset);
+               memcpy(buf, &data, size);
+       }
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
+                                     struct bin_attribute *attr, char *buf,
+                                     loff_t offset, size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       u32 data;
+       u64 qmdata;
+       int ret;
+
+       ret = qlcnic_sysfs_validate_crb(adapter, offset, size);
+       if (ret != 0)
+               return ret;
+
+       if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
+               memcpy(&qmdata, buf, size);
+               qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
+       } else {
+               memcpy(&data, buf, size);
+               QLCWR32(adapter, offset, data);
+       }
+       return size;
+}
+
+static int qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
+                                    loff_t offset, size_t size)
+{
+       if (!(adapter->flags & QLCNIC_DIAG_ENABLED))
+               return -EIO;
+
+       if ((size != 8) || (offset & 0x7))
+               return  -EIO;
+
+       return 0;
+}
+
+static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
+                                    struct bin_attribute *attr, char *buf,
+                                    loff_t offset, size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       u64 data;
+       int ret;
+
+       ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
+       if (ret != 0)
+               return ret;
+
+       if (qlcnic_pci_mem_read_2M(adapter, offset, &data))
+               return -EIO;
+
+       memcpy(buf, &data, size);
+
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
+                                     struct bin_attribute *attr, char *buf,
+                                     loff_t offset, size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       u64 data;
+       int ret;
+
+       ret = qlcnic_sysfs_validate_mem(adapter, offset, size);
+       if (ret != 0)
+               return ret;
+
+       memcpy(&data, buf, size);
+
+       if (qlcnic_pci_mem_write_2M(adapter, offset, data))
+               return -EIO;
+
+       return size;
+}
+
+static int validate_pm_config(struct qlcnic_adapter *adapter,
+                             struct qlcnic_pm_func_cfg *pm_cfg, int count)
+{
+       u8 src_pci_func, s_esw_id, d_esw_id, dest_pci_func;
+       int i;
+
+       for (i = 0; i < count; i++) {
+               src_pci_func = pm_cfg[i].pci_func;
+               dest_pci_func = pm_cfg[i].dest_npar;
+               if (src_pci_func >= QLCNIC_MAX_PCI_FUNC ||
+                   dest_pci_func >= QLCNIC_MAX_PCI_FUNC)
+                       return QL_STATUS_INVALID_PARAM;
+
+               if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC)
+                       return QL_STATUS_INVALID_PARAM;
+
+               if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC)
+                       return QL_STATUS_INVALID_PARAM;
+
+               s_esw_id = adapter->npars[src_pci_func].phy_port;
+               d_esw_id = adapter->npars[dest_pci_func].phy_port;
+
+               if (s_esw_id != d_esw_id)
+                       return QL_STATUS_INVALID_PARAM;
+       }
+       return 0;
+
+}
+
+static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
+                                           struct kobject *kobj,
+                                           struct bin_attribute *attr,
+                                           char *buf, loff_t offset,
+                                           size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_pm_func_cfg *pm_cfg;
+       u32 id, action, pci_func;
+       int count, rem, i, ret;
+
+       count   = size / sizeof(struct qlcnic_pm_func_cfg);
+       rem     = size % sizeof(struct qlcnic_pm_func_cfg);
+       if (rem)
+               return QL_STATUS_INVALID_PARAM;
+
+       pm_cfg = (struct qlcnic_pm_func_cfg *)buf;
+
+       ret = validate_pm_config(adapter, pm_cfg, count);
+       if (ret)
+               return ret;
+       for (i = 0; i < count; i++) {
+               pci_func = pm_cfg[i].pci_func;
+               action = !!pm_cfg[i].action;
+               id = adapter->npars[pci_func].phy_port;
+               ret = qlcnic_config_port_mirroring(adapter, id, action,
+                                                  pci_func);
+               if (ret)
+                       return ret;
+       }
+
+       for (i = 0; i < count; i++) {
+               pci_func = pm_cfg[i].pci_func;
+               id = adapter->npars[pci_func].phy_port;
+               adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action;
+               adapter->npars[pci_func].dest_npar = id;
+       }
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
+                                          struct kobject *kobj,
+                                          struct bin_attribute *attr,
+                                          char *buf, loff_t offset,
+                                          size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC];
+       int i;
+
+       if (size != sizeof(pm_cfg))
+               return QL_STATUS_INVALID_PARAM;
+
+       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+               if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+                       continue;
+               pm_cfg[i].action = adapter->npars[i].enable_pm;
+               pm_cfg[i].dest_npar = 0;
+               pm_cfg[i].pci_func = i;
+       }
+       memcpy(buf, &pm_cfg, size);
+
+       return size;
+}
+
+static int validate_esw_config(struct qlcnic_adapter *adapter,
+                              struct qlcnic_esw_func_cfg *esw_cfg, int count)
+{
+       u32 op_mode;
+       u8 pci_func;
+       int i;
+
+       op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE);
+
+       for (i = 0; i < count; i++) {
+               pci_func = esw_cfg[i].pci_func;
+               if (pci_func >= QLCNIC_MAX_PCI_FUNC)
+                       return QL_STATUS_INVALID_PARAM;
+
+               if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
+                       if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+                               return QL_STATUS_INVALID_PARAM;
+               }
+
+               switch (esw_cfg[i].op_mode) {
+               case QLCNIC_PORT_DEFAULTS:
+                       if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
+                                           QLCNIC_NON_PRIV_FUNC) {
+                               if (esw_cfg[i].mac_anti_spoof != 0)
+                                       return QL_STATUS_INVALID_PARAM;
+                               if (esw_cfg[i].mac_override != 1)
+                                       return QL_STATUS_INVALID_PARAM;
+                               if (esw_cfg[i].promisc_mode != 1)
+                                       return QL_STATUS_INVALID_PARAM;
+                       }
+                       break;
+               case QLCNIC_ADD_VLAN:
+                       if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
+                               return QL_STATUS_INVALID_PARAM;
+                       if (!esw_cfg[i].op_type)
+                               return QL_STATUS_INVALID_PARAM;
+                       break;
+               case QLCNIC_DEL_VLAN:
+                       if (!esw_cfg[i].op_type)
+                               return QL_STATUS_INVALID_PARAM;
+                       break;
+               default:
+                       return QL_STATUS_INVALID_PARAM;
+               }
+       }
+       return 0;
+}
+
+static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
+                                            struct kobject *kobj,
+                                            struct bin_attribute *attr,
+                                            char *buf, loff_t offset,
+                                            size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_esw_func_cfg *esw_cfg;
+       struct qlcnic_npar_info *npar;
+       int count, rem, i, ret;
+       u8 pci_func, op_mode = 0;
+
+       count   = size / sizeof(struct qlcnic_esw_func_cfg);
+       rem     = size % sizeof(struct qlcnic_esw_func_cfg);
+       if (rem)
+               return QL_STATUS_INVALID_PARAM;
+
+       esw_cfg = (struct qlcnic_esw_func_cfg *)buf;
+       ret = validate_esw_config(adapter, esw_cfg, count);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < count; i++) {
+               if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) {
+                       if (qlcnic_config_switch_port(adapter, &esw_cfg[i]))
+                               return QL_STATUS_INVALID_PARAM;
+               }
+
+               if (adapter->ahw->pci_func != esw_cfg[i].pci_func)
+                       continue;
+
+               op_mode = esw_cfg[i].op_mode;
+               qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]);
+               esw_cfg[i].op_mode = op_mode;
+               esw_cfg[i].pci_func = adapter->ahw->pci_func;
+
+               switch (esw_cfg[i].op_mode) {
+               case QLCNIC_PORT_DEFAULTS:
+                       qlcnic_set_eswitch_port_features(adapter, &esw_cfg[i]);
+                       break;
+               case QLCNIC_ADD_VLAN:
+                       qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+                       break;
+               case QLCNIC_DEL_VLAN:
+                       esw_cfg[i].vlan_id = 0;
+                       qlcnic_set_vlan_config(adapter, &esw_cfg[i]);
+                       break;
+               }
+       }
+
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+               goto out;
+
+       for (i = 0; i < count; i++) {
+               pci_func = esw_cfg[i].pci_func;
+               npar = &adapter->npars[pci_func];
+               switch (esw_cfg[i].op_mode) {
+               case QLCNIC_PORT_DEFAULTS:
+                       npar->promisc_mode = esw_cfg[i].promisc_mode;
+                       npar->mac_override = esw_cfg[i].mac_override;
+                       npar->offload_flags = esw_cfg[i].offload_flags;
+                       npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
+                       npar->discard_tagged = esw_cfg[i].discard_tagged;
+                       break;
+               case QLCNIC_ADD_VLAN:
+                       npar->pvid = esw_cfg[i].vlan_id;
+                       break;
+               case QLCNIC_DEL_VLAN:
+                       npar->pvid = 0;
+                       break;
+               }
+       }
+out:
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
+                                           struct kobject *kobj,
+                                           struct bin_attribute *attr,
+                                           char *buf, loff_t offset,
+                                           size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC];
+       u8 i;
+
+       if (size != sizeof(esw_cfg))
+               return QL_STATUS_INVALID_PARAM;
+
+       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+               if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+                       continue;
+               esw_cfg[i].pci_func = i;
+               if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i]))
+                       return QL_STATUS_INVALID_PARAM;
+       }
+       memcpy(buf, &esw_cfg, size);
+
+       return size;
+}
+
+static int validate_npar_config(struct qlcnic_adapter *adapter,
+                               struct qlcnic_npar_func_cfg *np_cfg,
+                               int count)
+{
+       u8 pci_func, i;
+
+       for (i = 0; i < count; i++) {
+               pci_func = np_cfg[i].pci_func;
+               if (pci_func >= QLCNIC_MAX_PCI_FUNC)
+                       return QL_STATUS_INVALID_PARAM;
+
+               if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
+                       return QL_STATUS_INVALID_PARAM;
+
+               if (!IS_VALID_BW(np_cfg[i].min_bw) ||
+                   !IS_VALID_BW(np_cfg[i].max_bw))
+                       return QL_STATUS_INVALID_PARAM;
+       }
+       return 0;
+}
+
+static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
+                                             struct kobject *kobj,
+                                             struct bin_attribute *attr,
+                                             char *buf, loff_t offset,
+                                             size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_info nic_info;
+       struct qlcnic_npar_func_cfg *np_cfg;
+       int i, count, rem, ret;
+       u8 pci_func;
+
+       count   = size / sizeof(struct qlcnic_npar_func_cfg);
+       rem     = size % sizeof(struct qlcnic_npar_func_cfg);
+       if (rem)
+               return QL_STATUS_INVALID_PARAM;
+
+       np_cfg = (struct qlcnic_npar_func_cfg *)buf;
+       ret = validate_npar_config(adapter, np_cfg, count);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < count ; i++) {
+               pci_func = np_cfg[i].pci_func;
+               ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func);
+               if (ret)
+                       return ret;
+               nic_info.pci_func = pci_func;
+               nic_info.min_tx_bw = np_cfg[i].min_bw;
+               nic_info.max_tx_bw = np_cfg[i].max_bw;
+               ret = qlcnic_set_nic_info(adapter, &nic_info);
+               if (ret)
+                       return ret;
+               adapter->npars[i].min_bw = nic_info.min_tx_bw;
+               adapter->npars[i].max_bw = nic_info.max_tx_bw;
+       }
+
+       return size;
+
+}
+
+static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
+                                            struct kobject *kobj,
+                                            struct bin_attribute *attr,
+                                            char *buf, loff_t offset,
+                                            size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_info nic_info;
+       struct qlcnic_npar_func_cfg np_cfg[QLCNIC_MAX_PCI_FUNC];
+       int i, ret;
+
+       if (size != sizeof(np_cfg))
+               return QL_STATUS_INVALID_PARAM;
+
+       for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+               if (adapter->npars[i].type != QLCNIC_TYPE_NIC)
+                       continue;
+               ret = qlcnic_get_nic_info(adapter, &nic_info, i);
+               if (ret)
+                       return ret;
+
+               np_cfg[i].pci_func = i;
+               np_cfg[i].op_mode = (u8)nic_info.op_mode;
+               np_cfg[i].port_num = nic_info.phys_port;
+               np_cfg[i].fw_capab = nic_info.capabilities;
+               np_cfg[i].min_bw = nic_info.min_tx_bw;
+               np_cfg[i].max_bw = nic_info.max_tx_bw;
+               np_cfg[i].max_tx_queues = nic_info.max_tx_ques;
+               np_cfg[i].max_rx_queues = nic_info.max_rx_ques;
+       }
+       memcpy(buf, &np_cfg, size);
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
+                                          struct kobject *kobj,
+                                          struct bin_attribute *attr,
+                                          char *buf, loff_t offset,
+                                          size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_esw_statistics port_stats;
+       int ret;
+
+       if (size != sizeof(struct qlcnic_esw_statistics))
+               return QL_STATUS_INVALID_PARAM;
+
+       if (offset >= QLCNIC_MAX_PCI_FUNC)
+               return QL_STATUS_INVALID_PARAM;
+
+       memset(&port_stats, 0, size);
+       ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+                                   &port_stats.rx);
+       if (ret)
+               return ret;
+
+       ret = qlcnic_get_port_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+                                   &port_stats.tx);
+       if (ret)
+               return ret;
+
+       memcpy(buf, &port_stats, size);
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
+                                         struct kobject *kobj,
+                                         struct bin_attribute *attr,
+                                         char *buf, loff_t offset,
+                                         size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_esw_statistics esw_stats;
+       int ret;
+
+       if (size != sizeof(struct qlcnic_esw_statistics))
+               return QL_STATUS_INVALID_PARAM;
+
+       if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+               return QL_STATUS_INVALID_PARAM;
+
+       memset(&esw_stats, 0, size);
+       ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_RX_COUNTER,
+                                      &esw_stats.rx);
+       if (ret)
+               return ret;
+
+       ret = qlcnic_get_eswitch_stats(adapter, offset, QLCNIC_QUERY_TX_COUNTER,
+                                      &esw_stats.tx);
+       if (ret)
+               return ret;
+
+       memcpy(buf, &esw_stats, size);
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
+                                           struct kobject *kobj,
+                                           struct bin_attribute *attr,
+                                           char *buf, loff_t offset,
+                                           size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       int ret;
+
+       if (offset >= QLCNIC_NIU_MAX_XG_PORTS)
+               return QL_STATUS_INVALID_PARAM;
+
+       ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+                                    QLCNIC_QUERY_RX_COUNTER);
+       if (ret)
+               return ret;
+
+       ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_ESWITCH, offset,
+                                    QLCNIC_QUERY_TX_COUNTER);
+       if (ret)
+               return ret;
+
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
+                                            struct kobject *kobj,
+                                            struct bin_attribute *attr,
+                                            char *buf, loff_t offset,
+                                            size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       int ret;
+
+       if (offset >= QLCNIC_MAX_PCI_FUNC)
+               return QL_STATUS_INVALID_PARAM;
+
+       ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+                                    QLCNIC_QUERY_RX_COUNTER);
+       if (ret)
+               return ret;
+
+       ret = qlcnic_clear_esw_stats(adapter, QLCNIC_STATS_PORT, offset,
+                                    QLCNIC_QUERY_TX_COUNTER);
+       if (ret)
+               return ret;
+
+       return size;
+}
+
+static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
+                                           struct kobject *kobj,
+                                           struct bin_attribute *attr,
+                                           char *buf, loff_t offset,
+                                           size_t size)
+{
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
+       struct qlcnic_pci_func_cfg pci_cfg[QLCNIC_MAX_PCI_FUNC];
+       struct qlcnic_pci_info *pci_info;
+       int i, ret;
+
+       if (size != sizeof(pci_cfg))
+               return QL_STATUS_INVALID_PARAM;
+
+       pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
+       if (!pci_info)
+               return -ENOMEM;
+
+       ret = qlcnic_get_pci_info(adapter, pci_info);
+       if (ret) {
+               kfree(pci_info);
+               return ret;
+       }
+
+       for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) {
+               pci_cfg[i].pci_func = pci_info[i].id;
+               pci_cfg[i].func_type = pci_info[i].type;
+               pci_cfg[i].port_num = pci_info[i].default_port;
+               pci_cfg[i].min_bw = pci_info[i].tx_min_bw;
+               pci_cfg[i].max_bw = pci_info[i].tx_max_bw;
+               memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN);
+       }
+       memcpy(buf, &pci_cfg, size);
+       kfree(pci_info);
+       return size;
+}
+
+static struct device_attribute dev_attr_bridged_mode = {
+       .attr = {.name = "bridged_mode", .mode = (S_IRUGO | S_IWUSR)},
+       .show = qlcnic_show_bridged_mode,
+       .store = qlcnic_store_bridged_mode,
+};
+
+static struct device_attribute dev_attr_diag_mode = {
+       .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)},
+       .show = qlcnic_show_diag_mode,
+       .store = qlcnic_store_diag_mode,
+};
+
+static struct device_attribute dev_attr_beacon = {
+       .attr = {.name = "beacon", .mode = (S_IRUGO | S_IWUSR)},
+       .show = qlcnic_show_beacon,
+       .store = qlcnic_store_beacon,
+};
+
+static struct bin_attribute bin_attr_crb = {
+       .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)},
+       .size = 0,
+       .read = qlcnic_sysfs_read_crb,
+       .write = qlcnic_sysfs_write_crb,
+};
+
+static struct bin_attribute bin_attr_mem = {
+       .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)},
+       .size = 0,
+       .read = qlcnic_sysfs_read_mem,
+       .write = qlcnic_sysfs_write_mem,
+};
+
+static struct bin_attribute bin_attr_npar_config = {
+       .attr = {.name = "npar_config", .mode = (S_IRUGO | S_IWUSR)},
+       .size = 0,
+       .read = qlcnic_sysfs_read_npar_config,
+       .write = qlcnic_sysfs_write_npar_config,
+};
+
+static struct bin_attribute bin_attr_pci_config = {
+       .attr = {.name = "pci_config", .mode = (S_IRUGO | S_IWUSR)},
+       .size = 0,
+       .read = qlcnic_sysfs_read_pci_config,
+       .write = NULL,
+};
+
+static struct bin_attribute bin_attr_port_stats = {
+       .attr = {.name = "port_stats", .mode = (S_IRUGO | S_IWUSR)},
+       .size = 0,
+       .read = qlcnic_sysfs_get_port_stats,
+       .write = qlcnic_sysfs_clear_port_stats,
+};
+
+static struct bin_attribute bin_attr_esw_stats = {
+       .attr = {.name = "esw_stats", .mode = (S_IRUGO | S_IWUSR)},
+       .size = 0,
+       .read = qlcnic_sysfs_get_esw_stats,
+       .write = qlcnic_sysfs_clear_esw_stats,
+};
+
+static struct bin_attribute bin_attr_esw_config = {
+       .attr = {.name = "esw_config", .mode = (S_IRUGO | S_IWUSR)},
+       .size = 0,
+       .read = qlcnic_sysfs_read_esw_config,
+       .write = qlcnic_sysfs_write_esw_config,
+};
+
+static struct bin_attribute bin_attr_pm_config = {
+       .attr = {.name = "pm_config", .mode = (S_IRUGO | S_IWUSR)},
+       .size = 0,
+       .read = qlcnic_sysfs_read_pm_config,
+       .write = qlcnic_sysfs_write_pm_config,
+};
+
+void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter)
+{
+       struct device *dev = &adapter->pdev->dev;
+
+       if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+               if (device_create_file(dev, &dev_attr_bridged_mode))
+                       dev_warn(dev,
+                                "failed to create bridged_mode sysfs entry\n");
+}
+
+void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
+{
+       struct device *dev = &adapter->pdev->dev;
+
+       if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_BDG)
+               device_remove_file(dev, &dev_attr_bridged_mode);
+}
+
+void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
+{
+       struct device *dev = &adapter->pdev->dev;
+       u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+
+       if (device_create_bin_file(dev, &bin_attr_port_stats))
+               dev_info(dev, "failed to create port stats sysfs entry");
+
+       if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
+               return;
+       if (device_create_file(dev, &dev_attr_diag_mode))
+               dev_info(dev, "failed to create diag_mode sysfs entry\n");
+       if (device_create_bin_file(dev, &bin_attr_crb))
+               dev_info(dev, "failed to create crb sysfs entry\n");
+       if (device_create_bin_file(dev, &bin_attr_mem))
+               dev_info(dev, "failed to create mem sysfs entry\n");
+
+       if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+               return;
+
+       if (device_create_bin_file(dev, &bin_attr_pci_config))
+               dev_info(dev, "failed to create pci config sysfs entry");
+       if (device_create_file(dev, &dev_attr_beacon))
+               dev_info(dev, "failed to create beacon sysfs entry");
+
+       if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+               return;
+       if (device_create_bin_file(dev, &bin_attr_esw_config))
+               dev_info(dev, "failed to create esw config sysfs entry");
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+               return;
+       if (device_create_bin_file(dev, &bin_attr_npar_config))
+               dev_info(dev, "failed to create npar config sysfs entry");
+       if (device_create_bin_file(dev, &bin_attr_pm_config))
+               dev_info(dev, "failed to create pm config sysfs entry");
+       if (device_create_bin_file(dev, &bin_attr_esw_stats))
+               dev_info(dev, "failed to create eswitch stats sysfs entry");
+}
+
+void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
+{
+       struct device *dev = &adapter->pdev->dev;
+       u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
+
+       device_remove_bin_file(dev, &bin_attr_port_stats);
+
+       if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC)
+               return;
+       device_remove_file(dev, &dev_attr_diag_mode);
+       device_remove_bin_file(dev, &bin_attr_crb);
+       device_remove_bin_file(dev, &bin_attr_mem);
+       if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
+               return;
+       device_remove_bin_file(dev, &bin_attr_pci_config);
+       device_remove_file(dev, &dev_attr_beacon);
+       if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED))
+               return;
+       device_remove_bin_file(dev, &bin_attr_esw_config);
+       if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
+               return;
+       device_remove_bin_file(dev, &bin_attr_npar_config);
+       device_remove_bin_file(dev, &bin_attr_pm_config);
+       device_remove_bin_file(dev, &bin_attr_esw_stats);
+}
index 58185b604b729c131c9215bbdf9c8cfbbb53f24c..10093f0c4c0f3d507514da946df9047b3d68d925 100644 (file)
@@ -86,7 +86,7 @@ exit:
 }
 
 /* Read out the SERDES registers */
-static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 * data)
+static int ql_read_serdes_reg(struct ql_adapter *qdev, u32 reg, u32 *data)
 {
        int status;
 
@@ -364,7 +364,7 @@ exit:
 /* Read the 400 xgmac control/statistics registers
  * skipping unused locations.
  */
-static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf,
+static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 *buf,
                                        unsigned int other_function)
 {
        int status = 0;
@@ -405,7 +405,7 @@ static int ql_get_xgmac_regs(struct ql_adapter *qdev, u32 * buf,
        return status;
 }
 
-static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_ets_regs(struct ql_adapter *qdev, u32 *buf)
 {
        int status = 0;
        int i;
@@ -423,7 +423,7 @@ static int ql_get_ets_regs(struct ql_adapter *qdev, u32 * buf)
        return status;
 }
 
-static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf)
+static void ql_get_intr_states(struct ql_adapter *qdev, u32 *buf)
 {
        int i;
 
@@ -434,7 +434,7 @@ static void ql_get_intr_states(struct ql_adapter *qdev, u32 * buf)
        }
 }
 
-static int ql_get_cam_entries(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_cam_entries(struct ql_adapter *qdev, u32 *buf)
 {
        int i, status;
        u32 value[3];
@@ -471,7 +471,7 @@ err:
        return status;
 }
 
-static int ql_get_routing_entries(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_routing_entries(struct ql_adapter *qdev, u32 *buf)
 {
        int status;
        u32 value, i;
@@ -496,7 +496,7 @@ err:
 }
 
 /* Read the MPI Processor shadow registers */
-static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 * buf)
+static int ql_get_mpi_shadow_regs(struct ql_adapter *qdev, u32 *buf)
 {
        u32 i;
        int status;
@@ -515,7 +515,7 @@ end:
 }
 
 /* Read the MPI Processor core registers */
-static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 * buf,
+static int ql_get_mpi_regs(struct ql_adapter *qdev, u32 *buf,
                                u32 offset, u32 count)
 {
        int i, status = 0;
index b262d6156816134e980c81915b23e10b526d8803..f80cd975daed2b84a31af47db58b828d28139638 100644 (file)
@@ -4491,8 +4491,8 @@ static void ql_release_all(struct pci_dev *pdev)
        pci_set_drvdata(pdev, NULL);
 }
 
-static int __devinit ql_init_device(struct pci_dev *pdev,
-                                   struct net_device *ndev, int cards_found)
+static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev,
+                         int cards_found)
 {
        struct ql_adapter *qdev = netdev_priv(ndev);
        int err = 0;
@@ -4656,8 +4656,8 @@ static void ql_timer(unsigned long data)
        mod_timer(&qdev->timer, jiffies + (5*HZ));
 }
 
-static int __devinit qlge_probe(struct pci_dev *pdev,
-                               const struct pci_device_id *pci_entry)
+static int qlge_probe(struct pci_dev *pdev,
+                     const struct pci_device_id *pci_entry)
 {
        struct net_device *ndev = NULL;
        struct ql_adapter *qdev = NULL;
@@ -4729,7 +4729,7 @@ int ql_clean_lb_rx_ring(struct rx_ring *rx_ring, int budget)
        return ql_clean_inbound_rx_ring(rx_ring, budget);
 }
 
-static void __devexit qlge_remove(struct pci_dev *pdev)
+static void qlge_remove(struct pci_dev *pdev)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
        struct ql_adapter *qdev = netdev_priv(ndev);
@@ -4921,7 +4921,7 @@ static struct pci_driver qlge_driver = {
        .name = DRV_NAME,
        .id_table = qlge_pci_tbl,
        .probe = qlge_probe,
-       .remove = __devexit_p(qlge_remove),
+       .remove = qlge_remove,
 #ifdef CONFIG_PM
        .suspend = qlge_suspend,
        .resume = qlge_resume,
index 557a26545d758df2cbcf196e1e9cd2306ae2315e..63c13125db6c9d0a58dcc70438d4af4058bcfd1e 100644 (file)
@@ -206,7 +206,7 @@ struct r6040_private {
        int old_duplex;
 };
 
-static char version[] __devinitdata = DRV_NAME
+static char version[] = DRV_NAME
        ": RDC R6040 NAPI net driver,"
        "version "DRV_VERSION " (" DRV_RELDATE ")";
 
@@ -1073,8 +1073,7 @@ static int r6040_mii_probe(struct net_device *dev)
        return 0;
 }
 
-static int __devinit r6040_init_one(struct pci_dev *pdev,
-                                        const struct pci_device_id *ent)
+static int r6040_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct r6040_private *lp;
@@ -1246,7 +1245,7 @@ err_out:
        return err;
 }
 
-static void __devexit r6040_remove_one(struct pci_dev *pdev)
+static void r6040_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct r6040_private *lp = netdev_priv(dev);
@@ -1274,7 +1273,7 @@ static struct pci_driver r6040_driver = {
        .name           = DRV_NAME,
        .id_table       = r6040_pci_tbl,
        .probe          = r6040_init_one,
-       .remove         = __devexit_p(r6040_remove_one),
+       .remove         = r6040_remove_one,
 };
 
 module_pci_driver(r6040_driver);
index 1c818254b7bec650da02fc352625570a3937b6f8..0da3f5e9b1a5b01d3572e92fd1acf7ecf2b1e2c1 100644 (file)
@@ -648,6 +648,7 @@ static void cp_tx (struct cp_private *cp)
 {
        unsigned tx_head = cp->tx_head;
        unsigned tx_tail = cp->tx_tail;
+       unsigned bytes_compl = 0, pkts_compl = 0;
 
        while (tx_tail != tx_head) {
                struct cp_desc *txd = cp->tx_ring + tx_tail;
@@ -666,6 +667,9 @@ static void cp_tx (struct cp_private *cp)
                                 le32_to_cpu(txd->opts1) & 0xffff,
                                 PCI_DMA_TODEVICE);
 
+               bytes_compl += skb->len;
+               pkts_compl++;
+
                if (status & LastFrag) {
                        if (status & (TxError | TxFIFOUnder)) {
                                netif_dbg(cp, tx_err, cp->dev,
@@ -697,6 +701,7 @@ static void cp_tx (struct cp_private *cp)
 
        cp->tx_tail = tx_tail;
 
+       netdev_completed_queue(cp->dev, pkts_compl, bytes_compl);
        if (TX_BUFFS_AVAIL(cp) > (MAX_SKB_FRAGS + 1))
                netif_wake_queue(cp->dev);
 }
@@ -843,6 +848,8 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb,
                wmb();
        }
        cp->tx_head = entry;
+
+       netdev_sent_queue(dev, skb->len);
        netif_dbg(cp, tx_queued, cp->dev, "tx queued, slot %d, skblen %d\n",
                  entry, skb->len);
        if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1))
@@ -937,6 +944,8 @@ static void cp_stop_hw (struct cp_private *cp)
 
        cp->rx_tail = 0;
        cp->tx_head = cp->tx_tail = 0;
+
+       netdev_reset_queue(cp->dev);
 }
 
 static void cp_reset_hw (struct cp_private *cp)
@@ -957,8 +966,38 @@ static void cp_reset_hw (struct cp_private *cp)
 
 static inline void cp_start_hw (struct cp_private *cp)
 {
+       dma_addr_t ring_dma;
+
        cpw16(CpCmd, cp->cpcmd);
+
+       /*
+        * These (at least TxRingAddr) need to be configured after the
+        * corresponding bits in CpCmd are enabled. Datasheet v1.6 §6.33
+        * (C+ Command Register) recommends that these and more be configured
+        * *after* the [RT]xEnable bits in CpCmd are set. And on some hardware
+        * it's been observed that the TxRingAddr is actually reset to garbage
+        * when C+ mode Tx is enabled in CpCmd.
+        */
+       cpw32_f(HiTxRingAddr, 0);
+       cpw32_f(HiTxRingAddr + 4, 0);
+
+       ring_dma = cp->ring_dma;
+       cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+       cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+       ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+       cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+       cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+       /*
+        * Strictly speaking, the datasheet says this should be enabled
+        * *before* setting the descriptor addresses. But what, then, would
+        * prevent it from doing DMA to random unconfigured addresses?
+        * This variant appears to work fine.
+        */
        cpw8(Cmd, RxOn | TxOn);
+
+       netdev_reset_queue(cp->dev);
 }
 
 static void cp_enable_irq(struct cp_private *cp)
@@ -969,7 +1008,6 @@ static void cp_enable_irq(struct cp_private *cp)
 static void cp_init_hw (struct cp_private *cp)
 {
        struct net_device *dev = cp->dev;
-       dma_addr_t ring_dma;
 
        cp_reset_hw(cp);
 
@@ -979,17 +1017,6 @@ static void cp_init_hw (struct cp_private *cp)
        cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
        cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4)));
 
-       cpw32_f(HiTxRingAddr, 0);
-       cpw32_f(HiTxRingAddr + 4, 0);
-
-       ring_dma = cp->ring_dma;
-       cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
-       cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
-       ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
-       cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
-       cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
        cp_start_hw(cp);
        cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */
 
@@ -1192,18 +1219,16 @@ static void cp_tx_timeout(struct net_device *dev)
        cp_clean_rings(cp);
        rc = cp_init_rings(cp);
        cp_start_hw(cp);
+       cp_enable_irq(cp);
 
        netif_wake_queue(dev);
 
        spin_unlock_irqrestore(&cp->lock, flags);
 }
 
-#ifdef BROKEN
 static int cp_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct cp_private *cp = netdev_priv(dev);
-       int rc;
-       unsigned long flags;
 
        /* check for invalid MTU, according to hardware limits */
        if (new_mtu < CP_MIN_MTU || new_mtu > CP_MAX_MTU)
@@ -1216,22 +1241,12 @@ static int cp_change_mtu(struct net_device *dev, int new_mtu)
                return 0;
        }
 
-       spin_lock_irqsave(&cp->lock, flags);
-
-       cp_stop_hw(cp);                 /* stop h/w and free rings */
-       cp_clean_rings(cp);
-
+       /* network IS up, close it, reset MTU, and come up again. */
+       cp_close(dev);
        dev->mtu = new_mtu;
-       cp_set_rxbufsize(cp);           /* set new rx buf size */
-
-       rc = cp_init_rings(cp);         /* realloc and restart h/w */
-       cp_start_hw(cp);
-
-       spin_unlock_irqrestore(&cp->lock, flags);
-
-       return rc;
+       cp_set_rxbufsize(cp);
+       return cp_open(dev);
 }
-#endif /* BROKEN */
 
 static const char mii_2_8139_map[8] = {
        BasicModeCtrl,
@@ -1807,9 +1822,7 @@ static const struct net_device_ops cp_netdev_ops = {
        .ndo_start_xmit         = cp_start_xmit,
        .ndo_tx_timeout         = cp_tx_timeout,
        .ndo_set_features       = cp_set_features,
-#ifdef BROKEN
        .ndo_change_mtu         = cp_change_mtu,
-#endif
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = cp_poll_controller,
index 3ed7add23c121df0b0a6577ed2ff4c5d327d941d..5dc1616301277346f9d5a931d89c82b340470442 100644 (file)
@@ -228,7 +228,7 @@ typedef enum {
 static const struct {
        const char *name;
        u32 hw_flags;
-} board_info[] __devinitconst = {
+} board_info[] = {
        { "RealTek RTL8139", RTL8139_CAPS },
        { "RealTek RTL8129", RTL8129_CAPS },
 };
@@ -748,7 +748,7 @@ static void rtl8139_chip_reset (void __iomem *ioaddr)
 }
 
 
-static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
+static struct net_device *rtl8139_init_board(struct pci_dev *pdev)
 {
        struct device *d = &pdev->dev;
        void __iomem *ioaddr;
@@ -935,8 +935,8 @@ static const struct net_device_ops rtl8139_netdev_ops = {
        .ndo_set_features       = rtl8139_set_features,
 };
 
-static int __devinit rtl8139_init_one (struct pci_dev *pdev,
-                                      const struct pci_device_id *ent)
+static int rtl8139_init_one(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        struct net_device *dev = NULL;
        struct rtl8139_private *tp;
@@ -1103,7 +1103,7 @@ err_out:
 }
 
 
-static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
+static void rtl8139_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata (pdev);
        struct rtl8139_private *tp = netdev_priv(dev);
@@ -1141,7 +1141,7 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
 #define EE_READ_CMD            (6)
 #define EE_ERASE_CMD   (7)
 
-static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len)
+static int read_eeprom(void __iomem *ioaddr, int location, int addr_len)
 {
        int i;
        unsigned retval = 0;
@@ -2652,7 +2652,7 @@ static struct pci_driver rtl8139_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = rtl8139_pci_tbl,
        .probe          = rtl8139_init_one,
-       .remove         = __devexit_p(rtl8139_remove_one),
+       .remove         = rtl8139_remove_one,
 #ifdef CONFIG_PM
        .suspend        = rtl8139_suspend,
        .resume         = rtl8139_resume,
index e02f04d7f3adb24112149238885a0b302a0d3faf..9f2d416de750882485ec5b4c5a60f59c2a55e98d 100644 (file)
@@ -175,8 +175,7 @@ struct net_local {
     unsigned int tx_unit_busy:1;
     unsigned char re_tx,       /* Number of packet retransmissions. */
                addr_mode,              /* Current Rx filter e.g. promiscuous, etc. */
-               pac_cnt_in_tx_buf,
-               chip_type;
+               pac_cnt_in_tx_buf;
 };
 
 /* This code, written by wwc@super.org, resets the adapter every
@@ -339,7 +338,6 @@ static int __init atp_probe1(long ioaddr)
        write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX);
 
        lp = netdev_priv(dev);
-       lp->chip_type = RTL8002;
        lp->addr_mode = CMR2h_Normal;
        spin_lock_init(&lp->lock);
 
@@ -852,7 +850,7 @@ net_close(struct net_device *dev)
  *     Set or clear the multicast filter for this adapter.
  */
 
-static void set_rx_mode_8002(struct net_device *dev)
+static void set_rx_mode(struct net_device *dev)
 {
        struct net_local *lp = netdev_priv(dev);
        long ioaddr = dev->base_addr;
@@ -864,58 +862,6 @@ static void set_rx_mode_8002(struct net_device *dev)
        write_reg_high(ioaddr, CMR2, lp->addr_mode);
 }
 
-static void set_rx_mode_8012(struct net_device *dev)
-{
-       struct net_local *lp = netdev_priv(dev);
-       long ioaddr = dev->base_addr;
-       unsigned char new_mode, mc_filter[8]; /* Multicast hash filter */
-       int i;
-
-       if (dev->flags & IFF_PROMISC) {                 /* Set promiscuous. */
-               new_mode = CMR2h_PROMISC;
-       } else if ((netdev_mc_count(dev) > 1000) ||
-                  (dev->flags & IFF_ALLMULTI)) {
-               /* Too many to filter perfectly -- accept all multicasts. */
-               memset(mc_filter, 0xff, sizeof(mc_filter));
-               new_mode = CMR2h_Normal;
-       } else {
-               struct netdev_hw_addr *ha;
-
-               memset(mc_filter, 0, sizeof(mc_filter));
-               netdev_for_each_mc_addr(ha, dev) {
-                       int filterbit = ether_crc_le(ETH_ALEN, ha->addr) & 0x3f;
-                       mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
-               }
-               new_mode = CMR2h_Normal;
-       }
-       lp->addr_mode = new_mode;
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT | 0x04); /* Switch to page 1. */
-    for (i = 0; i < 8; i++)
-               write_reg_byte(ioaddr, i, mc_filter[i]);
-       if (net_debug > 2 || 1) {
-               lp->addr_mode = 1;
-               printk(KERN_DEBUG "%s: Mode %d, setting multicast filter to",
-                          dev->name, lp->addr_mode);
-               for (i = 0; i < 8; i++)
-                       printk(" %2.2x", mc_filter[i]);
-               printk(".\n");
-       }
-
-       write_reg_high(ioaddr, CMR2, lp->addr_mode);
-    write_reg(ioaddr, CMR2, CMR2_IRQOUT); /* Switch back to page 0 */
-}
-
-static void set_rx_mode(struct net_device *dev)
-{
-       struct net_local *lp = netdev_priv(dev);
-
-       if (lp->chip_type == RTL8002)
-               return set_rx_mode_8002(dev);
-       else
-               return set_rx_mode_8012(dev);
-}
-
-
 static int __init atp_init_module(void) {
        if (debug)                                      /* Emit version even if no cards detected. */
                printk(KERN_INFO "%s", version);
index 0edc642c2c2f4c1d9a90d94d1db07c1a63c0a1bd..040b1373994749264374f0a9c44e217ae1997edf 100644 (file)
@@ -16,8 +16,6 @@ struct rx_header {
 #define PAR_STATUS     1
 #define PAR_CONTROL 2
 
-enum chip_type { RTL8002, RTL8012 };
-
 #define Ctrl_LNibRead  0x08    /* LP_PSELECP */
 #define Ctrl_HNibRead  0
 #define Ctrl_LNibWrite 0x08    /* LP_PSELECP */
index e7ff886e8047ac3d3a926e8c0384b3ec7568068b..ed96f309bca8e030a0c098df8b8e728314f04bb0 100644 (file)
@@ -78,24 +78,18 @@ static const int multicast_filter_limit = 32;
 
 #define MAX_READ_REQUEST_SHIFT 12
 #define TX_DMA_BURST   7       /* Maximum PCI burst, '7' is unlimited */
-#define SafeMtu                0x1c20  /* ... actually life sucks beyond ~7k */
 #define InterFrameGap  0x03    /* 3 means InterFrameGap = the shortest one */
 
 #define R8169_REGS_SIZE                256
 #define R8169_NAPI_WEIGHT      64
 #define NUM_TX_DESC    64      /* Number of Tx descriptor registers */
 #define NUM_RX_DESC    256     /* Number of Rx descriptor registers */
-#define RX_BUF_SIZE    1536    /* Rx Buffer size */
 #define R8169_TX_RING_BYTES    (NUM_TX_DESC * sizeof(struct TxDesc))
 #define R8169_RX_RING_BYTES    (NUM_RX_DESC * sizeof(struct RxDesc))
 
 #define RTL8169_TX_TIMEOUT     (6*HZ)
 #define RTL8169_PHY_TIMEOUT    (10*HZ)
 
-#define RTL_EEPROM_SIG         cpu_to_le32(0x8129)
-#define RTL_EEPROM_SIG_MASK    cpu_to_le32(0xffff)
-#define RTL_EEPROM_SIG_ADDR    0x0000
-
 /* write/read MMIO register */
 #define RTL_W8(reg, val8)      writeb ((val8), ioaddr + (reg))
 #define RTL_W16(reg, val16)    writew ((val16), ioaddr + (reg))
@@ -456,6 +450,7 @@ enum rtl8168_registers {
 #define PWM_EN                         (1 << 22)
 #define RXDV_GATED_EN                  (1 << 19)
 #define EARLY_TALLY_EN                 (1 << 16)
+#define FORCE_CLK                      (1 << 15) /* force clock request */
 };
 
 enum rtl_register_content {
@@ -519,6 +514,7 @@ enum rtl_register_content {
        PMEnable        = (1 << 0),     /* Power Management Enable */
 
        /* Config2 register p. 25 */
+       ClkReqEn        = (1 << 7),     /* Clock Request Enable */
        MSIEnable       = (1 << 5),     /* 8169 only. Reserved in the 8168. */
        PCI_Clock_66MHz = 0x01,
        PCI_Clock_33MHz = 0x00,
@@ -539,6 +535,7 @@ enum rtl_register_content {
        Spi_en          = (1 << 3),
        LanWake         = (1 << 1),     /* LanWake enable/disable */
        PMEStatus       = (1 << 0),     /* PME status can be reset by PCI RST# */
+       ASPM_en         = (1 << 0),     /* ASPM enable */
 
        /* TBICSR p.28 */
        TBIReset        = 0x80000000,
@@ -687,6 +684,7 @@ enum features {
        RTL_FEATURE_WOL         = (1 << 0),
        RTL_FEATURE_MSI         = (1 << 1),
        RTL_FEATURE_GMII        = (1 << 2),
+       RTL_FEATURE_FW_LOADED   = (1 << 3),
 };
 
 struct rtl8169_counters {
@@ -1816,8 +1814,7 @@ static int rtl8169_set_features(struct net_device *dev,
 }
 
 
-static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
-                                     struct sk_buff *skb)
+static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
 {
        return (vlan_tx_tag_present(skb)) ?
                TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
@@ -2394,8 +2391,10 @@ static void rtl_apply_firmware(struct rtl8169_private *tp)
        struct rtl_fw *rtl_fw = tp->rtl_fw;
 
        /* TODO: release firmware once rtl_phy_write_fw signals failures. */
-       if (!IS_ERR_OR_NULL(rtl_fw))
+       if (!IS_ERR_OR_NULL(rtl_fw)) {
                rtl_phy_write_fw(tp, rtl_fw);
+               tp->features |= RTL_FEATURE_FW_LOADED;
+       }
 }
 
 static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
@@ -2406,6 +2405,31 @@ static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
                rtl_apply_firmware(tp);
 }
 
+static void r810x_aldps_disable(struct rtl8169_private *tp)
+{
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_writephy(tp, 0x18, 0x0310);
+       msleep(100);
+}
+
+static void r810x_aldps_enable(struct rtl8169_private *tp)
+{
+       if (!(tp->features & RTL_FEATURE_FW_LOADED))
+               return;
+
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_writephy(tp, 0x18, 0x8310);
+}
+
+static void r8168_aldps_enable_1(struct rtl8169_private *tp)
+{
+       if (!(tp->features & RTL_FEATURE_FW_LOADED))
+               return;
+
+       rtl_writephy(tp, 0x1f, 0x0000);
+       rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000);
+}
+
 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
 {
        static const struct phy_reg phy_reg_init[] = {
@@ -3096,6 +3120,23 @@ static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x0d, 0x0000);
 }
 
+static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
+{
+       const u16 w[] = {
+               addr[0] | (addr[1] << 8),
+               addr[2] | (addr[3] << 8),
+               addr[4] | (addr[5] << 8)
+       };
+       const struct exgmac_reg e[] = {
+               { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) },
+               { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] },
+               { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 },
+               { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) }
+       };
+
+       rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
+}
+
 static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
 {
        static const struct phy_reg phy_reg_init[] = {
@@ -3178,6 +3219,11 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp)
        rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
        rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
        rtl_writephy(tp, 0x1f, 0x0000);
+
+       r8168_aldps_enable_1(tp);
+
+       /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */
+       rtl_rar_exgmac_set(tp, tp->dev->dev_addr);
 }
 
 static void rtl8168f_hw_phy_config(struct rtl8169_private *tp)
@@ -3250,6 +3296,8 @@ static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x05, 0x8b85);
        rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000);
        rtl_writephy(tp, 0x1f, 0x0000);
+
+       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
@@ -3257,6 +3305,8 @@ static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp)
        rtl_apply_firmware(tp);
 
        rtl8168f_hw_phy_config(tp);
+
+       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
@@ -3354,6 +3404,8 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp)
        rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001);
        rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400);
        rtl_writephy(tp, 0x1f, 0x0000);
+
+       r8168_aldps_enable_1(tp);
 }
 
 static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp)
@@ -3439,21 +3491,19 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
        };
 
        /* Disable ALDPS before ram code */
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, 0x18, 0x0310);
-       msleep(100);
+       r810x_aldps_disable(tp);
 
        rtl_apply_firmware(tp);
 
        rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+
+       r810x_aldps_enable(tp);
 }
 
 static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
 {
        /* Disable ALDPS before setting firmware */
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, 0x18, 0x0310);
-       msleep(20);
+       r810x_aldps_disable(tp);
 
        rtl_apply_firmware(tp);
 
@@ -3463,6 +3513,8 @@ static void rtl8402_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x10, 0x401f);
        rtl_writephy(tp, 0x19, 0x7030);
        rtl_writephy(tp, 0x1f, 0x0000);
+
+       r810x_aldps_enable(tp);
 }
 
 static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
@@ -3475,9 +3527,7 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
        };
 
        /* Disable ALDPS before ram code */
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, 0x18, 0x0310);
-       msleep(100);
+       r810x_aldps_disable(tp);
 
        rtl_apply_firmware(tp);
 
@@ -3485,6 +3535,8 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 
        rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
+
+       r810x_aldps_enable(tp);
 }
 
 static void rtl_hw_phy_config(struct net_device *dev)
@@ -3708,33 +3760,19 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
 static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
 {
        void __iomem *ioaddr = tp->mmio_addr;
-       u32 high;
-       u32 low;
-
-       low  = addr[0] | (addr[1] << 8) | (addr[2] << 16) | (addr[3] << 24);
-       high = addr[4] | (addr[5] << 8);
 
        rtl_lock_work(tp);
 
        RTL_W8(Cfg9346, Cfg9346_Unlock);
 
-       RTL_W32(MAC4, high);
+       RTL_W32(MAC4, addr[4] | addr[5] << 8);
        RTL_R32(MAC4);
 
-       RTL_W32(MAC0, low);
+       RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
        RTL_R32(MAC0);
 
-       if (tp->mac_version == RTL_GIGA_MAC_VER_34) {
-               const struct exgmac_reg e[] = {
-                       { .addr = 0xe0, ERIAR_MASK_1111, .val = low },
-                       { .addr = 0xe4, ERIAR_MASK_1111, .val = high },
-                       { .addr = 0xf0, ERIAR_MASK_1111, .val = low << 16 },
-                       { .addr = 0xf4, ERIAR_MASK_1111, .val = high << 16 |
-                                                               low  >> 16 },
-               };
-
-               rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e));
-       }
+       if (tp->mac_version == RTL_GIGA_MAC_VER_34)
+               rtl_rar_exgmac_set(tp, addr);
 
        RTL_W8(Cfg9346, Cfg9346_Lock);
 
@@ -3796,7 +3834,7 @@ static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
        }
 }
 
-static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp)
+static void rtl_init_mdio_ops(struct rtl8169_private *tp)
 {
        struct mdio_ops *ops = &tp->mdio_ops;
 
@@ -3827,6 +3865,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
        void __iomem *ioaddr = tp->mmio_addr;
 
        switch (tp->mac_version) {
+       case RTL_GIGA_MAC_VER_25:
+       case RTL_GIGA_MAC_VER_26:
        case RTL_GIGA_MAC_VER_29:
        case RTL_GIGA_MAC_VER_30:
        case RTL_GIGA_MAC_VER_32:
@@ -4046,7 +4086,7 @@ static void rtl_pll_power_up(struct rtl8169_private *tp)
        rtl_generic_op(tp, tp->pll_power_ops.up);
 }
 
-static void __devinit rtl_init_pll_power_ops(struct rtl8169_private *tp)
+static void rtl_init_pll_power_ops(struct rtl8169_private *tp)
 {
        struct pll_power_ops *ops = &tp->pll_power_ops;
 
@@ -4240,7 +4280,7 @@ static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
        RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0));
 }
 
-static void __devinit rtl_init_jumbo_ops(struct rtl8169_private *tp)
+static void rtl_init_jumbo_ops(struct rtl8169_private *tp)
 {
        struct jumbo_ops *ops = &tp->jumbo_ops;
 
@@ -4519,6 +4559,9 @@ static void rtl_set_rx_mode(struct net_device *dev)
                mc_filter[1] = swab32(data);
        }
 
+       if (tp->mac_version == RTL_GIGA_MAC_VER_35)
+               mc_filter[1] = mc_filter[0] = 0xffffffff;
+
        RTL_W32(MAR0 + 4, mc_filter[1]);
        RTL_W32(MAR0 + 0, mc_filter[0]);
 
@@ -4678,7 +4721,7 @@ static u32 r8402_csi_read(struct rtl8169_private *tp, int addr)
                RTL_R32(CSIDR) : ~0;
 }
 
-static void __devinit rtl_init_csi_ops(struct rtl8169_private *tp)
+static void rtl_init_csi_ops(struct rtl8169_private *tp)
 {
        struct csi_ops *ops = &tp->csi_ops;
 
@@ -5010,8 +5053,6 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
 
        RTL_W8(MaxTxPacketSize, EarlySize);
 
-       rtl_disable_clock_request(pdev);
-
        RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
        RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
 
@@ -5020,7 +5061,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
 
        RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
        RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
-       RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+       RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
+       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
 }
 
 static void rtl_hw_start_8168f(struct rtl8169_private *tp)
@@ -5045,13 +5087,12 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)
 
        RTL_W8(MaxTxPacketSize, EarlySize);
 
-       rtl_disable_clock_request(pdev);
-
        RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
        RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
        RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
-       RTL_W32(MISC, RTL_R32(MISC) | PWM_EN);
-       RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en);
+       RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK);
+       RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en);
+       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
 }
 
 static void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
@@ -5108,8 +5149,10 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
        rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC);
 
        RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
-       RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN);
+       RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN);
        RTL_W8(MaxTxPacketSize, EarlySize);
+       RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
 
        rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
        rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC);
@@ -5325,6 +5368,9 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
 
        RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
        RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN);
+       RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+       RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
 
        rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
 }
@@ -5350,6 +5396,9 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp)
 
        RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO);
        RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB);
+       RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
+       RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK);
 
        rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402));
 
@@ -5371,7 +5420,10 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
        /* Force LAN exit from ASPM if Rx/Tx are not idle */
        RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
 
-       RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
+       RTL_W32(MISC,
+               (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN);
+       RTL_W8(Config5, RTL_R8(Config5) | ASPM_en);
+       RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn);
        RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
        RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN);
 }
@@ -5769,7 +5821,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
        tp->tx_skb[entry].len = len;
        txd->addr = cpu_to_le64(mapping);
 
-       opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb));
+       opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb));
        opts[0] = DescOwn;
 
        rtl8169_tso_csum(tp, skb, opts);
@@ -6564,7 +6616,7 @@ static void rtl_shutdown(struct pci_dev *pdev)
        pm_runtime_put_noidle(d);
 }
 
-static void __devexit rtl_remove_one(struct pci_dev *pdev)
+static void rtl_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rtl8169_private *tp = netdev_priv(dev);
@@ -6684,7 +6736,7 @@ DECLARE_RTL_COND(rtl_rxtx_empty_cond)
        return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY;
 }
 
-static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp)
+static void rtl_hw_init_8168g(struct rtl8169_private *tp)
 {
        void __iomem *ioaddr = tp->mmio_addr;
        u32 data;
@@ -6718,7 +6770,7 @@ static void __devinit rtl_hw_init_8168g(struct rtl8169_private *tp)
                return;
 }
 
-static void __devinit rtl_hw_initialize(struct rtl8169_private *tp)
+static void rtl_hw_initialize(struct rtl8169_private *tp)
 {
        switch (tp->mac_version) {
        case RTL_GIGA_MAC_VER_40:
@@ -6731,7 +6783,7 @@ static void __devinit rtl_hw_initialize(struct rtl8169_private *tp)
        }
 }
 
-static int __devinit
+static int
 rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data;
@@ -6982,20 +7034,9 @@ static struct pci_driver rtl8169_pci_driver = {
        .name           = MODULENAME,
        .id_table       = rtl8169_pci_tbl,
        .probe          = rtl_init_one,
-       .remove         = __devexit_p(rtl_remove_one),
+       .remove         = rtl_remove_one,
        .shutdown       = rtl_shutdown,
        .driver.pm      = RTL8169_PM_OPS,
 };
 
-static int __init rtl8169_init_module(void)
-{
-       return pci_register_driver(&rtl8169_pci_driver);
-}
-
-static void __exit rtl8169_cleanup_module(void)
-{
-       pci_unregister_driver(&rtl8169_pci_driver);
-}
-
-module_init(rtl8169_init_module);
-module_exit(rtl8169_cleanup_module);
+module_pci_driver(rtl8169_pci_driver);
index c8bfea0524dd304408642b5df86c3119d7a6a65c..3d705862bd7d1176ec62235bc7fadc508b9dddbc 100644 (file)
@@ -2286,7 +2286,7 @@ static int sh_mdio_init(struct net_device *ndev, int id,
        for (i = 0; i < PHY_MAX_ADDR; i++)
                mdp->mii_bus->irq[i] = PHY_POLL;
 
-       /* regist mdio bus */
+       /* register mdio bus */
        ret = mdiobus_register(mdp->mii_bus);
        if (ret)
                goto out_free_irq;
index 2ed3ab4b3c2d61648633596662cf47489172d289..72fc57dd084d1a6b57a9301a8ae2bc43a3ffd249 100644 (file)
@@ -954,7 +954,7 @@ static struct net_device_stats *s6gmac_stats(struct net_device *dev)
        return st;
 }
 
-static int __devinit s6gmac_probe(struct platform_device *pdev)
+static int s6gmac_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct s6gmac *pd;
@@ -1030,7 +1030,7 @@ errirq:
        return res;
 }
 
-static int __devexit s6gmac_remove(struct platform_device *pdev)
+static int s6gmac_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        if (dev) {
@@ -1046,7 +1046,7 @@ static int __devexit s6gmac_remove(struct platform_device *pdev)
 
 static struct platform_driver s6gmac_driver = {
        .probe = s6gmac_probe,
-       .remove = __devexit_p(s6gmac_remove),
+       .remove = s6gmac_remove,
        .driver = {
                .name = "s6gmac",
                .owner = THIS_MODULE,
index 6a40dd03a32f16b2289db8605daf1f77e564a3f8..3aca57853ed470034d46e9eb01a848b761fbec28 100644 (file)
@@ -67,7 +67,7 @@
 #include <asm/ecard.h>
 #include <asm/io.h>
 
-static char version[] __devinitdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
+static char version[] = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
 
 #include "ether3.h"
 
@@ -194,7 +194,7 @@ static inline void ether3_ledon(struct net_device *dev)
  * Read the ethernet address string from the on board rom.
  * This is an ascii string!!!
  */
-static int __devinit
+static int
 ether3_addr(char *addr, struct expansion_card *ec)
 {
        struct in_chunk_dir cd;
@@ -219,7 +219,7 @@ ether3_addr(char *addr, struct expansion_card *ec)
 
 /* --------------------------------------------------------------------------- */
 
-static int __devinit
+static int
 ether3_ramtest(struct net_device *dev, unsigned char byte)
 {
        unsigned char *buffer = kmalloc(RX_END, GFP_KERNEL);
@@ -268,7 +268,7 @@ ether3_ramtest(struct net_device *dev, unsigned char byte)
 
 /* ------------------------------------------------------------------------------- */
 
-static int __devinit ether3_init_2(struct net_device *dev)
+static int ether3_init_2(struct net_device *dev)
 {
        int i;
 
@@ -399,12 +399,6 @@ ether3_probe_bus_16(struct net_device *dev, int val)
 static int
 ether3_open(struct net_device *dev)
 {
-       if (!is_valid_ether_addr(dev->dev_addr)) {
-               printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
-                       dev->name);
-               return -EINVAL;
-       }
-
        if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
                return -EAGAIN;
 
@@ -748,7 +742,7 @@ static void ether3_tx(struct net_device *dev)
        }
 }
 
-static void __devinit ether3_banner(void)
+static void ether3_banner(void)
 {
        static unsigned version_printed = 0;
 
@@ -767,7 +761,7 @@ static const struct net_device_ops ether3_netdev_ops = {
        .ndo_set_mac_address    = eth_mac_addr,
 };
 
-static int __devinit
+static int
 ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
        const struct ether3_data *data = id->data;
@@ -864,7 +858,7 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
        return ret;
 }
 
-static void __devexit ether3_remove(struct expansion_card *ec)
+static void ether3_remove(struct expansion_card *ec)
 {
        struct net_device *dev = ecard_get_drvdata(ec);
 
@@ -894,7 +888,7 @@ static const struct ecard_id ether3_ids[] = {
 
 static struct ecard_driver ether3_driver = {
        .probe          = ether3_probe,
-       .remove         = __devexit_p(ether3_remove),
+       .remove         = ether3_remove,
        .id_table       = ether3_ids,
        .drv = {
                .name   = "ether3",
index 4d15bf413bdc89f060964c8114d4486be337ce46..0fde9ca282696f53af4f32b8df32fed0cc0398e9 100644 (file)
@@ -721,7 +721,7 @@ static const struct net_device_ops sgiseeq_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit sgiseeq_probe(struct platform_device *pdev)
+static int sgiseeq_probe(struct platform_device *pdev)
 {
        struct sgiseeq_platform_data *pd = pdev->dev.platform_data;
        struct hpc3_regs *hpcregs = pd->hpc;
index 25906c1d1b1590825502bc192dffa1aa8d8e494e..435b4f1e348886b0294cfc2fb75c9ff0ecb25eac 100644 (file)
@@ -1,10 +1,11 @@
 config SFC
        tristate "Solarflare SFC4000/SFC9000-family support"
-       depends on PCI && INET
+       depends on PCI
        select MDIO
        select CRC32
        select I2C
        select I2C_ALGOBIT
+       select PTP_1588_CLOCK
        ---help---
          This driver supports 10-gigabit Ethernet cards based on
          the Solarflare SFC4000 and SFC9000-family controllers.
@@ -34,10 +35,3 @@ config SFC_SRIOV
          This enables support for the SFC9000 I/O Virtualization
          features, allowing accelerated network performance in
          virtualized environments.
-config SFC_PTP
-       bool "Solarflare SFC9000-family PTP support"
-       depends on SFC && PTP_1588_CLOCK && !(SFC=y && PTP_1588_CLOCK=m)
-       default y
-       ---help---
-         This enables support for the Precision Time Protocol (PTP)
-         on SFC9000-family NICs
index e11f2ecf69d9b5dfd0ae5600e33bb0fe1d7382fc..945bf06e69ef11c636849ed1f20263868a6b0947 100644 (file)
@@ -2,9 +2,8 @@ sfc-y                   += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
                           falcon_xmac.o mcdi_mac.o \
                           selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
                           tenxpress.o txc43128_phy.o falcon_boards.o \
-                          mcdi.o mcdi_phy.o mcdi_mon.o
+                          mcdi.o mcdi_phy.o mcdi_mon.o ptp.o
 sfc-$(CONFIG_SFC_MTD)  += mtd.o
 sfc-$(CONFIG_SFC_SRIOV)        += siena_sriov.o
-sfc-$(CONFIG_SFC_PTP)  += ptp.o
 
 obj-$(CONFIG_SFC)      += sfc.o
index 4f86d0cd516a3db2b4eff785d59d1f1a7c07a978..bf57b3cb16abdbc1e89e8aaa83c99a9c47888552 100644 (file)
@@ -106,8 +106,8 @@ static struct workqueue_struct *reset_workqueue;
  *
  * This is only used in MSI-X interrupt mode
  */
-static unsigned int separate_tx_channels;
-module_param(separate_tx_channels, uint, 0444);
+static bool separate_tx_channels;
+module_param(separate_tx_channels, bool, 0444);
 MODULE_PARM_DESC(separate_tx_channels,
                 "Use separate channels for TX and RX");
 
@@ -160,8 +160,8 @@ static unsigned int rss_cpus;
 module_param(rss_cpus, uint, 0444);
 MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
 
-static int phy_flash_cfg;
-module_param(phy_flash_cfg, int, 0644);
+static bool phy_flash_cfg;
+module_param(phy_flash_cfg, bool, 0644);
 MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially");
 
 static unsigned irq_adapt_low_thresh = 8000;
@@ -2279,7 +2279,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method)
        netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",
                   RESET_TYPE(method));
 
-       netif_device_detach(efx->net_dev);
+       efx_device_detach_sync(efx);
        efx_reset_down(efx, method);
 
        rc = efx->type->reset(efx, method);
@@ -2669,8 +2669,8 @@ static int efx_pci_probe_main(struct efx_nic *efx)
  * transmission; this is left to the first time one of the network
  * interfaces is brought up (i.e. efx_net_open).
  */
-static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
-                                  const struct pci_device_id *entry)
+static int efx_pci_probe(struct pci_dev *pci_dev,
+                        const struct pci_device_id *entry)
 {
        struct net_device *net_dev;
        struct efx_nic *efx;
@@ -2758,7 +2758,7 @@ static int efx_pm_freeze(struct device *dev)
        if (efx->state != STATE_DISABLED) {
                efx->state = STATE_UNINIT;
 
-               netif_device_detach(efx->net_dev);
+               efx_device_detach_sync(efx);
 
                efx_stop_all(efx);
                efx_stop_interrupts(efx, false);
index f11170bc48bf4f292d38c4ac5c31a55db10499ee..50247dfe8f574d2a7184c8ea675b5ecabdcc37cc 100644 (file)
@@ -163,4 +163,17 @@ extern void efx_link_status_changed(struct efx_nic *efx);
 extern void efx_link_set_advertising(struct efx_nic *efx, u32);
 extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8);
 
+static inline void efx_device_detach_sync(struct efx_nic *efx)
+{
+       struct net_device *dev = efx->net_dev;
+
+       /* Lock/freeze all TX queues so that we can be sure the
+        * TX scheduler is stopped when we're done and before
+        * netif_device_present() becomes false.
+        */
+       netif_tx_lock(dev);
+       netif_device_detach(dev);
+       netif_tx_unlock(dev);
+}
+
 #endif /* EFX_EFX_H */
index 90f078eff8e60d86b491763c7a2b40edf7012052..8e61cd06f66af16a693e5ba47e3b4ef29bf17ddd 100644 (file)
@@ -816,6 +816,9 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
 /* MAC address mask including only MC flag */
 static const u8 mac_addr_mc_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
 
+#define IP4_ADDR_FULL_MASK     ((__force __be32)~0)
+#define PORT_FULL_MASK         ((__force __be16)~0)
+
 static int efx_ethtool_get_class_rule(struct efx_nic *efx,
                                      struct ethtool_rx_flow_spec *rule)
 {
@@ -865,12 +868,12 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
                        &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst,
                        &ip_entry->ip4src, &ip_entry->psrc);
                EFX_WARN_ON_PARANOID(rc);
-               ip_mask->ip4src = ~0;
-               ip_mask->psrc = ~0;
+               ip_mask->ip4src = IP4_ADDR_FULL_MASK;
+               ip_mask->psrc = PORT_FULL_MASK;
        }
        rule->flow_type = (proto == IPPROTO_TCP) ? TCP_V4_FLOW : UDP_V4_FLOW;
-       ip_mask->ip4dst = ~0;
-       ip_mask->pdst = ~0;
+       ip_mask->ip4dst = IP4_ADDR_FULL_MASK;
+       ip_mask->pdst = PORT_FULL_MASK;
        return rc;
 }
 
@@ -971,7 +974,7 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
 
        /* Check for unsupported extensions */
        if ((rule->flow_type & FLOW_EXT) &&
-           (rule->m_ext.vlan_etype | rule->m_ext.data[0] |
+           (rule->m_ext.vlan_etype || rule->m_ext.data[0] ||
             rule->m_ext.data[1]))
                return -EINVAL;
 
@@ -986,16 +989,16 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
                            IPPROTO_TCP : IPPROTO_UDP);
 
                /* Must match all of destination, */
-               if ((__force u32)~ip_mask->ip4dst |
-                   (__force u16)~ip_mask->pdst)
+               if (!(ip_mask->ip4dst == IP4_ADDR_FULL_MASK &&
+                     ip_mask->pdst == PORT_FULL_MASK))
                        return -EINVAL;
                /* all or none of source, */
-               if ((ip_mask->ip4src | ip_mask->psrc) &&
-                   ((__force u32)~ip_mask->ip4src |
-                    (__force u16)~ip_mask->psrc))
+               if ((ip_mask->ip4src || ip_mask->psrc) &&
+                   !(ip_mask->ip4src == IP4_ADDR_FULL_MASK &&
+                     ip_mask->psrc == PORT_FULL_MASK))
                        return -EINVAL;
                /* and nothing else */
-               if (ip_mask->tos | rule->m_ext.vlan_tci)
+               if (ip_mask->tos || rule->m_ext.vlan_tci)
                        return -EINVAL;
 
                if (ip_mask->ip4src)
index 12b573a8e82b6a083da1bd86c714a37792624c1f..49bcd196e10d04b4bac011ba20e652756833c543 100644 (file)
@@ -1792,6 +1792,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
        .remove_port = falcon_remove_port,
        .handle_global_event = falcon_handle_global_event,
        .prepare_flush = falcon_prepare_flush,
+       .finish_flush = efx_port_dummy_op_void,
        .update_stats = falcon_update_nic_stats,
        .start_stats = falcon_start_nic_stats,
        .stop_stats = falcon_stop_nic_stats,
@@ -1834,6 +1835,7 @@ const struct efx_nic_type falcon_b0_nic_type = {
        .remove_port = falcon_remove_port,
        .handle_global_event = falcon_handle_global_event,
        .prepare_flush = falcon_prepare_flush,
+       .finish_flush = efx_port_dummy_op_void,
        .update_stats = falcon_update_nic_stats,
        .start_stats = falcon_start_nic_stats,
        .stop_stats = falcon_stop_nic_stats,
index 751d1ec112cc5d5e96f3755dec9482c8956457c8..96759aee1c6c2fcb372f83a3f3dd844d39489e97 100644 (file)
  *
  * Notes on locking strategy:
  *
- * Most CSRs are 128-bit (oword) and therefore cannot be read or
- * written atomically.  Access from the host is buffered by the Bus
- * Interface Unit (BIU).  Whenever the host reads from the lowest
- * address of such a register, or from the address of a different such
- * register, the BIU latches the register's value.  Subsequent reads
- * from higher addresses of the same register will read the latched
- * value.  Whenever the host writes part of such a register, the BIU
- * collects the written value and does not write to the underlying
- * register until all 4 dwords have been written.  A similar buffering
- * scheme applies to host access to the NIC's 64-bit SRAM.
+ * Many CSRs are very wide and cannot be read or written atomically.
+ * Writes from the host are buffered by the Bus Interface Unit (BIU)
+ * up to 128 bits.  Whenever the host writes part of such a register,
+ * the BIU collects the written value and does not write to the
+ * underlying register until all 4 dwords have been written.  A
+ * similar buffering scheme applies to host access to the NIC's 64-bit
+ * SRAM.
  *
- * Access to different CSRs and 64-bit SRAM words must be serialised,
- * since interleaved access can result in lost writes or lost
- * information from read-to-clear fields.  We use efx_nic::biu_lock
- * for this.  (We could use separate locks for read and write, but
- * this is not normally a performance bottleneck.)
+ * Writes to different CSRs and 64-bit SRAM words must be serialised,
+ * since interleaved access can result in lost writes.  We use
+ * efx_nic::biu_lock for this.
+ *
+ * We also serialise reads from 128-bit CSRs and SRAM with the same
+ * spinlock.  This may not be necessary, but it doesn't really matter
+ * as there are no such reads on the fast path.
  *
  * The DMA descriptor pointers (RX_DESC_UPD and TX_DESC_UPD) are
  * 128-bit but are special-cased in the BIU to avoid the need for
@@ -204,20 +203,6 @@ static inline void efx_reado_table(struct efx_nic *efx, efx_oword_t *value,
        efx_reado(efx, value, reg + index * sizeof(efx_oword_t));
 }
 
-/* Write a 32-bit CSR forming part of a table, or 32-bit SRAM */
-static inline void efx_writed_table(struct efx_nic *efx, efx_dword_t *value,
-                                      unsigned int reg, unsigned int index)
-{
-       efx_writed(efx, value, reg + index * sizeof(efx_oword_t));
-}
-
-/* Read a 32-bit CSR forming part of a table, or 32-bit SRAM */
-static inline void efx_readd_table(struct efx_nic *efx, efx_dword_t *value,
-                                  unsigned int reg, unsigned int index)
-{
-       efx_readd(efx, value, reg + index * sizeof(efx_dword_t));
-}
-
 /* Page-mapped register block size */
 #define EFX_PAGE_BLOCK_SIZE 0x2000
 
index aea43cbd05200acc1f19cd21e9f96d9e26782ca2..0095ce95150b9915b59cfea2344519879ca63ee5 100644 (file)
@@ -22,7 +22,7 @@
  **************************************************************************
  */
 
-#define MCDI_RPC_TIMEOUT       10 /*seconds */
+#define MCDI_RPC_TIMEOUT       (10 * HZ)
 
 #define MCDI_PDU(efx)                                                  \
        (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST)
@@ -120,7 +120,7 @@ static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
 static int efx_mcdi_poll(struct efx_nic *efx)
 {
        struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
-       unsigned int time, finish;
+       unsigned long time, finish;
        unsigned int respseq, respcmd, error;
        unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
        unsigned int rc, spins;
@@ -136,7 +136,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
         * and poll once a jiffy (approximately)
         */
        spins = TICK_USEC;
-       finish = get_seconds() + MCDI_RPC_TIMEOUT;
+       finish = jiffies + MCDI_RPC_TIMEOUT;
 
        while (1) {
                if (spins != 0) {
@@ -146,7 +146,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
                        schedule_timeout_uninterruptible(1);
                }
 
-               time = get_seconds();
+               time = jiffies;
 
                rmb();
                efx_readd(efx, &reg, pdu);
@@ -158,7 +158,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
                    EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE))
                        break;
 
-               if (time >= finish)
+               if (time_after(time, finish))
                        return -ETIMEDOUT;
        }
 
@@ -207,7 +207,9 @@ out:
        return 0;
 }
 
-/* Test and clear MC-rebooted flag for this port/function */
+/* Test and clear MC-rebooted flag for this port/function; reset
+ * software state as necessary.
+ */
 int efx_mcdi_poll_reboot(struct efx_nic *efx)
 {
        unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx);
@@ -223,6 +225,11 @@ int efx_mcdi_poll_reboot(struct efx_nic *efx)
        if (value == 0)
                return 0;
 
+       /* MAC statistics have been cleared on the NIC; clear our copy
+        * so that efx_update_diff_stat() can continue to work.
+        */
+       memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
+
        EFX_ZERO_DWORD(reg);
        efx_writed(efx, &reg, addr);
 
@@ -250,7 +257,7 @@ static int efx_mcdi_await_completion(struct efx_nic *efx)
        if (wait_event_timeout(
                    mcdi->wq,
                    atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED,
-                   msecs_to_jiffies(MCDI_RPC_TIMEOUT * 1000)) == 0)
+                   MCDI_RPC_TIMEOUT) == 0)
                return -ETIMEDOUT;
 
        /* Check if efx_mcdi_set_mode() switched us back to polled completions.
@@ -1216,7 +1223,7 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx)
 
        rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, (u8 *)qid,
                          count * sizeof(*qid), NULL, 0, NULL);
-       WARN_ON(rc > 0);
+       WARN_ON(rc < 0);
 
        kfree(qid);
 
index 576a31091165492879ee22edbfd00eee4972047a..2d756c1d71425823100f572065e224a59ca16813 100644 (file)
@@ -200,6 +200,7 @@ struct efx_tx_queue {
        /* Members shared between paths and sometimes updated */
        unsigned int empty_read_count ____cacheline_aligned_in_smp;
 #define EFX_EMPTY_COUNT_VALID 0x80000000
+       atomic_t flush_outstanding;
 };
 
 /**
@@ -868,9 +869,7 @@ struct efx_nic {
        struct work_struct peer_work;
 #endif
 
-#ifdef CONFIG_SFC_PTP
        struct efx_ptp_data *ptp_data;
-#endif
 
        /* The following fields may be written more often */
 
@@ -909,6 +908,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
  * @remove_port: Free resources allocated by probe_port()
  * @handle_global_event: Handle a "global" event (may be %NULL)
  * @prepare_flush: Prepare the hardware for flushing the DMA queues
+ * @finish_flush: Clean up after flushing the DMA queues
  * @update_stats: Update statistics not provided by event handling
  * @start_stats: Start the regular fetching of statistics
  * @stop_stats: Stop the regular fetching of statistics
@@ -956,6 +956,7 @@ struct efx_nic_type {
        void (*remove_port)(struct efx_nic *efx);
        bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *);
        void (*prepare_flush)(struct efx_nic *efx);
+       void (*finish_flush)(struct efx_nic *efx);
        void (*update_stats)(struct efx_nic *efx);
        void (*start_stats)(struct efx_nic *efx);
        void (*stop_stats)(struct efx_nic *efx);
index aab7cacb2e34a87203d199be8df72c20020b0e0b..0ad790cc473cb1697e71bd422af0e0086c0242a9 100644 (file)
@@ -73,6 +73,8 @@
        _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_TX_DRAIN,                 \
                           (_tx_queue)->queue)
 
+static void efx_magic_event(struct efx_channel *channel, u32 magic);
+
 /**************************************************************************
  *
  * Solarstorm hardware access
@@ -255,9 +257,6 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
        buffer->entries = len / EFX_BUF_SIZE;
        BUG_ON(buffer->dma_addr & (EFX_BUF_SIZE - 1));
 
-       /* All zeros is a potentially valid event so memset to 0xff */
-       memset(buffer->addr, 0xff, len);
-
        /* Select new buffer ID */
        buffer->index = efx->next_buffer_table;
        efx->next_buffer_table += buffer->entries;
@@ -494,6 +493,9 @@ static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue)
        struct efx_nic *efx = tx_queue->efx;
        efx_oword_t tx_flush_descq;
 
+       WARN_ON(atomic_read(&tx_queue->flush_outstanding));
+       atomic_set(&tx_queue->flush_outstanding, 1);
+
        EFX_POPULATE_OWORD_2(tx_flush_descq,
                             FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
                             FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue);
@@ -669,6 +671,47 @@ static bool efx_flush_wake(struct efx_nic *efx)
                 && atomic_read(&efx->rxq_flush_pending) > 0));
 }
 
+static bool efx_check_tx_flush_complete(struct efx_nic *efx)
+{
+       bool i = true;
+       efx_oword_t txd_ptr_tbl;
+       struct efx_channel *channel;
+       struct efx_tx_queue *tx_queue;
+
+       efx_for_each_channel(channel, efx) {
+               efx_for_each_channel_tx_queue(tx_queue, channel) {
+                       efx_reado_table(efx, &txd_ptr_tbl,
+                                       FR_BZ_TX_DESC_PTR_TBL, tx_queue->queue);
+                       if (EFX_OWORD_FIELD(txd_ptr_tbl,
+                                           FRF_AZ_TX_DESCQ_FLUSH) ||
+                           EFX_OWORD_FIELD(txd_ptr_tbl,
+                                           FRF_AZ_TX_DESCQ_EN)) {
+                               netif_dbg(efx, hw, efx->net_dev,
+                                         "flush did not complete on TXQ %d\n",
+                                         tx_queue->queue);
+                               i = false;
+                       } else if (atomic_cmpxchg(&tx_queue->flush_outstanding,
+                                                 1, 0)) {
+                               /* The flush is complete, but we didn't
+                                * receive a flush completion event
+                                */
+                               netif_dbg(efx, hw, efx->net_dev,
+                                         "flush complete on TXQ %d, so drain "
+                                         "the queue\n", tx_queue->queue);
+                               /* Don't need to increment drain_pending as it
+                                * has already been incremented for the queues
+                                * which did not drain
+                                */
+                               efx_magic_event(channel,
+                                               EFX_CHANNEL_MAGIC_TX_DRAIN(
+                                                       tx_queue));
+                       }
+               }
+       }
+
+       return i;
+}
+
 /* Flush all the transmit queues, and continue flushing receive queues until
  * they're all flushed. Wait for the DRAIN events to be recieved so that there
  * are no more RX and TX events left on any channel. */
@@ -680,7 +723,6 @@ int efx_nic_flush_queues(struct efx_nic *efx)
        struct efx_tx_queue *tx_queue;
        int rc = 0;
 
-       efx->fc_disable++;
        efx->type->prepare_flush(efx);
 
        efx_for_each_channel(channel, efx) {
@@ -730,7 +772,8 @@ int efx_nic_flush_queues(struct efx_nic *efx)
                                             timeout);
        }
 
-       if (atomic_read(&efx->drain_pending)) {
+       if (atomic_read(&efx->drain_pending) &&
+           !efx_check_tx_flush_complete(efx)) {
                netif_err(efx, hw, efx->net_dev, "failed to flush %d queues "
                          "(rx %d+%d)\n", atomic_read(&efx->drain_pending),
                          atomic_read(&efx->rxq_flush_outstanding),
@@ -742,7 +785,7 @@ int efx_nic_flush_queues(struct efx_nic *efx)
                atomic_set(&efx->rxq_flush_outstanding, 0);
        }
 
-       efx->fc_disable--;
+       efx->type->finish_flush(efx);
 
        return rc;
 }
@@ -766,8 +809,13 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
 
        EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR,
                             channel->eventq_read_ptr & channel->eventq_mask);
-       efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base,
-                        channel->channel);
+
+       /* For Falcon A1, EVQ_RPTR_KER is documented as having a step size
+        * of 4 bytes, but it is really 16 bytes just like later revisions.
+        */
+       efx_writed(efx, &reg,
+                  efx->type->evq_rptr_tbl_base +
+                  FR_BZ_EVQ_RPTR_STEP * channel->channel);
 }
 
 /* Use HW to insert a SW defined event */
@@ -1017,9 +1065,10 @@ efx_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event)
        if (qid < EFX_TXQ_TYPES * efx->n_tx_channels) {
                tx_queue = efx_get_tx_queue(efx, qid / EFX_TXQ_TYPES,
                                            qid % EFX_TXQ_TYPES);
-
-               efx_magic_event(tx_queue->channel,
-                               EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue));
+               if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0)) {
+                       efx_magic_event(tx_queue->channel,
+                                       EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue));
+               }
        }
 }
 
@@ -1565,7 +1614,9 @@ void efx_nic_push_rx_indir_table(struct efx_nic *efx)
        for (i = 0; i < FR_BZ_RX_INDIRECTION_TBL_ROWS; i++) {
                EFX_POPULATE_DWORD_1(dword, FRF_BZ_IT_QUEUE,
                                     efx->rx_indir_table[i]);
-               efx_writed_table(efx, &dword, FR_BZ_RX_INDIRECTION_TBL, i);
+               efx_writed(efx, &dword,
+                          FR_BZ_RX_INDIRECTION_TBL +
+                          FR_BZ_RX_INDIRECTION_TBL_STEP * i);
        }
 }
 
@@ -2029,15 +2080,15 @@ void efx_nic_get_regs(struct efx_nic *efx, void *buf)
 
                for (i = 0; i < table->rows; i++) {
                        switch (table->step) {
-                       case 4: /* 32-bit register or SRAM */
-                               efx_readd_table(efx, buf, table->offset, i);
+                       case 4: /* 32-bit SRAM */
+                               efx_readd(efx, buf, table->offset + 4 * i);
                                break;
                        case 8: /* 64-bit SRAM */
                                efx_sram_readq(efx,
                                               efx->membase + table->offset,
                                               buf, i);
                                break;
-                       case 16: /* 128-bit register */
+                       case 16: /* 128-bit-readable register */
                                efx_reado_table(efx, buf, table->offset, i);
                                break;
                        case 32: /* 128-bit register, interleaved */
index 438cef11f7270bd620ed04c42fb1c8ee8a9d3621..1b0003323498502741f2c36d5437586a8e8176f6 100644 (file)
@@ -252,7 +252,6 @@ extern int efx_sriov_set_vf_spoofchk(struct net_device *net_dev, int vf,
                                     bool spoofchk);
 
 struct ethtool_ts_info;
-#ifdef CONFIG_SFC_PTP
 extern void efx_ptp_probe(struct efx_nic *efx);
 extern int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd);
 extern int efx_ptp_get_ts_info(struct net_device *net_dev,
@@ -260,31 +259,6 @@ extern int efx_ptp_get_ts_info(struct net_device *net_dev,
 extern bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 extern int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb);
 extern void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev);
-#else
-static inline void efx_ptp_probe(struct efx_nic *efx) {}
-static inline int efx_ptp_ioctl(struct efx_nic *efx, struct ifreq *ifr, int cmd)
-{
-       return -EOPNOTSUPP;
-}
-static inline int efx_ptp_get_ts_info(struct net_device *net_dev,
-                                     struct ethtool_ts_info *ts_info)
-{
-       ts_info->so_timestamping = (SOF_TIMESTAMPING_SOFTWARE |
-                                   SOF_TIMESTAMPING_RX_SOFTWARE);
-       ts_info->phc_index = -1;
-
-       return 0;
-}
-static inline bool efx_ptp_is_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
-{
-       return false;
-}
-static inline int efx_ptp_tx(struct efx_nic *efx, struct sk_buff *skb)
-{
-       return NETDEV_TX_OK;
-}
-static inline void efx_ptp_event(struct efx_nic *efx, efx_qword_t *ev) {}
-#endif
 
 extern const struct efx_nic_type falcon_a1_nic_type;
 extern const struct efx_nic_type falcon_b0_nic_type;
@@ -370,6 +344,8 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx)
 
 /* Global Resources */
 extern int efx_nic_flush_queues(struct efx_nic *efx);
+extern void siena_prepare_flush(struct efx_nic *efx);
+extern void siena_finish_flush(struct efx_nic *efx);
 extern void falcon_start_nic_stats(struct efx_nic *efx);
 extern void falcon_stop_nic_stats(struct efx_nic *efx);
 extern void falcon_setup_xaui(struct efx_nic *efx);
index 9e0ad1b75c335c0bf014fd1b47962c6719705767..d780a0d096b4c5b0b87036c6404089309592d43b 100644 (file)
@@ -187,7 +187,6 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
        struct efx_nic *efx = rx_queue->efx;
        struct efx_rx_buffer *rx_buf;
        struct page *page;
-       void *page_addr;
        struct efx_rx_page_state *state;
        dma_addr_t dma_addr;
        unsigned index, count;
@@ -207,12 +206,10 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
                        __free_pages(page, efx->rx_buffer_order);
                        return -EIO;
                }
-               page_addr = page_address(page);
-               state = page_addr;
+               state = page_address(page);
                state->refcnt = 0;
                state->dma_addr = dma_addr;
 
-               page_addr += sizeof(struct efx_rx_page_state);
                dma_addr += sizeof(struct efx_rx_page_state);
 
        split:
@@ -230,7 +227,6 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
                        /* Use the second half of the page */
                        get_page(page);
                        dma_addr += (PAGE_SIZE >> 1);
-                       page_addr += (PAGE_SIZE >> 1);
                        ++count;
                        goto split;
                }
index ce72ae4f399fdf3861262967aeb8222d5856bd85..2069f51b2aa9a1412f342b7654a6fb21ae17d9ee 100644 (file)
@@ -373,7 +373,7 @@ static void efx_iterate_state(struct efx_nic *efx)
        /* saddr set later and used as incrementing count */
        payload->ip.daddr = htonl(INADDR_LOOPBACK);
        payload->ip.ihl = 5;
-       payload->ip.check = htons(0xdead);
+       payload->ip.check = (__force __sum16) htons(0xdead);
        payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr));
        payload->ip.version = IPVERSION;
        payload->ip.protocol = IPPROTO_UDP;
@@ -722,7 +722,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
        /* Detach the device so the kernel doesn't transmit during the
         * loopback test and the watchdog timeout doesn't fire.
         */
-       netif_device_detach(efx->net_dev);
+       efx_device_detach_sync(efx);
 
        if (efx->type->test_chip) {
                rc_reset = efx->type->test_chip(efx, tests);
index 84b41bf08a38a22ad8e9f0954ec32631628b4ad7..ba40f67e4f05da34c89475a68622375646da9dda 100644 (file)
@@ -127,6 +127,18 @@ static void siena_remove_port(struct efx_nic *efx)
        efx_nic_free_buffer(efx, &efx->stats_buffer);
 }
 
+void siena_prepare_flush(struct efx_nic *efx)
+{
+       if (efx->fc_disable++ == 0)
+               efx_mcdi_set_mac(efx);
+}
+
+void siena_finish_flush(struct efx_nic *efx)
+{
+       if (--efx->fc_disable == 0)
+               efx_mcdi_set_mac(efx);
+}
+
 static const struct efx_nic_register_test siena_register_tests[] = {
        { FR_AZ_ADR_REGION,
          EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) },
@@ -158,7 +170,7 @@ static const struct efx_nic_register_test siena_register_tests[] = {
 
 static int siena_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
 {
-       enum reset_type reset_method = reset_method;
+       enum reset_type reset_method = RESET_TYPE_ALL;
        int rc, rc2;
 
        efx_reset_down(efx, reset_method);
@@ -659,7 +671,8 @@ const struct efx_nic_type siena_a0_nic_type = {
        .reset = siena_reset_hw,
        .probe_port = siena_probe_port,
        .remove_port = siena_remove_port,
-       .prepare_flush = efx_port_dummy_op_void,
+       .prepare_flush = siena_prepare_flush,
+       .finish_flush = siena_finish_flush,
        .update_stats = siena_update_nic_stats,
        .start_stats = siena_start_nic_stats,
        .stop_stats = siena_stop_nic_stats,
index d49b53dc2a500a2602093a2df63daba5c5ad2538..90f8d1604f5fbc8c6e7d1153169b99e97388e901 100644 (file)
@@ -695,8 +695,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
                return VFDI_RC_ENOMEM;
 
        rtnl_lock();
-       if (efx->fc_disable++ == 0)
-               efx_mcdi_set_mac(efx);
+       siena_prepare_flush(efx);
        rtnl_unlock();
 
        /* Flush all the initialized queues */
@@ -733,8 +732,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf)
        }
 
        rtnl_lock();
-       if (--efx->fc_disable == 0)
-               efx_mcdi_set_mac(efx);
+       siena_finish_flush(efx);
        rtnl_unlock();
 
        /* Irrespective of success/failure, fini the queues */
@@ -995,7 +993,7 @@ static void efx_sriov_reset_vf(struct efx_vf *vf, struct efx_buffer *buffer)
                             FRF_AZ_EVQ_BUF_BASE_ID, buftbl);
        efx_writeo_table(efx, &reg, FR_BZ_EVQ_PTR_TBL, abs_evq);
        EFX_POPULATE_DWORD_1(ptr, FRF_AZ_EVQ_RPTR, 0);
-       efx_writed_table(efx, &ptr, FR_BZ_EVQ_RPTR, abs_evq);
+       efx_writed(efx, &ptr, FR_BZ_EVQ_RPTR + FR_BZ_EVQ_RPTR_STEP * abs_evq);
 
        mutex_unlock(&vf->status_lock);
 }
index 3e5519a0acc7ebcccb897ed3719b8506a3b585ba..dc171b4961e47f2a0b0b3247701da908d1dbd601 100644 (file)
@@ -1143,7 +1143,7 @@ static int ioc3_is_menet(struct pci_dev *pdev)
  * Can't use UPF_IOREMAP as the whole of IOC3 resources have already been
  * registered.
  */
-static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
+static void ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
 {
 #define COSMISC_CONSTANT 6
 
@@ -1169,7 +1169,7 @@ static void __devinit ioc3_8250_register(struct ioc3_uartregs __iomem *uart)
        serial8250_register_8250_port(&port);
 }
 
-static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
+static void ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
 {
        /*
         * We need to recognice and treat the fourth MENET serial as it
@@ -1229,8 +1229,7 @@ static const struct net_device_ops ioc3_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
 };
 
-static int __devinit ioc3_probe(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned int sw_physid1, sw_physid2;
        struct net_device *dev = NULL;
@@ -1368,7 +1367,7 @@ out:
        return err;
 }
 
-static void __devexit ioc3_remove_one (struct pci_dev *pdev)
+static void ioc3_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct ioc3_private *ip = netdev_priv(dev);
@@ -1396,7 +1395,7 @@ static struct pci_driver ioc3_driver = {
        .name           = "ioc3-eth",
        .id_table       = ioc3_pci_tbl,
        .probe          = ioc3_probe,
-       .remove         = __devexit_p(ioc3_remove_one),
+       .remove         = ioc3_remove_one,
 };
 
 static int __init ioc3_init_module(void)
index 53efe7c7b1c066e7ce749bcbdfe53a773d262874..79ad9c94a21bf4b660c1cdaa60352d97facfdbec 100644 (file)
@@ -825,7 +825,7 @@ static const struct net_device_ops meth_netdev_ops = {
 /*
  * The init function.
  */
-static int __devinit meth_probe(struct platform_device *pdev)
+static int meth_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct meth_private *priv;
index 32e55664df6e3d0dc7dd384fb763beb74cccb4ae..b2315324cc6d77cbd97195b923bbb4952b1d5bc5 100644 (file)
@@ -1395,8 +1395,7 @@ static const struct net_device_ops sc92031_netdev_ops = {
 #endif
 };
 
-static int __devinit sc92031_probe(struct pci_dev *pdev,
-               const struct pci_device_id *id)
+static int sc92031_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        int err;
        void __iomem* port_base;
@@ -1489,7 +1488,7 @@ out_enable_device:
        return err;
 }
 
-static void __devexit sc92031_remove(struct pci_dev *pdev)
+static void sc92031_remove(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct sc92031_priv *priv = netdev_priv(dev);
@@ -1574,7 +1573,7 @@ static struct pci_driver sc92031_pci_driver = {
        .name           = SC92031_NAME,
        .id_table       = sc92031_pci_device_id_table,
        .probe          = sc92031_probe,
-       .remove         = __devexit_p(sc92031_remove),
+       .remove         = sc92031_remove,
        .suspend        = sc92031_suspend,
        .resume         = sc92031_resume,
 };
index d8166012b7d4f2fe4c72203a54b1b5c2c356f1ee..9a9c379420d120049bb43e53da5849be904d234d 100644 (file)
@@ -415,7 +415,7 @@ static u16 mdio_read_latched(void __iomem *ioaddr, int phy_id, int reg)
        return mdio_read(ioaddr, phy_id, reg);
 }
 
-static u16 __devinit sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
+static u16 sis190_read_eeprom(void __iomem *ioaddr, u32 reg)
 {
        u16 data = 0xffff;
        unsigned int i;
@@ -1379,7 +1379,7 @@ static void sis190_mii_probe_88e1111_fixup(struct sis190_private *tp)
  *     Identify and set current phy if found one,
  *     return error if it failed to found.
  */
-static int __devinit sis190_mii_probe(struct net_device *dev)
+static int sis190_mii_probe(struct net_device *dev)
 {
        struct sis190_private *tp = netdev_priv(dev);
        struct mii_if_info *mii_if = &tp->mii_if;
@@ -1451,7 +1451,7 @@ static void sis190_release_board(struct pci_dev *pdev)
        free_netdev(dev);
 }
 
-static struct net_device * __devinit sis190_init_board(struct pci_dev *pdev)
+static struct net_device *sis190_init_board(struct pci_dev *pdev)
 {
        struct sis190_private *tp;
        struct net_device *dev;
@@ -1573,8 +1573,8 @@ static void sis190_set_rgmii(struct sis190_private *tp, u8 reg)
        tp->features |= (reg & 0x80) ? F_HAS_RGMII : 0;
 }
 
-static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
-                                                    struct net_device *dev)
+static int sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
+                                          struct net_device *dev)
 {
        struct sis190_private *tp = netdev_priv(dev);
        void __iomem *ioaddr = tp->mmio_addr;
@@ -1615,10 +1615,10 @@ static int __devinit sis190_get_mac_addr_from_eeprom(struct pci_dev *pdev,
  *     APC CMOS RAM is accessed through ISA bridge.
  *     MAC address is read into @net_dev->dev_addr.
  */
-static int __devinit sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
-                                                 struct net_device *dev)
+static int sis190_get_mac_addr_from_apc(struct pci_dev *pdev,
+                                       struct net_device *dev)
 {
-       static const u16 __devinitconst ids[] = { 0x0965, 0x0966, 0x0968 };
+       static const u16 ids[] = { 0x0965, 0x0966, 0x0968 };
        struct sis190_private *tp = netdev_priv(dev);
        struct pci_dev *isa_bridge;
        u8 reg, tmp8;
@@ -1693,8 +1693,7 @@ static inline void sis190_init_rxfilter(struct net_device *dev)
        SIS_PCI_COMMIT();
 }
 
-static int __devinit sis190_get_mac_addr(struct pci_dev *pdev,
-                                        struct net_device *dev)
+static int sis190_get_mac_addr(struct pci_dev *pdev, struct net_device *dev)
 {
        int rc;
 
@@ -1845,8 +1844,8 @@ static const struct net_device_ops sis190_netdev_ops = {
 #endif
 };
 
-static int __devinit sis190_init_one(struct pci_dev *pdev,
-                                    const struct pci_device_id *ent)
+static int sis190_init_one(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        static int printed_version = 0;
        struct sis190_private *tp;
@@ -1916,7 +1915,7 @@ err_release_board:
        goto out;
 }
 
-static void __devexit sis190_remove_one(struct pci_dev *pdev)
+static void sis190_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct sis190_private *tp = netdev_priv(dev);
@@ -1932,7 +1931,7 @@ static struct pci_driver sis190_pci_driver = {
        .name           = DRV_NAME,
        .id_table       = sis190_pci_tbl,
        .probe          = sis190_init_one,
-       .remove         = __devexit_p(sis190_remove_one),
+       .remove         = sis190_remove_one,
 };
 
 static int __init sis190_init_module(void)
index fb9f6b38511f97beddbff380c2ae7d31878e4ff4..5bffd9749a58e0e658a7413cf39ea7d21697756e 100644 (file)
@@ -81,7 +81,7 @@
 #define SIS900_MODULE_NAME "sis900"
 #define SIS900_DRV_VERSION "v1.08.10 Apr. 2 2006"
 
-static const char version[] __devinitconst =
+static const char version[] =
        KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
 
 static int max_interrupt_work = 40;
@@ -251,7 +251,8 @@ static const struct ethtool_ops sis900_ethtool_ops;
  *     @net_dev->perm_addr.
  */
 
-static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
+static int sis900_get_mac_addr(struct pci_dev *pci_dev,
+                              struct net_device *net_dev)
 {
        struct sis900_private *sis_priv = netdev_priv(net_dev);
        void __iomem *ioaddr = sis_priv->ioaddr;
@@ -287,8 +288,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
  *     @net_dev->perm_addr.
  */
 
-static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
-                                       struct net_device *net_dev)
+static int sis630e_get_mac_addr(struct pci_dev *pci_dev,
+                               struct net_device *net_dev)
 {
        struct pci_dev *isa_bridge = NULL;
        u8 reg;
@@ -330,8 +331,8 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
  *     @net_dev->dev_addr and @net_dev->perm_addr.
  */
 
-static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
-                                       struct net_device *net_dev)
+static int sis635_get_mac_addr(struct pci_dev *pci_dev,
+                              struct net_device *net_dev)
 {
        struct sis900_private *sis_priv = netdev_priv(net_dev);
        void __iomem *ioaddr = sis_priv->ioaddr;
@@ -377,8 +378,8 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
  *     MAC address is read into @net_dev->dev_addr and @net_dev->perm_addr.
  */
 
-static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
-                                       struct net_device *net_dev)
+static int sis96x_get_mac_addr(struct pci_dev *pci_dev,
+                              struct net_device *net_dev)
 {
        struct sis900_private *sis_priv = netdev_priv(net_dev);
        void __iomem *ioaddr = sis_priv->ioaddr;
@@ -433,8 +434,8 @@ static const struct net_device_ops sis900_netdev_ops = {
  *     ie: sis900_open(), sis900_start_xmit(), sis900_close(), etc.
  */
 
-static int __devinit sis900_probe(struct pci_dev *pci_dev,
-                               const struct pci_device_id *pci_id)
+static int sis900_probe(struct pci_dev *pci_dev,
+                       const struct pci_device_id *pci_id)
 {
        struct sis900_private *sis_priv;
        struct net_device *net_dev;
@@ -605,7 +606,7 @@ err_out_cleardev:
  *     return error if it failed to found.
  */
 
-static int __devinit sis900_mii_probe(struct net_device * net_dev)
+static int sis900_mii_probe(struct net_device *net_dev)
 {
        struct sis900_private *sis_priv = netdev_priv(net_dev);
        const char *dev_name = pci_name(sis_priv->pci_dev);
@@ -824,7 +825,7 @@ static void sis900_set_capability(struct net_device *net_dev, struct mii_phy *ph
  *     Note that location is in word (16 bits) unit
  */
 
-static u16 __devinit read_eeprom(void __iomem *ioaddr, int location)
+static u16 read_eeprom(void __iomem *ioaddr, int location)
 {
        u32 read_cmd = location | EEread;
        int i;
@@ -2410,7 +2411,7 @@ static void sis900_reset(struct net_device *net_dev)
  *     remove and release SiS900 net device
  */
 
-static void __devexit sis900_remove(struct pci_dev *pci_dev)
+static void sis900_remove(struct pci_dev *pci_dev)
 {
        struct net_device *net_dev = pci_get_drvdata(pci_dev);
        struct sis900_private *sis_priv = netdev_priv(net_dev);
@@ -2479,7 +2480,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
        netif_start_queue(net_dev);
 
        /* Workaround for EDB */
-       sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
+       sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
 
        /* Enable all known interrupts by setting the interrupt mask. */
        sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
@@ -2496,7 +2497,7 @@ static struct pci_driver sis900_pci_driver = {
        .name           = SIS900_MODULE_NAME,
        .id_table       = sis900_pci_tbl,
        .probe          = sis900_probe,
-       .remove         = __devexit_p(sis900_remove),
+       .remove         = sis900_remove,
 #ifdef CONFIG_PM
        .suspend        = sis900_suspend,
        .resume         = sis900_resume,
index d01e59c348ad4d75be016850070e8ba03ccd30c7..03b256af7ed5f8c68a75a47cea63cf8f6bc7bb2e 100644 (file)
@@ -90,9 +90,9 @@ static int rx_copybreak;
 #include <asm/byteorder.h>
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static char version[] =
 DRV_NAME ".c:v1.11 1/7/2001 Written by Donald Becker <becker@scyld.com>\n";
-static char version2[] __devinitdata =
+static char version2[] =
 "  (unofficial 2.4.x kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
@@ -318,8 +318,7 @@ static const struct net_device_ops epic_netdev_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit epic_init_one(struct pci_dev *pdev,
-                                  const struct pci_device_id *ent)
+static int epic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int card_idx = -1;
        void __iomem *ioaddr;
@@ -569,7 +568,7 @@ static inline void epic_napi_irq_on(struct net_device *dev,
        ew32(INTMASK, ep->irq_mask | EpicNapiEvent);
 }
 
-static int __devinit read_eeprom(struct epic_private *ep, int location)
+static int read_eeprom(struct epic_private *ep, int location)
 {
        void __iomem *ioaddr = ep->ioaddr;
        int i;
@@ -1524,7 +1523,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 }
 
 
-static void __devexit epic_remove_one(struct pci_dev *pdev)
+static void epic_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct epic_private *ep = netdev_priv(dev);
@@ -1577,7 +1576,7 @@ static struct pci_driver epic_driver = {
        .name           = DRV_NAME,
        .id_table       = epic_pci_tbl,
        .probe          = epic_init_one,
-       .remove         = __devexit_p(epic_remove_one),
+       .remove         = epic_remove_one,
 #ifdef CONFIG_PM
        .suspend        = epic_suspend,
        .resume         = epic_resume,
index 8d15f7a74b4520cc57d43a034900cc76fcc25282..59a6f88da8676154b34526aa42c0feb34314a014 100644 (file)
@@ -1400,16 +1400,6 @@ smc911x_open(struct net_device *dev)
 
        DBG(SMC_DEBUG_FUNC, "%s: --> %s\n", dev->name, __func__);
 
-       /*
-        * Check that the address is valid.  If its not, refuse
-        * to bring the device up.       The user must specify an
-        * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
-        */
-       if (!is_valid_ether_addr(dev->dev_addr)) {
-               PRINTK("%s: no valid ethernet hw addr\n", __func__);
-               return -EINVAL;
-       }
-
        /* reset the hardware */
        smc911x_reset(dev);
 
@@ -1722,7 +1712,7 @@ static const struct ethtool_ops smc911x_ethtool_ops = {
  * This routine has a simple purpose -- make the SMC chip generate an
  * interrupt, so an auto-detect routine can detect it, and find the IRQ,
  */
-static int __devinit smc911x_findirq(struct net_device *dev)
+static int smc911x_findirq(struct net_device *dev)
 {
        struct smc911x_local *lp = netdev_priv(dev);
        int timeout = 20;
@@ -1800,7 +1790,7 @@ static const struct net_device_ops smc911x_netdev_ops = {
  * o  actually GRAB the irq.
  * o  GRAB the region
  */
-static int __devinit smc911x_probe(struct net_device *dev)
+static int smc911x_probe(struct net_device *dev)
 {
        struct smc911x_local *lp = netdev_priv(dev);
        int i, retval;
@@ -2040,7 +2030,7 @@ err_out:
  *      0 --> there is a device
  *      anything else, error
  */
-static int __devinit smc911x_drv_probe(struct platform_device *pdev)
+static int smc911x_drv_probe(struct platform_device *pdev)
 {
        struct net_device *ndev;
        struct resource *res;
@@ -2115,7 +2105,7 @@ out:
        return ret;
 }
 
-static int __devexit smc911x_drv_remove(struct platform_device *pdev)
+static int smc911x_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct smc911x_local *lp = netdev_priv(ndev);
@@ -2186,7 +2176,7 @@ static int smc911x_drv_resume(struct platform_device *dev)
 
 static struct platform_driver smc911x_driver = {
        .probe           = smc911x_drv_probe,
-       .remove  = __devexit_p(smc911x_drv_remove),
+       .remove  = smc911x_drv_remove,
        .suspend         = smc911x_drv_suspend,
        .resume  = smc911x_drv_resume,
        .driver  = {
index 3269292efeccb3440b22c7fbaf7235ba691ea98e..d51261ba464243c936b0baaa3eaa6f8a68c6091a 100644 (file)
@@ -159,12 +159,12 @@ static inline void SMC_insl(struct smc911x_local *lp, int reg,
        void __iomem *ioaddr = lp->base + reg;
 
        if (lp->cfg.flags & SMC911X_USE_32BIT) {
-               readsl(ioaddr, addr, count);
+               ioread32_rep(ioaddr, addr, count);
                return;
        }
 
        if (lp->cfg.flags & SMC911X_USE_16BIT) {
-               readsw(ioaddr, addr, count * 2);
+               ioread16_rep(ioaddr, addr, count * 2);
                return;
        }
 
@@ -177,12 +177,12 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
        void __iomem *ioaddr = lp->base + reg;
 
        if (lp->cfg.flags & SMC911X_USE_32BIT) {
-               writesl(ioaddr, addr, count);
+               iowrite32_rep(ioaddr, addr, count);
                return;
        }
 
        if (lp->cfg.flags & SMC911X_USE_16BIT) {
-               writesw(ioaddr, addr, count * 2);
+               iowrite16_rep(ioaddr, addr, count * 2);
                return;
        }
 
@@ -196,14 +196,14 @@ static inline void SMC_outsl(struct smc911x_local *lp, int reg,
                 writew(v & 0xFFFF, (lp)->base + (r));   \
                 writew(v >> 16, (lp)->base + (r) + 2); \
         } while (0)
-#define SMC_insl(lp, r, p, l)   readsw((short*)((lp)->base + (r)), p, l*2)
-#define SMC_outsl(lp, r, p, l)  writesw((short*)((lp)->base + (r)), p, l*2)
+#define SMC_insl(lp, r, p, l)   ioread16_rep((short*)((lp)->base + (r)), p, l*2)
+#define SMC_outsl(lp, r, p, l)  iowrite16_rep((short*)((lp)->base + (r)), p, l*2)
 
 #elif  SMC_USE_32BIT
 #define SMC_inl(lp, r)          readl((lp)->base + (r))
 #define SMC_outl(v, lp, r)      writel(v, (lp)->base + (r))
-#define SMC_insl(lp, r, p, l)   readsl((int*)((lp)->base + (r)), p, l)
-#define SMC_outsl(lp, r, p, l)  writesl((int*)((lp)->base + (r)), p, l)
+#define SMC_insl(lp, r, p, l)   ioread32_rep((int*)((lp)->base + (r)), p, l)
+#define SMC_outsl(lp, r, p, l)  iowrite32_rep((int*)((lp)->base + (r)), p, l)
 
 #endif /* SMC_USE_16BIT */
 #endif /* SMC_DYNAMIC_BUS_CONFIG */
index 318adc935a53f72db7a354888aa5b5f65e11bf69..022b45bc14ff15eae3703df8131938212bd0bf68 100644 (file)
@@ -1474,16 +1474,6 @@ smc_open(struct net_device *dev)
 
        DBG(2, "%s: %s\n", dev->name, __func__);
 
-       /*
-        * Check that the address is valid.  If its not, refuse
-        * to bring the device up.  The user must specify an
-        * address using ifconfig eth0 hw ether xx:xx:xx:xx:xx:xx
-        */
-       if (!is_valid_ether_addr(dev->dev_addr)) {
-               PRINTK("%s: no valid ethernet hw addr\n", __func__);
-               return -EINVAL;
-       }
-
        /* Setup the default Register Modes */
        lp->tcr_cur_mode = TCR_DEFAULT;
        lp->rcr_cur_mode = RCR_DEFAULT;
@@ -1789,7 +1779,7 @@ static const struct net_device_ops smc_netdev_ops = {
  * I just deleted auto_irq.c, since it was never built...
  *   --jgarzik
  */
-static int __devinit smc_findirq(struct smc_local *lp)
+static int smc_findirq(struct smc_local *lp)
 {
        void __iomem *ioaddr = lp->base;
        int timeout = 20;
@@ -1863,8 +1853,8 @@ static int __devinit smc_findirq(struct smc_local *lp)
  * o  actually GRAB the irq.
  * o  GRAB the region
  */
-static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
-                           unsigned long irq_flags)
+static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
+                    unsigned long irq_flags)
 {
        struct smc_local *lp = netdev_priv(dev);
        static int version_printed = 0;
@@ -2211,7 +2201,7 @@ static void smc_release_datacs(struct platform_device *pdev, struct net_device *
  *     0 --> there is a device
  *     anything else, error
  */
-static int __devinit smc_drv_probe(struct platform_device *pdev)
+static int smc_drv_probe(struct platform_device *pdev)
 {
        struct smc91x_platdata *pd = pdev->dev.platform_data;
        struct smc_local *lp;
@@ -2324,7 +2314,7 @@ static int __devinit smc_drv_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit smc_drv_remove(struct platform_device *pdev)
+static int smc_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct smc_local *lp = netdev_priv(ndev);
@@ -2407,7 +2397,7 @@ static struct dev_pm_ops smc_drv_pm_ops = {
 
 static struct platform_driver smc_driver = {
        .probe          = smc_drv_probe,
-       .remove         = __devexit_p(smc_drv_remove),
+       .remove         = smc_drv_remove,
        .driver         = {
                .name   = CARDNAME,
                .owner  = THIS_MODULE,
index 5f53fbbf67be84acf2c1fe1e4f0e8541bce86617..370e13dde115a31a1bd4feba15d1c264b8fcdbef 100644 (file)
@@ -286,16 +286,16 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l)
 
 #define SMC_IO_SHIFT           (lp->io_shift)
 
-#define SMC_inb(a, r)          readb((a) + (r))
-#define SMC_inw(a, r)          readw((a) + (r))
-#define SMC_inl(a, r)          readl((a) + (r))
-#define SMC_outb(v, a, r)      writeb(v, (a) + (r))
-#define SMC_outw(v, a, r)      writew(v, (a) + (r))
-#define SMC_outl(v, a, r)      writel(v, (a) + (r))
-#define SMC_insw(a, r, p, l)   readsw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l)  writesw((a) + (r), p, l)
-#define SMC_insl(a, r, p, l)   readsl((a) + (r), p, l)
-#define SMC_outsl(a, r, p, l)  writesl((a) + (r), p, l)
+#define SMC_inb(a, r)          ioread8((a) + (r))
+#define SMC_inw(a, r)          ioread16((a) + (r))
+#define SMC_inl(a, r)          ioread32((a) + (r))
+#define SMC_outb(v, a, r)      iowrite8(v, (a) + (r))
+#define SMC_outw(v, a, r)      iowrite16(v, (a) + (r))
+#define SMC_outl(v, a, r)      iowrite32(v, (a) + (r))
+#define SMC_insw(a, r, p, l)   ioread16_rep((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)  iowrite16_rep((a) + (r), p, l)
+#define SMC_insl(a, r, p, l)   ioread32_rep((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)  iowrite32_rep((a) + (r), p, l)
 
 #define RPC_LSA_DEFAULT                RPC_LED_100_10
 #define RPC_LSB_DEFAULT                RPC_LED_TX_RX
index 62d1baf111ea8f7afb3f1fa049b63666853861f5..4616bf27d5150fc5b54a114c7d91f4aac15f8122 100644 (file)
@@ -253,7 +253,7 @@ smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
        }
 
        if (pdata->config.flags & SMSC911X_USE_32BIT) {
-               writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
+               iowrite32_rep(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
                goto out;
        }
 
@@ -285,7 +285,7 @@ smsc911x_tx_writefifo_shift(struct smsc911x_data *pdata, unsigned int *buf,
        }
 
        if (pdata->config.flags & SMSC911X_USE_32BIT) {
-               writesl(pdata->ioaddr + __smsc_shift(pdata,
+               iowrite32_rep(pdata->ioaddr + __smsc_shift(pdata,
                                                TX_DATA_FIFO), buf, wordcount);
                goto out;
        }
@@ -319,7 +319,7 @@ smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
        }
 
        if (pdata->config.flags & SMSC911X_USE_32BIT) {
-               readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
+               ioread32_rep(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
                goto out;
        }
 
@@ -351,7 +351,7 @@ smsc911x_rx_readfifo_shift(struct smsc911x_data *pdata, unsigned int *buf,
        }
 
        if (pdata->config.flags & SMSC911X_USE_32BIT) {
-               readsl(pdata->ioaddr + __smsc_shift(pdata,
+               ioread32_rep(pdata->ioaddr + __smsc_shift(pdata,
                                                RX_DATA_FIFO), buf, wordcount);
                goto out;
        }
@@ -1031,8 +1031,8 @@ static int smsc911x_mii_probe(struct net_device *dev)
        return 0;
 }
 
-static int __devinit smsc911x_mii_init(struct platform_device *pdev,
-                                      struct net_device *dev)
+static int smsc911x_mii_init(struct platform_device *pdev,
+                            struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
        int err = -ENXIO, i;
@@ -1463,11 +1463,6 @@ static int smsc911x_open(struct net_device *dev)
                return -EAGAIN;
        }
 
-       if (!is_valid_ether_addr(dev->dev_addr)) {
-               SMSC_WARN(pdata, hw, "dev_addr is not a valid MAC address");
-               return -EADDRNOTAVAIL;
-       }
-
        /* Reset the LAN911x */
        if (smsc911x_soft_reset(pdata)) {
                SMSC_WARN(pdata, hw, "soft reset failed");
@@ -2092,7 +2087,7 @@ static const struct net_device_ops smsc911x_netdev_ops = {
 };
 
 /* copies the current mac address from hardware to dev->dev_addr */
-static void __devinit smsc911x_read_mac_address(struct net_device *dev)
+static void smsc911x_read_mac_address(struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
        u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH);
@@ -2107,10 +2102,10 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev)
 }
 
 /* Initializing private device structures, only called from probe */
-static int __devinit smsc911x_init(struct net_device *dev)
+static int smsc911x_init(struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
-       unsigned int byte_test;
+       unsigned int byte_test, mask;
        unsigned int to = 100;
 
        SMSC_TRACE(pdata, probe, "Driver Parameters:");
@@ -2130,9 +2125,22 @@ static int __devinit smsc911x_init(struct net_device *dev)
        /*
         * poll the READY bit in PMT_CTRL. Any other access to the device is
         * forbidden while this bit isn't set. Try for 100ms
+        *
+        * Note that this test is done before the WORD_SWAP register is
+        * programmed. So in some configurations the READY bit is at 16 before
+        * WORD_SWAP is written to. This issue is worked around by waiting
+        * until either bit 0 or bit 16 gets set in PMT_CTRL.
+        *
+        * SMSC has confirmed that checking bit 16 (marked as reserved in
+        * the datasheet) is fine since these bits "will either never be set
+        * or can only go high after READY does (so also indicate the device
+        * is ready)".
         */
-       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+
+       mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_);
+       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to)
                udelay(1000);
+
        if (to == 0) {
                pr_err("Device not READY in 100ms aborting\n");
                return -ENODEV;
@@ -2231,7 +2239,7 @@ static int __devinit smsc911x_init(struct net_device *dev)
        return 0;
 }
 
-static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
+static int smsc911x_drv_remove(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct smsc911x_data *pdata;
@@ -2288,9 +2296,8 @@ static const struct smsc911x_ops shifted_smsc911x_ops = {
 };
 
 #ifdef CONFIG_OF
-static int __devinit smsc911x_probe_config_dt(
-                               struct smsc911x_platform_config *config,
-                               struct device_node *np)
+static int smsc911x_probe_config_dt(struct smsc911x_platform_config *config,
+                                   struct device_node *np)
 {
        const char *mac;
        u32 width = 0;
@@ -2338,7 +2345,7 @@ static inline int smsc911x_probe_config_dt(
 }
 #endif /* CONFIG_OF */
 
-static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
+static int smsc911x_drv_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
        struct net_device *dev;
@@ -2576,7 +2583,7 @@ MODULE_DEVICE_TABLE(of, smsc911x_dt_ids);
 
 static struct platform_driver smsc911x_driver = {
        .probe = smsc911x_drv_probe,
-       .remove = __devexit_p(smsc911x_drv_remove),
+       .remove = smsc911x_drv_remove,
        .driver = {
                .name   = SMSC_CHIPNAME,
                .owner  = THIS_MODULE,
index 1fcd914ec39b376bd79445c14deba77e3dae73e9..3c586585e1b3f62d3b1eaab29d3bdcbaf4fa6b65 100644 (file)
@@ -1577,7 +1577,7 @@ static const struct net_device_ops smsc9420_netdev_ops = {
 #endif /* CONFIG_NET_POLL_CONTROLLER */
 };
 
-static int __devinit
+static int
 smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct net_device *dev;
@@ -1702,7 +1702,7 @@ out_0:
        return -ENODEV;
 }
 
-static void __devexit smsc9420_remove(struct pci_dev *pdev)
+static void smsc9420_remove(struct pci_dev *pdev)
 {
        struct net_device *dev;
        struct smsc9420_pdata *pd;
@@ -1736,7 +1736,7 @@ static struct pci_driver smsc9420_driver = {
        .name = DRV_NAME,
        .id_table = smsc9420_id_table,
        .probe = smsc9420_probe,
-       .remove = __devexit_p(smsc9420_remove),
+       .remove = smsc9420_remove,
 #ifdef CONFIG_PM
        .suspend = smsc9420_suspend,
        .resume = smsc9420_resume,
index 9f448279e12a52ea7965c3500bd910c859afbb6b..1164930a40a5400ef9681b8cdc78b56f705e8c4d 100644 (file)
@@ -54,31 +54,6 @@ config STMMAC_DA
          By default, the DMA arbitration scheme is based on Round-robin
          (rx:tx priority is 1:1).
 
-config STMMAC_TIMER
-       bool "STMMAC Timer optimisation"
-       default n
-       depends on RTC_HCTOSYS_DEVICE
-       ---help---
-         Use an external timer for mitigating the number of network
-         interrupts. Currently, for SH architectures, it is possible
-         to use the TMU channel 2 and the SH-RTC device.
-
-choice
-        prompt "Select Timer device"
-        depends on STMMAC_TIMER
-
-config STMMAC_TMU_TIMER
-        bool "TMU channel 2"
-        depends on CPU_SH4
-       ---help---
-
-config STMMAC_RTC_TIMER
-        bool "Real time clock"
-        depends on RTC_CLASS
-       ---help---
-
-endchoice
-
 choice
        prompt "Select the DMA TX/RX descriptor operating modes"
        depends on STMMAC_ETH
index bc965ac9e0250e61f3d4a904989b4d6288abb86f..c8e8ea60ac19f1bc5d9ae56033e41fafec4e3c7e 100644 (file)
@@ -1,5 +1,4 @@
 obj-$(CONFIG_STMMAC_ETH) += stmmac.o
-stmmac-$(CONFIG_STMMAC_TIMER) += stmmac_timer.o
 stmmac-$(CONFIG_STMMAC_RING) += ring_mode.o
 stmmac-$(CONFIG_STMMAC_CHAINED) += chain_mode.o
 stmmac-$(CONFIG_STMMAC_PLATFORM) += stmmac_platform.o
index 719be3912aa9ca5cb7b0a527811df460c257561b..186d1480612210d39d26b05305243d8fc71e1c16 100644 (file)
 #define CHIP_DBG(fmt, args...)  do { } while (0)
 #endif
 
+/* Synopsys Core versions */
+#define        DWMAC_CORE_3_40 0x34
+#define        DWMAC_CORE_3_50 0x35
+
 #undef FRAME_FILTER_DEBUG
 /* #define FRAME_FILTER_DEBUG */
 
@@ -81,7 +85,7 @@ struct stmmac_extra_stats {
        unsigned long rx_missed_cntr;
        unsigned long rx_overflow_cntr;
        unsigned long rx_vlan;
-       /* Tx/Rx IRQ errors */
+       /* Tx/Rx IRQ error info */
        unsigned long tx_undeflow_irq;
        unsigned long tx_process_stopped_irq;
        unsigned long tx_jabber_irq;
@@ -91,18 +95,23 @@ struct stmmac_extra_stats {
        unsigned long rx_watchdog_irq;
        unsigned long tx_early_irq;
        unsigned long fatal_bus_error_irq;
-       /* Extra info */
+       /* Tx/Rx IRQ Events */
+       unsigned long rx_early_irq;
        unsigned long threshold;
        unsigned long tx_pkt_n;
        unsigned long rx_pkt_n;
-       unsigned long poll_n;
-       unsigned long sched_timer_n;
        unsigned long normal_irq_n;
+       unsigned long rx_normal_irq_n;
+       unsigned long napi_poll;
+       unsigned long tx_normal_irq_n;
+       unsigned long tx_clean;
+       unsigned long tx_reset_ic_bit;
+       unsigned long irq_receive_pmt_irq_n;
+       /* MMC info */
        unsigned long mmc_tx_irq_n;
        unsigned long mmc_rx_irq_n;
        unsigned long mmc_rx_csum_offload_irq_n;
        /* EEE */
-       unsigned long irq_receive_pmt_irq_n;
        unsigned long irq_tx_path_in_lpi_mode_n;
        unsigned long irq_tx_path_exit_lpi_mode_n;
        unsigned long irq_rx_path_in_lpi_mode_n;
@@ -162,6 +171,15 @@ struct stmmac_extra_stats {
 #define DMA_HW_FEAT_ACTPHYIF   0x70000000 /* Active/selected PHY interface */
 #define DEFAULT_DMA_PBL                8
 
+/* Max/Min RI Watchdog Timer count value */
+#define MAX_DMA_RIWT           0xff
+#define MIN_DMA_RIWT           0x20
+/* Tx coalesce parameters */
+#define STMMAC_COAL_TX_TIMER   40000
+#define STMMAC_MAX_COAL_TX_TICK        100000
+#define STMMAC_TX_MAX_FRAMES   256
+#define STMMAC_TX_FRAMES       64
+
 enum rx_frame_status { /* IPC status */
        good_frame = 0,
        discard_frame = 1,
@@ -169,10 +187,11 @@ enum rx_frame_status { /* IPC status */
        llc_snap = 4,
 };
 
-enum tx_dma_irq_status {
-       tx_hard_error = 1,
-       tx_hard_error_bump_tc = 2,
-       handle_tx_rx = 3,
+enum dma_irq_status {
+       tx_hard_error = 0x1,
+       tx_hard_error_bump_tc = 0x2,
+       handle_rx = 0x4,
+       handle_tx = 0x8,
 };
 
 enum core_specific_irq_mask {
@@ -296,6 +315,8 @@ struct stmmac_dma_ops {
                              struct stmmac_extra_stats *x);
        /* If supported then get the optional core features */
        unsigned int (*get_hw_feature) (void __iomem *ioaddr);
+       /* Program the HW RX Watchdog */
+       void (*rx_watchdog) (void __iomem *ioaddr, u32 riwt);
 };
 
 struct stmmac_ops {
index 0e4cacedc1f0e0cf44fad3bb84c5bac000f8e6ee..7ad56afd63247a9e3c73c27c923109e48e5f638d 100644 (file)
@@ -230,8 +230,5 @@ enum rtc_control {
 #define GMAC_MMC_TX_INTR   0x108
 #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
 
-/* Synopsys Core versions */
-#define        DWMAC_CORE_3_40 0x34
-
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
 #endif /* __DWMAC1000_H__ */
index 033500090f552aedbbc7bddb99e6acd77395ef69..bf83c03bfd06f3699164de132968622690a10965 100644 (file)
@@ -174,6 +174,11 @@ static unsigned int dwmac1000_get_hw_feature(void __iomem *ioaddr)
        return readl(ioaddr + DMA_HW_FEATURE);
 }
 
+static void dwmac1000_rx_watchdog(void __iomem *ioaddr, u32 riwt)
+{
+       writel(riwt, ioaddr + DMA_RX_WATCHDOG);
+}
+
 const struct stmmac_dma_ops dwmac1000_dma_ops = {
        .init = dwmac1000_dma_init,
        .dump_regs = dwmac1000_dump_dma_regs,
@@ -187,4 +192,5 @@ const struct stmmac_dma_ops dwmac1000_dma_ops = {
        .stop_rx = dwmac_dma_stop_rx,
        .dma_interrupt = dwmac_dma_interrupt,
        .get_hw_feature = dwmac1000_get_hw_feature,
+       .rx_watchdog = dwmac1000_rx_watchdog,
 };
index e49c9a0fd6ffe9a8ad52f19134e2e8c1aa7dcd2e..ab4896ecac1c531814aec2e07fbe199b5e965495 100644 (file)
 #define DMA_CONTROL            0x00001018      /* Ctrl (Operational Mode) */
 #define DMA_INTR_ENA           0x0000101c      /* Interrupt Enable */
 #define DMA_MISSED_FRAME_CTR   0x00001020      /* Missed Frame Counter */
-#define DMA_AXI_BUS_MODE       0x00001028      /* AXI Bus Mode */
+/* Rx watchdog register */
+#define DMA_RX_WATCHDOG                0x00001024
+/* AXI Bus Mode */
+#define DMA_AXI_BUS_MODE       0x00001028
 #define DMA_CUR_TX_BUF_ADDR    0x00001050      /* Current Host Tx Buffer */
 #define DMA_CUR_RX_BUF_ADDR    0x00001054      /* Current Host Rx Buffer */
 #define DMA_HW_FEATURE         0x00001058      /* HW Feature Register */
@@ -77,8 +80,6 @@
 #define DMA_STATUS_GPI         0x10000000      /* PMT interrupt */
 #define DMA_STATUS_GMI         0x08000000      /* MMC interrupt */
 #define DMA_STATUS_GLI         0x04000000      /* GMAC Line interface int */
-#define DMA_STATUS_GMI         0x08000000
-#define DMA_STATUS_GLI         0x04000000
 #define DMA_STATUS_EB_MASK     0x00380000      /* Error Bits Mask */
 #define DMA_STATUS_EB_TX_ABORT 0x00080000      /* Error Bits - TX Abort */
 #define DMA_STATUS_EB_RX_ABORT 0x00100000      /* Error Bits - RX Abort */
index 4e0e18a44fcce7bc5a3c35c1eb1f560afb07d77d..491d7e9306037a119ae1cb5e4454935213cc01e8 100644 (file)
@@ -204,16 +204,28 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
                }
        }
        /* TX/RX NORMAL interrupts */
-       if (intr_status & DMA_STATUS_NIS) {
+       if (likely(intr_status & DMA_STATUS_NIS)) {
                x->normal_irq_n++;
-               if (likely((intr_status & DMA_STATUS_RI) ||
-                        (intr_status & (DMA_STATUS_TI))))
-                               ret = handle_tx_rx;
+               if (likely(intr_status & DMA_STATUS_RI)) {
+                       u32 value = readl(ioaddr + DMA_INTR_ENA);
+                       /* to schedule NAPI on real RIE event. */
+                       if (likely(value & DMA_INTR_ENA_RIE)) {
+                               x->rx_normal_irq_n++;
+                               ret |= handle_rx;
+                       }
+               }
+               if (likely(intr_status & DMA_STATUS_TI)) {
+                       x->tx_normal_irq_n++;
+                       ret |= handle_tx;
+               }
+               if (unlikely(intr_status & DMA_STATUS_ERI))
+                       x->rx_early_irq++;
        }
        /* Optional hardware blocks, interrupts should be disabled */
        if (unlikely(intr_status &
                     (DMA_STATUS_GPI | DMA_STATUS_GMI | DMA_STATUS_GLI)))
                pr_info("%s: unexpected status %08x\n", __func__, intr_status);
+
        /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
        writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
 
index 7d51a65ab09960ac34baa8baa0b2a3a640a9dfc5..023a4fb4efa5769cf1953e44f9f1ca88b2a372b2 100644 (file)
 #define __STMMAC_H__
 
 #define STMMAC_RESOURCE_NAME   "stmmaceth"
-#define DRV_MODULE_VERSION     "March_2012"
+#define DRV_MODULE_VERSION     "Nov_2012"
 
 #include <linux/clk.h>
 #include <linux/stmmac.h>
 #include <linux/phy.h>
 #include <linux/pci.h>
 #include "common.h"
-#ifdef CONFIG_STMMAC_TIMER
-#include "stmmac_timer.h"
-#endif
 
 struct stmmac_priv {
        /* Frequently used values are kept adjacent for cache effect */
@@ -77,9 +74,6 @@ struct stmmac_priv {
        spinlock_t tx_lock;
        int wolopts;
        int wol_irq;
-#ifdef CONFIG_STMMAC_TIMER
-       struct stmmac_timer *tm;
-#endif
        struct plat_stmmacenet_data *plat;
        struct stmmac_counters mmc;
        struct dma_features dma_cap;
@@ -93,6 +87,12 @@ struct stmmac_priv {
        int eee_enabled;
        int eee_active;
        int tx_lpi_timer;
+       struct timer_list txtimer;
+       u32 tx_count_frames;
+       u32 tx_coal_frames;
+       u32 tx_coal_timer;
+       int use_riwt;
+       u32 rx_riwt;
 };
 
 extern int phyaddr;
index 76fd61aa005f18060806fd16430c56c869ac21dd..1372ce210b58b60aa32325b08a8da2d93b5abb6e 100644 (file)
@@ -76,7 +76,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
        STMMAC_STAT(rx_missed_cntr),
        STMMAC_STAT(rx_overflow_cntr),
        STMMAC_STAT(rx_vlan),
-       /* Tx/Rx IRQ errors */
+       /* Tx/Rx IRQ error info */
        STMMAC_STAT(tx_undeflow_irq),
        STMMAC_STAT(tx_process_stopped_irq),
        STMMAC_STAT(tx_jabber_irq),
@@ -86,18 +86,23 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
        STMMAC_STAT(rx_watchdog_irq),
        STMMAC_STAT(tx_early_irq),
        STMMAC_STAT(fatal_bus_error_irq),
-       /* Extra info */
+       /* Tx/Rx IRQ Events */
+       STMMAC_STAT(rx_early_irq),
        STMMAC_STAT(threshold),
        STMMAC_STAT(tx_pkt_n),
        STMMAC_STAT(rx_pkt_n),
-       STMMAC_STAT(poll_n),
-       STMMAC_STAT(sched_timer_n),
-       STMMAC_STAT(normal_irq_n),
        STMMAC_STAT(normal_irq_n),
+       STMMAC_STAT(rx_normal_irq_n),
+       STMMAC_STAT(napi_poll),
+       STMMAC_STAT(tx_normal_irq_n),
+       STMMAC_STAT(tx_clean),
+       STMMAC_STAT(tx_reset_ic_bit),
+       STMMAC_STAT(irq_receive_pmt_irq_n),
+       /* MMC info */
        STMMAC_STAT(mmc_tx_irq_n),
        STMMAC_STAT(mmc_rx_irq_n),
        STMMAC_STAT(mmc_rx_csum_offload_irq_n),
-       STMMAC_STAT(irq_receive_pmt_irq_n),
+       /* EEE */
        STMMAC_STAT(irq_tx_path_in_lpi_mode_n),
        STMMAC_STAT(irq_tx_path_exit_lpi_mode_n),
        STMMAC_STAT(irq_rx_path_in_lpi_mode_n),
@@ -519,6 +524,87 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
        return phy_ethtool_set_eee(priv->phydev, edata);
 }
 
+static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
+{
+       unsigned long clk = clk_get_rate(priv->stmmac_clk);
+
+       if (!clk)
+               return 0;
+
+       return (usec * (clk / 1000000)) / 256;
+}
+
+static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
+{
+       unsigned long clk = clk_get_rate(priv->stmmac_clk);
+
+       if (!clk)
+               return 0;
+
+       return (riwt * 256) / (clk / 1000000);
+}
+
+static int stmmac_get_coalesce(struct net_device *dev,
+                              struct ethtool_coalesce *ec)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       ec->tx_coalesce_usecs = priv->tx_coal_timer;
+       ec->tx_max_coalesced_frames = priv->tx_coal_frames;
+
+       if (priv->use_riwt)
+               ec->rx_coalesce_usecs = stmmac_riwt2usec(priv->rx_riwt, priv);
+
+       return 0;
+}
+
+static int stmmac_set_coalesce(struct net_device *dev,
+                              struct ethtool_coalesce *ec)
+{
+       struct stmmac_priv *priv = netdev_priv(dev);
+       unsigned int rx_riwt;
+
+       /* Check not supported parameters  */
+       if ((ec->rx_max_coalesced_frames) || (ec->rx_coalesce_usecs_irq) ||
+           (ec->rx_max_coalesced_frames_irq) || (ec->tx_coalesce_usecs_irq) ||
+           (ec->use_adaptive_rx_coalesce) || (ec->use_adaptive_tx_coalesce) ||
+           (ec->pkt_rate_low) || (ec->rx_coalesce_usecs_low) ||
+           (ec->rx_max_coalesced_frames_low) || (ec->tx_coalesce_usecs_high) ||
+           (ec->tx_max_coalesced_frames_low) || (ec->pkt_rate_high) ||
+           (ec->tx_coalesce_usecs_low) || (ec->rx_coalesce_usecs_high) ||
+           (ec->rx_max_coalesced_frames_high) ||
+           (ec->tx_max_coalesced_frames_irq) ||
+           (ec->stats_block_coalesce_usecs) ||
+           (ec->tx_max_coalesced_frames_high) || (ec->rate_sample_interval))
+               return -EOPNOTSUPP;
+
+       if (ec->rx_coalesce_usecs == 0)
+               return -EINVAL;
+
+       if ((ec->tx_coalesce_usecs == 0) &&
+           (ec->tx_max_coalesced_frames == 0))
+               return -EINVAL;
+
+       if ((ec->tx_coalesce_usecs > STMMAC_COAL_TX_TIMER) ||
+           (ec->tx_max_coalesced_frames > STMMAC_TX_MAX_FRAMES))
+               return -EINVAL;
+
+       rx_riwt = stmmac_usec2riwt(ec->rx_coalesce_usecs, priv);
+
+       if ((rx_riwt > MAX_DMA_RIWT) || (rx_riwt < MIN_DMA_RIWT))
+               return -EINVAL;
+       else if (!priv->use_riwt)
+               return -EOPNOTSUPP;
+
+       /* Only copy relevant parameters, ignore all others. */
+       priv->tx_coal_frames = ec->tx_max_coalesced_frames;
+       priv->tx_coal_timer = ec->tx_coalesce_usecs;
+       priv->rx_riwt = rx_riwt;
+       priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt);
+
+       return 0;
+}
+
 static const struct ethtool_ops stmmac_ethtool_ops = {
        .begin = stmmac_check_if_running,
        .get_drvinfo = stmmac_ethtool_getdrvinfo,
@@ -539,6 +625,8 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
        .set_eee = stmmac_ethtool_op_set_eee,
        .get_sset_count = stmmac_get_sset_count,
        .get_ts_info = ethtool_op_get_ts_info,
+       .get_coalesce = stmmac_get_coalesce,
+       .set_coalesce = stmmac_set_coalesce,
 };
 
 void stmmac_set_ethtool_ops(struct net_device *netdev)
index c6cdbc4eb05e613cd499cc35af4ee56300cafcf8..542edbcd92c715c3e0474f321f92de632725e173 100644 (file)
@@ -115,16 +115,6 @@ static int tc = TC_DEFAULT;
 module_param(tc, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(tc, "DMA threshold control value");
 
-/* Pay attention to tune this parameter; take care of both
- * hardware capability and network stabitily/performance impact.
- * Many tests showed that ~4ms latency seems to be good enough. */
-#ifdef CONFIG_STMMAC_TIMER
-#define DEFAULT_PERIODIC_RATE  256
-static int tmrate = DEFAULT_PERIODIC_RATE;
-module_param(tmrate, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(tmrate, "External timer freq. (default: 256Hz)");
-#endif
-
 #define DMA_BUFFER_SIZE        BUF_SIZE_2KiB
 static int buf_sz = DMA_BUFFER_SIZE;
 module_param(buf_sz, int, S_IRUGO | S_IWUSR);
@@ -147,6 +137,8 @@ static int stmmac_init_fs(struct net_device *dev);
 static void stmmac_exit_fs(void);
 #endif
 
+#define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
+
 /**
  * stmmac_verify_args - verify the driver parameters.
  * Description: it verifies if some wrong parameter is passed to the driver.
@@ -536,12 +528,6 @@ static void init_dma_desc_rings(struct net_device *dev)
        else
                bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
 
-#ifdef CONFIG_STMMAC_TIMER
-       /* Disable interrupts on completion for the reception if timer is on */
-       if (likely(priv->tm->enable))
-               dis_ic = 1;
-#endif
-
        DBG(probe, INFO, "stmmac: txsize %d, rxsize %d, bfsize %d\n",
            txsize, rxsize, bfsize);
 
@@ -617,6 +603,8 @@ static void init_dma_desc_rings(struct net_device *dev)
        priv->dirty_tx = 0;
        priv->cur_tx = 0;
 
+       if (priv->use_riwt)
+               dis_ic = 1;
        /* Clear the Rx/Tx descriptors */
        priv->hw->desc->init_rx_desc(priv->dma_rx, rxsize, dis_ic);
        priv->hw->desc->init_tx_desc(priv->dma_tx, txsize);
@@ -704,16 +692,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
 }
 
 /**
- * stmmac_tx:
- * @priv: private driver structure
+ * stmmac_tx_clean:
+ * @priv: private data pointer
  * Description: it reclaims resources after transmission completes.
  */
-static void stmmac_tx(struct stmmac_priv *priv)
+static void stmmac_tx_clean(struct stmmac_priv *priv)
 {
        unsigned int txsize = priv->dma_tx_size;
 
        spin_lock(&priv->tx_lock);
 
+       priv->xstats.tx_clean++;
+
        while (priv->dirty_tx != priv->cur_tx) {
                int last;
                unsigned int entry = priv->dirty_tx % txsize;
@@ -773,69 +763,16 @@ static void stmmac_tx(struct stmmac_priv *priv)
        spin_unlock(&priv->tx_lock);
 }
 
-static inline void stmmac_enable_irq(struct stmmac_priv *priv)
-{
-#ifdef CONFIG_STMMAC_TIMER
-       if (likely(priv->tm->enable))
-               priv->tm->timer_start(tmrate);
-       else
-#endif
-               priv->hw->dma->enable_dma_irq(priv->ioaddr);
-}
-
-static inline void stmmac_disable_irq(struct stmmac_priv *priv)
-{
-#ifdef CONFIG_STMMAC_TIMER
-       if (likely(priv->tm->enable))
-               priv->tm->timer_stop();
-       else
-#endif
-               priv->hw->dma->disable_dma_irq(priv->ioaddr);
-}
-
-static int stmmac_has_work(struct stmmac_priv *priv)
-{
-       unsigned int has_work = 0;
-       int rxret, tx_work = 0;
-
-       rxret = priv->hw->desc->get_rx_owner(priv->dma_rx +
-               (priv->cur_rx % priv->dma_rx_size));
-
-       if (priv->dirty_tx != priv->cur_tx)
-               tx_work = 1;
-
-       if (likely(!rxret || tx_work))
-               has_work = 1;
-
-       return has_work;
-}
-
-static inline void _stmmac_schedule(struct stmmac_priv *priv)
+static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
 {
-       if (likely(stmmac_has_work(priv))) {
-               stmmac_disable_irq(priv);
-               napi_schedule(&priv->napi);
-       }
+       priv->hw->dma->enable_dma_irq(priv->ioaddr);
 }
 
-#ifdef CONFIG_STMMAC_TIMER
-void stmmac_schedule(struct net_device *dev)
+static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
 {
-       struct stmmac_priv *priv = netdev_priv(dev);
-
-       priv->xstats.sched_timer_n++;
-
-       _stmmac_schedule(priv);
+       priv->hw->dma->disable_dma_irq(priv->ioaddr);
 }
 
-static void stmmac_no_timer_started(unsigned int x)
-{;
-};
-
-static void stmmac_no_timer_stopped(void)
-{;
-};
-#endif
 
 /**
  * stmmac_tx_err:
@@ -858,16 +795,18 @@ static void stmmac_tx_err(struct stmmac_priv *priv)
        netif_wake_queue(priv->dev);
 }
 
-
 static void stmmac_dma_interrupt(struct stmmac_priv *priv)
 {
        int status;
 
        status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
-       if (likely(status == handle_tx_rx))
-               _stmmac_schedule(priv);
-
-       else if (unlikely(status == tx_hard_error_bump_tc)) {
+       if (likely((status & handle_rx)) || (status & handle_tx)) {
+               if (likely(napi_schedule_prep(&priv->napi))) {
+                       stmmac_disable_dma_irq(priv);
+                       __napi_schedule(&priv->napi);
+               }
+       }
+       if (unlikely(status & tx_hard_error_bump_tc)) {
                /* Try to bump up the dma threshold on this failure */
                if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
                        tc += 64;
@@ -983,7 +922,6 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
                /* Alternate (enhanced) DESC mode*/
                priv->dma_cap.enh_desc =
                        (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
-
        }
 
        return hw_cap;
@@ -1024,6 +962,38 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
                                   priv->dma_rx_phy);
 }
 
+/**
+ * stmmac_tx_timer:
+ * @data: data pointer
+ * Description:
+ * This is the timer handler to directly invoke the stmmac_tx_clean.
+ */
+static void stmmac_tx_timer(unsigned long data)
+{
+       struct stmmac_priv *priv = (struct stmmac_priv *)data;
+
+       stmmac_tx_clean(priv);
+}
+
+/**
+ * stmmac_tx_timer:
+ * @priv: private data structure
+ * Description:
+ * This inits the transmit coalesce parameters: i.e. timer rate,
+ * timer handler and default threshold used for enabling the
+ * interrupt on completion bit.
+ */
+static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
+{
+       priv->tx_coal_frames = STMMAC_TX_FRAMES;
+       priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
+       init_timer(&priv->txtimer);
+       priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
+       priv->txtimer.data = (unsigned long)priv;
+       priv->txtimer.function = stmmac_tx_timer;
+       add_timer(&priv->txtimer);
+}
+
 /**
  *  stmmac_open - open entry point of the driver
  *  @dev : pointer to the device structure.
@@ -1038,23 +1008,6 @@ static int stmmac_open(struct net_device *dev)
        struct stmmac_priv *priv = netdev_priv(dev);
        int ret;
 
-#ifdef CONFIG_STMMAC_TIMER
-       priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
-       if (unlikely(priv->tm == NULL))
-               return -ENOMEM;
-
-       priv->tm->freq = tmrate;
-
-       /* Test if the external timer can be actually used.
-        * In case of failure continue without timer. */
-       if (unlikely((stmmac_open_ext_timer(dev, priv->tm)) < 0)) {
-               pr_warning("stmmaceth: cannot attach the external timer.\n");
-               priv->tm->freq = 0;
-               priv->tm->timer_start = stmmac_no_timer_started;
-               priv->tm->timer_stop = stmmac_no_timer_stopped;
-       } else
-               priv->tm->enable = 1;
-#endif
        clk_prepare_enable(priv->stmmac_clk);
 
        stmmac_check_ether_addr(priv);
@@ -1141,10 +1094,6 @@ static int stmmac_open(struct net_device *dev)
        priv->hw->dma->start_tx(priv->ioaddr);
        priv->hw->dma->start_rx(priv->ioaddr);
 
-#ifdef CONFIG_STMMAC_TIMER
-       priv->tm->timer_start(tmrate);
-#endif
-
        /* Dump DMA/MAC registers */
        if (netif_msg_hw(priv)) {
                priv->hw->mac->dump_regs(priv->ioaddr);
@@ -1157,6 +1106,13 @@ static int stmmac_open(struct net_device *dev)
        priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS_TIMER;
        priv->eee_enabled = stmmac_eee_init(priv);
 
+       stmmac_init_tx_coalesce(priv);
+
+       if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
+               priv->rx_riwt = MAX_DMA_RIWT;
+               priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
+       }
+
        napi_enable(&priv->napi);
        netif_start_queue(dev);
 
@@ -1170,9 +1126,6 @@ open_error_wolirq:
        free_irq(dev->irq, dev);
 
 open_error:
-#ifdef CONFIG_STMMAC_TIMER
-       kfree(priv->tm);
-#endif
        if (priv->phydev)
                phy_disconnect(priv->phydev);
 
@@ -1203,14 +1156,10 @@ static int stmmac_release(struct net_device *dev)
 
        netif_stop_queue(dev);
 
-#ifdef CONFIG_STMMAC_TIMER
-       /* Stop and release the timer */
-       stmmac_close_ext_timer();
-       if (priv->tm != NULL)
-               kfree(priv->tm);
-#endif
        napi_disable(&priv->napi);
 
+       del_timer_sync(&priv->txtimer);
+
        /* Free the IRQ lines */
        free_irq(dev->irq, dev);
        if (priv->wol_irq != dev->irq)
@@ -1273,11 +1222,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 #ifdef STMMAC_XMIT_DEBUG
        if ((skb->len > ETH_FRAME_LEN) || nfrags)
-               pr_info("stmmac xmit:\n"
-                      "\tskb addr %p - len: %d - nopaged_len: %d\n"
-                      "\tn_frags: %d - ip_summed: %d - %s gso\n",
-                      skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
-                      !skb_is_gso(skb) ? "isn't" : "is");
+               pr_debug("stmmac xmit: [entry %d]\n"
+                        "\tskb addr %p - len: %d - nopaged_len: %d\n"
+                        "\tn_frags: %d - ip_summed: %d - %s gso\n"
+                        "\ttx_count_frames %d\n", entry,
+                        skb, skb->len, nopaged_len, nfrags, skb->ip_summed,
+                        !skb_is_gso(skb) ? "isn't" : "is",
+                        priv->tx_count_frames);
 #endif
 
        csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
@@ -1287,9 +1238,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
 #ifdef STMMAC_XMIT_DEBUG
        if ((nfrags > 0) || (skb->len > ETH_FRAME_LEN))
-               pr_debug("stmmac xmit: skb len: %d, nopaged_len: %d,\n"
-                      "\t\tn_frags: %d, ip_summed: %d\n",
-                      skb->len, nopaged_len, nfrags, skb->ip_summed);
+               pr_debug("\tskb len: %d, nopaged_len: %d,\n"
+                        "\t\tn_frags: %d, ip_summed: %d\n",
+                        skb->len, nopaged_len, nfrags, skb->ip_summed);
 #endif
        priv->tx_skbuff[entry] = skb;
 
@@ -1320,16 +1271,24 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                wmb();
        }
 
-       /* Interrupt on completition only for the latest segment */
+       /* Finalize the latest segment. */
        priv->hw->desc->close_tx_desc(desc);
 
-#ifdef CONFIG_STMMAC_TIMER
-       /* Clean IC while using timer */
-       if (likely(priv->tm->enable))
-               priv->hw->desc->clear_tx_ic(desc);
-#endif
-
        wmb();
+       /* According to the coalesce parameter the IC bit for the latest
+        * segment could be reset and the timer re-started to invoke the
+        * stmmac_tx function. This approach takes care about the fragments.
+        */
+       priv->tx_count_frames += nfrags + 1;
+       if (priv->tx_coal_frames > priv->tx_count_frames) {
+               priv->hw->desc->clear_tx_ic(desc);
+               priv->xstats.tx_reset_ic_bit++;
+               TX_DBG("\t[entry %d]: tx_count_frames %d\n", entry,
+                      priv->tx_count_frames);
+               mod_timer(&priv->txtimer,
+                         STMMAC_COAL_TIMER(priv->tx_coal_timer));
+       } else
+               priv->tx_count_frames = 0;
 
        /* To avoid raise condition */
        priv->hw->desc->set_tx_owner(first);
@@ -1471,14 +1430,12 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
 #endif
                        skb->protocol = eth_type_trans(skb, priv->dev);
 
-                       if (unlikely(!priv->plat->rx_coe)) {
-                               /* No RX COE for old mac10/100 devices */
+                       if (unlikely(!priv->plat->rx_coe))
                                skb_checksum_none_assert(skb);
-                               netif_receive_skb(skb);
-                       } else {
+                       else
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
-                               napi_gro_receive(&priv->napi, skb);
-                       }
+
+                       napi_gro_receive(&priv->napi, skb);
 
                        priv->dev->stats.rx_packets++;
                        priv->dev->stats.rx_bytes += frame_len;
@@ -1500,21 +1457,20 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
  *  @budget : maximum number of packets that the current CPU can receive from
  *           all interfaces.
  *  Description :
- *   This function implements the the reception process.
- *   Also it runs the TX completion thread
+ *  To look at the incoming frames and clear the tx resources.
  */
 static int stmmac_poll(struct napi_struct *napi, int budget)
 {
        struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
        int work_done = 0;
 
-       priv->xstats.poll_n++;
-       stmmac_tx(priv);
-       work_done = stmmac_rx(priv, budget);
+       priv->xstats.napi_poll++;
+       stmmac_tx_clean(priv);
 
+       work_done = stmmac_rx(priv, budget);
        if (work_done < budget) {
                napi_complete(napi);
-               stmmac_enable_irq(priv);
+               stmmac_enable_dma_irq(priv);
        }
        return work_done;
 }
@@ -1523,7 +1479,7 @@ static int stmmac_poll(struct napi_struct *napi, int budget)
  *  stmmac_tx_timeout
  *  @dev : Pointer to net device structure
  *  Description: this function is called when a packet transmission fails to
- *   complete within a reasonable tmrate. The driver will mark the error in the
+ *   complete within a reasonable time. The driver will mark the error in the
  *   netdev structure and arrange for the device to be reset to a sane state
  *   in order to transmit a new packet.
  */
@@ -2050,6 +2006,16 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
        if (flow_ctrl)
                priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
 
+       /* Rx Watchdog is available in the COREs newer than the 3.40.
+        * In some case, for example on bugged HW this feature
+        * has to be disable and this can be done by passing the
+        * riwt_off field from the platform.
+        */
+       if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
+               priv->use_riwt = 1;
+               pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
+       }
+
        netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
 
        spin_lock_init(&priv->lock);
@@ -2141,11 +2107,9 @@ int stmmac_suspend(struct net_device *ndev)
        netif_device_detach(ndev);
        netif_stop_queue(ndev);
 
-#ifdef CONFIG_STMMAC_TIMER
-       priv->tm->timer_stop();
-       if (likely(priv->tm->enable))
+       if (priv->use_riwt)
                dis_ic = 1;
-#endif
+
        napi_disable(&priv->napi);
 
        /* Stop TX/RX DMA */
@@ -2196,10 +2160,6 @@ int stmmac_resume(struct net_device *ndev)
        priv->hw->dma->start_tx(priv->ioaddr);
        priv->hw->dma->start_rx(priv->ioaddr);
 
-#ifdef CONFIG_STMMAC_TIMER
-       if (likely(priv->tm->enable))
-               priv->tm->timer_start(tmrate);
-#endif
        napi_enable(&priv->napi);
 
        netif_start_queue(ndev);
@@ -2295,11 +2255,6 @@ static int __init stmmac_cmdline_opt(char *str)
                } else if (!strncmp(opt, "eee_timer:", 6)) {
                        if (kstrtoint(opt + 10, 0, &eee_timer))
                                goto err;
-#ifdef CONFIG_STMMAC_TIMER
-               } else if (!strncmp(opt, "tmrate:", 7)) {
-                       if (kstrtoint(opt + 7, 0, &tmrate))
-                               goto err;
-#endif
                }
        }
        return 0;
index 1f069b0f6af592342ecc1f6a023b9334acc4099b..064eaac9616f59a03e178a259371d1a10c14b7ca 100644 (file)
@@ -61,8 +61,8 @@ static void stmmac_default_data(void)
  * matches the device. The probe functions returns zero when the driver choose
  * to take "ownership" of the device or an error code(-ve no) otherwise.
  */
-static int __devinit stmmac_pci_probe(struct pci_dev *pdev,
-                                     const struct pci_device_id *id)
+static int stmmac_pci_probe(struct pci_dev *pdev,
+                           const struct pci_device_id *id)
 {
        int ret = 0;
        void __iomem *addr = NULL;
@@ -130,7 +130,7 @@ err_out_req_reg_failed:
  * Description: this function calls the main to free the net resources
  * and releases the PCI resources.
  */
-static void __devexit stmmac_pci_remove(struct pci_dev *pdev)
+static void stmmac_pci_remove(struct pci_dev *pdev)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
        struct stmmac_priv *priv = netdev_priv(ndev);
@@ -182,7 +182,7 @@ struct pci_driver stmmac_pci_driver = {
        .name = STMMAC_RESOURCE_NAME,
        .id_table = stmmac_id_table,
        .probe = stmmac_pci_probe,
-       .remove = __devexit_p(stmmac_pci_remove),
+       .remove = stmmac_pci_remove,
 #ifdef CONFIG_PM
        .suspend = stmmac_pci_suspend,
        .resume = stmmac_pci_resume,
index ed112b55ae7f95a587150a0f5ed23d58ca318f97..b43d68b40e50f6156ea10ccfad3f0924d04d1b01 100644 (file)
@@ -29,9 +29,9 @@
 #include "stmmac.h"
 
 #ifdef CONFIG_OF
-static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
-                                           struct plat_stmmacenet_data *plat,
-                                           const char **mac)
+static int stmmac_probe_config_dt(struct platform_device *pdev,
+                                 struct plat_stmmacenet_data *plat,
+                                 const char **mac)
 {
        struct device_node *np = pdev->dev.of_node;
 
@@ -59,9 +59,9 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
        return 0;
 }
 #else
-static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
-                                           struct plat_stmmacenet_data *plat,
-                                           const char **mac)
+static int stmmac_probe_config_dt(struct platform_device *pdev,
+                                 struct plat_stmmacenet_data *plat,
+                                 const char **mac)
 {
        return -ENOSYS;
 }
@@ -74,7 +74,7 @@ static int __devinit stmmac_probe_config_dt(struct platform_device *pdev,
  * the necessary resources and invokes the main to init
  * the net device, register the mdio bus etc.
  */
-static int __devinit stmmac_pltfr_probe(struct platform_device *pdev)
+static int stmmac_pltfr_probe(struct platform_device *pdev)
 {
        int ret = 0;
        struct resource *res;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
deleted file mode 100644 (file)
index 4ccd4e2..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*******************************************************************************
-  STMMAC external timer support.
-
-  Copyright (C) 2007-2009  STMicroelectronics Ltd
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
-*******************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/etherdevice.h>
-#include "stmmac_timer.h"
-
-static void stmmac_timer_handler(void *data)
-{
-       struct net_device *dev = (struct net_device *)data;
-
-       stmmac_schedule(dev);
-}
-
-#define STMMAC_TIMER_MSG(timer, freq) \
-printk(KERN_INFO "stmmac_timer: %s Timer ON (freq %dHz)\n", timer, freq);
-
-#if defined(CONFIG_STMMAC_RTC_TIMER)
-#include <linux/rtc.h>
-static struct rtc_device *stmmac_rtc;
-static rtc_task_t stmmac_task;
-
-static void stmmac_rtc_start(unsigned int new_freq)
-{
-       rtc_irq_set_freq(stmmac_rtc, &stmmac_task, new_freq);
-       rtc_irq_set_state(stmmac_rtc, &stmmac_task, 1);
-}
-
-static void stmmac_rtc_stop(void)
-{
-       rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
-}
-
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
-{
-       stmmac_task.private_data = dev;
-       stmmac_task.func = stmmac_timer_handler;
-
-       stmmac_rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
-       if (stmmac_rtc == NULL) {
-               pr_err("open rtc device failed\n");
-               return -ENODEV;
-       }
-
-       rtc_irq_register(stmmac_rtc, &stmmac_task);
-
-       /* Periodic mode is not supported */
-       if ((rtc_irq_set_freq(stmmac_rtc, &stmmac_task, tm->freq) < 0)) {
-               pr_err("set periodic failed\n");
-               rtc_irq_unregister(stmmac_rtc, &stmmac_task);
-               rtc_class_close(stmmac_rtc);
-               return -1;
-       }
-
-       STMMAC_TIMER_MSG(CONFIG_RTC_HCTOSYS_DEVICE, tm->freq);
-
-       tm->timer_start = stmmac_rtc_start;
-       tm->timer_stop = stmmac_rtc_stop;
-
-       return 0;
-}
-
-int stmmac_close_ext_timer(void)
-{
-       rtc_irq_set_state(stmmac_rtc, &stmmac_task, 0);
-       rtc_irq_unregister(stmmac_rtc, &stmmac_task);
-       rtc_class_close(stmmac_rtc);
-       return 0;
-}
-
-#elif defined(CONFIG_STMMAC_TMU_TIMER)
-#include <linux/clk.h>
-#define TMU_CHANNEL "tmu2_clk"
-static struct clk *timer_clock;
-
-static void stmmac_tmu_start(unsigned int new_freq)
-{
-       clk_set_rate(timer_clock, new_freq);
-       clk_prepare_enable(timer_clock);
-}
-
-static void stmmac_tmu_stop(void)
-{
-       clk_disable_unprepare(timer_clock);
-}
-
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
-{
-       timer_clock = clk_get(NULL, TMU_CHANNEL);
-
-       if (IS_ERR(timer_clock))
-               return -1;
-
-       if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) {
-               timer_clock = NULL;
-               return -1;
-       }
-
-       STMMAC_TIMER_MSG("TMU2", tm->freq);
-       tm->timer_start = stmmac_tmu_start;
-       tm->timer_stop = stmmac_tmu_stop;
-
-       return 0;
-}
-
-int stmmac_close_ext_timer(void)
-{
-       clk_disable_unprepare(timer_clock);
-       tmu2_unregister_user();
-       clk_put(timer_clock);
-       return 0;
-}
-#endif
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
deleted file mode 100644 (file)
index aea9b14..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*******************************************************************************
-  STMMAC external timer Header File.
-
-  Copyright (C) 2007-2009  STMicroelectronics Ltd
-
-  This program is free software; you can redistribute it and/or modify it
-  under the terms and conditions of the GNU General Public License,
-  version 2, as published by the Free Software Foundation.
-
-  This program is distributed in the hope it will be useful, but WITHOUT
-  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
-  more details.
-
-  You should have received a copy of the GNU General Public License along with
-  this program; if not, write to the Free Software Foundation, Inc.,
-  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
-
-  The full GNU General Public License is included in this distribution in
-  the file called "COPYING".
-
-  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
-*******************************************************************************/
-#ifndef __STMMAC_TIMER_H__
-#define __STMMAC_TIMER_H__
-
-struct stmmac_timer {
-       void (*timer_start) (unsigned int new_freq);
-       void (*timer_stop) (void);
-       unsigned int freq;
-       unsigned int enable;
-};
-
-/* Open the HW timer device and return 0 in case of success */
-int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm);
-/* Stop the timer and release it */
-int stmmac_close_ext_timer(void);
-/* Function used for scheduling task within the stmmac */
-void stmmac_schedule(struct net_device *dev);
-
-#if defined(CONFIG_STMMAC_TMU_TIMER)
-extern int tmu2_register_user(void *fnt, void *data);
-extern void tmu2_unregister_user(void);
-#endif
-
-#endif /* __STMMAC_TIMER_H__ */
index c8251be104d6ad6bde2d37b6cea7f2a0c9810429..4c682a3d04240b47efb71736b6a234fdf30cb8cf 100644 (file)
 #define CAS_RESET_SPARE                 3
 #endif
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 static int cassini_debug = -1; /* -1 == use CAS_DEF_MSG_ENABLE as value */
@@ -222,7 +222,7 @@ static int link_transition_timeout;
 
 
 
-static u16 link_modes[] __devinitdata = {
+static u16 link_modes[] = {
        BMCR_ANENABLE,                   /* 0 : autoneg */
        0,                               /* 1 : 10bt half duplex */
        BMCR_SPEED100,                   /* 2 : 100bt half duplex */
@@ -4820,7 +4820,7 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  * only subordinate device and we can tweak the bridge settings to
  * reflect that fact.
  */
-static void __devinit cas_program_bridge(struct pci_dev *cas_pdev)
+static void cas_program_bridge(struct pci_dev *cas_pdev)
 {
        struct pci_dev *pdev = cas_pdev->bus->self;
        u32 val;
@@ -4916,8 +4916,7 @@ static const struct net_device_ops cas_netdev_ops = {
 #endif
 };
 
-static int __devinit cas_init_one(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int cas_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int cas_version_printed = 0;
        unsigned long casreg_len;
@@ -5175,7 +5174,7 @@ err_out_disable_pdev:
        return -ENODEV;
 }
 
-static void __devexit cas_remove_one(struct pci_dev *pdev)
+static void cas_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct cas *cp;
@@ -5273,7 +5272,7 @@ static struct pci_driver cas_driver = {
        .name           = DRV_MODULE_NAME,
        .id_table       = cas_pci_tbl,
        .probe          = cas_init_one,
-       .remove         = __devexit_p(cas_remove_one),
+       .remove         = cas_remove_one,
 #ifdef CONFIG_PM
        .suspend        = cas_suspend,
        .resume         = cas_resume
index 275b430aeb75daebc70cdaeec7695954168d6a04..a0bdf077946614e50fcf30379d18c8192767b6f9 100644 (file)
@@ -38,7 +38,7 @@
 #define DRV_MODULE_VERSION     "1.1"
 #define DRV_MODULE_RELDATE     "Apr 22, 2010"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
@@ -7977,7 +7977,7 @@ static int niu_set_ldg_sid(struct niu *np, int ldg, int func, int vector)
        return 0;
 }
 
-static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr)
+static int niu_pci_eeprom_read(struct niu *np, u32 addr)
 {
        u64 frame, frame_base = (ESPC_PIO_STAT_READ_START |
                                 (addr << ESPC_PIO_STAT_ADDR_SHIFT));
@@ -8020,7 +8020,7 @@ static int __devinit niu_pci_eeprom_read(struct niu *np, u32 addr)
        return (frame & ESPC_PIO_STAT_DATA) >> ESPC_PIO_STAT_DATA_SHIFT;
 }
 
-static int __devinit niu_pci_eeprom_read16(struct niu *np, u32 off)
+static int niu_pci_eeprom_read16(struct niu *np, u32 off)
 {
        int err = niu_pci_eeprom_read(np, off);
        u16 val;
@@ -8036,7 +8036,7 @@ static int __devinit niu_pci_eeprom_read16(struct niu *np, u32 off)
        return val;
 }
 
-static int __devinit niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
+static int niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
 {
        int err = niu_pci_eeprom_read(np, off);
        u16 val;
@@ -8054,10 +8054,8 @@ static int __devinit niu_pci_eeprom_read16_swp(struct niu *np, u32 off)
        return val;
 }
 
-static int __devinit niu_pci_vpd_get_propname(struct niu *np,
-                                             u32 off,
-                                             char *namebuf,
-                                             int namebuf_len)
+static int niu_pci_vpd_get_propname(struct niu *np, u32 off, char *namebuf,
+                                   int namebuf_len)
 {
        int i;
 
@@ -8075,7 +8073,7 @@ static int __devinit niu_pci_vpd_get_propname(struct niu *np,
        return i + 1;
 }
 
-static void __devinit niu_vpd_parse_version(struct niu *np)
+static void niu_vpd_parse_version(struct niu *np)
 {
        struct niu_vpd *vpd = &np->vpd;
        int len = strlen(vpd->version) + 1;
@@ -8102,8 +8100,7 @@ static void __devinit niu_vpd_parse_version(struct niu *np)
 }
 
 /* ESPC_PIO_EN_ENABLE must be set */
-static int __devinit niu_pci_vpd_scan_props(struct niu *np,
-                                           u32 start, u32 end)
+static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
 {
        unsigned int found_mask = 0;
 #define FOUND_MASK_MODEL       0x00000001
@@ -8189,7 +8186,7 @@ static int __devinit niu_pci_vpd_scan_props(struct niu *np,
 }
 
 /* ESPC_PIO_EN_ENABLE must be set */
-static void __devinit niu_pci_vpd_fetch(struct niu *np, u32 start)
+static void niu_pci_vpd_fetch(struct niu *np, u32 start)
 {
        u32 offset;
        int err;
@@ -8224,7 +8221,7 @@ static void __devinit niu_pci_vpd_fetch(struct niu *np, u32 start)
 }
 
 /* ESPC_PIO_EN_ENABLE must be set */
-static u32 __devinit niu_pci_vpd_offset(struct niu *np)
+static u32 niu_pci_vpd_offset(struct niu *np)
 {
        u32 start = 0, end = ESPC_EEPROM_SIZE, ret;
        int err;
@@ -8279,8 +8276,7 @@ static u32 __devinit niu_pci_vpd_offset(struct niu *np)
        return 0;
 }
 
-static int __devinit niu_phy_type_prop_decode(struct niu *np,
-                                             const char *phy_prop)
+static int niu_phy_type_prop_decode(struct niu *np, const char *phy_prop)
 {
        if (!strcmp(phy_prop, "mif")) {
                /* 1G copper, MII */
@@ -8334,7 +8330,7 @@ static int niu_pci_vpd_get_nports(struct niu *np)
        return ports;
 }
 
-static void __devinit niu_pci_vpd_validate(struct niu *np)
+static void niu_pci_vpd_validate(struct niu *np)
 {
        struct net_device *dev = np->dev;
        struct niu_vpd *vpd = &np->vpd;
@@ -8380,7 +8376,7 @@ static void __devinit niu_pci_vpd_validate(struct niu *np)
        memcpy(dev->dev_addr, dev->perm_addr, dev->addr_len);
 }
 
-static int __devinit niu_pci_probe_sprom(struct niu *np)
+static int niu_pci_probe_sprom(struct niu *np)
 {
        struct net_device *dev = np->dev;
        int len, i;
@@ -8538,7 +8534,7 @@ static int __devinit niu_pci_probe_sprom(struct niu *np)
        return 0;
 }
 
-static int __devinit niu_get_and_validate_port(struct niu *np)
+static int niu_get_and_validate_port(struct niu *np)
 {
        struct niu_parent *parent = np->parent;
 
@@ -8572,10 +8568,8 @@ static int __devinit niu_get_and_validate_port(struct niu *np)
        return 0;
 }
 
-static int __devinit phy_record(struct niu_parent *parent,
-                               struct phy_probe_info *p,
-                               int dev_id_1, int dev_id_2, u8 phy_port,
-                               int type)
+static int phy_record(struct niu_parent *parent, struct phy_probe_info *p,
+                     int dev_id_1, int dev_id_2, u8 phy_port, int type)
 {
        u32 id = (dev_id_1 << 16) | dev_id_2;
        u8 idx;
@@ -8611,7 +8605,7 @@ static int __devinit phy_record(struct niu_parent *parent,
        return 0;
 }
 
-static int __devinit port_has_10g(struct phy_probe_info *p, int port)
+static int port_has_10g(struct phy_probe_info *p, int port)
 {
        int i;
 
@@ -8627,7 +8621,7 @@ static int __devinit port_has_10g(struct phy_probe_info *p, int port)
        return 0;
 }
 
-static int __devinit count_10g_ports(struct phy_probe_info *p, int *lowest)
+static int count_10g_ports(struct phy_probe_info *p, int *lowest)
 {
        int port, cnt;
 
@@ -8644,7 +8638,7 @@ static int __devinit count_10g_ports(struct phy_probe_info *p, int *lowest)
        return cnt;
 }
 
-static int __devinit count_1g_ports(struct phy_probe_info *p, int *lowest)
+static int count_1g_ports(struct phy_probe_info *p, int *lowest)
 {
        *lowest = 32;
        if (p->cur[PHY_TYPE_MII])
@@ -8653,7 +8647,7 @@ static int __devinit count_1g_ports(struct phy_probe_info *p, int *lowest)
        return p->cur[PHY_TYPE_MII];
 }
 
-static void __devinit niu_n2_divide_channels(struct niu_parent *parent)
+static void niu_n2_divide_channels(struct niu_parent *parent)
 {
        int num_ports = parent->num_ports;
        int i;
@@ -8669,8 +8663,8 @@ static void __devinit niu_n2_divide_channels(struct niu_parent *parent)
        }
 }
 
-static void __devinit niu_divide_channels(struct niu_parent *parent,
-                                         int num_10g, int num_1g)
+static void niu_divide_channels(struct niu_parent *parent,
+                               int num_10g, int num_1g)
 {
        int num_ports = parent->num_ports;
        int rx_chans_per_10g, rx_chans_per_1g;
@@ -8731,8 +8725,8 @@ static void __devinit niu_divide_channels(struct niu_parent *parent,
        }
 }
 
-static void __devinit niu_divide_rdc_groups(struct niu_parent *parent,
-                                           int num_10g, int num_1g)
+static void niu_divide_rdc_groups(struct niu_parent *parent,
+                                 int num_10g, int num_1g)
 {
        int i, num_ports = parent->num_ports;
        int rdc_group, rdc_groups_per_port;
@@ -8776,9 +8770,8 @@ static void __devinit niu_divide_rdc_groups(struct niu_parent *parent,
        }
 }
 
-static int __devinit fill_phy_probe_info(struct niu *np,
-                                        struct niu_parent *parent,
-                                        struct phy_probe_info *info)
+static int fill_phy_probe_info(struct niu *np, struct niu_parent *parent,
+                              struct phy_probe_info *info)
 {
        unsigned long flags;
        int port, err;
@@ -8819,7 +8812,7 @@ static int __devinit fill_phy_probe_info(struct niu *np,
        return err;
 }
 
-static int __devinit walk_phys(struct niu *np, struct niu_parent *parent)
+static int walk_phys(struct niu *np, struct niu_parent *parent)
 {
        struct phy_probe_info *info = &parent->phy_probe_info;
        int lowest_10g, lowest_1g;
@@ -8948,7 +8941,7 @@ unknown_vg_1g_port:
        return -EINVAL;
 }
 
-static int __devinit niu_probe_ports(struct niu *np)
+static int niu_probe_ports(struct niu *np)
 {
        struct niu_parent *parent = np->parent;
        int err, i;
@@ -8969,7 +8962,7 @@ static int __devinit niu_probe_ports(struct niu *np)
        return 0;
 }
 
-static int __devinit niu_classifier_swstate_init(struct niu *np)
+static int niu_classifier_swstate_init(struct niu *np)
 {
        struct niu_classifier *cp = &np->clas;
 
@@ -8981,7 +8974,7 @@ static int __devinit niu_classifier_swstate_init(struct niu *np)
        return fflp_early_init(np);
 }
 
-static void __devinit niu_link_config_init(struct niu *np)
+static void niu_link_config_init(struct niu *np)
 {
        struct niu_link_config *lp = &np->link_config;
 
@@ -9006,7 +8999,7 @@ static void __devinit niu_link_config_init(struct niu *np)
 #endif
 }
 
-static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np)
+static int niu_init_mac_ipp_pcs_base(struct niu *np)
 {
        switch (np->port) {
        case 0:
@@ -9045,7 +9038,7 @@ static int __devinit niu_init_mac_ipp_pcs_base(struct niu *np)
        return 0;
 }
 
-static void __devinit niu_try_msix(struct niu *np, u8 *ldg_num_map)
+static void niu_try_msix(struct niu *np, u8 *ldg_num_map)
 {
        struct msix_entry msi_vec[NIU_NUM_LDG];
        struct niu_parent *parent = np->parent;
@@ -9084,7 +9077,7 @@ retry:
        np->num_ldg = num_irqs;
 }
 
-static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
+static int niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
 {
 #ifdef CONFIG_SPARC64
        struct platform_device *op = np->op;
@@ -9108,7 +9101,7 @@ static int __devinit niu_n2_irq_init(struct niu *np, u8 *ldg_num_map)
 #endif
 }
 
-static int __devinit niu_ldg_init(struct niu *np)
+static int niu_ldg_init(struct niu *np)
 {
        struct niu_parent *parent = np->parent;
        u8 ldg_num_map[NIU_NUM_LDG];
@@ -9225,13 +9218,13 @@ static int __devinit niu_ldg_init(struct niu *np)
        return 0;
 }
 
-static void __devexit niu_ldg_free(struct niu *np)
+static void niu_ldg_free(struct niu *np)
 {
        if (np->flags & NIU_FLAGS_MSIX)
                pci_disable_msix(np->pdev);
 }
 
-static int __devinit niu_get_of_props(struct niu *np)
+static int niu_get_of_props(struct niu *np)
 {
 #ifdef CONFIG_SPARC64
        struct net_device *dev = np->dev;
@@ -9300,7 +9293,7 @@ static int __devinit niu_get_of_props(struct niu *np)
 #endif
 }
 
-static int __devinit niu_get_invariants(struct niu *np)
+static int niu_get_invariants(struct niu *np)
 {
        int err, have_props;
        u32 offset;
@@ -9479,9 +9472,8 @@ static struct device_attribute niu_parent_attributes[] = {
        {}
 };
 
-static struct niu_parent * __devinit niu_new_parent(struct niu *np,
-                                                   union niu_parent_id *id,
-                                                   u8 ptype)
+static struct niu_parent *niu_new_parent(struct niu *np,
+                                        union niu_parent_id *id, u8 ptype)
 {
        struct platform_device *plat_dev;
        struct niu_parent *p;
@@ -9544,9 +9536,8 @@ fail_unregister:
        return NULL;
 }
 
-static struct niu_parent * __devinit niu_get_parent(struct niu *np,
-                                                   union niu_parent_id *id,
-                                                   u8 ptype)
+static struct niu_parent *niu_get_parent(struct niu *np,
+                                        union niu_parent_id *id, u8 ptype)
 {
        struct niu_parent *p, *tmp;
        int port = np->port;
@@ -9662,7 +9653,7 @@ static const struct niu_ops niu_pci_ops = {
        .unmap_single   = niu_pci_unmap_single,
 };
 
-static void __devinit niu_driver_version(void)
+static void niu_driver_version(void)
 {
        static int niu_version_printed;
 
@@ -9670,10 +9661,10 @@ static void __devinit niu_driver_version(void)
                pr_info("%s", version);
 }
 
-static struct net_device * __devinit niu_alloc_and_init(
-       struct device *gen_dev, struct pci_dev *pdev,
-       struct platform_device *op, const struct niu_ops *ops,
-       u8 port)
+static struct net_device *niu_alloc_and_init(struct device *gen_dev,
+                                            struct pci_dev *pdev,
+                                            struct platform_device *op,
+                                            const struct niu_ops *ops, u8 port)
 {
        struct net_device *dev;
        struct niu *np;
@@ -9714,14 +9705,14 @@ static const struct net_device_ops niu_netdev_ops = {
        .ndo_change_mtu         = niu_change_mtu,
 };
 
-static void __devinit niu_assign_netdev_ops(struct net_device *dev)
+static void niu_assign_netdev_ops(struct net_device *dev)
 {
        dev->netdev_ops = &niu_netdev_ops;
        dev->ethtool_ops = &niu_ethtool_ops;
        dev->watchdog_timeo = NIU_TX_TIMEOUT;
 }
 
-static void __devinit niu_device_announce(struct niu *np)
+static void niu_device_announce(struct niu *np)
 {
        struct net_device *dev = np->dev;
 
@@ -9750,14 +9741,14 @@ static void __devinit niu_device_announce(struct niu *np)
        }
 }
 
-static void __devinit niu_set_basic_features(struct net_device *dev)
+static void niu_set_basic_features(struct net_device *dev)
 {
        dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXHASH;
        dev->features |= dev->hw_features | NETIF_F_RXCSUM;
 }
 
-static int __devinit niu_pci_init_one(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int niu_pci_init_one(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        union niu_parent_id parent_id;
        struct net_device *dev;
@@ -9895,7 +9886,7 @@ err_out_disable_pdev:
        return err;
 }
 
-static void __devexit niu_pci_remove_one(struct pci_dev *pdev)
+static void niu_pci_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -9980,7 +9971,7 @@ static struct pci_driver niu_pci_driver = {
        .name           = DRV_MODULE_NAME,
        .id_table       = niu_pci_tbl,
        .probe          = niu_pci_init_one,
-       .remove         = __devexit_p(niu_pci_remove_one),
+       .remove         = niu_pci_remove_one,
        .suspend        = niu_suspend,
        .resume         = niu_resume,
 };
@@ -10044,7 +10035,7 @@ static const struct niu_ops niu_phys_ops = {
        .unmap_single   = niu_phys_unmap_single,
 };
 
-static int __devinit niu_of_probe(struct platform_device *op)
+static int niu_of_probe(struct platform_device *op)
 {
        union niu_parent_id parent_id;
        struct net_device *dev;
@@ -10158,7 +10149,7 @@ err_out:
        return err;
 }
 
-static int __devexit niu_of_remove(struct platform_device *op)
+static int niu_of_remove(struct platform_device *op)
 {
        struct net_device *dev = dev_get_drvdata(&op->dev);
 
@@ -10211,7 +10202,7 @@ static struct platform_driver niu_of_driver = {
                .of_match_table = niu_match,
        },
        .probe          = niu_of_probe,
-       .remove         = __devexit_p(niu_of_remove),
+       .remove         = niu_of_remove,
 };
 
 #endif /* CONFIG_SPARC64 */
index c9c977bf02ace45e1e4be1b863d682995d39185f..be82f6d13c5199228053ca37a69f847821542f35 100644 (file)
@@ -1074,8 +1074,8 @@ static const struct net_device_ops bigmac_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit bigmac_ether_init(struct platform_device *op,
-                                      struct platform_device *qec_op)
+static int bigmac_ether_init(struct platform_device *op,
+                            struct platform_device *qec_op)
 {
        static int version_printed;
        struct net_device *dev;
@@ -1233,7 +1233,7 @@ fail_and_cleanup:
 /* QEC can be the parent of either QuadEthernet or a BigMAC.  We want
  * the latter.
  */
-static int __devinit bigmac_sbus_probe(struct platform_device *op)
+static int bigmac_sbus_probe(struct platform_device *op)
 {
        struct device *parent = op->dev.parent;
        struct platform_device *qec_op;
@@ -1243,7 +1243,7 @@ static int __devinit bigmac_sbus_probe(struct platform_device *op)
        return bigmac_ether_init(op, qec_op);
 }
 
-static int __devexit bigmac_sbus_remove(struct platform_device *op)
+static int bigmac_sbus_remove(struct platform_device *op)
 {
        struct bigmac *bp = dev_get_drvdata(&op->dev);
        struct device *parent = op->dev.parent;
@@ -1286,7 +1286,7 @@ static struct platform_driver bigmac_sbus_driver = {
                .of_match_table = bigmac_sbus_match,
        },
        .probe          = bigmac_sbus_probe,
-       .remove         = __devexit_p(bigmac_sbus_remove),
+       .remove         = bigmac_sbus_remove,
 };
 
 module_platform_driver(bigmac_sbus_driver);
index 6c8695ec7cb9846fc0a53bbff830ce839fa95a21..5f3f9d52757dbffb60eb277d45acdc6a29eb49f6 100644 (file)
@@ -77,7 +77,7 @@
 #define DRV_VERSION    "1.0"
 #define DRV_AUTHOR     "David S. Miller <davem@redhat.com>"
 
-static char version[] __devinitdata =
+static char version[] =
         DRV_NAME ".c:v" DRV_VERSION " " DRV_AUTHOR "\n";
 
 MODULE_AUTHOR(DRV_AUTHOR);
@@ -2763,7 +2763,7 @@ static void get_gem_mac_nonobp(struct pci_dev *pdev, unsigned char *dev_addr)
 }
 #endif /* not Sparc and not PPC */
 
-static int __devinit gem_get_device_address(struct gem *gp)
+static int gem_get_device_address(struct gem *gp)
 {
 #if defined(CONFIG_SPARC) || defined(CONFIG_PPC_PMAC)
        struct net_device *dev = gp->dev;
@@ -2827,8 +2827,7 @@ static const struct net_device_ops gem_netdev_ops = {
 #endif
 };
 
-static int __devinit gem_init_one(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        unsigned long gemreg_base, gemreg_len;
        struct net_device *dev;
index 73f341b8befbe2e719ce131168c6ceda4f269a48..a1bff49a815549e862bcaf0d938deb24558d0e54 100644 (file)
@@ -2499,7 +2499,7 @@ static int hme_version_printed;
  *
  * Return NULL on failure.
  */
-static struct quattro * __devinit quattro_sbus_find(struct platform_device *child)
+static struct quattro *quattro_sbus_find(struct platform_device *child)
 {
        struct device *parent = child->dev.parent;
        struct platform_device *op;
@@ -2580,7 +2580,7 @@ static void quattro_sbus_free_irqs(void)
 #endif /* CONFIG_SBUS */
 
 #ifdef CONFIG_PCI
-static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev)
+static struct quattro *quattro_pci_find(struct pci_dev *pdev)
 {
        struct pci_dev *bdev = pdev->bus->self;
        struct quattro *qp;
@@ -2623,7 +2623,7 @@ static const struct net_device_ops hme_netdev_ops = {
 };
 
 #ifdef CONFIG_SBUS
-static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
+static int happy_meal_sbus_probe_one(struct platform_device *op, int is_qfe)
 {
        struct device_node *dp = op->dev.of_node, *sbus_dp;
        struct quattro *qp = NULL;
@@ -2927,8 +2927,8 @@ static void get_hme_mac_nonsparc(struct pci_dev *pdev, unsigned char *dev_addr)
 }
 #endif /* !(CONFIG_SPARC) */
 
-static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
-                                         const struct pci_device_id *ent)
+static int happy_meal_pci_probe(struct pci_dev *pdev,
+                               const struct pci_device_id *ent)
 {
        struct quattro *qp = NULL;
 #ifdef CONFIG_SPARC
@@ -3162,7 +3162,7 @@ err_out:
        return err;
 }
 
-static void __devexit happy_meal_pci_remove(struct pci_dev *pdev)
+static void happy_meal_pci_remove(struct pci_dev *pdev)
 {
        struct happy_meal *hp = dev_get_drvdata(&pdev->dev);
        struct net_device *net_dev = hp->dev;
@@ -3190,7 +3190,7 @@ static struct pci_driver hme_pci_driver = {
        .name           = "hme",
        .id_table       = happymeal_pci_ids,
        .probe          = happy_meal_pci_probe,
-       .remove         = __devexit_p(happy_meal_pci_remove),
+       .remove         = happy_meal_pci_remove,
 };
 
 static int __init happy_meal_pci_init(void)
@@ -3216,7 +3216,7 @@ static void happy_meal_pci_exit(void)
 
 #ifdef CONFIG_SBUS
 static const struct of_device_id hme_sbus_match[];
-static int __devinit hme_sbus_probe(struct platform_device *op)
+static int hme_sbus_probe(struct platform_device *op)
 {
        const struct of_device_id *match;
        struct device_node *dp = op->dev.of_node;
@@ -3234,7 +3234,7 @@ static int __devinit hme_sbus_probe(struct platform_device *op)
        return happy_meal_sbus_probe_one(op, is_qfe);
 }
 
-static int __devexit hme_sbus_remove(struct platform_device *op)
+static int hme_sbus_remove(struct platform_device *op)
 {
        struct happy_meal *hp = dev_get_drvdata(&op->dev);
        struct net_device *net_dev = hp->dev;
@@ -3284,7 +3284,7 @@ static struct platform_driver hme_sbus_driver = {
                .of_match_table = hme_sbus_match,
        },
        .probe          = hme_sbus_probe,
-       .remove         = __devexit_p(hme_sbus_remove),
+       .remove         = hme_sbus_remove,
 };
 
 static int __init happy_meal_sbus_init(void)
index aeded7ff1c8f96ac9903f33c784aa6e594726858..1dcee6915843cd67f11169eab68c36fbbeb51a4c 100644 (file)
@@ -744,7 +744,7 @@ static void qec_init_once(struct sunqec *qecp, struct platform_device *op)
                    qecp->gregs + GLOB_RSIZE);
 }
 
-static u8 __devinit qec_get_burst(struct device_node *dp)
+static u8 qec_get_burst(struct device_node *dp)
 {
        u8 bsizes, bsizes_more;
 
@@ -764,7 +764,7 @@ static u8 __devinit qec_get_burst(struct device_node *dp)
        return bsizes;
 }
 
-static struct sunqec * __devinit get_qec(struct platform_device *child)
+static struct sunqec *get_qec(struct platform_device *child)
 {
        struct platform_device *op = to_platform_device(child->dev.parent);
        struct sunqec *qecp;
@@ -830,7 +830,7 @@ static const struct net_device_ops qec_ops = {
        .ndo_validate_addr      = eth_validate_addr,
 };
 
-static int __devinit qec_ether_init(struct platform_device *op)
+static int qec_ether_init(struct platform_device *op)
 {
        static unsigned version_printed;
        struct net_device *dev;
@@ -929,12 +929,12 @@ fail:
        return res;
 }
 
-static int __devinit qec_sbus_probe(struct platform_device *op)
+static int qec_sbus_probe(struct platform_device *op)
 {
        return qec_ether_init(op);
 }
 
-static int __devexit qec_sbus_remove(struct platform_device *op)
+static int qec_sbus_remove(struct platform_device *op)
 {
        struct sunqe *qp = dev_get_drvdata(&op->dev);
        struct net_device *net_dev = qp->dev;
@@ -971,7 +971,7 @@ static struct platform_driver qec_sbus_driver = {
                .of_match_table = qec_sbus_match,
        },
        .probe          = qec_sbus_probe,
-       .remove         = __devexit_p(qec_sbus_remove),
+       .remove         = qec_sbus_remove,
 };
 
 static int __init qec_init(void)
index a108db35924ed9f0aa943db43e94b2a5fac33f50..e1b8955308277fae7c953274492e3d9eb936f961 100644 (file)
@@ -25,7 +25,7 @@
 #define DRV_MODULE_VERSION     "1.0"
 #define DRV_MODULE_RELDATE     "June 25, 2007"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
 MODULE_DESCRIPTION("Sun LDOM virtual network driver");
@@ -937,7 +937,7 @@ static void vnet_port_free_tx_bufs(struct vnet_port *port)
        }
 }
 
-static int __devinit vnet_port_alloc_tx_bufs(struct vnet_port *port)
+static int vnet_port_alloc_tx_bufs(struct vnet_port *port)
 {
        struct vio_dring_state *dr;
        unsigned long len;
@@ -1019,7 +1019,7 @@ static const struct net_device_ops vnet_ops = {
        .ndo_start_xmit         = vnet_start_xmit,
 };
 
-static struct vnet * __devinit vnet_new(const u64 *local_mac)
+static struct vnet *vnet_new(const u64 *local_mac)
 {
        struct net_device *dev;
        struct vnet *vp;
@@ -1067,7 +1067,7 @@ err_out_free_dev:
        return ERR_PTR(err);
 }
 
-static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac)
+static struct vnet *vnet_find_or_create(const u64 *local_mac)
 {
        struct vnet *iter, *vp;
 
@@ -1088,7 +1088,7 @@ static struct vnet * __devinit vnet_find_or_create(const u64 *local_mac)
 
 static const char *local_mac_prop = "local-mac-address";
 
-static struct vnet * __devinit vnet_find_parent(struct mdesc_handle *hp,
+static struct vnet *vnet_find_parent(struct mdesc_handle *hp,
                                                u64 port_node)
 {
        const u64 *local_mac = NULL;
@@ -1125,15 +1125,14 @@ static struct vio_driver_ops vnet_vio_ops = {
        .handshake_complete     = vnet_handshake_complete,
 };
 
-static void __devinit print_version(void)
+static void print_version(void)
 {
        printk_once(KERN_INFO "%s", version);
 }
 
 const char *remote_macaddr_prop = "remote-mac-address";
 
-static int __devinit vnet_port_probe(struct vio_dev *vdev,
-                                    const struct vio_device_id *id)
+static int vnet_port_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 {
        struct mdesc_handle *hp;
        struct vnet_port *port;
index 6ce9edd95c04d9ea88826ad8c871f0549f2b85fd..1e4d743ff03e7b86e0cd72002166f0dc28212b73 100644 (file)
@@ -1914,7 +1914,7 @@ static const struct net_device_ops bdx_netdev_ops = {
  */
 
 /* TBD: netif_msg should be checked and implemented. I disable it for now */
-static int __devinit
+static int
 bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *ndev;
@@ -2427,7 +2427,7 @@ static void bdx_set_ethtool_ops(struct net_device *netdev)
  * Hot-Plug event, or because the driver is going to be removed from
  * memory.
  **/
-static void __devexit bdx_remove(struct pci_dev *pdev)
+static void bdx_remove(struct pci_dev *pdev)
 {
        struct pci_nic *nic = pci_get_drvdata(pdev);
        struct net_device *ndev;
@@ -2458,7 +2458,7 @@ static struct pci_driver bdx_pci_driver = {
        .name = BDX_DRV_NAME,
        .id_table = bdx_pci_tbl,
        .probe = bdx_probe,
-       .remove = __devexit_p(bdx_remove),
+       .remove = bdx_remove,
 };
 
 /*
index b26cbda5efa9b5264dd4e2bb885d35ea7e26b692..4426151d4ac9d7bd3415bee2ac97e9944ac4f633 100644 (file)
@@ -5,7 +5,7 @@
 config NET_VENDOR_TI
        bool "Texas Instruments (TI) devices"
        default y
-       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3))
+       depends on PCI || EISA || AR7 || (ARM && (ARCH_DAVINCI || ARCH_OMAP3 || SOC_AM33XX))
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y
          and read the Ethernet-HOWTO, available from
@@ -60,6 +60,15 @@ config TI_CPSW
          To compile this driver as a module, choose M here: the module
          will be called cpsw.
 
+config TI_CPTS
+       boolean "TI Common Platform Time Sync (CPTS) Support"
+       depends on TI_CPSW
+       select PTP_1588_CLOCK
+       ---help---
+         This driver supports the Common Platform Time Sync unit of
+         the CPSW Ethernet Switch. The unit can time stamp PTP UDP/IPv4
+         and Layer 2 packets, and the driver offers a PTP Hardware Clock.
+
 config TLAN
        tristate "TI ThunderLAN support"
        depends on (PCI || EISA)
index 91bd8bba78ffb872faa4b4f60cc43196e4893773..c65148e8aa1d4810e00cbe6d7448fa72572847d7 100644 (file)
@@ -8,4 +8,4 @@ obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
 obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
 obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
 obj-$(CONFIG_TI_CPSW) += ti_cpsw.o
-ti_cpsw-y := cpsw_ale.o cpsw.o
+ti_cpsw-y := cpsw_ale.o cpsw.o cpts.o
index 860c2526f08d0dd470b777756ca4db1d93094a62..d9625f62b026cd06bbfdff222af8950b90bd3027 100644 (file)
@@ -1110,7 +1110,7 @@ static const struct net_device_ops cpmac_netdev_ops = {
 
 static int external_switch;
 
-static int __devinit cpmac_probe(struct platform_device *pdev)
+static int cpmac_probe(struct platform_device *pdev)
 {
        int rc, phy_id;
        char mdio_bus_id[MII_BUS_ID_SIZE];
@@ -1204,7 +1204,7 @@ fail:
        return rc;
 }
 
-static int __devexit cpmac_remove(struct platform_device *pdev)
+static int cpmac_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        unregister_netdev(dev);
@@ -1216,10 +1216,10 @@ static struct platform_driver cpmac_driver = {
        .driver.name = "cpmac",
        .driver.owner = THIS_MODULE,
        .probe = cpmac_probe,
-       .remove = __devexit_p(cpmac_remove),
+       .remove = cpmac_remove,
 };
 
-int __devinit cpmac_init(void)
+int cpmac_init(void)
 {
        u32 mask;
        int i, res;
@@ -1290,7 +1290,7 @@ fail_alloc:
        return res;
 }
 
-void __devexit cpmac_exit(void)
+void cpmac_exit(void)
 {
        platform_driver_unregister(&cpmac_driver);
        mdiobus_unregister(cpmac_mii);
index df55e240374646e2f076d9b4764fab6dc0a07bab..40aff684aa23af64fc3ff03f0c5a54df798c0484 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/if_ether.h>
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/workqueue.h>
 #include <linux/delay.h>
@@ -35,6 +36,7 @@
 #include <linux/platform_data/cpsw.h>
 
 #include "cpsw_ale.h"
+#include "cpts.h"
 #include "davinci_cpdma.h"
 
 #define CPSW_DEBUG     (NETIF_MSG_HW           | NETIF_MSG_WOL         | \
@@ -70,10 +72,37 @@ do {                                                                \
                dev_notice(priv->dev, format, ## __VA_ARGS__);  \
 } while (0)
 
+#define ALE_ALL_PORTS          0x7
+
 #define CPSW_MAJOR_VERSION(reg)                (reg >> 8 & 0x7)
 #define CPSW_MINOR_VERSION(reg)                (reg & 0xff)
 #define CPSW_RTL_VERSION(reg)          ((reg >> 11) & 0x1f)
 
+#define CPSW_VERSION_1         0x19010a
+#define CPSW_VERSION_2         0x19010c
+
+#define HOST_PORT_NUM          0
+#define SLIVER_SIZE            0x40
+
+#define CPSW1_HOST_PORT_OFFSET 0x028
+#define CPSW1_SLAVE_OFFSET     0x050
+#define CPSW1_SLAVE_SIZE       0x040
+#define CPSW1_CPDMA_OFFSET     0x100
+#define CPSW1_STATERAM_OFFSET  0x200
+#define CPSW1_CPTS_OFFSET      0x500
+#define CPSW1_ALE_OFFSET       0x600
+#define CPSW1_SLIVER_OFFSET    0x700
+
+#define CPSW2_HOST_PORT_OFFSET 0x108
+#define CPSW2_SLAVE_OFFSET     0x200
+#define CPSW2_SLAVE_SIZE       0x100
+#define CPSW2_CPDMA_OFFSET     0x800
+#define CPSW2_STATERAM_OFFSET  0xa00
+#define CPSW2_CPTS_OFFSET      0xc00
+#define CPSW2_ALE_OFFSET       0xd00
+#define CPSW2_SLIVER_OFFSET    0xd80
+#define CPSW2_BD_OFFSET                0x2000
+
 #define CPDMA_RXTHRESH         0x0c0
 #define CPDMA_RXFREE           0x0e0
 #define CPDMA_TXHDP            0x00
@@ -81,21 +110,6 @@ do {                                                                \
 #define CPDMA_TXCP             0x40
 #define CPDMA_RXCP             0x60
 
-#define cpsw_dma_regs(base, offset)            \
-       (void __iomem *)((base) + (offset))
-#define cpsw_dma_rxthresh(base, offset)                \
-       (void __iomem *)((base) + (offset) + CPDMA_RXTHRESH)
-#define cpsw_dma_rxfree(base, offset)          \
-       (void __iomem *)((base) + (offset) + CPDMA_RXFREE)
-#define cpsw_dma_txhdp(base, offset)           \
-       (void __iomem *)((base) + (offset) + CPDMA_TXHDP)
-#define cpsw_dma_rxhdp(base, offset)           \
-       (void __iomem *)((base) + (offset) + CPDMA_RXHDP)
-#define cpsw_dma_txcp(base, offset)            \
-       (void __iomem *)((base) + (offset) + CPDMA_TXCP)
-#define cpsw_dma_rxcp(base, offset)            \
-       (void __iomem *)((base) + (offset) + CPDMA_RXCP)
-
 #define CPSW_POLL_WEIGHT       64
 #define CPSW_MIN_PACKET_SIZE   60
 #define CPSW_MAX_PACKET_SIZE   (1500 + 14 + 4 + 4)
@@ -129,7 +143,7 @@ static int rx_packet_max = CPSW_MAX_PACKET_SIZE;
 module_param(rx_packet_max, int, 0);
 MODULE_PARM_DESC(rx_packet_max, "maximum receive packet size (bytes)");
 
-struct cpsw_ss_regs {
+struct cpsw_wr_regs {
        u32     id_ver;
        u32     soft_reset;
        u32     control;
@@ -140,26 +154,98 @@ struct cpsw_ss_regs {
        u32     misc_en;
 };
 
-struct cpsw_regs {
+struct cpsw_ss_regs {
        u32     id_ver;
        u32     control;
        u32     soft_reset;
        u32     stat_port_en;
        u32     ptype;
+       u32     soft_idle;
+       u32     thru_rate;
+       u32     gap_thresh;
+       u32     tx_start_wds;
+       u32     flow_control;
+       u32     vlan_ltype;
+       u32     ts_ltype;
+       u32     dlr_ltype;
 };
 
-struct cpsw_slave_regs {
-       u32     max_blks;
-       u32     blk_cnt;
-       u32     flow_thresh;
-       u32     port_vlan;
-       u32     tx_pri_map;
-       u32     ts_ctl;
-       u32     ts_seq_ltype;
-       u32     ts_vlan;
-       u32     sa_lo;
-       u32     sa_hi;
-};
+/* CPSW_PORT_V1 */
+#define CPSW1_MAX_BLKS      0x00 /* Maximum FIFO Blocks */
+#define CPSW1_BLK_CNT       0x04 /* FIFO Block Usage Count (Read Only) */
+#define CPSW1_TX_IN_CTL     0x08 /* Transmit FIFO Control */
+#define CPSW1_PORT_VLAN     0x0c /* VLAN Register */
+#define CPSW1_TX_PRI_MAP    0x10 /* Tx Header Priority to Switch Pri Mapping */
+#define CPSW1_TS_CTL        0x14 /* Time Sync Control */
+#define CPSW1_TS_SEQ_LTYPE  0x18 /* Time Sync Sequence ID Offset and Msg Type */
+#define CPSW1_TS_VLAN       0x1c /* Time Sync VLAN1 and VLAN2 */
+
+/* CPSW_PORT_V2 */
+#define CPSW2_CONTROL       0x00 /* Control Register */
+#define CPSW2_MAX_BLKS      0x08 /* Maximum FIFO Blocks */
+#define CPSW2_BLK_CNT       0x0c /* FIFO Block Usage Count (Read Only) */
+#define CPSW2_TX_IN_CTL     0x10 /* Transmit FIFO Control */
+#define CPSW2_PORT_VLAN     0x14 /* VLAN Register */
+#define CPSW2_TX_PRI_MAP    0x18 /* Tx Header Priority to Switch Pri Mapping */
+#define CPSW2_TS_SEQ_MTYPE  0x1c /* Time Sync Sequence ID Offset and Msg Type */
+
+/* CPSW_PORT_V1 and V2 */
+#define SA_LO               0x20 /* CPGMAC_SL Source Address Low */
+#define SA_HI               0x24 /* CPGMAC_SL Source Address High */
+#define SEND_PERCENT        0x28 /* Transmit Queue Send Percentages */
+
+/* CPSW_PORT_V2 only */
+#define RX_DSCP_PRI_MAP0    0x30 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP1    0x34 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP2    0x38 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP3    0x3c /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP4    0x40 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP5    0x44 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP6    0x48 /* Rx DSCP Priority to Rx Packet Mapping */
+#define RX_DSCP_PRI_MAP7    0x4c /* Rx DSCP Priority to Rx Packet Mapping */
+
+/* Bit definitions for the CPSW2_CONTROL register */
+#define PASS_PRI_TAGGED     (1<<24) /* Pass Priority Tagged */
+#define VLAN_LTYPE2_EN      (1<<21) /* VLAN LTYPE 2 enable */
+#define VLAN_LTYPE1_EN      (1<<20) /* VLAN LTYPE 1 enable */
+#define DSCP_PRI_EN         (1<<16) /* DSCP Priority Enable */
+#define TS_320              (1<<14) /* Time Sync Dest Port 320 enable */
+#define TS_319              (1<<13) /* Time Sync Dest Port 319 enable */
+#define TS_132              (1<<12) /* Time Sync Dest IP Addr 132 enable */
+#define TS_131              (1<<11) /* Time Sync Dest IP Addr 131 enable */
+#define TS_130              (1<<10) /* Time Sync Dest IP Addr 130 enable */
+#define TS_129              (1<<9)  /* Time Sync Dest IP Addr 129 enable */
+#define TS_BIT8             (1<<8)  /* ts_ttl_nonzero? */
+#define TS_ANNEX_D_EN       (1<<4)  /* Time Sync Annex D enable */
+#define TS_LTYPE2_EN        (1<<3)  /* Time Sync LTYPE 2 enable */
+#define TS_LTYPE1_EN        (1<<2)  /* Time Sync LTYPE 1 enable */
+#define TS_TX_EN            (1<<1)  /* Time Sync Transmit Enable */
+#define TS_RX_EN            (1<<0)  /* Time Sync Receive Enable */
+
+#define CTRL_TS_BITS \
+       (TS_320 | TS_319 | TS_132 | TS_131 | TS_130 | TS_129 | TS_BIT8 | \
+        TS_ANNEX_D_EN | TS_LTYPE1_EN)
+
+#define CTRL_ALL_TS_MASK (CTRL_TS_BITS | TS_TX_EN | TS_RX_EN)
+#define CTRL_TX_TS_BITS  (CTRL_TS_BITS | TS_TX_EN)
+#define CTRL_RX_TS_BITS  (CTRL_TS_BITS | TS_RX_EN)
+
+/* Bit definitions for the CPSW2_TS_SEQ_MTYPE register */
+#define TS_SEQ_ID_OFFSET_SHIFT   (16)    /* Time Sync Sequence ID Offset */
+#define TS_SEQ_ID_OFFSET_MASK    (0x3f)
+#define TS_MSG_TYPE_EN_SHIFT     (0)     /* Time Sync Message Type Enable */
+#define TS_MSG_TYPE_EN_MASK      (0xffff)
+
+/* The PTP event messages - Sync, Delay_Req, Pdelay_Req, and Pdelay_Resp. */
+#define EVENT_MSG_BITS ((1<<0) | (1<<1) | (1<<2) | (1<<3))
+
+/* Bit definitions for the CPSW1_TS_CTL register */
+#define CPSW_V1_TS_RX_EN               BIT(0)
+#define CPSW_V1_TS_TX_EN               BIT(4)
+#define CPSW_V1_MSG_TYPE_OFS           16
+
+/* Bit definitions for the CPSW1_TS_SEQ_LTYPE register */
+#define CPSW_V1_SEQ_ID_OFS_SHIFT       16
 
 struct cpsw_host_regs {
        u32     max_blks;
@@ -185,7 +271,7 @@ struct cpsw_sliver_regs {
 };
 
 struct cpsw_slave {
-       struct cpsw_slave_regs __iomem  *regs;
+       void __iomem                    *regs;
        struct cpsw_sliver_regs __iomem *sliver;
        int                             slave_num;
        u32                             mac_control;
@@ -193,19 +279,30 @@ struct cpsw_slave {
        struct phy_device               *phy;
 };
 
+static inline u32 slave_read(struct cpsw_slave *slave, u32 offset)
+{
+       return __raw_readl(slave->regs + offset);
+}
+
+static inline void slave_write(struct cpsw_slave *slave, u32 val, u32 offset)
+{
+       __raw_writel(val, slave->regs + offset);
+}
+
 struct cpsw_priv {
        spinlock_t                      lock;
        struct platform_device          *pdev;
        struct net_device               *ndev;
        struct resource                 *cpsw_res;
-       struct resource                 *cpsw_ss_res;
+       struct resource                 *cpsw_wr_res;
        struct napi_struct              napi;
        struct device                   *dev;
        struct cpsw_platform_data       data;
-       struct cpsw_regs __iomem        *regs;
-       struct cpsw_ss_regs __iomem     *ss_regs;
+       struct cpsw_ss_regs __iomem     *regs;
+       struct cpsw_wr_regs __iomem     *wr_regs;
        struct cpsw_host_regs __iomem   *host_port_regs;
        u32                             msg_enable;
+       u32                             version;
        struct net_device_stats         stats;
        int                             rx_packet_max;
        int                             host_port;
@@ -218,6 +315,7 @@ struct cpsw_priv {
        /* snapshot of IRQ numbers */
        u32 irqs_table[4];
        u32 num_irqs;
+       struct cpts cpts;
 };
 
 #define napi_to_priv(napi)     container_of(napi, struct cpsw_priv, napi)
@@ -228,10 +326,34 @@ struct cpsw_priv {
                        (func)((priv)->slaves + idx, ##arg);    \
        } while (0)
 
+static void cpsw_ndo_set_rx_mode(struct net_device *ndev)
+{
+       struct cpsw_priv *priv = netdev_priv(ndev);
+
+       if (ndev->flags & IFF_PROMISC) {
+               /* Enable promiscuous mode */
+               dev_err(priv->dev, "Ignoring Promiscuous mode\n");
+               return;
+       }
+
+       /* Clear all mcast from ALE */
+       cpsw_ale_flush_multicast(priv->ale, ALE_ALL_PORTS << priv->host_port);
+
+       if (!netdev_mc_empty(ndev)) {
+               struct netdev_hw_addr *ha;
+
+               /* program multicast address list into ALE register */
+               netdev_for_each_mc_addr(ha, ndev) {
+                       cpsw_ale_add_mcast(priv->ale, (u8 *)ha->addr,
+                               ALE_ALL_PORTS << priv->host_port, 0, 0);
+               }
+       }
+}
+
 static void cpsw_intr_enable(struct cpsw_priv *priv)
 {
-       __raw_writel(0xFF, &priv->ss_regs->tx_en);
-       __raw_writel(0xFF, &priv->ss_regs->rx_en);
+       __raw_writel(0xFF, &priv->wr_regs->tx_en);
+       __raw_writel(0xFF, &priv->wr_regs->rx_en);
 
        cpdma_ctlr_int_ctrl(priv->dma, true);
        return;
@@ -239,8 +361,8 @@ static void cpsw_intr_enable(struct cpsw_priv *priv)
 
 static void cpsw_intr_disable(struct cpsw_priv *priv)
 {
-       __raw_writel(0, &priv->ss_regs->tx_en);
-       __raw_writel(0, &priv->ss_regs->rx_en);
+       __raw_writel(0, &priv->wr_regs->tx_en);
+       __raw_writel(0, &priv->wr_regs->rx_en);
 
        cpdma_ctlr_int_ctrl(priv->dma, false);
        return;
@@ -254,6 +376,7 @@ void cpsw_tx_handler(void *token, int len, int status)
 
        if (unlikely(netif_queue_stopped(ndev)))
                netif_start_queue(ndev);
+       cpts_tx_timestamp(&priv->cpts, skb);
        priv->stats.tx_packets++;
        priv->stats.tx_bytes += len;
        dev_kfree_skb_any(skb);
@@ -274,6 +397,7 @@ void cpsw_rx_handler(void *token, int len, int status)
        }
        if (likely(status >= 0)) {
                skb_put(skb, len);
+               cpts_rx_timestamp(&priv->cpts, skb);
                skb->protocol = eth_type_trans(skb, ndev);
                netif_receive_skb(skb);
                priv->stats.rx_bytes += len;
@@ -359,8 +483,8 @@ static inline void soft_reset(const char *module, void __iomem *reg)
 static void cpsw_set_slave_mac(struct cpsw_slave *slave,
                               struct cpsw_priv *priv)
 {
-       __raw_writel(mac_hi(priv->mac_addr), &slave->regs->sa_hi);
-       __raw_writel(mac_lo(priv->mac_addr), &slave->regs->sa_lo);
+       slave_write(slave, mac_hi(priv->mac_addr), SA_HI);
+       slave_write(slave, mac_lo(priv->mac_addr), SA_LO);
 }
 
 static void _cpsw_adjust_link(struct cpsw_slave *slave,
@@ -446,7 +570,15 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
 
        /* setup priority mapping */
        __raw_writel(RX_PRIORITY_MAPPING, &slave->sliver->rx_pri_map);
-       __raw_writel(TX_PRIORITY_MAPPING, &slave->regs->tx_pri_map);
+
+       switch (priv->version) {
+       case CPSW_VERSION_1:
+               slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP);
+               break;
+       case CPSW_VERSION_2:
+               slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP);
+               break;
+       }
 
        /* setup max packet size, and mac address */
        __raw_writel(priv->rx_packet_max, &slave->sliver->rx_maxlen);
@@ -505,7 +637,7 @@ static int cpsw_ndo_open(struct net_device *ndev)
 
        pm_runtime_get_sync(&priv->pdev->dev);
 
-       reg = __raw_readl(&priv->regs->id_ver);
+       reg = priv->version;
 
        dev_info(priv->dev, "initializing cpsw version %d.%d (%d)\n",
                 CPSW_MAJOR_VERSION(reg), CPSW_MINOR_VERSION(reg),
@@ -566,12 +698,12 @@ static int cpsw_ndo_stop(struct net_device *ndev)
        struct cpsw_priv *priv = netdev_priv(ndev);
 
        cpsw_info(priv, ifdown, "shutting down cpsw device\n");
-       cpsw_intr_disable(priv);
-       cpdma_ctlr_int_ctrl(priv->dma, false);
-       cpdma_ctlr_stop(priv->dma);
        netif_stop_queue(priv->ndev);
        napi_disable(&priv->napi);
        netif_carrier_off(priv->ndev);
+       cpsw_intr_disable(priv);
+       cpdma_ctlr_int_ctrl(priv->dma, false);
+       cpdma_ctlr_stop(priv->dma);
        cpsw_ale_stop(priv->ale);
        for_each_slave(priv, cpsw_slave_stop, priv);
        pm_runtime_put_sync(&priv->pdev->dev);
@@ -592,6 +724,11 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
+       if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP && priv->cpts.tx_enable)
+               skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+
+       skb_tx_timestamp(skb);
+
        ret = cpdma_chan_submit(priv->txch, skb, skb->data,
                                skb->len, GFP_KERNEL);
        if (unlikely(ret != 0)) {
@@ -629,6 +766,129 @@ static void cpsw_ndo_change_rx_flags(struct net_device *ndev, int flags)
                dev_err(&ndev->dev, "multicast traffic cannot be filtered!\n");
 }
 
+#ifdef CONFIG_TI_CPTS
+
+static void cpsw_hwtstamp_v1(struct cpsw_priv *priv)
+{
+       struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+       u32 ts_en, seq_id;
+
+       if (!priv->cpts.tx_enable && !priv->cpts.rx_enable) {
+               slave_write(slave, 0, CPSW1_TS_CTL);
+               return;
+       }
+
+       seq_id = (30 << CPSW_V1_SEQ_ID_OFS_SHIFT) | ETH_P_1588;
+       ts_en = EVENT_MSG_BITS << CPSW_V1_MSG_TYPE_OFS;
+
+       if (priv->cpts.tx_enable)
+               ts_en |= CPSW_V1_TS_TX_EN;
+
+       if (priv->cpts.rx_enable)
+               ts_en |= CPSW_V1_TS_RX_EN;
+
+       slave_write(slave, ts_en, CPSW1_TS_CTL);
+       slave_write(slave, seq_id, CPSW1_TS_SEQ_LTYPE);
+}
+
+static void cpsw_hwtstamp_v2(struct cpsw_priv *priv)
+{
+       struct cpsw_slave *slave = &priv->slaves[priv->data.cpts_active_slave];
+       u32 ctrl, mtype;
+
+       ctrl = slave_read(slave, CPSW2_CONTROL);
+       ctrl &= ~CTRL_ALL_TS_MASK;
+
+       if (priv->cpts.tx_enable)
+               ctrl |= CTRL_TX_TS_BITS;
+
+       if (priv->cpts.rx_enable)
+               ctrl |= CTRL_RX_TS_BITS;
+
+       mtype = (30 << TS_SEQ_ID_OFFSET_SHIFT) | EVENT_MSG_BITS;
+
+       slave_write(slave, mtype, CPSW2_TS_SEQ_MTYPE);
+       slave_write(slave, ctrl, CPSW2_CONTROL);
+       __raw_writel(ETH_P_1588, &priv->regs->ts_ltype);
+}
+
+static int cpsw_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
+{
+       struct cpsw_priv *priv = netdev_priv(dev);
+       struct cpts *cpts = &priv->cpts;
+       struct hwtstamp_config cfg;
+
+       if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
+               return -EFAULT;
+
+       /* reserved for future extensions */
+       if (cfg.flags)
+               return -EINVAL;
+
+       switch (cfg.tx_type) {
+       case HWTSTAMP_TX_OFF:
+               cpts->tx_enable = 0;
+               break;
+       case HWTSTAMP_TX_ON:
+               cpts->tx_enable = 1;
+               break;
+       default:
+               return -ERANGE;
+       }
+
+       switch (cfg.rx_filter) {
+       case HWTSTAMP_FILTER_NONE:
+               cpts->rx_enable = 0;
+               break;
+       case HWTSTAMP_FILTER_ALL:
+       case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
+       case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
+       case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
+               return -ERANGE;
+       case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+       case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+       case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+       case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+       case HWTSTAMP_FILTER_PTP_V2_EVENT:
+       case HWTSTAMP_FILTER_PTP_V2_SYNC:
+       case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+               cpts->rx_enable = 1;
+               cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
+               break;
+       default:
+               return -ERANGE;
+       }
+
+       switch (priv->version) {
+       case CPSW_VERSION_1:
+               cpsw_hwtstamp_v1(priv);
+               break;
+       case CPSW_VERSION_2:
+               cpsw_hwtstamp_v2(priv);
+               break;
+       default:
+               return -ENOTSUPP;
+       }
+
+       return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+}
+
+#endif /*CONFIG_TI_CPTS*/
+
+static int cpsw_ndo_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+       if (!netif_running(dev))
+               return -EINVAL;
+
+#ifdef CONFIG_TI_CPTS
+       if (cmd == SIOCSHWTSTAMP)
+               return cpsw_hwtstamp_ioctl(dev, req);
+#endif
+       return -ENOTSUPP;
+}
+
 static void cpsw_ndo_tx_timeout(struct net_device *ndev)
 {
        struct cpsw_priv *priv = netdev_priv(ndev);
@@ -669,10 +929,12 @@ static const struct net_device_ops cpsw_netdev_ops = {
        .ndo_stop               = cpsw_ndo_stop,
        .ndo_start_xmit         = cpsw_ndo_start_xmit,
        .ndo_change_rx_flags    = cpsw_ndo_change_rx_flags,
+       .ndo_do_ioctl           = cpsw_ndo_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_change_mtu         = eth_change_mtu,
        .ndo_tx_timeout         = cpsw_ndo_tx_timeout,
        .ndo_get_stats          = cpsw_ndo_get_stats,
+       .ndo_set_rx_mode        = cpsw_ndo_set_rx_mode,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = cpsw_ndo_poll_controller,
 #endif
@@ -699,22 +961,56 @@ static void cpsw_set_msglevel(struct net_device *ndev, u32 value)
        priv->msg_enable = value;
 }
 
+static int cpsw_get_ts_info(struct net_device *ndev,
+                           struct ethtool_ts_info *info)
+{
+#ifdef CONFIG_TI_CPTS
+       struct cpsw_priv *priv = netdev_priv(ndev);
+
+       info->so_timestamping =
+               SOF_TIMESTAMPING_TX_HARDWARE |
+               SOF_TIMESTAMPING_TX_SOFTWARE |
+               SOF_TIMESTAMPING_RX_HARDWARE |
+               SOF_TIMESTAMPING_RX_SOFTWARE |
+               SOF_TIMESTAMPING_SOFTWARE |
+               SOF_TIMESTAMPING_RAW_HARDWARE;
+       info->phc_index = priv->cpts.phc_index;
+       info->tx_types =
+               (1 << HWTSTAMP_TX_OFF) |
+               (1 << HWTSTAMP_TX_ON);
+       info->rx_filters =
+               (1 << HWTSTAMP_FILTER_NONE) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT);
+#else
+       info->so_timestamping =
+               SOF_TIMESTAMPING_TX_SOFTWARE |
+               SOF_TIMESTAMPING_RX_SOFTWARE |
+               SOF_TIMESTAMPING_SOFTWARE;
+       info->phc_index = -1;
+       info->tx_types = 0;
+       info->rx_filters = 0;
+#endif
+       return 0;
+}
+
 static const struct ethtool_ops cpsw_ethtool_ops = {
        .get_drvinfo    = cpsw_get_drvinfo,
        .get_msglevel   = cpsw_get_msglevel,
        .set_msglevel   = cpsw_set_msglevel,
        .get_link       = ethtool_op_get_link,
+       .get_ts_info    = cpsw_get_ts_info,
 };
 
-static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
+static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
+                           u32 slave_reg_ofs, u32 sliver_reg_ofs)
 {
        void __iomem            *regs = priv->regs;
        int                     slave_num = slave->slave_num;
        struct cpsw_slave_data  *data = priv->data.slave_data + slave_num;
 
        slave->data     = data;
-       slave->regs     = regs + data->slave_reg_ofs;
-       slave->sliver   = regs + data->sliver_reg_ofs;
+       slave->regs     = regs + slave_reg_ofs;
+       slave->sliver   = regs + sliver_reg_ofs;
 }
 
 static int cpsw_probe_dt(struct cpsw_platform_data *data,
@@ -734,49 +1030,40 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
        }
        data->slaves = prop;
 
-       data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
-                                  data->slaves, GFP_KERNEL);
-       if (!data->slave_data) {
-               pr_err("Could not allocate slave memory.\n");
-               return -EINVAL;
-       }
-
-       data->no_bd_ram = of_property_read_bool(node, "no_bd_ram");
-
-       if (of_property_read_u32(node, "cpdma_channels", &prop)) {
-               pr_err("Missing cpdma_channels property in the DT.\n");
+       if (of_property_read_u32(node, "cpts_active_slave", &prop)) {
+               pr_err("Missing cpts_active_slave property in the DT.\n");
                ret = -EINVAL;
                goto error_ret;
        }
-       data->channels = prop;
+       data->cpts_active_slave = prop;
 
-       if (of_property_read_u32(node, "host_port_no", &prop)) {
-               pr_err("Missing host_port_no property in the DT.\n");
+       if (of_property_read_u32(node, "cpts_clock_mult", &prop)) {
+               pr_err("Missing cpts_clock_mult property in the DT.\n");
                ret = -EINVAL;
                goto error_ret;
        }
-       data->host_port_num = prop;
+       data->cpts_clock_mult = prop;
 
-       if (of_property_read_u32(node, "cpdma_reg_ofs", &prop)) {
-               pr_err("Missing cpdma_reg_ofs property in the DT.\n");
+       if (of_property_read_u32(node, "cpts_clock_shift", &prop)) {
+               pr_err("Missing cpts_clock_shift property in the DT.\n");
                ret = -EINVAL;
                goto error_ret;
        }
-       data->cpdma_reg_ofs = prop;
+       data->cpts_clock_shift = prop;
 
-       if (of_property_read_u32(node, "cpdma_sram_ofs", &prop)) {
-               pr_err("Missing cpdma_sram_ofs property in the DT.\n");
-               ret = -EINVAL;
-               goto error_ret;
+       data->slave_data = kzalloc(sizeof(struct cpsw_slave_data) *
+                                  data->slaves, GFP_KERNEL);
+       if (!data->slave_data) {
+               pr_err("Could not allocate slave memory.\n");
+               return -EINVAL;
        }
-       data->cpdma_sram_ofs = prop;
 
-       if (of_property_read_u32(node, "ale_reg_ofs", &prop)) {
-               pr_err("Missing ale_reg_ofs property in the DT.\n");
+       if (of_property_read_u32(node, "cpdma_channels", &prop)) {
+               pr_err("Missing cpdma_channels property in the DT.\n");
                ret = -EINVAL;
                goto error_ret;
        }
-       data->ale_reg_ofs = prop;
+       data->channels = prop;
 
        if (of_property_read_u32(node, "ale_entries", &prop)) {
                pr_err("Missing ale_entries property in the DT.\n");
@@ -785,27 +1072,6 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
        }
        data->ale_entries = prop;
 
-       if (of_property_read_u32(node, "host_port_reg_ofs", &prop)) {
-               pr_err("Missing host_port_reg_ofs property in the DT.\n");
-               ret = -EINVAL;
-               goto error_ret;
-       }
-       data->host_port_reg_ofs = prop;
-
-       if (of_property_read_u32(node, "hw_stats_reg_ofs", &prop)) {
-               pr_err("Missing hw_stats_reg_ofs property in the DT.\n");
-               ret = -EINVAL;
-               goto error_ret;
-       }
-       data->hw_stats_reg_ofs = prop;
-
-       if (of_property_read_u32(node, "bd_ram_ofs", &prop)) {
-               pr_err("Missing bd_ram_ofs property in the DT.\n");
-               ret = -EINVAL;
-               goto error_ret;
-       }
-       data->bd_ram_ofs = prop;
-
        if (of_property_read_u32(node, "bd_ram_size", &prop)) {
                pr_err("Missing bd_ram_size property in the DT.\n");
                ret = -EINVAL;
@@ -827,33 +1093,34 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
        }
        data->mac_control = prop;
 
-       for_each_child_of_node(node, slave_node) {
+       /*
+        * Populate all the child nodes here...
+        */
+       ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+       /* We do not want to force this, as in some cases may not have child */
+       if (ret)
+               pr_warn("Doesn't have any child node\n");
+
+       for_each_node_by_name(slave_node, "slave") {
                struct cpsw_slave_data *slave_data = data->slave_data + i;
-               const char *phy_id = NULL;
                const void *mac_addr = NULL;
-
-               if (of_property_read_string(slave_node, "phy_id", &phy_id)) {
+               u32 phyid;
+               int lenp;
+               const __be32 *parp;
+               struct device_node *mdio_node;
+               struct platform_device *mdio;
+
+               parp = of_get_property(slave_node, "phy_id", &lenp);
+               if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) {
                        pr_err("Missing slave[%d] phy_id property\n", i);
                        ret = -EINVAL;
                        goto error_ret;
                }
-               slave_data->phy_id = phy_id;
-
-               if (of_property_read_u32(slave_node, "slave_reg_ofs", &prop)) {
-                       pr_err("Missing slave[%d] slave_reg_ofs property\n", i);
-                       ret = -EINVAL;
-                       goto error_ret;
-               }
-               slave_data->slave_reg_ofs = prop;
-
-               if (of_property_read_u32(slave_node, "sliver_reg_ofs",
-                                        &prop)) {
-                       pr_err("Missing slave[%d] sliver_reg_ofs property\n",
-                               i);
-                       ret = -EINVAL;
-                       goto error_ret;
-               }
-               slave_data->sliver_reg_ofs = prop;
+               mdio_node = of_find_node_by_phandle(be32_to_cpup(parp));
+               phyid = be32_to_cpup(parp+1);
+               mdio = of_find_device_by_node(mdio_node);
+               snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
+                        PHY_ID_FMT, mdio->name, phyid);
 
                mac_addr = of_get_mac_address(slave_node);
                if (mac_addr)
@@ -869,15 +1136,16 @@ error_ret:
        return ret;
 }
 
-static int __devinit cpsw_probe(struct platform_device *pdev)
+static int cpsw_probe(struct platform_device *pdev)
 {
        struct cpsw_platform_data       *data = pdev->dev.platform_data;
        struct net_device               *ndev;
        struct cpsw_priv                *priv;
        struct cpdma_params             dma_params;
        struct cpsw_ale_params          ale_params;
-       void __iomem                    *regs;
+       void __iomem                    *ss_regs, *wr_regs;
        struct resource                 *res;
+       u32 slave_offset, sliver_offset, slave_size;
        int ret = 0, i, k = 0;
 
        ndev = alloc_etherdev(sizeof(struct cpsw_priv));
@@ -895,6 +1163,11 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
        priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
        priv->rx_packet_max = max(rx_packet_max, 128);
 
+       /*
+        * This may be required here for child devices.
+        */
+       pm_runtime_enable(&pdev->dev);
+
        if (cpsw_probe_dt(&priv->data, pdev)) {
                pr_err("cpsw: platform data missing\n");
                ret = -ENODEV;
@@ -921,7 +1194,6 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
        for (i = 0; i < data->slaves; i++)
                priv->slaves[i].slave_num = i;
 
-       pm_runtime_enable(&pdev->dev);
        priv->clk = clk_get(&pdev->dev, "fck");
        if (IS_ERR(priv->clk)) {
                dev_err(&pdev->dev, "fck is not found\n");
@@ -935,63 +1207,86 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
                ret = -ENOENT;
                goto clean_clk_ret;
        }
-
        if (!request_mem_region(priv->cpsw_res->start,
                                resource_size(priv->cpsw_res), ndev->name)) {
                dev_err(priv->dev, "failed request i/o region\n");
                ret = -ENXIO;
                goto clean_clk_ret;
        }
-
-       regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
-       if (!regs) {
+       ss_regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
+       if (!ss_regs) {
                dev_err(priv->dev, "unable to map i/o region\n");
                goto clean_cpsw_iores_ret;
        }
-       priv->regs = regs;
-       priv->host_port = data->host_port_num;
-       priv->host_port_regs = regs + data->host_port_reg_ofs;
+       priv->regs = ss_regs;
+       priv->version = __raw_readl(&priv->regs->id_ver);
+       priv->host_port = HOST_PORT_NUM;
 
-       priv->cpsw_ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!priv->cpsw_ss_res) {
+       priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       if (!priv->cpsw_wr_res) {
                dev_err(priv->dev, "error getting i/o resource\n");
                ret = -ENOENT;
-               goto clean_clk_ret;
+               goto clean_iomap_ret;
        }
-
-       if (!request_mem_region(priv->cpsw_ss_res->start,
-                       resource_size(priv->cpsw_ss_res), ndev->name)) {
+       if (!request_mem_region(priv->cpsw_wr_res->start,
+                       resource_size(priv->cpsw_wr_res), ndev->name)) {
                dev_err(priv->dev, "failed request i/o region\n");
                ret = -ENXIO;
-               goto clean_clk_ret;
+               goto clean_iomap_ret;
        }
-
-       regs = ioremap(priv->cpsw_ss_res->start,
-                               resource_size(priv->cpsw_ss_res));
-       if (!regs) {
+       wr_regs = ioremap(priv->cpsw_wr_res->start,
+                               resource_size(priv->cpsw_wr_res));
+       if (!wr_regs) {
                dev_err(priv->dev, "unable to map i/o region\n");
-               goto clean_cpsw_ss_iores_ret;
+               goto clean_cpsw_wr_iores_ret;
        }
-       priv->ss_regs = regs;
-
-       for_each_slave(priv, cpsw_slave_init, priv);
+       priv->wr_regs = wr_regs;
 
        memset(&dma_params, 0, sizeof(dma_params));
+       memset(&ale_params, 0, sizeof(ale_params));
+
+       switch (priv->version) {
+       case CPSW_VERSION_1:
+               priv->host_port_regs = ss_regs + CPSW1_HOST_PORT_OFFSET;
+               priv->cpts.reg       = ss_regs + CPSW1_CPTS_OFFSET;
+               dma_params.dmaregs   = ss_regs + CPSW1_CPDMA_OFFSET;
+               dma_params.txhdp     = ss_regs + CPSW1_STATERAM_OFFSET;
+               ale_params.ale_regs  = ss_regs + CPSW1_ALE_OFFSET;
+               slave_offset         = CPSW1_SLAVE_OFFSET;
+               slave_size           = CPSW1_SLAVE_SIZE;
+               sliver_offset        = CPSW1_SLIVER_OFFSET;
+               dma_params.desc_mem_phys = 0;
+               break;
+       case CPSW_VERSION_2:
+               priv->host_port_regs = ss_regs + CPSW2_HOST_PORT_OFFSET;
+               priv->cpts.reg       = ss_regs + CPSW2_CPTS_OFFSET;
+               dma_params.dmaregs   = ss_regs + CPSW2_CPDMA_OFFSET;
+               dma_params.txhdp     = ss_regs + CPSW2_STATERAM_OFFSET;
+               ale_params.ale_regs  = ss_regs + CPSW2_ALE_OFFSET;
+               slave_offset         = CPSW2_SLAVE_OFFSET;
+               slave_size           = CPSW2_SLAVE_SIZE;
+               sliver_offset        = CPSW2_SLIVER_OFFSET;
+               dma_params.desc_mem_phys =
+                       (u32 __force) priv->cpsw_res->start + CPSW2_BD_OFFSET;
+               break;
+       default:
+               dev_err(priv->dev, "unknown version 0x%08x\n", priv->version);
+               ret = -ENODEV;
+               goto clean_cpsw_wr_iores_ret;
+       }
+       for (i = 0; i < priv->data.slaves; i++) {
+               struct cpsw_slave *slave = &priv->slaves[i];
+               cpsw_slave_init(slave, priv, slave_offset, sliver_offset);
+               slave_offset  += slave_size;
+               sliver_offset += SLIVER_SIZE;
+       }
+
        dma_params.dev          = &pdev->dev;
-       dma_params.dmaregs      = cpsw_dma_regs((u32)priv->regs,
-                                               data->cpdma_reg_ofs);
-       dma_params.rxthresh     = cpsw_dma_rxthresh((u32)priv->regs,
-                                                   data->cpdma_reg_ofs);
-       dma_params.rxfree       = cpsw_dma_rxfree((u32)priv->regs,
-                                                 data->cpdma_reg_ofs);
-       dma_params.txhdp        = cpsw_dma_txhdp((u32)priv->regs,
-                                                data->cpdma_sram_ofs);
-       dma_params.rxhdp        = cpsw_dma_rxhdp((u32)priv->regs,
-                                                data->cpdma_sram_ofs);
-       dma_params.txcp         = cpsw_dma_txcp((u32)priv->regs,
-                                               data->cpdma_sram_ofs);
-       dma_params.rxcp         = cpsw_dma_rxcp((u32)priv->regs,
-                                               data->cpdma_sram_ofs);
+       dma_params.rxthresh     = dma_params.dmaregs + CPDMA_RXTHRESH;
+       dma_params.rxfree       = dma_params.dmaregs + CPDMA_RXFREE;
+       dma_params.rxhdp        = dma_params.txhdp + CPDMA_RXHDP;
+       dma_params.txcp         = dma_params.txhdp + CPDMA_TXCP;
+       dma_params.rxcp         = dma_params.txhdp + CPDMA_RXCP;
 
        dma_params.num_chan             = data->channels;
        dma_params.has_soft_reset       = true;
@@ -999,16 +1294,13 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
        dma_params.desc_mem_size        = data->bd_ram_size;
        dma_params.desc_align           = 16;
        dma_params.has_ext_regs         = true;
-       dma_params.desc_mem_phys        = data->no_bd_ram ? 0 :
-                       (u32 __force)priv->cpsw_res->start + data->bd_ram_ofs;
-       dma_params.desc_hw_addr         = data->hw_ram_addr ?
-                       data->hw_ram_addr : dma_params.desc_mem_phys ;
+       dma_params.desc_hw_addr         = dma_params.desc_mem_phys;
 
        priv->dma = cpdma_ctlr_create(&dma_params);
        if (!priv->dma) {
                dev_err(priv->dev, "error initializing dma\n");
                ret = -ENOMEM;
-               goto clean_iomap_ret;
+               goto clean_wr_iomap_ret;
        }
 
        priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0),
@@ -1022,10 +1314,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
                goto clean_dma_ret;
        }
 
-       memset(&ale_params, 0, sizeof(ale_params));
        ale_params.dev                  = &ndev->dev;
-       ale_params.ale_regs             = (void *)((u32)priv->regs) +
-                                               ((u32)data->ale_reg_ofs);
        ale_params.ale_ageout           = ale_ageout;
        ale_params.ale_entries          = data->ale_entries;
        ale_params.ale_ports            = data->slaves;
@@ -1072,6 +1361,10 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
                goto clean_irq_ret;
        }
 
+       if (cpts_register(&pdev->dev, &priv->cpts,
+                         data->cpts_clock_mult, data->cpts_clock_shift))
+               dev_err(priv->dev, "error registering cpts device\n");
+
        cpsw_notice(priv, probe, "initialized device (regs %x, irq %d)\n",
                  priv->cpsw_res->start, ndev->irq);
 
@@ -1085,11 +1378,13 @@ clean_dma_ret:
        cpdma_chan_destroy(priv->txch);
        cpdma_chan_destroy(priv->rxch);
        cpdma_ctlr_destroy(priv->dma);
+clean_wr_iomap_ret:
+       iounmap(priv->wr_regs);
+clean_cpsw_wr_iores_ret:
+       release_mem_region(priv->cpsw_wr_res->start,
+                          resource_size(priv->cpsw_wr_res));
 clean_iomap_ret:
        iounmap(priv->regs);
-clean_cpsw_ss_iores_ret:
-       release_mem_region(priv->cpsw_ss_res->start,
-                          resource_size(priv->cpsw_ss_res));
 clean_cpsw_iores_ret:
        release_mem_region(priv->cpsw_res->start,
                           resource_size(priv->cpsw_res));
@@ -1103,7 +1398,7 @@ clean_ndev_ret:
        return ret;
 }
 
-static int __devexit cpsw_remove(struct platform_device *pdev)
+static int cpsw_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct cpsw_priv *priv = netdev_priv(ndev);
@@ -1111,6 +1406,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
        pr_info("removing device");
        platform_set_drvdata(pdev, NULL);
 
+       cpts_unregister(&priv->cpts);
        free_irq(ndev->irq, priv);
        cpsw_ale_destroy(priv->ale);
        cpdma_chan_destroy(priv->txch);
@@ -1119,8 +1415,9 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
        iounmap(priv->regs);
        release_mem_region(priv->cpsw_res->start,
                           resource_size(priv->cpsw_res));
-       release_mem_region(priv->cpsw_ss_res->start,
-                          resource_size(priv->cpsw_ss_res));
+       iounmap(priv->wr_regs);
+       release_mem_region(priv->cpsw_wr_res->start,
+                          resource_size(priv->cpsw_wr_res));
        pm_runtime_disable(&pdev->dev);
        clk_put(priv->clk);
        kfree(priv->slaves);
@@ -1170,7 +1467,7 @@ static struct platform_driver cpsw_driver = {
                .of_match_table = of_match_ptr(cpsw_of_mtable),
        },
        .probe = cpsw_probe,
-       .remove = __devexit_p(cpsw_remove),
+       .remove = cpsw_remove,
 };
 
 static int __init cpsw_init(void)
index ca0d48a7e508059fd35b6c7bff8cd24295caadbf..0e9ccc2cf91fefce7bda15f6c9ad4ee580e6aa5d 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/stat.h>
 #include <linux/sysfs.h>
+#include <linux/etherdevice.h>
 
 #include "cpsw_ale.h"
 
@@ -211,10 +212,34 @@ static void cpsw_ale_flush_mcast(struct cpsw_ale *ale, u32 *ale_entry,
        mask &= ~port_mask;
 
        /* free if only remaining port is host port */
-       if (mask == BIT(ale->params.ale_ports))
-               cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
-       else
+       if (mask)
                cpsw_ale_set_port_mask(ale_entry, mask);
+       else
+               cpsw_ale_set_entry_type(ale_entry, ALE_TYPE_FREE);
+}
+
+int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask)
+{
+       u32 ale_entry[ALE_ENTRY_WORDS];
+       int ret, idx;
+
+       for (idx = 0; idx < ale->params.ale_entries; idx++) {
+               cpsw_ale_read(ale, idx, ale_entry);
+               ret = cpsw_ale_get_entry_type(ale_entry);
+               if (ret != ALE_TYPE_ADDR && ret != ALE_TYPE_VLAN_ADDR)
+                       continue;
+
+               if (cpsw_ale_get_mcast(ale_entry)) {
+                       u8 addr[6];
+
+                       cpsw_ale_get_addr(ale_entry, addr);
+                       if (!is_broadcast_ether_addr(addr))
+                               cpsw_ale_flush_mcast(ale, ale_entry, port_mask);
+               }
+
+               cpsw_ale_write(ale, idx, ale_entry);
+       }
+       return 0;
 }
 
 static void cpsw_ale_flush_ucast(struct cpsw_ale *ale, u32 *ale_entry,
index a95b37beb02d56e809c15239247085304c6a2cba..2bd09cbce522dc222fb5a72f9691d368a3b57094 100644 (file)
@@ -80,6 +80,7 @@ void cpsw_ale_stop(struct cpsw_ale *ale);
 
 int cpsw_ale_set_ageout(struct cpsw_ale *ale, int ageout);
 int cpsw_ale_flush(struct cpsw_ale *ale, int port_mask);
+int cpsw_ale_flush_multicast(struct cpsw_ale *ale, int port_mask);
 int cpsw_ale_add_ucast(struct cpsw_ale *ale, u8 *addr, int port, int flags);
 int cpsw_ale_del_ucast(struct cpsw_ale *ale, u8 *addr, int port);
 int cpsw_ale_add_mcast(struct cpsw_ale *ale, u8 *addr, int port_mask,
diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c
new file mode 100644 (file)
index 0000000..3377667
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * TI Common Platform Time Sync
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#include <linux/err.h>
+#include <linux/if.h>
+#include <linux/hrtimer.h>
+#include <linux/module.h>
+#include <linux/net_tstamp.h>
+#include <linux/ptp_classify.h>
+#include <linux/time.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+
+#include <plat/clock.h>
+
+#include "cpts.h"
+
+#ifdef CONFIG_TI_CPTS
+
+static struct sock_filter ptp_filter[] = {
+       PTP_FILTER
+};
+
+#define cpts_read32(c, r)      __raw_readl(&c->reg->r)
+#define cpts_write32(c, v, r)  __raw_writel(v, &c->reg->r)
+
+static int event_expired(struct cpts_event *event)
+{
+       return time_after(jiffies, event->tmo);
+}
+
+static int event_type(struct cpts_event *event)
+{
+       return (event->high >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK;
+}
+
+static int cpts_fifo_pop(struct cpts *cpts, u32 *high, u32 *low)
+{
+       u32 r = cpts_read32(cpts, intstat_raw);
+
+       if (r & TS_PEND_RAW) {
+               *high = cpts_read32(cpts, event_high);
+               *low  = cpts_read32(cpts, event_low);
+               cpts_write32(cpts, EVENT_POP, event_pop);
+               return 0;
+       }
+       return -1;
+}
+
+/*
+ * Returns zero if matching event type was found.
+ */
+static int cpts_fifo_read(struct cpts *cpts, int match)
+{
+       int i, type = -1;
+       u32 hi, lo;
+       struct cpts_event *event;
+
+       for (i = 0; i < CPTS_FIFO_DEPTH; i++) {
+               if (cpts_fifo_pop(cpts, &hi, &lo))
+                       break;
+               if (list_empty(&cpts->pool)) {
+                       pr_err("cpts: event pool is empty\n");
+                       return -1;
+               }
+               event = list_first_entry(&cpts->pool, struct cpts_event, list);
+               event->tmo = jiffies + 2;
+               event->high = hi;
+               event->low = lo;
+               type = event_type(event);
+               switch (type) {
+               case CPTS_EV_PUSH:
+               case CPTS_EV_RX:
+               case CPTS_EV_TX:
+                       list_del_init(&event->list);
+                       list_add_tail(&event->list, &cpts->events);
+                       break;
+               case CPTS_EV_ROLL:
+               case CPTS_EV_HALF:
+               case CPTS_EV_HW:
+                       break;
+               default:
+                       pr_err("cpts: unkown event type\n");
+                       break;
+               }
+               if (type == match)
+                       break;
+       }
+       return type == match ? 0 : -1;
+}
+
+static cycle_t cpts_systim_read(const struct cyclecounter *cc)
+{
+       u64 val = 0;
+       struct cpts_event *event;
+       struct list_head *this, *next;
+       struct cpts *cpts = container_of(cc, struct cpts, cc);
+
+       cpts_write32(cpts, TS_PUSH, ts_push);
+       if (cpts_fifo_read(cpts, CPTS_EV_PUSH))
+               pr_err("cpts: unable to obtain a time stamp\n");
+
+       list_for_each_safe(this, next, &cpts->events) {
+               event = list_entry(this, struct cpts_event, list);
+               if (event_type(event) == CPTS_EV_PUSH) {
+                       list_del_init(&event->list);
+                       list_add(&event->list, &cpts->pool);
+                       val = event->low;
+                       break;
+               }
+       }
+
+       return val;
+}
+
+/* PTP clock operations */
+
+static int cpts_ptp_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
+{
+       u64 adj;
+       u32 diff, mult;
+       int neg_adj = 0;
+       unsigned long flags;
+       struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+       if (ppb < 0) {
+               neg_adj = 1;
+               ppb = -ppb;
+       }
+       mult = cpts->cc_mult;
+       adj = mult;
+       adj *= ppb;
+       diff = div_u64(adj, 1000000000ULL);
+
+       spin_lock_irqsave(&cpts->lock, flags);
+
+       timecounter_read(&cpts->tc);
+
+       cpts->cc.mult = neg_adj ? mult - diff : mult + diff;
+
+       spin_unlock_irqrestore(&cpts->lock, flags);
+
+       return 0;
+}
+
+static int cpts_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
+{
+       s64 now;
+       unsigned long flags;
+       struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+       spin_lock_irqsave(&cpts->lock, flags);
+       now = timecounter_read(&cpts->tc);
+       now += delta;
+       timecounter_init(&cpts->tc, &cpts->cc, now);
+       spin_unlock_irqrestore(&cpts->lock, flags);
+
+       return 0;
+}
+
+static int cpts_ptp_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
+{
+       u64 ns;
+       u32 remainder;
+       unsigned long flags;
+       struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+       spin_lock_irqsave(&cpts->lock, flags);
+       ns = timecounter_read(&cpts->tc);
+       spin_unlock_irqrestore(&cpts->lock, flags);
+
+       ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
+       ts->tv_nsec = remainder;
+
+       return 0;
+}
+
+static int cpts_ptp_settime(struct ptp_clock_info *ptp,
+                           const struct timespec *ts)
+{
+       u64 ns;
+       unsigned long flags;
+       struct cpts *cpts = container_of(ptp, struct cpts, info);
+
+       ns = ts->tv_sec * 1000000000ULL;
+       ns += ts->tv_nsec;
+
+       spin_lock_irqsave(&cpts->lock, flags);
+       timecounter_init(&cpts->tc, &cpts->cc, ns);
+       spin_unlock_irqrestore(&cpts->lock, flags);
+
+       return 0;
+}
+
+static int cpts_ptp_enable(struct ptp_clock_info *ptp,
+                          struct ptp_clock_request *rq, int on)
+{
+       return -EOPNOTSUPP;
+}
+
+static struct ptp_clock_info cpts_info = {
+       .owner          = THIS_MODULE,
+       .name           = "CTPS timer",
+       .max_adj        = 1000000,
+       .n_ext_ts       = 0,
+       .pps            = 0,
+       .adjfreq        = cpts_ptp_adjfreq,
+       .adjtime        = cpts_ptp_adjtime,
+       .gettime        = cpts_ptp_gettime,
+       .settime        = cpts_ptp_settime,
+       .enable         = cpts_ptp_enable,
+};
+
+static void cpts_overflow_check(struct work_struct *work)
+{
+       struct timespec ts;
+       struct cpts *cpts = container_of(work, struct cpts, overflow_work.work);
+
+       cpts_write32(cpts, CPTS_EN, control);
+       cpts_write32(cpts, TS_PEND_EN, int_enable);
+       cpts_ptp_gettime(&cpts->info, &ts);
+       pr_debug("cpts overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec);
+       schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+}
+
+#define CPTS_REF_CLOCK_NAME "cpsw_cpts_rft_clk"
+
+static void cpts_clk_init(struct cpts *cpts)
+{
+       cpts->refclk = clk_get(NULL, CPTS_REF_CLOCK_NAME);
+       if (IS_ERR(cpts->refclk)) {
+               pr_err("Failed to clk_get %s\n", CPTS_REF_CLOCK_NAME);
+               cpts->refclk = NULL;
+               return;
+       }
+       clk_enable(cpts->refclk);
+       cpts->freq = cpts->refclk->recalc(cpts->refclk);
+}
+
+static void cpts_clk_release(struct cpts *cpts)
+{
+       clk_disable(cpts->refclk);
+       clk_put(cpts->refclk);
+}
+
+static int cpts_match(struct sk_buff *skb, unsigned int ptp_class,
+                     u16 ts_seqid, u8 ts_msgtype)
+{
+       u16 *seqid;
+       unsigned int offset;
+       u8 *msgtype, *data = skb->data;
+
+       switch (ptp_class) {
+       case PTP_CLASS_V1_IPV4:
+       case PTP_CLASS_V2_IPV4:
+               offset = ETH_HLEN + IPV4_HLEN(data) + UDP_HLEN;
+               break;
+       case PTP_CLASS_V1_IPV6:
+       case PTP_CLASS_V2_IPV6:
+               offset = OFF_PTP6;
+               break;
+       case PTP_CLASS_V2_L2:
+               offset = ETH_HLEN;
+               break;
+       case PTP_CLASS_V2_VLAN:
+               offset = ETH_HLEN + VLAN_HLEN;
+               break;
+       default:
+               return 0;
+       }
+
+       if (skb->len + ETH_HLEN < offset + OFF_PTP_SEQUENCE_ID + sizeof(*seqid))
+               return 0;
+
+       if (unlikely(ptp_class & PTP_CLASS_V1))
+               msgtype = data + offset + OFF_PTP_CONTROL;
+       else
+               msgtype = data + offset;
+
+       seqid = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID);
+
+       return (ts_msgtype == (*msgtype & 0xf) && ts_seqid == ntohs(*seqid));
+}
+
+static u64 cpts_find_ts(struct cpts *cpts, struct sk_buff *skb, int ev_type)
+{
+       u64 ns = 0;
+       struct cpts_event *event;
+       struct list_head *this, *next;
+       unsigned int class = sk_run_filter(skb, ptp_filter);
+       unsigned long flags;
+       u16 seqid;
+       u8 mtype;
+
+       if (class == PTP_CLASS_NONE)
+               return 0;
+
+       spin_lock_irqsave(&cpts->lock, flags);
+       cpts_fifo_read(cpts, CPTS_EV_PUSH);
+       list_for_each_safe(this, next, &cpts->events) {
+               event = list_entry(this, struct cpts_event, list);
+               if (event_expired(event)) {
+                       list_del_init(&event->list);
+                       list_add(&event->list, &cpts->pool);
+                       continue;
+               }
+               mtype = (event->high >> MESSAGE_TYPE_SHIFT) & MESSAGE_TYPE_MASK;
+               seqid = (event->high >> SEQUENCE_ID_SHIFT) & SEQUENCE_ID_MASK;
+               if (ev_type == event_type(event) &&
+                   cpts_match(skb, class, seqid, mtype)) {
+                       ns = timecounter_cyc2time(&cpts->tc, event->low);
+                       list_del_init(&event->list);
+                       list_add(&event->list, &cpts->pool);
+                       break;
+               }
+       }
+       spin_unlock_irqrestore(&cpts->lock, flags);
+
+       return ns;
+}
+
+void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+       u64 ns;
+       struct skb_shared_hwtstamps *ssh;
+
+       if (!cpts->rx_enable)
+               return;
+       ns = cpts_find_ts(cpts, skb, CPTS_EV_RX);
+       if (!ns)
+               return;
+       ssh = skb_hwtstamps(skb);
+       memset(ssh, 0, sizeof(*ssh));
+       ssh->hwtstamp = ns_to_ktime(ns);
+}
+
+void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+       u64 ns;
+       struct skb_shared_hwtstamps ssh;
+
+       if (!(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))
+               return;
+       ns = cpts_find_ts(cpts, skb, CPTS_EV_TX);
+       if (!ns)
+               return;
+       memset(&ssh, 0, sizeof(ssh));
+       ssh.hwtstamp = ns_to_ktime(ns);
+       skb_tstamp_tx(skb, &ssh);
+}
+
+#endif /*CONFIG_TI_CPTS*/
+
+int cpts_register(struct device *dev, struct cpts *cpts,
+                 u32 mult, u32 shift)
+{
+#ifdef CONFIG_TI_CPTS
+       int err, i;
+       unsigned long flags;
+
+       if (ptp_filter_init(ptp_filter, ARRAY_SIZE(ptp_filter))) {
+               pr_err("cpts: bad ptp filter\n");
+               return -EINVAL;
+       }
+       cpts->info = cpts_info;
+       cpts->clock = ptp_clock_register(&cpts->info, dev);
+       if (IS_ERR(cpts->clock)) {
+               err = PTR_ERR(cpts->clock);
+               cpts->clock = NULL;
+               return err;
+       }
+       spin_lock_init(&cpts->lock);
+
+       cpts->cc.read = cpts_systim_read;
+       cpts->cc.mask = CLOCKSOURCE_MASK(32);
+       cpts->cc_mult = mult;
+       cpts->cc.mult = mult;
+       cpts->cc.shift = shift;
+
+       INIT_LIST_HEAD(&cpts->events);
+       INIT_LIST_HEAD(&cpts->pool);
+       for (i = 0; i < CPTS_MAX_EVENTS; i++)
+               list_add(&cpts->pool_data[i].list, &cpts->pool);
+
+       cpts_clk_init(cpts);
+       cpts_write32(cpts, CPTS_EN, control);
+       cpts_write32(cpts, TS_PEND_EN, int_enable);
+
+       spin_lock_irqsave(&cpts->lock, flags);
+       timecounter_init(&cpts->tc, &cpts->cc, ktime_to_ns(ktime_get_real()));
+       spin_unlock_irqrestore(&cpts->lock, flags);
+
+       INIT_DELAYED_WORK(&cpts->overflow_work, cpts_overflow_check);
+       schedule_delayed_work(&cpts->overflow_work, CPTS_OVERFLOW_PERIOD);
+
+       cpts->phc_index = ptp_clock_index(cpts->clock);
+#endif
+       return 0;
+}
+
+void cpts_unregister(struct cpts *cpts)
+{
+#ifdef CONFIG_TI_CPTS
+       if (cpts->clock) {
+               ptp_clock_unregister(cpts->clock);
+               cancel_delayed_work_sync(&cpts->overflow_work);
+       }
+       if (cpts->refclk)
+               cpts_clk_release(cpts);
+#endif
+}
diff --git a/drivers/net/ethernet/ti/cpts.h b/drivers/net/ethernet/ti/cpts.h
new file mode 100644 (file)
index 0000000..e1bba3a
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * TI Common Platform Time Sync
+ *
+ * Copyright (C) 2012 Richard Cochran <richardcochran@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+#ifndef _TI_CPTS_H_
+#define _TI_CPTS_H_
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clocksource.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/ptp_clock_kernel.h>
+#include <linux/skbuff.h>
+
+struct cpsw_cpts {
+       u32 idver;                /* Identification and version */
+       u32 control;              /* Time sync control */
+       u32 res1;
+       u32 ts_push;              /* Time stamp event push */
+       u32 ts_load_val;          /* Time stamp load value */
+       u32 ts_load_en;           /* Time stamp load enable */
+       u32 res2[2];
+       u32 intstat_raw;          /* Time sync interrupt status raw */
+       u32 intstat_masked;       /* Time sync interrupt status masked */
+       u32 int_enable;           /* Time sync interrupt enable */
+       u32 res3;
+       u32 event_pop;            /* Event interrupt pop */
+       u32 event_low;            /* 32 Bit Event Time Stamp */
+       u32 event_high;           /* Event Type Fields */
+};
+
+/* Bit definitions for the IDVER register */
+#define TX_IDENT_SHIFT       (16)    /* TX Identification Value */
+#define TX_IDENT_MASK        (0xffff)
+#define RTL_VER_SHIFT        (11)    /* RTL Version Value */
+#define RTL_VER_MASK         (0x1f)
+#define MAJOR_VER_SHIFT      (8)     /* Major Version Value */
+#define MAJOR_VER_MASK       (0x7)
+#define MINOR_VER_SHIFT      (0)     /* Minor Version Value */
+#define MINOR_VER_MASK       (0xff)
+
+/* Bit definitions for the CONTROL register */
+#define HW4_TS_PUSH_EN       (1<<11) /* Hardware push 4 enable */
+#define HW3_TS_PUSH_EN       (1<<10) /* Hardware push 3 enable */
+#define HW2_TS_PUSH_EN       (1<<9)  /* Hardware push 2 enable */
+#define HW1_TS_PUSH_EN       (1<<8)  /* Hardware push 1 enable */
+#define INT_TEST             (1<<1)  /* Interrupt Test */
+#define CPTS_EN              (1<<0)  /* Time Sync Enable */
+
+/*
+ * Definitions for the single bit resisters:
+ * TS_PUSH TS_LOAD_EN  INTSTAT_RAW INTSTAT_MASKED INT_ENABLE EVENT_POP
+ */
+#define TS_PUSH             (1<<0)  /* Time stamp event push */
+#define TS_LOAD_EN          (1<<0)  /* Time Stamp Load */
+#define TS_PEND_RAW         (1<<0)  /* int read (before enable) */
+#define TS_PEND             (1<<0)  /* masked interrupt read (after enable) */
+#define TS_PEND_EN          (1<<0)  /* masked interrupt enable */
+#define EVENT_POP           (1<<0)  /* writing discards one event */
+
+/* Bit definitions for the EVENT_HIGH register */
+#define PORT_NUMBER_SHIFT    (24)    /* Indicates Ethernet port or HW pin */
+#define PORT_NUMBER_MASK     (0x1f)
+#define EVENT_TYPE_SHIFT     (20)    /* Time sync event type */
+#define EVENT_TYPE_MASK      (0xf)
+#define MESSAGE_TYPE_SHIFT   (16)    /* PTP message type */
+#define MESSAGE_TYPE_MASK    (0xf)
+#define SEQUENCE_ID_SHIFT    (0)     /* PTP message sequence ID */
+#define SEQUENCE_ID_MASK     (0xffff)
+
+enum {
+       CPTS_EV_PUSH, /* Time Stamp Push Event */
+       CPTS_EV_ROLL, /* Time Stamp Rollover Event */
+       CPTS_EV_HALF, /* Time Stamp Half Rollover Event */
+       CPTS_EV_HW,   /* Hardware Time Stamp Push Event */
+       CPTS_EV_RX,   /* Ethernet Receive Event */
+       CPTS_EV_TX,   /* Ethernet Transmit Event */
+};
+
+/* This covers any input clock up to about 500 MHz. */
+#define CPTS_OVERFLOW_PERIOD (HZ * 8)
+
+#define CPTS_FIFO_DEPTH 16
+#define CPTS_MAX_EVENTS 32
+
+struct cpts_event {
+       struct list_head list;
+       unsigned long tmo;
+       u32 high;
+       u32 low;
+};
+
+struct cpts {
+       struct cpsw_cpts __iomem *reg;
+       int tx_enable;
+       int rx_enable;
+#ifdef CONFIG_TI_CPTS
+       struct ptp_clock_info info;
+       struct ptp_clock *clock;
+       spinlock_t lock; /* protects time registers */
+       u32 cc_mult; /* for the nominal frequency */
+       struct cyclecounter cc;
+       struct timecounter tc;
+       struct delayed_work overflow_work;
+       int phc_index;
+       struct clk *refclk;
+       unsigned long freq;
+       struct list_head events;
+       struct list_head pool;
+       struct cpts_event pool_data[CPTS_MAX_EVENTS];
+#endif
+};
+
+#ifdef CONFIG_TI_CPTS
+extern void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+extern void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb);
+#else
+static inline void cpts_rx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+}
+static inline void cpts_tx_timestamp(struct cpts *cpts, struct sk_buff *skb)
+{
+}
+#endif
+
+extern int cpts_register(struct device *dev, struct cpts *cpts,
+                        u32 mult, u32 shift);
+extern void cpts_unregister(struct cpts *cpts);
+
+#endif
index fce89a0ab06ed14d7168c1fb135574908d5461b0..2a3e2c56bc60ef8a8d2a959086c13d75b8494f96 100644 (file)
@@ -1850,7 +1850,7 @@ static struct emac_platform_data
  * resource information from platform init and register a network device
  * and allocate resources necessary for driver to perform
  */
-static int __devinit davinci_emac_probe(struct platform_device *pdev)
+static int davinci_emac_probe(struct platform_device *pdev)
 {
        int rc = 0;
        struct resource *res;
@@ -2039,7 +2039,7 @@ no_ndev:
  * Called when removing the device driver. We disable clock usage and release
  * the resources taken up by the driver and unregister network device
  */
-static int __devexit davinci_emac_remove(struct platform_device *pdev)
+static int davinci_emac_remove(struct platform_device *pdev)
 {
        struct resource *res;
        struct net_device *ndev = platform_get_drvdata(pdev);
@@ -2107,7 +2107,7 @@ static struct platform_driver davinci_emac_driver = {
                .of_match_table = of_match_ptr(davinci_emac_of_match),
        },
        .probe = davinci_emac_probe,
-       .remove = __devexit_p(davinci_emac_remove),
+       .remove = davinci_emac_remove,
 };
 
 /**
index 51a96dbee9accbae9dbe32e8eb3d81a367819307..cca25509b0392113c7c6f359836ba837607dbd96 100644 (file)
@@ -310,7 +310,7 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data,
 }
 
 
-static int __devinit davinci_mdio_probe(struct platform_device *pdev)
+static int davinci_mdio_probe(struct platform_device *pdev)
 {
        struct mdio_platform_data *pdata = pdev->dev.platform_data;
        struct device *dev = &pdev->dev;
@@ -416,7 +416,7 @@ bail_out:
        return ret;
 }
 
-static int __devexit davinci_mdio_remove(struct platform_device *pdev)
+static int davinci_mdio_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct davinci_mdio_data *data = dev_get_drvdata(dev);
@@ -465,7 +465,7 @@ static int davinci_mdio_resume(struct device *dev)
        u32 ctrl;
 
        spin_lock(&data->lock);
-       pm_runtime_put_sync(data->dev);
+       pm_runtime_get_sync(data->dev);
 
        /* restart the scan state machine */
        ctrl = __raw_readl(&data->regs->control);
@@ -496,7 +496,7 @@ static struct platform_driver davinci_mdio_driver = {
                .of_match_table = of_match_ptr(davinci_mdio_of_mtable),
        },
        .probe = davinci_mdio_probe,
-       .remove = __devexit_p(davinci_mdio_remove),
+       .remove = davinci_mdio_remove,
 };
 
 static int __init davinci_mdio_init(void)
index 3e6abf0f27714e4163bcdd6f959f057dbc5d3388..22725386c5de78fd94afb6715f30ed0bf24821b0 100644 (file)
@@ -300,7 +300,7 @@ these functions are more or less common to all linux network drivers.
  **************************************************************/
 
 
-static void __devexit tlan_remove_one(struct pci_dev *pdev)
+static void tlan_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tlan_priv        *priv = netdev_priv(dev);
@@ -392,7 +392,7 @@ static struct pci_driver tlan_driver = {
        .name           = "tlan",
        .id_table       = tlan_pci_tbl,
        .probe          = tlan_init_one,
-       .remove         = __devexit_p(tlan_remove_one),
+       .remove         = tlan_remove_one,
        .suspend        = tlan_suspend,
        .resume         = tlan_resume,
 };
@@ -434,7 +434,7 @@ err_out_pci_free:
 }
 
 
-static int __devinit tlan_init_one(struct pci_dev *pdev,
+static int tlan_init_one(struct pci_dev *pdev,
                                   const struct pci_device_id *ent)
 {
        return tlan_probe1(pdev, -1, -1, 0, ent);
@@ -460,9 +460,8 @@ static int __devinit tlan_init_one(struct pci_dev *pdev,
 *
 **************************************************************/
 
-static int __devinit tlan_probe1(struct pci_dev *pdev,
-                                long ioaddr, int irq, int rev,
-                                const struct pci_device_id *ent)
+static int tlan_probe1(struct pci_dev *pdev, long ioaddr, int irq, int rev,
+                      const struct pci_device_id *ent)
 {
 
        struct net_device  *dev;
index 4e2a1628484dfbc3a6fff901d976cf751bf8c151..66e025ad5df1a6e998ce0115f7057f89067b7bd3 100644 (file)
@@ -917,7 +917,7 @@ static int tile_net_setup_interrupts(struct net_device *dev)
        ingress_irq = rc;
        tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU);
        rc = request_irq(ingress_irq, tile_net_handle_ingress_irq,
-                        0, NULL, NULL);
+                        0, "tile_net", NULL);
        if (rc != 0) {
                netdev_err(dev, "request_irq failed: %d\n", rc);
                destroy_irq(ingress_irq);
@@ -1334,11 +1334,11 @@ static int tso_count_edescs(struct sk_buff *skb)
 {
        struct skb_shared_info *sh = skb_shinfo(skb);
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned int p_len = sh->gso_size;
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
        long n;            /* size of the current piece of payload */
        int num_edescs = 0;
        int segment;
@@ -1353,7 +1353,7 @@ static int tso_count_edescs(struct sk_buff *skb)
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_used = 0;
                        }
 
@@ -1384,13 +1384,13 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
        struct iphdr *ih;
        struct tcphdr *th;
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned char *data = skb->data;
        unsigned int ih_off, th_off, p_len;
        unsigned int isum_seed, tsum_seed, id, seq;
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
        long n;            /* size of the current piece of payload */
        int segment;
 
@@ -1405,7 +1405,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
        isum_seed = ((0xFFFF - ih->check) +
                     (0xFFFF - ih->tot_len) +
                     (0xFFFF - ih->id));
-       tsum_seed = th->check + (0xFFFF ^ htons(sh_len + data_len));
+       tsum_seed = th->check + (0xFFFF ^ htons(skb->len));
        id = ntohs(ih->id);
        seq = ntohl(th->seq);
 
@@ -1444,7 +1444,7 @@ static void tso_headers_prepare(struct sk_buff *skb, unsigned char *headers,
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_used = 0;
                        }
 
@@ -1478,14 +1478,14 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
        struct tile_net_priv *priv = netdev_priv(dev);
        struct skb_shared_info *sh = skb_shinfo(skb);
        unsigned int sh_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
-       unsigned int data_len = skb->data_len + skb->hdr_len - sh_len;
+       unsigned int data_len = skb->len - sh_len;
        unsigned int p_len = sh->gso_size;
        gxio_mpipe_edesc_t edesc_head = { { 0 } };
        gxio_mpipe_edesc_t edesc_body = { { 0 } };
        long f_id = -1;    /* id of the current fragment */
-       long f_size = skb->hdr_len;  /* size of the current fragment */
-       long f_used = sh_len;  /* bytes used from the current fragment */
-       void *f_data = skb->data;
+       long f_size = skb_headlen(skb) - sh_len;  /* current fragment size */
+       long f_used = 0;  /* bytes used from the current fragment */
+       void *f_data = skb->data + sh_len;
        long n;            /* size of the current piece of payload */
        unsigned long tx_packets = 0, tx_bytes = 0;
        unsigned int csum_start;
@@ -1516,15 +1516,18 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
 
                /* Egress the payload. */
                while (p_used < p_len) {
+                       void *va;
 
                        /* Advance as needed. */
                        while (f_used >= f_size) {
                                f_id++;
-                               f_size = sh->frags[f_id].size;
-                               f_used = 0;
+                               f_size = skb_frag_size(&sh->frags[f_id]);
                                f_data = tile_net_frag_buf(&sh->frags[f_id]);
+                               f_used = 0;
                        }
 
+                       va = f_data + f_used;
+
                        /* Use bytes from the current fragment. */
                        n = p_len - p_used;
                        if (n > f_size - f_used)
@@ -1533,7 +1536,7 @@ static void tso_egress(struct net_device *dev, gxio_mpipe_equeue_t *equeue,
                        p_used += n;
 
                        /* Egress a piece of the payload. */
-                       edesc_body.va = va_to_tile_io_addr(f_data) + f_used;
+                       edesc_body.va = va_to_tile_io_addr(va);
                        edesc_body.xfer_size = n;
                        edesc_body.bound = !(p_used < p_len);
                        gxio_mpipe_equeue_put_at(equeue, edesc_body, slot);
index 5ee82a77723b2537e38094e90e76b6c595158f70..e321d0b6fc882a4969a1a45ef2ce4b7a5de29864 100644 (file)
@@ -234,10 +234,9 @@ static void gelic_card_free_chain(struct gelic_card *card,
  *
  * returns 0 on success, <0 on failure
  */
-static int __devinit gelic_card_init_chain(struct gelic_card *card,
-                                          struct gelic_descr_chain *chain,
-                                          struct gelic_descr *start_descr,
-                                          int no)
+static int gelic_card_init_chain(struct gelic_card *card,
+                                struct gelic_descr_chain *chain,
+                                struct gelic_descr *start_descr, int no)
 {
        int i;
        struct gelic_descr *descr;
@@ -428,7 +427,7 @@ rewind:
  *
  * returns 0 on success, < 0 on failure
  */
-static int __devinit gelic_card_alloc_rx_skbs(struct gelic_card *card)
+static int gelic_card_alloc_rx_skbs(struct gelic_card *card)
 {
        struct gelic_descr_chain *chain;
        int ret;
@@ -1468,8 +1467,8 @@ static const struct net_device_ops gelic_netdevice_ops = {
  *
  * fills out function pointers in the net_device structure
  */
-static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev,
-                                                  struct napi_struct *napi)
+static void gelic_ether_setup_netdev_ops(struct net_device *netdev,
+                                        struct napi_struct *napi)
 {
        netdev->watchdog_timeo = GELIC_NET_WATCHDOG_TIMEOUT;
        /* NAPI */
@@ -1489,8 +1488,7 @@ static void __devinit gelic_ether_setup_netdev_ops(struct net_device *netdev,
  * gelic_ether_setup_netdev initializes the net_device structure
  * and register it.
  **/
-int __devinit gelic_net_setup_netdev(struct net_device *netdev,
-                                    struct gelic_card *card)
+int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
 {
        int status;
        u64 v1, v2;
@@ -1542,7 +1540,7 @@ int __devinit gelic_net_setup_netdev(struct net_device *netdev,
  * the card and net_device structures are linked to each other
  */
 #define GELIC_ALIGN (32)
-static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **netdev)
+static struct gelic_card *gelic_alloc_card_net(struct net_device **netdev)
 {
        struct gelic_card *card;
        struct gelic_port *port;
@@ -1593,7 +1591,7 @@ static struct gelic_card * __devinit gelic_alloc_card_net(struct net_device **ne
        return card;
 }
 
-static void __devinit gelic_card_get_vlan_info(struct gelic_card *card)
+static void gelic_card_get_vlan_info(struct gelic_card *card)
 {
        u64 v1, v2;
        int status;
@@ -1667,7 +1665,7 @@ static void __devinit gelic_card_get_vlan_info(struct gelic_card *card)
 /**
  * ps3_gelic_driver_probe - add a device to the control of this driver
  */
-static int __devinit ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
+static int ps3_gelic_driver_probe(struct ps3_system_bus_device *dev)
 {
        struct gelic_card *card;
        struct net_device *netdev;
index 72b775fd49c8d887da18d4d380bc333a76247128..d568af1eb4f4b4a49cbe032a39f6b7cf8b8ee3da 100644 (file)
@@ -2305,7 +2305,7 @@ static const struct iw_handler_def gelic_wl_wext_handler_def = {
        .get_wireless_stats     = gelic_wl_get_wireless_stats,
 };
 
-static struct net_device * __devinit gelic_wl_alloc(struct gelic_card *card)
+static struct net_device *gelic_wl_alloc(struct gelic_card *card)
 {
        struct net_device *netdev;
        struct gelic_port *port;
@@ -2582,7 +2582,7 @@ static const struct ethtool_ops gelic_wl_ethtool_ops = {
        .get_link       = gelic_wl_get_link,
 };
 
-static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev)
+static void gelic_wl_setup_netdev_ops(struct net_device *netdev)
 {
        struct gelic_wl_info *wl;
        wl = port_wl(netdev_priv(netdev));
@@ -2598,7 +2598,7 @@ static void __devinit gelic_wl_setup_netdev_ops(struct net_device *netdev)
 /*
  * driver probe/remove
  */
-int __devinit gelic_wl_driver_probe(struct gelic_card *card)
+int gelic_wl_driver_probe(struct gelic_card *card)
 {
        int ret;
        struct net_device *netdev;
index c1ebfe9efcb383080cb868996e4dc6fcb39e25bb..f1b91fd7e41c9b088de874e98dc3101c6942af61 100644 (file)
@@ -2492,7 +2492,7 @@ out_disable_dev:
  * spider_net_probe initializes pdev and registers a net_device
  * structure for it. After that, the device can be ifconfig'ed up
  **/
-static int __devinit
+static int
 spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        int err = -EIO;
@@ -2531,7 +2531,7 @@ out:
  * spider_net_remove is called to remove the device and unregisters the
  * net_device
  **/
-static void __devexit
+static void
 spider_net_remove(struct pci_dev *pdev)
 {
        struct net_device *netdev;
@@ -2559,7 +2559,7 @@ static struct pci_driver spider_net_driver = {
        .name           = spider_net_driver_name,
        .id_table       = spider_net_pci_tbl,
        .probe          = spider_net_probe,
-       .remove         = __devexit_p(spider_net_remove)
+       .remove         = spider_net_remove
 };
 
 /**
index 651a70c55e6e69aa40aa62fa77ee7b955dd0dba0..9819349eaa1e88a1a3cfe2ffd3958b9665ee5b20 100644 (file)
@@ -60,7 +60,7 @@ enum tc35815_chiptype {
 /* indexed by tc35815_chiptype, above */
 static const struct {
        const char *name;
-} chip_info[] __devinitdata = {
+} chip_info[] = {
        { "TOSHIBA TC35815CF 10/100BaseTX" },
        { "TOSHIBA TC35815 with Wake on LAN" },
        { "TOSHIBA TC35815/TX4939" },
@@ -719,7 +719,7 @@ err_out:
  * should provide a "tc35815-mac" device with a MAC address in its
  * platform_data.
  */
-static int __devinit tc35815_mac_match(struct device *dev, void *data)
+static int tc35815_mac_match(struct device *dev, void *data)
 {
        struct platform_device *plat_dev = to_platform_device(dev);
        struct pci_dev *pci_dev = data;
@@ -727,7 +727,7 @@ static int __devinit tc35815_mac_match(struct device *dev, void *data)
        return !strcmp(plat_dev->name, "tc35815-mac") && plat_dev->id == id;
 }
 
-static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+static int tc35815_read_plat_dev_addr(struct net_device *dev)
 {
        struct tc35815_local *lp = netdev_priv(dev);
        struct device *pd = bus_find_device(&platform_bus_type, NULL,
@@ -741,13 +741,13 @@ static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
        return -ENODEV;
 }
 #else
-static int __devinit tc35815_read_plat_dev_addr(struct net_device *dev)
+static int tc35815_read_plat_dev_addr(struct net_device *dev)
 {
        return -ENODEV;
 }
 #endif
 
-static int __devinit tc35815_init_dev_addr(struct net_device *dev)
+static int tc35815_init_dev_addr(struct net_device *dev)
 {
        struct tc35815_regs __iomem *tr =
                (struct tc35815_regs __iomem *)dev->base_addr;
@@ -785,8 +785,8 @@ static const struct net_device_ops tc35815_netdev_ops = {
 #endif
 };
 
-static int __devinit tc35815_init_one(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int tc35815_init_one(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        void __iomem *ioaddr = NULL;
        struct net_device *dev;
@@ -878,7 +878,7 @@ err_out:
 }
 
 
-static void __devexit tc35815_remove_one(struct pci_dev *pdev)
+static void tc35815_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tc35815_local *lp = netdev_priv(dev);
@@ -2198,7 +2198,7 @@ static struct pci_driver tc35815_pci_driver = {
        .name           = MODNAME,
        .id_table       = tc35815_pci_tbl,
        .probe          = tc35815_init_one,
-       .remove         = __devexit_p(tc35815_remove_one),
+       .remove         = tc35815_remove_one,
 #ifdef CONFIG_PM
        .suspend        = tc35815_suspend,
        .resume         = tc35815_resume,
index 0459c096629f0b71df679cdf2fa2bd28449f0d26..7992b3e05d3dd5a48f7701114a2264d23f3ce4e8 100644 (file)
@@ -113,7 +113,7 @@ static const int multicast_filter_limit = 32;
 #include <linux/dmi.h>
 
 /* These identify the driver base version and may not be removed. */
-static const char version[] __devinitconst =
+static const char version[] =
        "v1.10-LK" DRV_VERSION " " DRV_RELDATE " Written by Donald Becker";
 
 /* This driver was written to use PCI memory space. Some early versions
@@ -657,7 +657,7 @@ static void enable_mmio(long pioaddr, u32 quirks)
  * Loads bytes 0x00-0x05, 0x6E-0x6F, 0x78-0x7B from EEPROM
  * (plus 0x6C for Rhine-I/II)
  */
-static void __devinit rhine_reload_eeprom(long pioaddr, struct net_device *dev)
+static void rhine_reload_eeprom(long pioaddr, struct net_device *dev)
 {
        struct rhine_private *rp = netdev_priv(dev);
        void __iomem *ioaddr = rp->base;
@@ -823,7 +823,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget)
        return work_done;
 }
 
-static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
+static void rhine_hw_init(struct net_device *dev, long pioaddr)
 {
        struct rhine_private *rp = netdev_priv(dev);
 
@@ -856,8 +856,7 @@ static const struct net_device_ops rhine_netdev_ops = {
 #endif
 };
 
-static int __devinit rhine_init_one(struct pci_dev *pdev,
-                                   const struct pci_device_id *ent)
+static int rhine_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
        struct rhine_private *rp;
@@ -2232,7 +2231,7 @@ static int rhine_close(struct net_device *dev)
 }
 
 
-static void __devexit rhine_remove_one(struct pci_dev *pdev)
+static void rhine_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rhine_private *rp = netdev_priv(dev);
@@ -2359,7 +2358,7 @@ static struct pci_driver rhine_driver = {
        .name           = DRV_NAME,
        .id_table       = rhine_pci_tbl,
        .probe          = rhine_init_one,
-       .remove         = __devexit_p(rhine_remove_one),
+       .remove         = rhine_remove_one,
        .shutdown       = rhine_shutdown,
        .driver.pm      = RHINE_PM_OPS,
 };
index a46c19859683ada38d0be5f4d3cf4020d8b0c7d8..1bc7f9fd25836643771c58bc2977eab640ee021f 100644 (file)
@@ -375,7 +375,7 @@ MODULE_DEVICE_TABLE(pci, velocity_id_table);
  *     Given a chip identifier return a suitable description. Returns
  *     a pointer a static string valid while the driver is loaded.
  */
-static const char __devinit *get_chip_name(enum chip_type chip_id)
+static const char *get_chip_name(enum chip_type chip_id)
 {
        int i;
        for (i = 0; chip_info_table[i].name != NULL; i++)
@@ -392,7 +392,7 @@ static const char __devinit *get_chip_name(enum chip_type chip_id)
  *     unload for each active device that is present. Disconnects
  *     the device from the network layer and frees all the resources
  */
-static void __devexit velocity_remove1(struct pci_dev *pdev)
+static void velocity_remove1(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct velocity_info *vptr = netdev_priv(dev);
@@ -421,7 +421,8 @@ static void __devexit velocity_remove1(struct pci_dev *pdev)
  *     all the verification and checking as well as reporting so that
  *     we don't duplicate code for each option.
  */
-static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max, int def, char *name, const char *devname)
+static void velocity_set_int_opt(int *opt, int val, int min, int max, int def,
+                                char *name, const char *devname)
 {
        if (val == -1)
                *opt = def;
@@ -449,7 +450,8 @@ static void __devinit velocity_set_int_opt(int *opt, int val, int min, int max,
  *     all the verification and checking as well as reporting so that
  *     we don't duplicate code for each option.
  */
-static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag, char *name, const char *devname)
+static void velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag,
+                                 char *name, const char *devname)
 {
        (*opt) &= (~flag);
        if (val == -1)
@@ -474,7 +476,8 @@ static void __devinit velocity_set_bool_opt(u32 *opt, int val, int def, u32 flag
  *     Turn the module and command options into a single structure
  *     for the current device
  */
-static void __devinit velocity_get_options(struct velocity_opt *opts, int index, const char *devname)
+static void velocity_get_options(struct velocity_opt *opts, int index,
+                                const char *devname)
 {
 
        velocity_set_int_opt(&opts->rx_thresh, rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh", devname);
@@ -2627,9 +2630,8 @@ static const struct net_device_ops velocity_netdev_ops = {
  *     Set up the initial velocity_info struct for the device that has been
  *     discovered.
  */
-static void __devinit velocity_init_info(struct pci_dev *pdev,
-                                        struct velocity_info *vptr,
-                                        const struct velocity_info_tbl *info)
+static void velocity_init_info(struct pci_dev *pdev, struct velocity_info *vptr,
+                              const struct velocity_info_tbl *info)
 {
        memset(vptr, 0, sizeof(struct velocity_info));
 
@@ -2648,7 +2650,8 @@ static void __devinit velocity_init_info(struct pci_dev *pdev,
  *     Retrieve the PCI configuration space data that interests us from
  *     the kernel PCI layer
  */
-static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pci_dev *pdev)
+static int velocity_get_pci_info(struct velocity_info *vptr,
+                                struct pci_dev *pdev)
 {
        vptr->rev_id = pdev->revision;
 
@@ -2685,7 +2688,7 @@ static int __devinit velocity_get_pci_info(struct velocity_info *vptr, struct pc
  *     Print per driver data as the kernel driver finds Velocity
  *     hardware
  */
-static void __devinit velocity_print_info(struct velocity_info *vptr)
+static void velocity_print_info(struct velocity_info *vptr)
 {
        struct net_device *dev = vptr->dev;
 
@@ -2709,7 +2712,8 @@ static u32 velocity_get_link(struct net_device *dev)
  *     Configure a discovered adapter from scratch. Return a negative
  *     errno error code on failure paths.
  */
-static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int velocity_found1(struct pci_dev *pdev,
+                          const struct pci_device_id *ent)
 {
        static int first = 1;
        struct net_device *dev;
@@ -3108,7 +3112,7 @@ static struct pci_driver velocity_driver = {
        .name           = VELOCITY_NAME,
        .id_table       = velocity_id_table,
        .probe          = velocity_found1,
-       .remove         = __devexit_p(velocity_remove1),
+       .remove         = velocity_remove1,
 #ifdef CONFIG_PM
        .suspend        = velocity_suspend,
        .resume         = velocity_resume,
index 2c08bf6e7bf3b326f828585a3a8fefc96d62ddb3..35238389032669576f0080a17d1dd56a4919737e 100644 (file)
@@ -580,8 +580,6 @@ static int w5100_open(struct net_device *ndev)
        struct w5100_priv *priv = netdev_priv(ndev);
 
        netif_info(priv, ifup, ndev, "enabling\n");
-       if (!is_valid_ether_addr(ndev->dev_addr))
-               return -EINVAL;
        w5100_hw_start(priv);
        napi_enable(&priv->napi);
        netif_start_queue(ndev);
@@ -623,7 +621,7 @@ static const struct net_device_ops w5100_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
 };
 
-static int __devinit w5100_hw_probe(struct platform_device *pdev)
+static int w5100_hw_probe(struct platform_device *pdev)
 {
        struct wiznet_platform_data *data = pdev->dev.platform_data;
        struct net_device *ndev = platform_get_drvdata(pdev);
@@ -698,7 +696,7 @@ static int __devinit w5100_hw_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit w5100_probe(struct platform_device *pdev)
+static int w5100_probe(struct platform_device *pdev)
 {
        struct w5100_priv *priv;
        struct net_device *ndev;
@@ -741,7 +739,7 @@ err_register:
        return err;
 }
 
-static int __devexit w5100_remove(struct platform_device *pdev)
+static int w5100_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct w5100_priv *priv = netdev_priv(ndev);
@@ -801,7 +799,7 @@ static struct platform_driver w5100_driver = {
                .pm     = &w5100_pm_ops,
        },
        .probe          = w5100_probe,
-       .remove         = __devexit_p(w5100_remove),
+       .remove         = w5100_remove,
 };
 
 module_platform_driver(w5100_driver);
index 88943d90c7653565283a064e3a8ed25f65d5d213..9d1d986f8d409bf8cc87a43acbeb2270b3b8594a 100644 (file)
@@ -500,8 +500,6 @@ static int w5300_open(struct net_device *ndev)
        struct w5300_priv *priv = netdev_priv(ndev);
 
        netif_info(priv, ifup, ndev, "enabling\n");
-       if (!is_valid_ether_addr(ndev->dev_addr))
-               return -EINVAL;
        w5300_hw_start(priv);
        napi_enable(&priv->napi);
        netif_start_queue(ndev);
@@ -543,7 +541,7 @@ static const struct net_device_ops w5300_netdev_ops = {
        .ndo_change_mtu         = eth_change_mtu,
 };
 
-static int __devinit w5300_hw_probe(struct platform_device *pdev)
+static int w5300_hw_probe(struct platform_device *pdev)
 {
        struct wiznet_platform_data *data = pdev->dev.platform_data;
        struct net_device *ndev = platform_get_drvdata(pdev);
@@ -610,7 +608,7 @@ static int __devinit w5300_hw_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devinit w5300_probe(struct platform_device *pdev)
+static int w5300_probe(struct platform_device *pdev)
 {
        struct w5300_priv *priv;
        struct net_device *ndev;
@@ -653,7 +651,7 @@ err_register:
        return err;
 }
 
-static int __devexit w5300_remove(struct platform_device *pdev)
+static int w5300_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct w5300_priv *priv = netdev_priv(ndev);
@@ -713,7 +711,7 @@ static struct platform_driver w5300_driver = {
                .pm     = &w5300_pm_ops,
        },
        .probe          = w5300_probe,
-       .remove         = __devexit_p(w5300_remove),
+       .remove         = w5300_remove,
 };
 
 module_platform_driver(w5300_driver);
index f8e351880119674c0c10b270a45fdf47469dd702..aad909d793d75c2817a00ea580f7303e7ba37257 100644 (file)
@@ -1002,7 +1002,7 @@ static const struct ethtool_ops temac_ethtool_ops = {
        .get_ts_info = ethtool_op_get_ts_info,
 };
 
-static int __devinit temac_of_probe(struct platform_device *op)
+static int temac_of_probe(struct platform_device *op)
 {
        struct device_node *np;
        struct temac_local *lp;
@@ -1144,7 +1144,7 @@ static int __devinit temac_of_probe(struct platform_device *op)
        return rc;
 }
 
-static int __devexit temac_of_remove(struct platform_device *op)
+static int temac_of_remove(struct platform_device *op)
 {
        struct net_device *ndev = dev_get_drvdata(&op->dev);
        struct temac_local *lp = netdev_priv(ndev);
@@ -1163,7 +1163,7 @@ static int __devexit temac_of_remove(struct platform_device *op)
        return 0;
 }
 
-static struct of_device_id temac_of_match[] __devinitdata = {
+static struct of_device_id temac_of_match[] = {
        { .compatible = "xlnx,xps-ll-temac-1.01.b", },
        { .compatible = "xlnx,xps-ll-temac-2.00.a", },
        { .compatible = "xlnx,xps-ll-temac-2.02.a", },
@@ -1174,7 +1174,7 @@ MODULE_DEVICE_TABLE(of, temac_of_match);
 
 static struct platform_driver temac_of_driver = {
        .probe = temac_of_probe,
-       .remove = __devexit_p(temac_of_remove),
+       .remove = temac_of_remove,
        .driver = {
                .owner = THIS_MODULE,
                .name = "xilinx_temac",
index 0793299bd39ec9489908a206b073c32e0e8b3923..d9f69b82cc4ff638981798e23bbe3c0e9e6329f1 100644 (file)
@@ -48,7 +48,7 @@
 #define AXIENET_REGS_N         32
 
 /* Match table for of_platform binding */
-static struct of_device_id axienet_of_match[] __devinitdata = {
+static struct of_device_id axienet_of_match[] = {
        { .compatible = "xlnx,axi-ethernet-1.00.a", },
        { .compatible = "xlnx,axi-ethernet-1.01.a", },
        { .compatible = "xlnx,axi-ethernet-2.01.a", },
@@ -894,6 +894,8 @@ out:
        return IRQ_HANDLED;
 }
 
+static void axienet_dma_err_handler(unsigned long data);
+
 /**
  * axienet_open - Driver open routine.
  * @ndev:      Pointer to net_device structure
@@ -942,6 +944,10 @@ static int axienet_open(struct net_device *ndev)
                phy_start(lp->phy_dev);
        }
 
+       /* Enable tasklets for Axi DMA error handling */
+       tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
+                    (unsigned long) lp);
+
        /* Enable interrupts for Axi DMA Tx */
        ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
        if (ret)
@@ -950,8 +956,7 @@ static int axienet_open(struct net_device *ndev)
        ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev);
        if (ret)
                goto err_rx_irq;
-       /* Enable tasklets for Axi DMA error handling */
-       tasklet_enable(&lp->dma_err_tasklet);
+
        return 0;
 
 err_rx_irq:
@@ -960,6 +965,7 @@ err_tx_irq:
        if (lp->phy_dev)
                phy_disconnect(lp->phy_dev);
        lp->phy_dev = NULL;
+       tasklet_kill(&lp->dma_err_tasklet);
        dev_err(lp->dev, "request_irq() failed\n");
        return ret;
 }
@@ -990,7 +996,7 @@ static int axienet_stop(struct net_device *ndev)
        axienet_setoptions(ndev, lp->options &
                           ~(XAE_OPTION_TXEN | XAE_OPTION_RXEN));
 
-       tasklet_disable(&lp->dma_err_tasklet);
+       tasklet_kill(&lp->dma_err_tasklet);
 
        free_irq(lp->tx_irq, ndev);
        free_irq(lp->rx_irq, ndev);
@@ -1476,7 +1482,7 @@ static void axienet_dma_err_handler(unsigned long data)
  * device. Parses through device tree and populates fields of
  * axienet_local. It registers the Ethernet device.
  */
-static int __devinit axienet_of_probe(struct platform_device *op)
+static int axienet_of_probe(struct platform_device *op)
 {
        __be32 *p;
        int size, ret = 0;
@@ -1613,10 +1619,6 @@ static int __devinit axienet_of_probe(struct platform_device *op)
                goto err_iounmap_2;
        }
 
-       tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
-                    (unsigned long) lp);
-       tasklet_disable(&lp->dma_err_tasklet);
-
        return 0;
 
 err_iounmap_2:
@@ -1630,7 +1632,7 @@ nodev:
        return ret;
 }
 
-static int __devexit axienet_of_remove(struct platform_device *op)
+static int axienet_of_remove(struct platform_device *op)
 {
        struct net_device *ndev = dev_get_drvdata(&op->dev);
        struct axienet_local *lp = netdev_priv(ndev);
@@ -1654,7 +1656,7 @@ static int __devexit axienet_of_remove(struct platform_device *op)
 
 static struct platform_driver axienet_of_driver = {
        .probe = axienet_of_probe,
-       .remove = __devexit_p(axienet_of_remove),
+       .remove = axienet_of_remove,
        .driver = {
                 .owner = THIS_MODULE,
                 .name = "xilinx_axienet",
index 77cfe5110318ab7c1dd40bac9c0dd18ad37c8610..919b983114e907242bc49ce64ba95eb00c3e2008 100644 (file)
@@ -1107,7 +1107,7 @@ static struct net_device_ops xemaclite_netdev_ops;
  * Return:     0, if the driver is bound to the Emaclite device, or
  *             a negative error if there is failure.
  */
-static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
+static int xemaclite_of_probe(struct platform_device *ofdev)
 {
        struct resource r_irq; /* Interrupt resources */
        struct resource r_mem; /* IO mem resources */
@@ -1229,7 +1229,7 @@ error2:
  *
  * Return:     0, always.
  */
-static int __devexit xemaclite_of_remove(struct platform_device *of_dev)
+static int xemaclite_of_remove(struct platform_device *of_dev)
 {
        struct device *dev = &of_dev->dev;
        struct net_device *ndev = dev_get_drvdata(dev);
@@ -1280,7 +1280,7 @@ static struct net_device_ops xemaclite_netdev_ops = {
 };
 
 /* Match table for OF platform binding */
-static struct of_device_id xemaclite_of_match[] __devinitdata = {
+static struct of_device_id xemaclite_of_match[] = {
        { .compatible = "xlnx,opb-ethernetlite-1.01.a", },
        { .compatible = "xlnx,opb-ethernetlite-1.01.b", },
        { .compatible = "xlnx,xps-ethernetlite-1.00.a", },
@@ -1298,7 +1298,7 @@ static struct platform_driver xemaclite_of_driver = {
                .of_match_table = xemaclite_of_match,
        },
        .probe          = xemaclite_of_probe,
-       .remove         = __devexit_p(xemaclite_of_remove),
+       .remove         = xemaclite_of_remove,
 };
 
 module_platform_driver(xemaclite_of_driver);
index 98934bdf6acffc053fcd317721e8d92cf649ba14..d3ebb73277bed4306363aaa20b9ea699d49bcc20 100644 (file)
@@ -1102,10 +1102,12 @@ static int init_queues(struct port *port)
 {
        int i;
 
-       if (!ports_open)
-               if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-                                                POOL_ALLOC_SIZE, 32, 0)))
+       if (!ports_open) {
+               dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+                                          POOL_ALLOC_SIZE, 32, 0);
+               if (!dma_pool)
                        return -ENOMEM;
+       }
 
        if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
                                              &port->desc_tab_phys)))
@@ -1377,7 +1379,7 @@ static const struct net_device_ops ixp4xx_netdev_ops = {
        .ndo_validate_addr = eth_validate_addr,
 };
 
-static int __devinit eth_init_one(struct platform_device *pdev)
+static int eth_init_one(struct platform_device *pdev)
 {
        struct port *port;
        struct net_device *dev;
@@ -1478,7 +1480,7 @@ err_free:
        return err;
 }
 
-static int __devexit eth_remove_one(struct platform_device *pdev)
+static int eth_remove_one(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct port *port = netdev_priv(dev);
index 6695a1dadf4e32d592118feea843eb33aaa5f327..502c8ff1d985b80dd96423040e54fc54dedabaeb 100644 (file)
 #define DRV_VERSION "v1.10"
 #define DRV_RELDATE "2006/12/14"
 
-static char version[] __devinitdata =
+static char version[] =
        DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
        "  Lawrence V. Stefani and others\n";
 
@@ -515,7 +515,7 @@ static const struct net_device_ops dfx_netdev_ops = {
  *   initialized and the board resources are read and stored in
  *   the device structure.
  */
-static int __devinit dfx_register(struct device *bdev)
+static int dfx_register(struct device *bdev)
 {
        static int version_disp;
        int dfx_bus_pci = DFX_BUS_PCI(bdev);
@@ -663,7 +663,7 @@ err_out:
  *   enabled yet.
  */
 
-static void __devinit dfx_bus_init(struct net_device *dev)
+static void dfx_bus_init(struct net_device *dev)
 {
        DFX_board_t *bp = netdev_priv(dev);
        struct device *bdev = bp->bus_dev;
@@ -809,7 +809,7 @@ static void __devinit dfx_bus_init(struct net_device *dev)
  *   Interrupts are disabled at the adapter bus-specific logic.
  */
 
-static void __devexit dfx_bus_uninit(struct net_device *dev)
+static void dfx_bus_uninit(struct net_device *dev)
 {
        DFX_board_t *bp = netdev_priv(dev);
        struct device *bdev = bp->bus_dev;
@@ -866,7 +866,7 @@ static void __devexit dfx_bus_uninit(struct net_device *dev)
  *   None
  */
 
-static void __devinit dfx_bus_config_check(DFX_board_t *bp)
+static void dfx_bus_config_check(DFX_board_t *bp)
 {
        struct device __maybe_unused *bdev = bp->bus_dev;
        int dfx_bus_eisa = DFX_BUS_EISA(bdev);
@@ -962,9 +962,8 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp)
  *   returning from this routine.
  */
 
-static int __devinit dfx_driver_init(struct net_device *dev,
-                                    const char *print_name,
-                                    resource_size_t bar_start)
+static int dfx_driver_init(struct net_device *dev, const char *print_name,
+                          resource_size_t bar_start)
 {
        DFX_board_t *bp = netdev_priv(dev);
        struct device *bdev = bp->bus_dev;
@@ -3579,7 +3578,7 @@ static void dfx_xmt_flush( DFX_board_t *bp )
  *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
  *   freed.
  */
-static void __devexit dfx_unregister(struct device *bdev)
+static void dfx_unregister(struct device *bdev)
 {
        struct net_device *dev = dev_get_drvdata(bdev);
        DFX_board_t *bp = netdev_priv(dev);
@@ -3619,13 +3618,12 @@ static void __devexit dfx_unregister(struct device *bdev)
 }
 
 
-static int __devinit __maybe_unused dfx_dev_register(struct device *);
-static int __devexit __maybe_unused dfx_dev_unregister(struct device *);
+static int __maybe_unused dfx_dev_register(struct device *);
+static int __maybe_unused dfx_dev_unregister(struct device *);
 
 #ifdef CONFIG_PCI
-static int __devinit dfx_pci_register(struct pci_dev *,
-                                     const struct pci_device_id *);
-static void __devexit dfx_pci_unregister(struct pci_dev *);
+static int dfx_pci_register(struct pci_dev *, const struct pci_device_id *);
+static void dfx_pci_unregister(struct pci_dev *);
 
 static DEFINE_PCI_DEVICE_TABLE(dfx_pci_table) = {
        { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
@@ -3637,16 +3635,16 @@ static struct pci_driver dfx_pci_driver = {
        .name           = "defxx",
        .id_table       = dfx_pci_table,
        .probe          = dfx_pci_register,
-       .remove         = __devexit_p(dfx_pci_unregister),
+       .remove         = dfx_pci_unregister,
 };
 
-static __devinit int dfx_pci_register(struct pci_dev *pdev,
-                                     const struct pci_device_id *ent)
+static int dfx_pci_register(struct pci_dev *pdev,
+                           const struct pci_device_id *ent)
 {
        return dfx_register(&pdev->dev);
 }
 
-static void __devexit dfx_pci_unregister(struct pci_dev *pdev)
+static void dfx_pci_unregister(struct pci_dev *pdev)
 {
        dfx_unregister(&pdev->dev);
 }
@@ -3668,7 +3666,7 @@ static struct eisa_driver dfx_eisa_driver = {
                .name   = "defxx",
                .bus    = &eisa_bus_type,
                .probe  = dfx_dev_register,
-               .remove = __devexit_p(dfx_dev_unregister),
+               .remove = dfx_dev_unregister,
        },
 };
 #endif /* CONFIG_EISA */
@@ -3689,12 +3687,12 @@ static struct tc_driver dfx_tc_driver = {
                .name   = "defxx",
                .bus    = &tc_bus_type,
                .probe  = dfx_dev_register,
-               .remove = __devexit_p(dfx_dev_unregister),
+               .remove = dfx_dev_unregister,
        },
 };
 #endif /* CONFIG_TC */
 
-static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
+static int __maybe_unused dfx_dev_register(struct device *dev)
 {
        int status;
 
@@ -3704,7 +3702,7 @@ static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
        return status;
 }
 
-static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
+static int __maybe_unused dfx_dev_unregister(struct device *dev)
 {
        put_device(dev);
        dfx_unregister(dev);
@@ -3712,7 +3710,7 @@ static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
 }
 
 
-static int __devinit dfx_init(void)
+static int dfx_init(void)
 {
        int status;
 
@@ -3724,7 +3722,7 @@ static int __devinit dfx_init(void)
        return status;
 }
 
-static void __devexit dfx_cleanup(void)
+static void dfx_cleanup(void)
 {
        tc_unregister_driver(&dfx_tc_driver);
        eisa_driver_unregister(&dfx_eisa_driver);
index 3d9a4596a423d22029992830e01cecc3dd09efe6..d5bd563ac131e59362b7df5c33b25f5266f9370f 100644 (file)
@@ -321,7 +321,7 @@ err_out1:
 /*
  * Called for each adapter board from pci_unregister_driver
  */
-static void __devexit skfp_remove_one(struct pci_dev *pdev)
+static void skfp_remove_one(struct pci_dev *pdev)
 {
        struct net_device *p = pci_get_drvdata(pdev);
        struct s_smc *lp = netdev_priv(p);
@@ -2243,7 +2243,7 @@ static struct pci_driver skfddi_pci_driver = {
        .name           = "skfddi",
        .id_table       = skfddi_pci_tbl,
        .probe          = skfp_init_one,
-       .remove         = __devexit_p(skfp_remove_one),
+       .remove         = skfp_remove_one,
 };
 
 static int __init skfd_init(void)
index d4719632ffc687ec6e3aa69b52cc5de337b49bc8..e5b19b05690967ed93f9ac50be4d1548911bf38a 100644 (file)
@@ -61,7 +61,7 @@ MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");
 MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
 MODULE_LICENSE("GPL");
 
-static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
+static char version[] = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
 
 
 static const struct net_device_ops rr_netdev_ops = {
@@ -88,8 +88,7 @@ static const struct net_device_ops rr_netdev_ops = {
  * stack will need to know about I/O vectors or something similar.
  */
 
-static int __devinit rr_init_one(struct pci_dev *pdev,
-       const struct pci_device_id *ent)
+static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *dev;
        static int version_disp;
@@ -221,7 +220,7 @@ static int __devinit rr_init_one(struct pci_dev *pdev,
        return ret;
 }
 
-static void __devexit rr_remove_one (struct pci_dev *pdev)
+static void rr_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
        struct rr_private *rr = netdev_priv(dev);
@@ -503,7 +502,7 @@ static unsigned int write_eeprom(struct rr_private *rrpriv,
 }
 
 
-static int __devinit rr_init(struct net_device *dev)
+static int rr_init(struct net_device *dev)
 {
        struct rr_private *rrpriv;
        struct rr_regs __iomem *regs;
@@ -1681,7 +1680,7 @@ static struct pci_driver rr_driver = {
        .name           = "rrunner",
        .id_table       = rr_pci_tbl,
        .probe          = rr_init_one,
-       .remove         = __devexit_p(rr_remove_one),
+       .remove         = rr_remove_one,
 };
 
 static int __init rr_init_module(void)
index 928148cc32207a90da8cf173258c0ef8cc2b7e36..2b657d4d63a8cc86950db8f50c805c3f96e017d1 100644 (file)
@@ -363,11 +363,6 @@ static void rndis_filter_receive_data(struct rndis_device *dev,
 
        rndis_pkt = &msg->msg.pkt;
 
-       /*
-        * FIXME: Handle multiple rndis pkt msgs that maybe enclosed in this
-        * netvsc packet (ie TotalDataBufferLength != MessageLength)
-        */
-
        /* Remove the rndis header and pass it back up the stack */
        data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
 
@@ -610,8 +605,11 @@ int rndis_filter_set_device_mac(struct hv_device *hdev, char *mac)
                return -EBUSY;
        } else {
                set_complete = &request->response_msg.msg.set_complete;
-               if (set_complete->status != RNDIS_STATUS_SUCCESS)
+               if (set_complete->status != RNDIS_STATUS_SUCCESS) {
+                       netdev_err(ndev, "Fail to set MAC on host side:0x%x\n",
+                                  set_complete->status);
                        ret = -EINVAL;
+               }
        }
 
 cleanup:
index ba753d87a32f5120a8ebf1a8e8641273259db65f..a4a62e170ec08533773881189eeaea63c4a0cdf0 100644 (file)
@@ -778,7 +778,7 @@ static int at86rf230_fill_data(struct spi_device *spi)
        return 0;
 }
 
-static int __devinit at86rf230_probe(struct spi_device *spi)
+static int at86rf230_probe(struct spi_device *spi)
 {
        struct ieee802154_dev *dev;
        struct at86rf230_local *lp;
@@ -920,7 +920,7 @@ err_fill:
        return rc;
 }
 
-static int __devexit at86rf230_remove(struct spi_device *spi)
+static int at86rf230_remove(struct spi_device *spi)
 {
        struct at86rf230_local *lp = spi_get_drvdata(spi);
 
@@ -947,7 +947,7 @@ static struct spi_driver at86rf230_driver = {
                .owner  = THIS_MODULE,
        },
        .probe      = at86rf230_probe,
-       .remove     = __devexit_p(at86rf230_remove),
+       .remove     = at86rf230_remove,
        .suspend    = at86rf230_suspend,
        .resume     = at86rf230_resume,
 };
index 7d39add7d467712f8cb21ec9aee4d01cd6606c7f..1e9cb0bbf62cbcf0c4738388802560ab961f0657 100644 (file)
@@ -354,7 +354,7 @@ static void ieee802154_fake_setup(struct net_device *dev)
 }
 
 
-static int __devinit ieee802154fake_probe(struct platform_device *pdev)
+static int ieee802154fake_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct fakehard_priv *priv;
@@ -412,7 +412,7 @@ out:
        return err;
 }
 
-static int __devexit ieee802154fake_remove(struct platform_device *pdev)
+static int ieee802154fake_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        unregister_netdev(dev);
@@ -423,7 +423,7 @@ static struct platform_device *ieee802154fake_dev;
 
 static struct platform_driver ieee802154fake_driver = {
        .probe = ieee802154fake_probe,
-       .remove = __devexit_p(ieee802154fake_remove),
+       .remove = ieee802154fake_remove,
        .driver = {
                        .name = "ieee802154hardmac",
                        .owner = THIS_MODULE,
index e7456fcd0913fbaf09d146112d9d3c9ab539cae0..b8d22173925dee1aed62df3ccd4d23deb44b976b 100644 (file)
@@ -221,7 +221,7 @@ static void fakelb_del(struct fakelb_dev_priv *priv)
        ieee802154_free_device(priv->dev);
 }
 
-static int __devinit fakelb_probe(struct platform_device *pdev)
+static int fakelb_probe(struct platform_device *pdev)
 {
        struct fakelb_priv *priv;
        struct fakelb_dev_priv *dp;
@@ -253,7 +253,7 @@ err_alloc:
        return err;
 }
 
-static int __devexit fakelb_remove(struct platform_device *pdev)
+static int fakelb_remove(struct platform_device *pdev)
 {
        struct fakelb_priv *priv = platform_get_drvdata(pdev);
        struct fakelb_dev_priv *dp, *temp;
@@ -269,7 +269,7 @@ static struct platform_device *ieee802154fake_dev;
 
 static struct platform_driver ieee802154fake_driver = {
        .probe = fakelb_probe,
-       .remove = __devexit_p(fakelb_remove),
+       .remove = fakelb_remove,
        .driver = {
                        .name = "ieee802154fakelb",
                        .owner = THIS_MODULE,
index ed7521693980e43241a71b6369b0a22b7b8ab460..3f2c7aaf28c4be64356cfc0149dfc486389ae380 100644 (file)
@@ -618,7 +618,7 @@ out:
        enable_irq(devrec->spi->irq);
 }
 
-static int __devinit mrf24j40_probe(struct spi_device *spi)
+static int mrf24j40_probe(struct spi_device *spi)
 {
        int ret = -ENOMEM;
        u8 val;
@@ -711,7 +711,7 @@ err_devrec:
        return ret;
 }
 
-static int __devexit mrf24j40_remove(struct spi_device *spi)
+static int mrf24j40_remove(struct spi_device *spi)
 {
        struct mrf24j40 *devrec = dev_get_drvdata(&spi->dev);
 
@@ -746,7 +746,7 @@ static struct spi_driver mrf24j40_driver = {
        },
        .id_table = mrf24j40_ids,
        .probe = mrf24j40_probe,
-       .remove = __devexit_p(mrf24j40_remove),
+       .remove = mrf24j40_remove,
 };
 
 static int __init mrf24j40_init(void)
index e09417df8f39bed4aeebb2f1c6bc2b34cce9e8ed..b5151e4ced612b0847abe72327d6f483d13757fe 100644 (file)
@@ -760,7 +760,7 @@ static const struct net_device_ops au1k_irda_netdev_ops = {
        .ndo_do_ioctl           = au1k_irda_ioctl,
 };
 
-static int __devinit au1k_irda_net_init(struct net_device *dev)
+static int au1k_irda_net_init(struct net_device *dev)
 {
        struct au1k_private *aup = netdev_priv(dev);
        struct db_dest *pDB, *pDBfree;
@@ -849,7 +849,7 @@ out1:
        return retval;
 }
 
-static int __devinit au1k_irda_probe(struct platform_device *pdev)
+static int au1k_irda_probe(struct platform_device *pdev)
 {
        struct au1k_private *aup;
        struct net_device *dev;
@@ -921,7 +921,7 @@ out:
        return err;
 }
 
-static int __devexit au1k_irda_remove(struct platform_device *pdev)
+static int au1k_irda_remove(struct platform_device *pdev)
 {
        struct net_device *dev = platform_get_drvdata(pdev);
        struct au1k_private *aup = netdev_priv(dev);
@@ -949,7 +949,7 @@ static struct platform_driver au1k_irda_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = au1k_irda_probe,
-       .remove         = __devexit_p(au1k_irda_remove),
+       .remove         = au1k_irda_remove,
 };
 
 static int __init au1k_irda_load(void)
index c6a0299aa9f912241e6b544727df47913b01db1d..fed4a05d55c77bfd520494b5af8fcaaaffbcce39 100644 (file)
@@ -31,7 +31,7 @@ static void turnaround_delay(unsigned long last_jif, int mtt)
        schedule_timeout_uninterruptible(ticks);
 }
 
-static void __devinit bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev)
+static void bfin_sir_init_ports(struct bfin_sir_port *sp, struct platform_device *pdev)
 {
        int i;
        struct resource *res;
@@ -688,7 +688,7 @@ static const struct net_device_ops bfin_sir_ndo = {
        .ndo_get_stats          = bfin_sir_stats,
 };
 
-static int __devinit bfin_sir_probe(struct platform_device *pdev)
+static int bfin_sir_probe(struct platform_device *pdev)
 {
        struct net_device *dev;
        struct bfin_sir_self *self;
@@ -775,7 +775,7 @@ err_mem_0:
        return err;
 }
 
-static int __devexit bfin_sir_remove(struct platform_device *pdev)
+static int bfin_sir_remove(struct platform_device *pdev)
 {
        struct bfin_sir_port *sir_port;
        struct net_device *dev = NULL;
@@ -798,7 +798,7 @@ static int __devexit bfin_sir_remove(struct platform_device *pdev)
 
 static struct platform_driver bfin_ir_driver = {
        .probe   = bfin_sir_probe,
-       .remove  = __devexit_p(bfin_sir_remove),
+       .remove  = bfin_sir_remove,
        .suspend = bfin_sir_suspend,
        .resume  = bfin_sir_resume,
        .driver  = {
index f83c5b881d2d2c5210af46a7de2b5ec729f5b5c0..5fe1f4dd3369917d5531135d6f39784fc6dc5294 100644 (file)
@@ -1,52 +1,18 @@
 /*
- * IR port driver for the Cirrus Logic EP7211 processor.
+ * IR port driver for the Cirrus Logic CLPS711X processors
  *
  * Copyright 2001, Blue Mug Inc.  All rights reserved.
  * Copyright 2007, Samuel Ortiz <samuel@sortiz.org>
  */
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
 
-#include <net/irda/irda.h>
-#include <net/irda/irda_device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
 
-#include <asm/io.h>
 #include <mach/hardware.h>
 
 #include "sir-dev.h"
 
-#define MIN_DELAY 25      /* 15 us, but wait a little more to be sure */
-#define MAX_DELAY 10000   /* 1 ms */
-
-static int ep7211_open(struct sir_dev *dev);
-static int ep7211_close(struct sir_dev *dev);
-static int ep7211_change_speed(struct sir_dev *dev, unsigned speed);
-static int ep7211_reset(struct sir_dev *dev);
-
-static struct dongle_driver ep7211 = {
-       .owner          = THIS_MODULE,
-       .driver_name    = "EP7211 IR driver",
-       .type           = IRDA_EP7211_DONGLE,
-       .open           = ep7211_open,
-       .close          = ep7211_close,
-       .reset          = ep7211_reset,
-       .set_speed      = ep7211_change_speed,
-};
-
-static int __init ep7211_sir_init(void)
-{
-       return irda_register_dongle(&ep7211);
-}
-
-static void __exit ep7211_sir_cleanup(void)
-{
-       irda_unregister_dongle(&ep7211);
-}
-
-static int ep7211_open(struct sir_dev *dev)
+static int clps711x_dongle_open(struct sir_dev *dev)
 {
        unsigned int syscon;
 
@@ -58,7 +24,7 @@ static int ep7211_open(struct sir_dev *dev)
        return 0;
 }
 
-static int ep7211_close(struct sir_dev *dev)
+static int clps711x_dongle_close(struct sir_dev *dev)
 {
        unsigned int syscon;
 
@@ -70,20 +36,35 @@ static int ep7211_close(struct sir_dev *dev)
        return 0;
 }
 
-static int ep7211_change_speed(struct sir_dev *dev, unsigned speed)
+static struct dongle_driver clps711x_dongle = {
+       .owner          = THIS_MODULE,
+       .driver_name    = "EP7211 IR driver",
+       .type           = IRDA_EP7211_DONGLE,
+       .open           = clps711x_dongle_open,
+       .close          = clps711x_dongle_close,
+};
+
+static int clps711x_sir_probe(struct platform_device *pdev)
 {
-       return 0;
+       return irda_register_dongle(&clps711x_dongle);
 }
 
-static int ep7211_reset(struct sir_dev *dev)
+static int clps711x_sir_remove(struct platform_device *pdev)
 {
-       return 0;
+       return irda_unregister_dongle(&clps711x_dongle);
 }
 
+static struct platform_driver clps711x_sir_driver = {
+       .driver = {
+               .name   = "sir-clps711x",
+               .owner  = THIS_MODULE,
+       },
+       .probe  = clps711x_sir_probe,
+       .remove = clps711x_sir_remove,
+};
+module_platform_driver(clps711x_sir_driver);
+
 MODULE_AUTHOR("Samuel Ortiz <samuel@sortiz.org>");
 MODULE_DESCRIPTION("EP7211 IR dongle driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("irda-dongle-13"); /* IRDA_EP7211_DONGLE */
-
-module_init(ep7211_sir_init);
-module_exit(ep7211_sir_cleanup);
index 4b746d9bd8e7e74b227e0ea6bea63193c9942c21..9448587de4531c79517f05d0928b36163d474325 100644 (file)
 
 #define DRIVER_NAME "sh_irda"
 
-#if defined(CONFIG_ARCH_SH7367) || defined(CONFIG_ARCH_SH7377)
-#define __IRDARAM_LEN  0x13FF
-#else
 #define __IRDARAM_LEN  0x1039
-#endif
 
 #define IRTMR          0x1F00 /* Transfer mode */
 #define IRCFR          0x1F02 /* Configuration */
@@ -757,7 +753,7 @@ static const struct net_device_ops sh_irda_ndo = {
 
 
 ************************************************************************/
-static int __devinit sh_irda_probe(struct platform_device *pdev)
+static int sh_irda_probe(struct platform_device *pdev)
 {
        struct net_device *ndev;
        struct sh_irda_self *self;
@@ -829,7 +825,7 @@ exit:
        return err;
 }
 
-static int __devexit sh_irda_remove(struct platform_device *pdev)
+static int sh_irda_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct sh_irda_self *self = netdev_priv(ndev);
@@ -866,7 +862,7 @@ static const struct dev_pm_ops sh_irda_pm_ops = {
 
 static struct platform_driver sh_irda_driver = {
        .probe  = sh_irda_probe,
-       .remove = __devexit_p(sh_irda_remove),
+       .remove = sh_irda_remove,
        .driver = {
                .name   = DRIVER_NAME,
                .pm     = &sh_irda_pm_ops,
index 624ac1939e857a90a71d66d6dd22e5bddffe71f9..24aefcd840654aa10ca97cee1f7b323d9d7a404e 100644 (file)
@@ -705,7 +705,7 @@ static const struct net_device_ops sh_sir_ndo = {
 
 
 ************************************************************************/
-static int __devinit sh_sir_probe(struct platform_device *pdev)
+static int sh_sir_probe(struct platform_device *pdev)
 {
        struct net_device *ndev;
        struct sh_sir_self *self;
@@ -783,7 +783,7 @@ exit:
        return err;
 }
 
-static int __devexit sh_sir_remove(struct platform_device *pdev)
+static int sh_sir_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct sh_sir_self *self = netdev_priv(ndev);
@@ -803,7 +803,7 @@ static int __devexit sh_sir_remove(struct platform_device *pdev)
 
 static struct platform_driver sh_sir_driver = {
        .probe   = sh_sir_probe,
-       .remove  = __devexit_p(sh_sir_remove),
+       .remove  = sh_sir_remove,
        .driver  = {
                .name = DRIVER_NAME,
        },
index 5039f08f5a5b23cacd0f145cd790a30fce47806e..43e9ab4f4d7edc0b6771c1664d2064c164e37ec3 100644 (file)
@@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work)
                        break;
 
                case SIRDEV_STATE_DONGLE_SPEED:
-                       if (dev->dongle_drv->reset) {
+                       if (dev->dongle_drv->set_speed) {
                                ret = dev->dongle_drv->set_speed(dev, fsm->param);
                                if (ret < 0) {
                                        fsm->result = ret;
index a926813ee91d53b93efe008781f3ba8f47a88aa8..5290952b60c25235f13f308f5041b68795083971 100644 (file)
@@ -376,8 +376,8 @@ MODULE_DEVICE_TABLE(pnp, smsc_ircc_pnp_table);
 static int pnp_driver_registered;
 
 #ifdef CONFIG_PNP
-static int __devinit smsc_ircc_pnp_probe(struct pnp_dev *dev,
-                                     const struct pnp_device_id *dev_id)
+static int smsc_ircc_pnp_probe(struct pnp_dev *dev,
+                              const struct pnp_device_id *dev_id)
 {
        unsigned int firbase, sirbase;
        u8 dma, irq;
@@ -515,7 +515,7 @@ static const struct net_device_ops smsc_ircc_netdev_ops = {
  *    Try to open driver instance
  *
  */
-static int __devinit smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
+static int smsc_ircc_open(unsigned int fir_base, unsigned int sir_base, u8 dma, u8 irq)
 {
        struct smsc_ircc_cb *self;
        struct net_device *dev;
index 1a89fd459dd51110cc0a08931ad917f1e4850a8e..f9033c6a888c8ab7f14a4c1db884d35e14b42923 100644 (file)
@@ -77,7 +77,7 @@ static int dongle_id = 0;     /* default: probe */
 module_param(dongle_id, int, 0);
 
 /* Some prototypes */
-static int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
+static int via_ircc_open(struct pci_dev *pdev, chipio_t *info,
                         unsigned int id);
 static int via_ircc_dma_receive(struct via_ircc_cb *self);
 static int via_ircc_dma_receive_complete(struct via_ircc_cb *self,
@@ -102,8 +102,8 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase);
 static void hwreset(struct via_ircc_cb *self);
 static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase);
 static int upload_rxdata(struct via_ircc_cb *self, int iobase);
-static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id);
-static void __devexit via_remove_one (struct pci_dev *pdev);
+static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id);
+static void via_remove_one(struct pci_dev *pdev);
 
 /* FIXME : Should use udelay() instead, even if we are x86 only - Jean II */
 static void iodelay(int udelay)
@@ -132,7 +132,7 @@ static struct pci_driver via_driver = {
        .name           = VIA_MODULE_NAME,
        .id_table       = via_pci_tbl,
        .probe          = via_init_one,
-       .remove         = __devexit_p(via_remove_one),
+       .remove         = via_remove_one,
 };
 
 
@@ -156,7 +156,7 @@ static int __init via_ircc_init(void)
        return 0;
 }
 
-static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id)
+static int via_init_one(struct pci_dev *pcidev, const struct pci_device_id *id)
 {
        int rc;
         u8 temp,oldPCI_40,oldPCI_44,bTmp,bTmp1;
@@ -286,8 +286,7 @@ static const struct net_device_ops via_ircc_fir_ops = {
  *    Open driver instance
  *
  */
-static __devinit int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
-                                  unsigned int id)
+static int via_ircc_open(struct pci_dev *pdev, chipio_t *info, unsigned int id)
 {
        struct net_device *dev;
        struct via_ircc_cb *self;
@@ -424,7 +423,7 @@ static __devinit int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
  *    Close driver instance
  *
  */
-static void __devexit via_remove_one(struct pci_dev *pdev)
+static void via_remove_one(struct pci_dev *pdev)
 {
        struct via_ircc_cb *self = pci_get_drvdata(pdev);
        int iobase;
index 9021d01317277143110542b5c68b9073e349421b..2f99f8881dfc4c53eb209e888f2f496f97450989 100644 (file)
@@ -1627,7 +1627,7 @@ static int vlsi_irda_init(struct net_device *ndev)
 
 /**************************************************************/
 
-static int __devinit
+static int
 vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct net_device       *ndev;
@@ -1699,7 +1699,7 @@ out:
        return -ENODEV;
 }
 
-static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
+static void vlsi_irda_remove(struct pci_dev *pdev)
 {
        struct net_device *ndev = pci_get_drvdata(pdev);
        vlsi_irda_dev_t *idev;
@@ -1832,7 +1832,7 @@ static struct pci_driver vlsi_irda_driver = {
        .name           = drivername,
        .id_table       = vlsi_irda_table,
        .probe          = vlsi_irda_probe,
-       .remove         = __devexit_p(vlsi_irda_remove),
+       .remove         = vlsi_irda_remove,
 #ifdef CONFIG_PM
        .suspend        = vlsi_irda_suspend,
        .resume         = vlsi_irda_resume,
index b3321129a83c6dc33180fbbb07aadad296f14554..6989ebe2bc7902c44e429dfefda4c432d3eb7131 100644 (file)
@@ -56,6 +56,10 @@ static char config[MAX_PARAM_LENGTH];
 module_param_string(netconsole, config, MAX_PARAM_LENGTH, 0);
 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]");
 
+static bool oops_only = false;
+module_param(oops_only, bool, 0600);
+MODULE_PARM_DESC(oops_only, "Only log oops messages");
+
 #ifndef        MODULE
 static int __init option_setup(char *opt)
 {
@@ -683,6 +687,8 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
        struct netconsole_target *nt;
        const char *tmp;
 
+       if (oops_only && !oops_in_progress)
+               return;
        /* Avoid taking lock and disabling interrupts unnecessarily */
        if (list_empty(&target_list))
                return;
index 983bbf4d5ef6a7437118ac2d21ba2cb66599bc8c..961f0b2939132b0b2e50a94e7610cfb72ce8faf4 100644 (file)
@@ -15,6 +15,11 @@ if PHYLIB
 
 comment "MII PHY device drivers"
 
+config AT803X_PHY
+       tristate "Drivers for Atheros AT803X PHYs"
+       ---help---
+         Currently supports the AT8030 and AT8035 model
+
 config AMD_PHY
        tristate "Drivers for the AMD PHYs"
        ---help---
index 426674debae44dfb9967e305ad571f7012010afb..9645e389a58d34fbdb0c74a737d61b33a4885b6a 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_STE10XP)         += ste10Xp.o
 obj-$(CONFIG_MICREL_PHY)       += micrel.o
 obj-$(CONFIG_MDIO_OCTEON)      += mdio-octeon.o
 obj-$(CONFIG_MICREL_KS8995MA)  += spi_ks8995.o
+obj-$(CONFIG_AT803X_PHY)       += at803x.o
 obj-$(CONFIG_AMD_PHY)          += amd.o
 obj-$(CONFIG_MDIO_BUS_MUX)     += mdio-mux.o
 obj-$(CONFIG_MDIO_BUS_MUX_GPIO)        += mdio-mux-gpio.o
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
new file mode 100644 (file)
index 0000000..45cbc10
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * drivers/net/phy/at803x.c
+ *
+ * Driver for Atheros 803x PHY
+ *
+ * Author: Matus Ujhelyi <ujhelyi.m@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/phy.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define AT803X_INTR_ENABLE                     0x12
+#define AT803X_INTR_STATUS                     0x13
+#define AT803X_WOL_ENABLE                      0x01
+#define AT803X_DEVICE_ADDR                     0x03
+#define AT803X_LOC_MAC_ADDR_0_15_OFFSET                0x804C
+#define AT803X_LOC_MAC_ADDR_16_31_OFFSET       0x804B
+#define AT803X_LOC_MAC_ADDR_32_47_OFFSET       0x804A
+#define AT803X_MMD_ACCESS_CONTROL              0x0D
+#define AT803X_MMD_ACCESS_CONTROL_DATA         0x0E
+#define AT803X_FUNC_DATA                       0x4003
+
+MODULE_DESCRIPTION("Atheros 803x PHY driver");
+MODULE_AUTHOR("Matus Ujhelyi");
+MODULE_LICENSE("GPL");
+
+static void at803x_set_wol_mac_addr(struct phy_device *phydev)
+{
+       struct net_device *ndev = phydev->attached_dev;
+       const u8 *mac;
+       unsigned int i, offsets[] = {
+               AT803X_LOC_MAC_ADDR_32_47_OFFSET,
+               AT803X_LOC_MAC_ADDR_16_31_OFFSET,
+               AT803X_LOC_MAC_ADDR_0_15_OFFSET,
+       };
+
+       if (!ndev)
+               return;
+
+       mac = (const u8 *) ndev->dev_addr;
+
+       if (!is_valid_ether_addr(mac))
+               return;
+
+       for (i = 0; i < 3; i++) {
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                                 AT803X_DEVICE_ADDR);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                                 offsets[i]);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL,
+                                 AT803X_FUNC_DATA);
+               phy_write(phydev, AT803X_MMD_ACCESS_CONTROL_DATA,
+                                 mac[(i * 2) + 1] | (mac[(i * 2)] << 8));
+       }
+}
+
+static int at803x_config_init(struct phy_device *phydev)
+{
+       int val;
+       u32 features;
+       int status;
+
+       features = SUPPORTED_TP | SUPPORTED_MII | SUPPORTED_AUI |
+                  SUPPORTED_FIBRE | SUPPORTED_BNC;
+
+       val = phy_read(phydev, MII_BMSR);
+       if (val < 0)
+               return val;
+
+       if (val & BMSR_ANEGCAPABLE)
+               features |= SUPPORTED_Autoneg;
+       if (val & BMSR_100FULL)
+               features |= SUPPORTED_100baseT_Full;
+       if (val & BMSR_100HALF)
+               features |= SUPPORTED_100baseT_Half;
+       if (val & BMSR_10FULL)
+               features |= SUPPORTED_10baseT_Full;
+       if (val & BMSR_10HALF)
+               features |= SUPPORTED_10baseT_Half;
+
+       if (val & BMSR_ESTATEN) {
+               val = phy_read(phydev, MII_ESTATUS);
+               if (val < 0)
+                       return val;
+
+               if (val & ESTATUS_1000_TFULL)
+                       features |= SUPPORTED_1000baseT_Full;
+               if (val & ESTATUS_1000_THALF)
+                       features |= SUPPORTED_1000baseT_Half;
+       }
+
+       phydev->supported = features;
+       phydev->advertising = features;
+
+       /* enable WOL */
+       at803x_set_wol_mac_addr(phydev);
+       status = phy_write(phydev, AT803X_INTR_ENABLE, AT803X_WOL_ENABLE);
+       status = phy_read(phydev, AT803X_INTR_STATUS);
+
+       return 0;
+}
+
+/* ATHEROS 8035 */
+static struct phy_driver at8035_driver = {
+       .phy_id         = 0x004dd072,
+       .name           = "Atheros 8035 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+};
+
+/* ATHEROS 8030 */
+static struct phy_driver at8030_driver = {
+       .phy_id         = 0x004dd076,
+       .name           = "Atheros 8030 ethernet",
+       .phy_id_mask    = 0xffffffef,
+       .config_init    = at803x_config_init,
+       .features       = PHY_GBIT_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
+       .config_aneg    = &genphy_config_aneg,
+       .read_status    = &genphy_read_status,
+       .driver         = {
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init atheros_init(void)
+{
+       int ret;
+
+       ret = phy_driver_register(&at8035_driver);
+       if (ret)
+               goto err1;
+
+       ret = phy_driver_register(&at8030_driver);
+       if (ret)
+               goto err2;
+
+       return 0;
+
+err2:
+       phy_driver_unregister(&at8035_driver);
+err1:
+       return ret;
+}
+
+static void __exit atheros_exit(void)
+{
+       phy_driver_unregister(&at8035_driver);
+       phy_driver_unregister(&at8030_driver);
+}
+
+module_init(atheros_init);
+module_exit(atheros_exit);
+
+static struct mdio_device_id __maybe_unused atheros_tbl[] = {
+       { 0x004dd076, 0xffffffef },
+       { 0x004dd072, 0xffffffef },
+       { }
+};
+
+MODULE_DEVICE_TABLE(mdio, atheros_tbl);
index 81c7bc010dd8752fbe2ac97ff5326408ebadaa21..383e8338ad865c3d8fabf5c9722fc883ac3923de 100644 (file)
@@ -150,18 +150,24 @@ static struct phy_driver dm91xx_driver[] = {
        .name           = "Davicom DM9161E",
        .phy_id_mask    = 0x0ffffff0,
        .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
        .config_init    = dm9161_config_init,
        .config_aneg    = dm9161_config_aneg,
        .read_status    = genphy_read_status,
+       .ack_interrupt  = dm9161_ack_interrupt,
+       .config_intr    = dm9161_config_intr,
        .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = 0x0181b8a0,
        .name           = "Davicom DM9161A",
        .phy_id_mask    = 0x0ffffff0,
        .features       = PHY_BASIC_FEATURES,
+       .flags          = PHY_HAS_INTERRUPT,
        .config_init    = dm9161_config_init,
        .config_aneg    = dm9161_config_aneg,
        .read_status    = genphy_read_status,
+       .ack_interrupt  = dm9161_ack_interrupt,
+       .config_intr    = dm9161_config_intr,
        .driver         = { .owner = THIS_MODULE,},
 }, {
        .phy_id         = 0x00181b80,
index 24e05c43bff872e34e35e1deb4d385884057ae4a..7490b6c866e685072f8bef2c0b63a090b4061b10 100644 (file)
 #define CAL_TRIGGER    7
 #define PER_TRIGGER    6
 
+#define MII_DP83640_MICR 0x11
+#define MII_DP83640_MISR 0x12
+
+#define MII_DP83640_MICR_OE 0x1
+#define MII_DP83640_MICR_IE 0x2
+
+#define MII_DP83640_MISR_RHF_INT_EN 0x01
+#define MII_DP83640_MISR_FHF_INT_EN 0x02
+#define MII_DP83640_MISR_ANC_INT_EN 0x04
+#define MII_DP83640_MISR_DUP_INT_EN 0x08
+#define MII_DP83640_MISR_SPD_INT_EN 0x10
+#define MII_DP83640_MISR_LINK_INT_EN 0x20
+#define MII_DP83640_MISR_ED_INT_EN 0x40
+#define MII_DP83640_MISR_LQ_INT_EN 0x80
+
 /* phyter seems to miss the mark by 16 ns */
 #define ADJTIME_FIX    16
 
@@ -1043,6 +1058,65 @@ static void dp83640_remove(struct phy_device *phydev)
        kfree(dp83640);
 }
 
+static int dp83640_ack_interrupt(struct phy_device *phydev)
+{
+       int err = phy_read(phydev, MII_DP83640_MISR);
+
+       if (err < 0)
+               return err;
+
+       return 0;
+}
+
+static int dp83640_config_intr(struct phy_device *phydev)
+{
+       int micr;
+       int misr;
+       int err;
+
+       if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+               misr = phy_read(phydev, MII_DP83640_MISR);
+               if (misr < 0)
+                       return misr;
+               misr |=
+                       (MII_DP83640_MISR_ANC_INT_EN |
+                       MII_DP83640_MISR_DUP_INT_EN |
+                       MII_DP83640_MISR_SPD_INT_EN |
+                       MII_DP83640_MISR_LINK_INT_EN);
+               err = phy_write(phydev, MII_DP83640_MISR, misr);
+               if (err < 0)
+                       return err;
+
+               micr = phy_read(phydev, MII_DP83640_MICR);
+               if (micr < 0)
+                       return micr;
+               micr |=
+                       (MII_DP83640_MICR_OE |
+                       MII_DP83640_MICR_IE);
+               return phy_write(phydev, MII_DP83640_MICR, micr);
+       } else {
+               micr = phy_read(phydev, MII_DP83640_MICR);
+               if (micr < 0)
+                       return micr;
+               micr &=
+                       ~(MII_DP83640_MICR_OE |
+                       MII_DP83640_MICR_IE);
+               err = phy_write(phydev, MII_DP83640_MICR, micr);
+               if (err < 0)
+                       return err;
+
+               misr = phy_read(phydev, MII_DP83640_MISR);
+               if (misr < 0)
+                       return misr;
+               misr &=
+                       ~(MII_DP83640_MISR_ANC_INT_EN |
+                       MII_DP83640_MISR_DUP_INT_EN |
+                       MII_DP83640_MISR_SPD_INT_EN |
+                       MII_DP83640_MISR_LINK_INT_EN);
+               return phy_write(phydev, MII_DP83640_MISR, misr);
+       }
+}
+
 static int dp83640_hwtstamp(struct phy_device *phydev, struct ifreq *ifr)
 {
        struct dp83640_private *dp83640 = phydev->priv;
@@ -1253,11 +1327,13 @@ static struct phy_driver dp83640_driver = {
        .phy_id_mask    = 0xfffffff0,
        .name           = "NatSemi DP83640",
        .features       = PHY_BASIC_FEATURES,
-       .flags          = 0,
+       .flags          = PHY_HAS_INTERRUPT,
        .probe          = dp83640_probe,
        .remove         = dp83640_remove,
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
+       .ack_interrupt  = dp83640_ack_interrupt,
+       .config_intr    = dp83640_config_intr,
        .ts_info        = dp83640_ts_info,
        .hwtstamp       = dp83640_hwtstamp,
        .rxtstamp       = dp83640_rxtstamp,
index 899274f2f9b1dd1da0aac0442807b6e42b0cddc2..27274986ab56eb7580788bd376f1b3893388d173 100644 (file)
@@ -103,9 +103,9 @@ static struct mdiobb_ops mdio_gpio_ops = {
        .get_mdio_data = mdio_get,
 };
 
-static struct mii_bus * __devinit mdio_gpio_bus_init(struct device *dev,
-                                       struct mdio_gpio_platform_data *pdata,
-                                       int bus_id)
+static struct mii_bus *mdio_gpio_bus_init(struct device *dev,
+                                         struct mdio_gpio_platform_data *pdata,
+                                         int bus_id)
 {
        struct mii_bus *new_bus;
        struct mdio_gpio_info *bitbang;
@@ -173,7 +173,7 @@ static void mdio_gpio_bus_deinit(struct device *dev)
        kfree(bitbang);
 }
 
-static void __devexit mdio_gpio_bus_destroy(struct device *dev)
+static void mdio_gpio_bus_destroy(struct device *dev)
 {
        struct mii_bus *bus = dev_get_drvdata(dev);
 
@@ -181,21 +181,24 @@ static void __devexit mdio_gpio_bus_destroy(struct device *dev)
        mdio_gpio_bus_deinit(dev);
 }
 
-static int __devinit mdio_gpio_probe(struct platform_device *pdev)
+static int mdio_gpio_probe(struct platform_device *pdev)
 {
        struct mdio_gpio_platform_data *pdata;
        struct mii_bus *new_bus;
-       int ret;
+       int ret, bus_id;
 
-       if (pdev->dev.of_node)
+       if (pdev->dev.of_node) {
                pdata = mdio_gpio_of_get_data(pdev);
-       else
+               bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio");
+       } else {
                pdata = pdev->dev.platform_data;
+               bus_id = pdev->id;
+       }
 
        if (!pdata)
                return -ENODEV;
 
-       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, bus_id);
        if (!new_bus)
                return -ENODEV;
 
@@ -210,7 +213,7 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit mdio_gpio_remove(struct platform_device *pdev)
+static int mdio_gpio_remove(struct platform_device *pdev)
 {
        mdio_gpio_bus_destroy(&pdev->dev);
 
@@ -224,7 +227,7 @@ static struct of_device_id mdio_gpio_of_match[] = {
 
 static struct platform_driver mdio_gpio_driver = {
        .probe = mdio_gpio_probe,
-       .remove = __devexit_p(mdio_gpio_remove),
+       .remove = mdio_gpio_remove,
        .driver         = {
                .name   = "mdio-gpio",
                .owner  = THIS_MODULE,
index eefe49e8713ca633c8383b1c388826f45e5c9e0c..0c9accb1c14f6a4abbb62641b6ec14fbb07a28ad 100644 (file)
@@ -49,7 +49,7 @@ static int mdio_mux_gpio_switch_fn(int current_child, int desired_child,
        return 0;
 }
 
-static int __devinit mdio_mux_gpio_probe(struct platform_device *pdev)
+static int mdio_mux_gpio_probe(struct platform_device *pdev)
 {
        enum of_gpio_flags f;
        struct mdio_mux_gpio_state *s;
@@ -104,7 +104,7 @@ err:
        return r;
 }
 
-static int __devexit mdio_mux_gpio_remove(struct platform_device *pdev)
+static int mdio_mux_gpio_remove(struct platform_device *pdev)
 {
        struct mdio_mux_gpio_state *s = pdev->dev.platform_data;
        mdio_mux_uninit(s->mux_handle);
@@ -130,7 +130,7 @@ static struct platform_driver mdio_mux_gpio_driver = {
                .of_match_table = mdio_mux_gpio_match,
        },
        .probe          = mdio_mux_gpio_probe,
-       .remove         = __devexit_p(mdio_mux_gpio_remove),
+       .remove         = mdio_mux_gpio_remove,
 };
 
 module_platform_driver(mdio_mux_gpio_driver);
index 9061ba622ac4c44223eb170e4bd0c5c34ae0d79e..9733bd239a866d4a38552c8c41fb9b9864b6e50f 100644 (file)
@@ -67,7 +67,7 @@ static int mdio_mux_mmioreg_switch_fn(int current_child, int desired_child,
        return 0;
 }
 
-static int __devinit mdio_mux_mmioreg_probe(struct platform_device *pdev)
+static int mdio_mux_mmioreg_probe(struct platform_device *pdev)
 {
        struct device_node *np2, *np = pdev->dev.of_node;
        struct mdio_mux_mmioreg_state *s;
@@ -137,7 +137,7 @@ static int __devinit mdio_mux_mmioreg_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit mdio_mux_mmioreg_remove(struct platform_device *pdev)
+static int mdio_mux_mmioreg_remove(struct platform_device *pdev)
 {
        struct mdio_mux_mmioreg_state *s = dev_get_platdata(&pdev->dev);
 
@@ -161,7 +161,7 @@ static struct platform_driver mdio_mux_mmioreg_driver = {
                .of_match_table = mdio_mux_mmioreg_match,
        },
        .probe          = mdio_mux_mmioreg_probe,
-       .remove         = __devexit_p(mdio_mux_mmioreg_remove),
+       .remove         = mdio_mux_mmioreg_remove,
 };
 
 module_platform_driver(mdio_mux_mmioreg_driver);
index d4015aa663e6422f7be98e6d8f7f07f1561592de..09297fe05ae5fd6e1d666d500ac06b6ec4d9a3fc 100644 (file)
@@ -96,7 +96,7 @@ static int octeon_mdiobus_write(struct mii_bus *bus, int phy_id,
        return 0;
 }
 
-static int __devinit octeon_mdiobus_probe(struct platform_device *pdev)
+static int octeon_mdiobus_probe(struct platform_device *pdev)
 {
        struct octeon_mdiobus *bus;
        struct resource *res_mem;
@@ -159,7 +159,7 @@ fail:
        return err;
 }
 
-static int __devexit octeon_mdiobus_remove(struct platform_device *pdev)
+static int octeon_mdiobus_remove(struct platform_device *pdev)
 {
        struct octeon_mdiobus *bus;
        union cvmx_smix_en smi_en;
@@ -188,7 +188,7 @@ static struct platform_driver octeon_mdiobus_driver = {
                .of_match_table = octeon_mdiobus_match,
        },
        .probe          = octeon_mdiobus_probe,
-       .remove         = __devexit_p(octeon_mdiobus_remove),
+       .remove         = octeon_mdiobus_remove,
 };
 
 void octeon_mdiobus_force_mod_depencency(void)
index c1ef3000ea6065a9c394ae1fef99e0fa76bd852f..044b5326459fe807fc53e7af30de56c630c5cad3 100644 (file)
@@ -431,10 +431,24 @@ static struct dev_pm_ops mdio_bus_pm_ops = {
 
 #endif /* CONFIG_PM */
 
+static ssize_t
+phy_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct phy_device *phydev = to_phy_device(dev);
+
+       return sprintf(buf, "0x%.8lx\n", (unsigned long)phydev->phy_id);
+}
+
+static struct device_attribute mdio_dev_attrs[] = {
+       __ATTR_RO(phy_id),
+       __ATTR_NULL
+};
+
 struct bus_type mdio_bus_type = {
        .name           = "mdio_bus",
        .match          = mdio_bus_match,
        .pm             = MDIO_BUS_PM_OPS,
+       .dev_attrs      = mdio_dev_attrs,
 };
 EXPORT_SYMBOL(mdio_bus_type);
 
index 2165d5fdb8c0f08675772f8dded60f3a15ac34ba..b983596abcbb740bb6416646afe0f401dbf0eaa7 100644 (file)
@@ -127,6 +127,39 @@ static int ks8051_config_init(struct phy_device *phydev)
        return 0;
 }
 
+#define KSZ8873MLL_GLOBAL_CONTROL_4    0x06
+#define KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX     (1 << 6)
+#define KSZ8873MLL_GLOBAL_CONTROL_4_SPEED      (1 << 4)
+int ksz8873mll_read_status(struct phy_device *phydev)
+{
+       int regval;
+
+       /* dummy read */
+       regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+
+       regval = phy_read(phydev, KSZ8873MLL_GLOBAL_CONTROL_4);
+
+       if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_DUPLEX)
+               phydev->duplex = DUPLEX_HALF;
+       else
+               phydev->duplex = DUPLEX_FULL;
+
+       if (regval & KSZ8873MLL_GLOBAL_CONTROL_4_SPEED)
+               phydev->speed = SPEED_10;
+       else
+               phydev->speed = SPEED_100;
+
+       phydev->link = 1;
+       phydev->pause = phydev->asym_pause = 0;
+
+       return 0;
+}
+
+static int ksz8873mll_config_aneg(struct phy_device *phydev)
+{
+       return 0;
+}
+
 static struct phy_driver ksphy_driver[] = {
 {
        .phy_id         = PHY_ID_KS8737,
@@ -204,6 +237,16 @@ static struct phy_driver ksphy_driver[] = {
        .ack_interrupt  = kszphy_ack_interrupt,
        .config_intr    = ksz9021_config_intr,
        .driver         = { .owner = THIS_MODULE, },
+}, {
+       .phy_id         = PHY_ID_KSZ8873MLL,
+       .phy_id_mask    = 0x00fffff0,
+       .name           = "Micrel KSZ8873MLL Switch",
+       .features       = (SUPPORTED_Pause | SUPPORTED_Asym_Pause),
+       .flags          = PHY_HAS_MAGICANEG,
+       .config_init    = kszphy_config_init,
+       .config_aneg    = ksz8873mll_config_aneg,
+       .read_status    = ksz8873mll_read_status,
+       .driver         = { .owner = THIS_MODULE, },
 } };
 
 static int __init ksphy_init(void)
@@ -232,6 +275,7 @@ static struct mdio_device_id __maybe_unused micrel_tbl[] = {
        { PHY_ID_KSZ8021, 0x00ffffff },
        { PHY_ID_KSZ8041, 0x00fffff0 },
        { PHY_ID_KSZ8051, 0x00fffff0 },
+       { PHY_ID_KSZ8873MLL, 0x00fffff0 },
        { }
 };
 
index 88e3991464e7e1531934bcb562718e97abcbfb9b..11f34813e23fb5423ccf90cf9d25e208ed2275f3 100644 (file)
@@ -43,7 +43,31 @@ static int smsc_phy_ack_interrupt(struct phy_device *phydev)
 
 static int smsc_phy_config_init(struct phy_device *phydev)
 {
-       int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+       int rc = phy_read(phydev, MII_LAN83C185_SPECIAL_MODES);
+       if (rc < 0)
+               return rc;
+
+       /* If the SMSC PHY is in power down mode, then set it
+        * in all capable mode before using it.
+        */
+       if ((rc & MII_LAN83C185_MODE_MASK) == MII_LAN83C185_MODE_POWERDOWN) {
+               int timeout = 50000;
+
+               /* set "all capable" mode and reset the phy */
+               rc |= MII_LAN83C185_MODE_ALL;
+               phy_write(phydev, MII_LAN83C185_SPECIAL_MODES, rc);
+               phy_write(phydev, MII_BMCR, BMCR_RESET);
+
+               /* wait end of reset (max 500 ms) */
+               do {
+                       udelay(10);
+                       if (timeout-- == 0)
+                               return -1;
+                       rc = phy_read(phydev, MII_BMCR);
+               } while (rc & BMCR_RESET);
+       }
+
+       rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
        if (rc < 0)
                return rc;
 
@@ -56,35 +80,52 @@ static int smsc_phy_config_init(struct phy_device *phydev)
        return smsc_phy_ack_interrupt (phydev);
 }
 
-static int lan87xx_config_init(struct phy_device *phydev)
+static int lan911x_config_init(struct phy_device *phydev)
 {
-       /*
-        * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
-        * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
-        * to a bug on the chip.
-        *
-        * When the system is powered on with the network cable being
-        * disconnected all the way until after ifconfig ethX up is
-        * issued for the LAN port with this PHY, connecting the cable
-        * afterwards does not cause LINK change detection, while the
-        * expected behavior is the Link UP being detected.
-        */
-       int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
-       if (rc < 0)
-               return rc;
-
-       rc &= ~MII_LAN83C185_EDPWRDOWN;
-
-       rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
-       if (rc < 0)
-               return rc;
-
        return smsc_phy_ack_interrupt(phydev);
 }
 
-static int lan911x_config_init(struct phy_device *phydev)
+/*
+ * The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
+ * other in order to set the ENERGYON bit and exit EDPD mode.  If a link partner
+ * does send the pulses within this interval, the PHY will remained powered
+ * down.
+ *
+ * This workaround will manually toggle the PHY on/off upon calls to read_status
+ * in order to generate link test pulses if the link is down.  If a link partner
+ * is present, it will respond to the pulses, which will cause the ENERGYON bit
+ * to be set and will cause the EDPD mode to be exited.
+ */
+static int lan87xx_read_status(struct phy_device *phydev)
 {
-       return smsc_phy_ack_interrupt(phydev);
+       int err = genphy_read_status(phydev);
+
+       if (!phydev->link) {
+               /* Disable EDPD to wake up PHY */
+               int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+               if (rc < 0)
+                       return rc;
+
+               rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+                              rc & ~MII_LAN83C185_EDPWRDOWN);
+               if (rc < 0)
+                       return rc;
+
+               /* Sleep 64 ms to allow ~5 link test pulses to be sent */
+               msleep(64);
+
+               /* Re-enable EDPD */
+               rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+               if (rc < 0)
+                       return rc;
+
+               rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS,
+                              rc | MII_LAN83C185_EDPWRDOWN);
+               if (rc < 0)
+                       return rc;
+       }
+
+       return err;
 }
 
 static struct phy_driver smsc_phy_driver[] = {
@@ -187,8 +228,8 @@ static struct phy_driver smsc_phy_driver[] = {
 
        /* basic functions */
        .config_aneg    = genphy_config_aneg,
-       .read_status    = genphy_read_status,
-       .config_init    = lan87xx_config_init,
+       .read_status    = lan87xx_read_status,
+       .config_init    = smsc_phy_config_init,
 
        /* IRQ related */
        .ack_interrupt  = smsc_phy_ack_interrupt,
index 1c3abce78b6a2bdc5f212f31a8779dd012be107e..41eb8ffeb53d72b4357a02782238e0c34bdb42f7 100644 (file)
@@ -264,7 +264,7 @@ static struct bin_attribute ks8995_registers_attr = {
 
 /* ------------------------------------------------------------------------ */
 
-static int __devinit ks8995_probe(struct spi_device *spi)
+static int ks8995_probe(struct spi_device *spi)
 {
        struct ks8995_switch    *ks;
        struct ks8995_pdata     *pdata;
@@ -332,7 +332,7 @@ err_drvdata:
        return err;
 }
 
-static int __devexit ks8995_remove(struct spi_device *spi)
+static int ks8995_remove(struct spi_device *spi)
 {
        struct ks8995_data      *ks8995;
 
@@ -353,7 +353,7 @@ static struct spi_driver ks8995_driver = {
                .owner     = THIS_MODULE,
        },
        .probe    = ks8995_probe,
-       .remove   = __devexit_p(ks8995_remove),
+       .remove   = ks8995_remove,
 };
 
 static int __init ks8995_init(void)
index eb3f5cefeba3c6ddcbd53a44cb63a759d9b803ef..0b2706abe3e3b06dbd158eff440d8c2ccc4fb50b 100644 (file)
@@ -1034,7 +1034,7 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        return err;
 }
 
-struct rtnl_link_stats64*
+static struct rtnl_link_stats64*
 ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
 {
        struct ppp *ppp = netdev_priv(dev);
index d44cca327588858e26023a99cee8c64a940cf173..ad86660fb8f92b092f06c9b41d03e416991f4636 100644 (file)
@@ -1794,10 +1794,12 @@ static void team_setup(struct net_device *dev)
 
        dev->features |= NETIF_F_LLTX;
        dev->features |= NETIF_F_GRO;
-       dev->hw_features = NETIF_F_HW_VLAN_TX |
+       dev->hw_features = TEAM_VLAN_FEATURES |
+                          NETIF_F_HW_VLAN_TX |
                           NETIF_F_HW_VLAN_RX |
                           NETIF_F_HW_VLAN_FILTER;
 
+       dev->hw_features &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_HW_CSUM);
        dev->features |= dev->hw_features;
 }
 
index 9db0171e93669f483eeae19791ed4e090c333bb0..c5db428e73fa2200f3ef8a5ea5124ceeebb6ef78 100644 (file)
@@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
                        if (last) {
                                skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2) {
-                                       ret = team_dev_queue_xmit(team, last,
-                                                                 skb2);
+                                       ret = !team_dev_queue_xmit(team, last,
+                                                                  skb2);
                                        if (!sum_ret)
                                                sum_ret = ret;
                                }
@@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
                }
        }
        if (last) {
-               ret = team_dev_queue_xmit(team, last, skb);
+               ret = !team_dev_queue_xmit(team, last, skb);
                if (!sum_ret)
                        sum_ret = ret;
        }
index 0873cdcf39bebb09d75b1cadbffce4c2d614f593..2ac2164a1e39bd70b0a046ee6dc7df05b76e1045 100644 (file)
@@ -68,7 +68,6 @@
 #include <net/netns/generic.h>
 #include <net/rtnetlink.h>
 #include <net/sock.h>
-#include <net/cls_cgroup.h>
 
 #include <asm/uaccess.h>
 
@@ -110,16 +109,56 @@ struct tap_filter {
        unsigned char   addr[FLT_EXACT_COUNT][ETH_ALEN];
 };
 
+/* 1024 is probably a high enough limit: modern hypervisors seem to support on
+ * the order of 100-200 CPUs so this leaves us some breathing space if we want
+ * to match a queue per guest CPU.
+ */
+#define MAX_TAP_QUEUES 1024
+
+#define TUN_FLOW_EXPIRE (3 * HZ)
+
+/* A tun_file connects an open character device to a tuntap netdevice. It
+ * also contains all socket related strctures (except sock_fprog and tap_filter)
+ * to serve as one transmit queue for tuntap device. The sock_fprog and
+ * tap_filter were kept in tun_struct since they were used for filtering for the
+ * netdevice not for a specific queue (at least I didn't see the requirement for
+ * this).
+ *
+ * RCU usage:
+ * The tun_file and tun_struct are loosely coupled, the pointer from one to the
+ * other can only be read while rcu_read_lock or rtnl_lock is held.
+ */
 struct tun_file {
-       atomic_t count;
-       struct tun_struct *tun;
+       struct sock sk;
+       struct socket socket;
+       struct socket_wq wq;
+       struct tun_struct __rcu *tun;
        struct net *net;
+       struct fasync_struct *fasync;
+       /* only used for fasnyc */
+       unsigned int flags;
+       u16 queue_index;
+};
+
+struct tun_flow_entry {
+       struct hlist_node hash_link;
+       struct rcu_head rcu;
+       struct tun_struct *tun;
+
+       u32 rxhash;
+       int queue_index;
+       unsigned long updated;
 };
 
-struct tun_sock;
+#define TUN_NUM_FLOW_ENTRIES 1024
 
+/* Since the socket were moved to tun_file, to preserve the behavior of persist
+ * device, socket filter, sndbuf and vnet header size were restore when the
+ * file were attached to a persist device.
+ */
 struct tun_struct {
-       struct tun_file         *tfile;
+       struct tun_file __rcu   *tfiles[MAX_TAP_QUEUES];
+       unsigned int            numqueues;
        unsigned int            flags;
        kuid_t                  owner;
        kgid_t                  group;
@@ -128,88 +167,349 @@ struct tun_struct {
        netdev_features_t       set_features;
 #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
                          NETIF_F_TSO6|NETIF_F_UFO)
-       struct fasync_struct    *fasync;
-
-       struct tap_filter       txflt;
-       struct socket           socket;
-       struct socket_wq        wq;
 
        int                     vnet_hdr_sz;
-
+       int                     sndbuf;
+       struct tap_filter       txflt;
+       struct sock_fprog       fprog;
+       /* protected by rtnl lock */
+       bool                    filter_attached;
 #ifdef TUN_DEBUG
        int debug;
 #endif
+       spinlock_t lock;
+       struct kmem_cache *flow_cache;
+       struct hlist_head flows[TUN_NUM_FLOW_ENTRIES];
+       struct timer_list flow_gc_timer;
+       unsigned long ageing_time;
 };
 
-struct tun_sock {
-       struct sock             sk;
-       struct tun_struct       *tun;
-};
+static inline u32 tun_hashfn(u32 rxhash)
+{
+       return rxhash & 0x3ff;
+}
 
-static inline struct tun_sock *tun_sk(struct sock *sk)
+static struct tun_flow_entry *tun_flow_find(struct hlist_head *head, u32 rxhash)
 {
-       return container_of(sk, struct tun_sock, sk);
+       struct tun_flow_entry *e;
+       struct hlist_node *n;
+
+       hlist_for_each_entry_rcu(e, n, head, hash_link) {
+               if (e->rxhash == rxhash)
+                       return e;
+       }
+       return NULL;
 }
 
-static int tun_attach(struct tun_struct *tun, struct file *file)
+static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun,
+                                             struct hlist_head *head,
+                                             u32 rxhash, u16 queue_index)
 {
-       struct tun_file *tfile = file->private_data;
-       int err;
+       struct tun_flow_entry *e = kmem_cache_alloc(tun->flow_cache,
+                                                   GFP_ATOMIC);
+       if (e) {
+               tun_debug(KERN_INFO, tun, "create flow: hash %u index %u\n",
+                         rxhash, queue_index);
+               e->updated = jiffies;
+               e->rxhash = rxhash;
+               e->queue_index = queue_index;
+               e->tun = tun;
+               hlist_add_head_rcu(&e->hash_link, head);
+       }
+       return e;
+}
 
-       ASSERT_RTNL();
+static void tun_flow_free(struct rcu_head *head)
+{
+       struct tun_flow_entry *e
+               = container_of(head, struct tun_flow_entry, rcu);
+       kmem_cache_free(e->tun->flow_cache, e);
+}
 
-       netif_tx_lock_bh(tun->dev);
+static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e)
+{
+       tun_debug(KERN_INFO, tun, "delete flow: hash %u index %u\n",
+                 e->rxhash, e->queue_index);
+       hlist_del_rcu(&e->hash_link);
+       call_rcu(&e->rcu, tun_flow_free);
+}
 
-       err = -EINVAL;
-       if (tfile->tun)
-               goto out;
+static void tun_flow_flush(struct tun_struct *tun)
+{
+       int i;
 
-       err = -EBUSY;
-       if (tun->tfile)
-               goto out;
+       spin_lock_bh(&tun->lock);
+       for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+               struct tun_flow_entry *e;
+               struct hlist_node *h, *n;
 
-       err = 0;
-       tfile->tun = tun;
-       tun->tfile = tfile;
-       tun->socket.file = file;
-       netif_carrier_on(tun->dev);
-       dev_hold(tun->dev);
-       sock_hold(tun->socket.sk);
-       atomic_inc(&tfile->count);
+               hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link)
+                       tun_flow_delete(tun, e);
+       }
+       spin_unlock_bh(&tun->lock);
+}
 
-out:
-       netif_tx_unlock_bh(tun->dev);
-       return err;
+static void tun_flow_delete_by_queue(struct tun_struct *tun, u16 queue_index)
+{
+       int i;
+
+       spin_lock_bh(&tun->lock);
+       for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+               struct tun_flow_entry *e;
+               struct hlist_node *h, *n;
+
+               hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link) {
+                       if (e->queue_index == queue_index)
+                               tun_flow_delete(tun, e);
+               }
+       }
+       spin_unlock_bh(&tun->lock);
 }
 
-static void __tun_detach(struct tun_struct *tun)
+static void tun_flow_cleanup(unsigned long data)
 {
-       /* Detach from net device */
-       netif_tx_lock_bh(tun->dev);
-       netif_carrier_off(tun->dev);
-       tun->tfile = NULL;
-       netif_tx_unlock_bh(tun->dev);
+       struct tun_struct *tun = (struct tun_struct *)data;
+       unsigned long delay = tun->ageing_time;
+       unsigned long next_timer = jiffies + delay;
+       unsigned long count = 0;
+       int i;
 
-       /* Drop read queue */
-       skb_queue_purge(&tun->socket.sk->sk_receive_queue);
+       tun_debug(KERN_INFO, tun, "tun_flow_cleanup\n");
+
+       spin_lock_bh(&tun->lock);
+       for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
+               struct tun_flow_entry *e;
+               struct hlist_node *h, *n;
+
+               hlist_for_each_entry_safe(e, h, n, &tun->flows[i], hash_link) {
+                       unsigned long this_timer;
+                       count++;
+                       this_timer = e->updated + delay;
+                       if (time_before_eq(this_timer, jiffies))
+                               tun_flow_delete(tun, e);
+                       else if (time_before(this_timer, next_timer))
+                               next_timer = this_timer;
+               }
+       }
 
-       /* Drop the extra count on the net device */
-       dev_put(tun->dev);
+       if (count)
+               mod_timer(&tun->flow_gc_timer, round_jiffies_up(next_timer));
+       spin_unlock_bh(&tun->lock);
 }
 
-static void tun_detach(struct tun_struct *tun)
+static void tun_flow_update(struct tun_struct *tun, struct sk_buff *skb,
+                           u16 queue_index)
+{
+       struct hlist_head *head;
+       struct tun_flow_entry *e;
+       unsigned long delay = tun->ageing_time;
+       u32 rxhash = skb_get_rxhash(skb);
+
+       if (!rxhash)
+               return;
+       else
+               head = &tun->flows[tun_hashfn(rxhash)];
+
+       rcu_read_lock();
+
+       if (tun->numqueues == 1)
+               goto unlock;
+
+       e = tun_flow_find(head, rxhash);
+       if (likely(e)) {
+               /* TODO: keep queueing to old queue until it's empty? */
+               e->queue_index = queue_index;
+               e->updated = jiffies;
+       } else {
+               spin_lock_bh(&tun->lock);
+               if (!tun_flow_find(head, rxhash))
+                       tun_flow_create(tun, head, rxhash, queue_index);
+
+               if (!timer_pending(&tun->flow_gc_timer))
+                       mod_timer(&tun->flow_gc_timer,
+                                 round_jiffies_up(jiffies + delay));
+               spin_unlock_bh(&tun->lock);
+       }
+
+unlock:
+       rcu_read_unlock();
+}
+
+/* We try to identify a flow through its rxhash first. The reason that
+ * we do not check rxq no. is becuase some cards(e.g 82599), chooses
+ * the rxq based on the txq where the last packet of the flow comes. As
+ * the userspace application move between processors, we may get a
+ * different rxq no. here. If we could not get rxhash, then we would
+ * hope the rxq no. may help here.
+ */
+static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+       struct tun_struct *tun = netdev_priv(dev);
+       struct tun_flow_entry *e;
+       u32 txq = 0;
+       u32 numqueues = 0;
+
+       rcu_read_lock();
+       numqueues = tun->numqueues;
+
+       txq = skb_get_rxhash(skb);
+       if (txq) {
+               e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
+               if (e)
+                       txq = e->queue_index;
+               else
+                       /* use multiply and shift instead of expensive divide */
+                       txq = ((u64)txq * numqueues) >> 32;
+       } else if (likely(skb_rx_queue_recorded(skb))) {
+               txq = skb_get_rx_queue(skb);
+               while (unlikely(txq >= numqueues))
+                       txq -= numqueues;
+       }
+
+       rcu_read_unlock();
+       return txq;
+}
+
+static inline bool tun_not_capable(struct tun_struct *tun)
+{
+       const struct cred *cred = current_cred();
+       struct net *net = dev_net(tun->dev);
+
+       return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
+                 (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
+               !ns_capable(net->user_ns, CAP_NET_ADMIN);
+}
+
+static void tun_set_real_num_queues(struct tun_struct *tun)
+{
+       netif_set_real_num_tx_queues(tun->dev, tun->numqueues);
+       netif_set_real_num_rx_queues(tun->dev, tun->numqueues);
+}
+
+static void __tun_detach(struct tun_file *tfile, bool clean)
+{
+       struct tun_file *ntfile;
+       struct tun_struct *tun;
+       struct net_device *dev;
+
+       tun = rcu_dereference_protected(tfile->tun,
+                                       lockdep_rtnl_is_held());
+       if (tun) {
+               u16 index = tfile->queue_index;
+               BUG_ON(index >= tun->numqueues);
+               dev = tun->dev;
+
+               rcu_assign_pointer(tun->tfiles[index],
+                                  tun->tfiles[tun->numqueues - 1]);
+               rcu_assign_pointer(tfile->tun, NULL);
+               ntfile = rcu_dereference_protected(tun->tfiles[index],
+                                                  lockdep_rtnl_is_held());
+               ntfile->queue_index = index;
+
+               --tun->numqueues;
+               sock_put(&tfile->sk);
+
+               synchronize_net();
+               tun_flow_delete_by_queue(tun, tun->numqueues + 1);
+               /* Drop read queue */
+               skb_queue_purge(&tfile->sk.sk_receive_queue);
+               tun_set_real_num_queues(tun);
+
+               if (tun->numqueues == 0 && !(tun->flags & TUN_PERSIST))
+                       if (dev->reg_state == NETREG_REGISTERED)
+                               unregister_netdevice(dev);
+       }
+
+       if (clean) {
+               BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED,
+                                &tfile->socket.flags));
+               sk_release_kernel(&tfile->sk);
+       }
+}
+
+static void tun_detach(struct tun_file *tfile, bool clean)
 {
        rtnl_lock();
-       __tun_detach(tun);
+       __tun_detach(tfile, clean);
        rtnl_unlock();
 }
 
+static void tun_detach_all(struct net_device *dev)
+{
+       struct tun_struct *tun = netdev_priv(dev);
+       struct tun_file *tfile;
+       int i, n = tun->numqueues;
+
+       for (i = 0; i < n; i++) {
+               tfile = rcu_dereference_protected(tun->tfiles[i],
+                                                 lockdep_rtnl_is_held());
+               BUG_ON(!tfile);
+               wake_up_all(&tfile->wq.wait);
+               rcu_assign_pointer(tfile->tun, NULL);
+               --tun->numqueues;
+       }
+       BUG_ON(tun->numqueues != 0);
+
+       synchronize_net();
+       for (i = 0; i < n; i++) {
+               tfile = rcu_dereference_protected(tun->tfiles[i],
+                                                 lockdep_rtnl_is_held());
+               /* Drop read queue */
+               skb_queue_purge(&tfile->sk.sk_receive_queue);
+               sock_put(&tfile->sk);
+       }
+}
+
+static int tun_attach(struct tun_struct *tun, struct file *file)
+{
+       struct tun_file *tfile = file->private_data;
+       int err;
+
+       err = -EINVAL;
+       if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held()))
+               goto out;
+
+       err = -EBUSY;
+       if (!(tun->flags & TUN_TAP_MQ) && tun->numqueues == 1)
+               goto out;
+
+       err = -E2BIG;
+       if (tun->numqueues == MAX_TAP_QUEUES)
+               goto out;
+
+       err = 0;
+
+       /* Re-attach the filter to presist device */
+       if (tun->filter_attached == true) {
+               err = sk_attach_filter(&tun->fprog, tfile->socket.sk);
+               if (!err)
+                       goto out;
+       }
+       tfile->queue_index = tun->numqueues;
+       rcu_assign_pointer(tfile->tun, tun);
+       rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+       sock_hold(&tfile->sk);
+       tun->numqueues++;
+
+       tun_set_real_num_queues(tun);
+
+       /* device is allowed to go away first, so no need to hold extra
+        * refcnt.
+        */
+
+out:
+       return err;
+}
+
 static struct tun_struct *__tun_get(struct tun_file *tfile)
 {
-       struct tun_struct *tun = NULL;
+       struct tun_struct *tun;
 
-       if (atomic_inc_not_zero(&tfile->count))
-               tun = tfile->tun;
+       rcu_read_lock();
+       tun = rcu_dereference(tfile->tun);
+       if (tun)
+               dev_hold(tun->dev);
+       rcu_read_unlock();
 
        return tun;
 }
@@ -221,10 +521,7 @@ static struct tun_struct *tun_get(struct file *file)
 
 static void tun_put(struct tun_struct *tun)
 {
-       struct tun_file *tfile = tun->tfile;
-
-       if (atomic_dec_and_test(&tfile->count))
-               tun_detach(tfile->tun);
+       dev_put(tun->dev);
 }
 
 /* TAP filtering */
@@ -344,38 +641,20 @@ static const struct ethtool_ops tun_ethtool_ops;
 /* Net device detach from fd. */
 static void tun_net_uninit(struct net_device *dev)
 {
-       struct tun_struct *tun = netdev_priv(dev);
-       struct tun_file *tfile = tun->tfile;
-
-       /* Inform the methods they need to stop using the dev.
-        */
-       if (tfile) {
-               wake_up_all(&tun->wq.wait);
-               if (atomic_dec_and_test(&tfile->count))
-                       __tun_detach(tun);
-       }
-}
-
-static void tun_free_netdev(struct net_device *dev)
-{
-       struct tun_struct *tun = netdev_priv(dev);
-
-       BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags));
-
-       sk_release_kernel(tun->socket.sk);
+       tun_detach_all(dev);
 }
 
 /* Net device open. */
 static int tun_net_open(struct net_device *dev)
 {
-       netif_start_queue(dev);
+       netif_tx_start_all_queues(dev);
        return 0;
 }
 
 /* Net device close. */
 static int tun_net_close(struct net_device *dev)
 {
-       netif_stop_queue(dev);
+       netif_tx_stop_all_queues(dev);
        return 0;
 }
 
@@ -383,38 +662,36 @@ static int tun_net_close(struct net_device *dev)
 static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct tun_struct *tun = netdev_priv(dev);
+       int txq = skb->queue_mapping;
+       struct tun_file *tfile;
 
-       tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
+       rcu_read_lock();
+       tfile = rcu_dereference(tun->tfiles[txq]);
 
        /* Drop packet if interface is not attached */
-       if (!tun->tfile)
+       if (txq >= tun->numqueues)
                goto drop;
 
+       tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
+
+       BUG_ON(!tfile);
+
        /* Drop if the filter does not like it.
         * This is a noop if the filter is disabled.
         * Filter can be enabled only for the TAP devices. */
        if (!check_filter(&tun->txflt, skb))
                goto drop;
 
-       if (tun->socket.sk->sk_filter &&
-           sk_filter(tun->socket.sk, skb))
+       if (tfile->socket.sk->sk_filter &&
+           sk_filter(tfile->socket.sk, skb))
                goto drop;
 
-       if (skb_queue_len(&tun->socket.sk->sk_receive_queue) >= dev->tx_queue_len) {
-               if (!(tun->flags & TUN_ONE_QUEUE)) {
-                       /* Normal queueing mode. */
-                       /* Packet scheduler handles dropping of further packets. */
-                       netif_stop_queue(dev);
-
-                       /* We won't see all dropped packets individually, so overrun
-                        * error is more appropriate. */
-                       dev->stats.tx_fifo_errors++;
-               } else {
-                       /* Single queue mode.
-                        * Driver handles dropping of all packets itself. */
-                       goto drop;
-               }
-       }
+       /* Limit the number of packets queued by dividing txq length with the
+        * number of queues.
+        */
+       if (skb_queue_len(&tfile->socket.sk->sk_receive_queue)
+                         >= dev->tx_queue_len / tun->numqueues)
+               goto drop;
 
        /* Orphan the skb - required as we might hang on to it
         * for indefinite time. */
@@ -423,18 +700,22 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
        skb_orphan(skb);
 
        /* Enqueue packet */
-       skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb);
+       skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb);
 
        /* Notify and wake up reader process */
-       if (tun->flags & TUN_FASYNC)
-               kill_fasync(&tun->fasync, SIGIO, POLL_IN);
-       wake_up_interruptible_poll(&tun->wq.wait, POLLIN |
+       if (tfile->flags & TUN_FASYNC)
+               kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
+       wake_up_interruptible_poll(&tfile->wq.wait, POLLIN |
                                   POLLRDNORM | POLLRDBAND);
+
+       rcu_read_unlock();
        return NETDEV_TX_OK;
 
 drop:
        dev->stats.tx_dropped++;
+       skb_tx_error(skb);
        kfree_skb(skb);
+       rcu_read_unlock();
        return NETDEV_TX_OK;
 }
 
@@ -490,6 +771,7 @@ static const struct net_device_ops tun_netdev_ops = {
        .ndo_start_xmit         = tun_net_xmit,
        .ndo_change_mtu         = tun_net_change_mtu,
        .ndo_fix_features       = tun_net_fix_features,
+       .ndo_select_queue       = tun_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = tun_poll_controller,
 #endif
@@ -505,11 +787,43 @@ static const struct net_device_ops tap_netdev_ops = {
        .ndo_set_rx_mode        = tun_net_mclist,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
+       .ndo_select_queue       = tun_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller    = tun_poll_controller,
 #endif
 };
 
+static int tun_flow_init(struct tun_struct *tun)
+{
+       int i;
+
+       tun->flow_cache = kmem_cache_create("tun_flow_cache",
+                                           sizeof(struct tun_flow_entry), 0, 0,
+                                           NULL);
+       if (!tun->flow_cache)
+               return -ENOMEM;
+
+       for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++)
+               INIT_HLIST_HEAD(&tun->flows[i]);
+
+       tun->ageing_time = TUN_FLOW_EXPIRE;
+       setup_timer(&tun->flow_gc_timer, tun_flow_cleanup, (unsigned long)tun);
+       mod_timer(&tun->flow_gc_timer,
+                 round_jiffies_up(jiffies + tun->ageing_time));
+
+       return 0;
+}
+
+static void tun_flow_uninit(struct tun_struct *tun)
+{
+       del_timer_sync(&tun->flow_gc_timer);
+       tun_flow_flush(tun);
+
+       /* Wait for completion of call_rcu()'s */
+       rcu_barrier();
+       kmem_cache_destroy(tun->flow_cache);
+}
+
 /* Initialize net device. */
 static void tun_net_init(struct net_device *dev)
 {
@@ -535,6 +849,7 @@ static void tun_net_init(struct net_device *dev)
                /* Ethernet TAP Device */
                ether_setup(dev);
                dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+               dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
                eth_hw_addr_random(dev);
 
@@ -546,7 +861,7 @@ static void tun_net_init(struct net_device *dev)
 /* Character device part */
 
 /* Poll */
-static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
+static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
 {
        struct tun_file *tfile = file->private_data;
        struct tun_struct *tun = __tun_get(tfile);
@@ -556,11 +871,11 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
        if (!tun)
                return POLLERR;
 
-       sk = tun->socket.sk;
+       sk = tfile->socket.sk;
 
        tun_debug(KERN_INFO, tun, "tun_chr_poll\n");
 
-       poll_wait(file, &tun->wq.wait, wait);
+       poll_wait(file, &tfile->wq.wait, wait);
 
        if (!skb_queue_empty(&sk->sk_receive_queue))
                mask |= POLLIN | POLLRDNORM;
@@ -579,16 +894,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait)
 
 /* prepad is the amount to reserve at front.  len is length after that.
  * linear is a hint as to how much to copy (usually headers). */
-static struct sk_buff *tun_alloc_skb(struct tun_struct *tun,
+static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
                                     size_t prepad, size_t len,
                                     size_t linear, int noblock)
 {
-       struct sock *sk = tun->socket.sk;
+       struct sock *sk = tfile->socket.sk;
        struct sk_buff *skb;
        int err;
 
-       sock_update_classid(sk);
-
        /* Under a page?  Don't bother with paged skb. */
        if (prepad + len < PAGE_SIZE || !linear)
                linear = len;
@@ -685,9 +998,9 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from,
 }
 
 /* Get packet from user space buffer */
-static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
-                           const struct iovec *iv, size_t total_len,
-                           size_t count, int noblock)
+static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
+                           void *msg_control, const struct iovec *iv,
+                           size_t total_len, size_t count, int noblock)
 {
        struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) };
        struct sk_buff *skb;
@@ -757,7 +1070,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
        } else
                copylen = len;
 
-       skb = tun_alloc_skb(tun, align, copylen, gso.hdr_len, noblock);
+       skb = tun_alloc_skb(tfile, align, copylen, gso.hdr_len, noblock);
        if (IS_ERR(skb)) {
                if (PTR_ERR(skb) != -EAGAIN)
                        tun->dev->stats.rx_dropped++;
@@ -854,6 +1167,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, void *msg_control,
        tun->dev->stats.rx_packets++;
        tun->dev->stats.rx_bytes += len;
 
+       tun_flow_update(tun, skb, tfile->queue_index);
        return total_len;
 }
 
@@ -862,6 +1176,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 {
        struct file *file = iocb->ki_filp;
        struct tun_struct *tun = tun_get(file);
+       struct tun_file *tfile = file->private_data;
        ssize_t result;
 
        if (!tun)
@@ -869,8 +1184,8 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 
        tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count);
 
-       result = tun_get_user(tun, NULL, iv, iov_length(iv, count), count,
-                             file->f_flags & O_NONBLOCK);
+       result = tun_get_user(tun, tfile, NULL, iv, iov_length(iv, count),
+                             count, file->f_flags & O_NONBLOCK);
 
        tun_put(tun);
        return result;
@@ -878,6 +1193,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv,
 
 /* Put packet to the user space buffer */
 static ssize_t tun_put_user(struct tun_struct *tun,
+                           struct tun_file *tfile,
                            struct sk_buff *skb,
                            const struct iovec *iv, int len)
 {
@@ -957,7 +1273,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
        return total;
 }
 
-static ssize_t tun_do_read(struct tun_struct *tun,
+static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
                           struct kiocb *iocb, const struct iovec *iv,
                           ssize_t len, int noblock)
 {
@@ -965,15 +1281,15 @@ static ssize_t tun_do_read(struct tun_struct *tun,
        struct sk_buff *skb;
        ssize_t ret = 0;
 
-       tun_debug(KERN_INFO, tun, "tun_chr_read\n");
+       tun_debug(KERN_INFO, tun, "tun_do_read\n");
 
        if (unlikely(!noblock))
-               add_wait_queue(&tun->wq.wait, &wait);
+               add_wait_queue(&tfile->wq.wait, &wait);
        while (len) {
                current->state = TASK_INTERRUPTIBLE;
 
                /* Read frames from the queue */
-               if (!(skb=skb_dequeue(&tun->socket.sk->sk_receive_queue))) {
+               if (!(skb = skb_dequeue(&tfile->socket.sk->sk_receive_queue))) {
                        if (noblock) {
                                ret = -EAGAIN;
                                break;
@@ -991,16 +1307,15 @@ static ssize_t tun_do_read(struct tun_struct *tun,
                        schedule();
                        continue;
                }
-               netif_wake_queue(tun->dev);
 
-               ret = tun_put_user(tun, skb, iv, len);
+               ret = tun_put_user(tun, tfile, skb, iv, len);
                kfree_skb(skb);
                break;
        }
 
        current->state = TASK_RUNNING;
        if (unlikely(!noblock))
-               remove_wait_queue(&tun->wq.wait, &wait);
+               remove_wait_queue(&tfile->wq.wait, &wait);
 
        return ret;
 }
@@ -1021,13 +1336,22 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv,
                goto out;
        }
 
-       ret = tun_do_read(tun, iocb, iv, len, file->f_flags & O_NONBLOCK);
+       ret = tun_do_read(tun, tfile, iocb, iv, len,
+                         file->f_flags & O_NONBLOCK);
        ret = min_t(ssize_t, ret, len);
 out:
        tun_put(tun);
        return ret;
 }
 
+static void tun_free_netdev(struct net_device *dev)
+{
+       struct tun_struct *tun = netdev_priv(dev);
+
+       tun_flow_uninit(tun);
+       free_netdev(dev);
+}
+
 static void tun_setup(struct net_device *dev)
 {
        struct tun_struct *tun = netdev_priv(dev);
@@ -1056,7 +1380,7 @@ static struct rtnl_link_ops tun_link_ops __read_mostly = {
 
 static void tun_sock_write_space(struct sock *sk)
 {
-       struct tun_struct *tun;
+       struct tun_file *tfile;
        wait_queue_head_t *wqueue;
 
        if (!sock_writeable(sk))
@@ -1070,37 +1394,46 @@ static void tun_sock_write_space(struct sock *sk)
                wake_up_interruptible_sync_poll(wqueue, POLLOUT |
                                                POLLWRNORM | POLLWRBAND);
 
-       tun = tun_sk(sk)->tun;
-       kill_fasync(&tun->fasync, SIGIO, POLL_OUT);
-}
-
-static void tun_sock_destruct(struct sock *sk)
-{
-       free_netdev(tun_sk(sk)->tun->dev);
+       tfile = container_of(sk, struct tun_file, sk);
+       kill_fasync(&tfile->fasync, SIGIO, POLL_OUT);
 }
 
 static int tun_sendmsg(struct kiocb *iocb, struct socket *sock,
                       struct msghdr *m, size_t total_len)
 {
-       struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
-       return tun_get_user(tun, m->msg_control, m->msg_iov, total_len,
-                           m->msg_iovlen, m->msg_flags & MSG_DONTWAIT);
+       int ret;
+       struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+       struct tun_struct *tun = __tun_get(tfile);
+
+       if (!tun)
+               return -EBADFD;
+       ret = tun_get_user(tun, tfile, m->msg_control, m->msg_iov, total_len,
+                          m->msg_iovlen, m->msg_flags & MSG_DONTWAIT);
+       tun_put(tun);
+       return ret;
 }
 
+
 static int tun_recvmsg(struct kiocb *iocb, struct socket *sock,
                       struct msghdr *m, size_t total_len,
                       int flags)
 {
-       struct tun_struct *tun = container_of(sock, struct tun_struct, socket);
+       struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+       struct tun_struct *tun = __tun_get(tfile);
        int ret;
+
+       if (!tun)
+               return -EBADFD;
+
        if (flags & ~(MSG_DONTWAIT|MSG_TRUNC))
                return -EINVAL;
-       ret = tun_do_read(tun, iocb, m->msg_iov, total_len,
+       ret = tun_do_read(tun, tfile, iocb, m->msg_iov, total_len,
                          flags & MSG_DONTWAIT);
        if (ret > total_len) {
                m->msg_flags |= MSG_TRUNC;
                ret = flags & MSG_TRUNC ? ret : total_len;
        }
+       tun_put(tun);
        return ret;
 }
 
@@ -1121,7 +1454,7 @@ static const struct proto_ops tun_socket_ops = {
 static struct proto tun_proto = {
        .name           = "tun",
        .owner          = THIS_MODULE,
-       .obj_size       = sizeof(struct tun_sock),
+       .obj_size       = sizeof(struct tun_file),
 };
 
 static int tun_flags(struct tun_struct *tun)
@@ -1136,12 +1469,18 @@ static int tun_flags(struct tun_struct *tun)
        if (tun->flags & TUN_NO_PI)
                flags |= IFF_NO_PI;
 
+       /* This flag has no real effect.  We track the value for backwards
+        * compatibility.
+        */
        if (tun->flags & TUN_ONE_QUEUE)
                flags |= IFF_ONE_QUEUE;
 
        if (tun->flags & TUN_VNET_HDR)
                flags |= IFF_VNET_HDR;
 
+       if (tun->flags & TUN_TAP_MQ)
+               flags |= IFF_MULTI_QUEUE;
+
        return flags;
 }
 
@@ -1178,15 +1517,13 @@ static DEVICE_ATTR(group, 0444, tun_show_group, NULL);
 
 static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 {
-       struct sock *sk;
        struct tun_struct *tun;
+       struct tun_file *tfile = file->private_data;
        struct net_device *dev;
        int err;
 
        dev = __dev_get_by_name(net, ifr->ifr_name);
        if (dev) {
-               const struct cred *cred = current_cred();
-
                if (ifr->ifr_flags & IFF_TUN_EXCL)
                        return -EBUSY;
                if ((ifr->ifr_flags & IFF_TUN) && dev->netdev_ops == &tun_netdev_ops)
@@ -1196,11 +1533,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                else
                        return -EINVAL;
 
-               if (((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
-                    (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
-                   !capable(CAP_NET_ADMIN))
+               if (tun_not_capable(tun))
                        return -EPERM;
-               err = security_tun_dev_attach(tun->socket.sk);
+               err = security_tun_dev_attach(tfile->socket.sk);
                if (err < 0)
                        return err;
 
@@ -1212,7 +1547,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                char *name;
                unsigned long flags = 0;
 
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
                err = security_tun_dev_create();
                if (err < 0)
@@ -1233,8 +1568,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                if (*ifr->ifr_name)
                        name = ifr->ifr_name;
 
-               dev = alloc_netdev(sizeof(struct tun_struct), name,
-                                  tun_setup);
+               dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,
+                                      tun_setup,
+                                      MAX_TAP_QUEUES, MAX_TAP_QUEUES);
                if (!dev)
                        return -ENOMEM;
 
@@ -1246,46 +1582,38 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                tun->flags = flags;
                tun->txflt.count = 0;
                tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr);
-               set_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags);
-
-               err = -ENOMEM;
-               sk = sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, &tun_proto);
-               if (!sk)
-                       goto err_free_dev;
 
-               sk_change_net(sk, net);
-               tun->socket.wq = &tun->wq;
-               init_waitqueue_head(&tun->wq.wait);
-               tun->socket.ops = &tun_socket_ops;
-               sock_init_data(&tun->socket, sk);
-               sk->sk_write_space = tun_sock_write_space;
-               sk->sk_sndbuf = INT_MAX;
-               sock_set_flag(sk, SOCK_ZEROCOPY);
+               tun->filter_attached = false;
+               tun->sndbuf = tfile->socket.sk->sk_sndbuf;
 
-               tun_sk(sk)->tun = tun;
+               spin_lock_init(&tun->lock);
 
-               security_tun_dev_post_create(sk);
+               security_tun_dev_post_create(&tfile->sk);
 
                tun_net_init(dev);
 
+               err = tun_flow_init(tun);
+               if (err < 0)
+                       goto err_free_dev;
+
                dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST |
                        TUN_USER_FEATURES;
                dev->features = dev->hw_features;
 
+               err = tun_attach(tun, file);
+               if (err < 0)
+                       goto err_free_dev;
+
                err = register_netdevice(tun->dev);
                if (err < 0)
-                       goto err_free_sk;
+                       goto err_free_dev;
 
                if (device_create_file(&tun->dev->dev, &dev_attr_tun_flags) ||
                    device_create_file(&tun->dev->dev, &dev_attr_owner) ||
                    device_create_file(&tun->dev->dev, &dev_attr_group))
                        pr_err("Failed to create tun sysfs files\n");
 
-               sk->sk_destruct = tun_sock_destruct;
-
-               err = tun_attach(tun, file);
-               if (err < 0)
-                       goto failed;
+               netif_carrier_on(tun->dev);
        }
 
        tun_debug(KERN_INFO, tun, "tun_set_iff\n");
@@ -1295,6 +1623,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
        else
                tun->flags &= ~TUN_NO_PI;
 
+       /* This flag has no real effect.  We track the value for backwards
+        * compatibility.
+        */
        if (ifr->ifr_flags & IFF_ONE_QUEUE)
                tun->flags |= TUN_ONE_QUEUE;
        else
@@ -1305,24 +1636,26 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
        else
                tun->flags &= ~TUN_VNET_HDR;
 
+       if (ifr->ifr_flags & IFF_MULTI_QUEUE)
+               tun->flags |= TUN_TAP_MQ;
+       else
+               tun->flags &= ~TUN_TAP_MQ;
+
        /* Make sure persistent devices do not get stuck in
         * xoff state.
         */
        if (netif_running(tun->dev))
-               netif_wake_queue(tun->dev);
+               netif_tx_wake_all_queues(tun->dev);
 
        strcpy(ifr->ifr_name, tun->dev->name);
        return 0;
 
- err_free_sk:
-       tun_free_netdev(dev);
  err_free_dev:
        free_netdev(dev);
- failed:
        return err;
 }
 
-static int tun_get_iff(struct net *net, struct tun_struct *tun,
+static void tun_get_iff(struct net *net, struct tun_struct *tun,
                       struct ifreq *ifr)
 {
        tun_debug(KERN_INFO, tun, "tun_get_iff\n");
@@ -1331,7 +1664,6 @@ static int tun_get_iff(struct net *net, struct tun_struct *tun,
 
        ifr->ifr_flags = tun_flags(tun);
 
-       return 0;
 }
 
 /* This is like a cut-down ethtool ops, except done via tun fd so no
@@ -1373,13 +1705,91 @@ static int set_offload(struct tun_struct *tun, unsigned long arg)
        return 0;
 }
 
+static void tun_detach_filter(struct tun_struct *tun, int n)
+{
+       int i;
+       struct tun_file *tfile;
+
+       for (i = 0; i < n; i++) {
+               tfile = rcu_dereference_protected(tun->tfiles[i],
+                                                 lockdep_rtnl_is_held());
+               sk_detach_filter(tfile->socket.sk);
+       }
+
+       tun->filter_attached = false;
+}
+
+static int tun_attach_filter(struct tun_struct *tun)
+{
+       int i, ret = 0;
+       struct tun_file *tfile;
+
+       for (i = 0; i < tun->numqueues; i++) {
+               tfile = rcu_dereference_protected(tun->tfiles[i],
+                                                 lockdep_rtnl_is_held());
+               ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);
+               if (ret) {
+                       tun_detach_filter(tun, i);
+                       return ret;
+               }
+       }
+
+       tun->filter_attached = true;
+       return ret;
+}
+
+static void tun_set_sndbuf(struct tun_struct *tun)
+{
+       struct tun_file *tfile;
+       int i;
+
+       for (i = 0; i < tun->numqueues; i++) {
+               tfile = rcu_dereference_protected(tun->tfiles[i],
+                                               lockdep_rtnl_is_held());
+               tfile->socket.sk->sk_sndbuf = tun->sndbuf;
+       }
+}
+
+static int tun_set_queue(struct file *file, struct ifreq *ifr)
+{
+       struct tun_file *tfile = file->private_data;
+       struct tun_struct *tun;
+       struct net_device *dev;
+       int ret = 0;
+
+       rtnl_lock();
+
+       if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
+               dev = __dev_get_by_name(tfile->net, ifr->ifr_name);
+               if (!dev) {
+                       ret = -EINVAL;
+                       goto unlock;
+               }
+
+               tun = netdev_priv(dev);
+               if (dev->netdev_ops != &tap_netdev_ops &&
+                       dev->netdev_ops != &tun_netdev_ops)
+                       ret = -EINVAL;
+               else if (tun_not_capable(tun))
+                       ret = -EPERM;
+               else
+                       ret = tun_attach(tun, file);
+       } else if (ifr->ifr_flags & IFF_DETACH_QUEUE)
+               __tun_detach(tfile, false);
+       else
+               ret = -EINVAL;
+
+unlock:
+       rtnl_unlock();
+       return ret;
+}
+
 static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                            unsigned long arg, int ifreq_len)
 {
        struct tun_file *tfile = file->private_data;
        struct tun_struct *tun;
        void __user* argp = (void __user*)arg;
-       struct sock_fprog fprog;
        struct ifreq ifr;
        kuid_t owner;
        kgid_t group;
@@ -1387,7 +1797,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
        int vnet_hdr_sz;
        int ret;
 
-       if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) {
+       if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || _IOC_TYPE(cmd) == 0x89) {
                if (copy_from_user(&ifr, argp, ifreq_len))
                        return -EFAULT;
        } else {
@@ -1398,10 +1808,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                 * This is needed because we never checked for invalid flags on
                 * TUNSETIFF. */
                return put_user(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
-                               IFF_VNET_HDR,
+                               IFF_VNET_HDR | IFF_MULTI_QUEUE,
                                (unsigned int __user*)argp);
-       }
+       } else if (cmd == TUNSETQUEUE)
+               return tun_set_queue(file, &ifr);
 
+       ret = 0;
        rtnl_lock();
 
        tun = __tun_get(tfile);
@@ -1422,14 +1834,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
        if (!tun)
                goto unlock;
 
-       tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %d\n", cmd);
+       tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %u\n", cmd);
 
        ret = 0;
        switch (cmd) {
        case TUNGETIFF:
-               ret = tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
-               if (ret)
-                       break;
+               tun_get_iff(current->nsproxy->net_ns, tun, &ifr);
 
                if (copy_to_user(argp, &ifr, ifreq_len))
                        ret = -EFAULT;
@@ -1444,11 +1854,16 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                break;
 
        case TUNSETPERSIST:
-               /* Disable/Enable persist mode */
-               if (arg)
+               /* Disable/Enable persist mode. Keep an extra reference to the
+                * module to prevent the module being unprobed.
+                */
+               if (arg) {
                        tun->flags |= TUN_PERSIST;
-               else
+                       __module_get(THIS_MODULE);
+               } else {
                        tun->flags &= ~TUN_PERSIST;
+                       module_put(THIS_MODULE);
+               }
 
                tun_debug(KERN_INFO, tun, "persist %s\n",
                          arg ? "enabled" : "disabled");
@@ -1462,7 +1877,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                        break;
                }
                tun->owner = owner;
-               tun_debug(KERN_INFO, tun, "owner set to %d\n",
+               tun_debug(KERN_INFO, tun, "owner set to %u\n",
                          from_kuid(&init_user_ns, tun->owner));
                break;
 
@@ -1474,7 +1889,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                        break;
                }
                tun->group = group;
-               tun_debug(KERN_INFO, tun, "group set to %d\n",
+               tun_debug(KERN_INFO, tun, "group set to %u\n",
                          from_kgid(&init_user_ns, tun->group));
                break;
 
@@ -1526,7 +1941,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                break;
 
        case TUNGETSNDBUF:
-               sndbuf = tun->socket.sk->sk_sndbuf;
+               sndbuf = tfile->socket.sk->sk_sndbuf;
                if (copy_to_user(argp, &sndbuf, sizeof(sndbuf)))
                        ret = -EFAULT;
                break;
@@ -1537,7 +1952,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                        break;
                }
 
-               tun->socket.sk->sk_sndbuf = sndbuf;
+               tun->sndbuf = sndbuf;
+               tun_set_sndbuf(tun);
                break;
 
        case TUNGETVNETHDRSZ:
@@ -1565,10 +1981,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
                        break;
                ret = -EFAULT;
-               if (copy_from_user(&fprog, argp, sizeof(fprog)))
+               if (copy_from_user(&tun->fprog, argp, sizeof(tun->fprog)))
                        break;
 
-               ret = sk_attach_filter(&fprog, tun->socket.sk);
+               ret = tun_attach_filter(tun);
                break;
 
        case TUNDETACHFILTER:
@@ -1576,7 +1992,8 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                ret = -EINVAL;
                if ((tun->flags & TUN_TYPE_MASK) != TUN_TAP_DEV)
                        break;
-               ret = sk_detach_filter(tun->socket.sk);
+               ret = 0;
+               tun_detach_filter(tun, tun->numqueues);
                break;
 
        default:
@@ -1628,27 +2045,21 @@ static long tun_chr_compat_ioctl(struct file *file,
 
 static int tun_chr_fasync(int fd, struct file *file, int on)
 {
-       struct tun_struct *tun = tun_get(file);
+       struct tun_file *tfile = file->private_data;
        int ret;
 
-       if (!tun)
-               return -EBADFD;
-
-       tun_debug(KERN_INFO, tun, "tun_chr_fasync %d\n", on);
-
-       if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
+       if ((ret = fasync_helper(fd, file, on, &tfile->fasync)) < 0)
                goto out;
 
        if (on) {
                ret = __f_setown(file, task_pid(current), PIDTYPE_PID, 0);
                if (ret)
                        goto out;
-               tun->flags |= TUN_FASYNC;
+               tfile->flags |= TUN_FASYNC;
        } else
-               tun->flags &= ~TUN_FASYNC;
+               tfile->flags &= ~TUN_FASYNC;
        ret = 0;
 out:
-       tun_put(tun);
        return ret;
 }
 
@@ -1658,44 +2069,39 @@ static int tun_chr_open(struct inode *inode, struct file * file)
 
        DBG1(KERN_INFO, "tunX: tun_chr_open\n");
 
-       tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
+       tfile = (struct tun_file *)sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL,
+                                           &tun_proto);
        if (!tfile)
                return -ENOMEM;
-       atomic_set(&tfile->count, 0);
-       tfile->tun = NULL;
+       rcu_assign_pointer(tfile->tun, NULL);
        tfile->net = get_net(current->nsproxy->net_ns);
+       tfile->flags = 0;
+
+       rcu_assign_pointer(tfile->socket.wq, &tfile->wq);
+       init_waitqueue_head(&tfile->wq.wait);
+
+       tfile->socket.file = file;
+       tfile->socket.ops = &tun_socket_ops;
+
+       sock_init_data(&tfile->socket, &tfile->sk);
+       sk_change_net(&tfile->sk, tfile->net);
+
+       tfile->sk.sk_write_space = tun_sock_write_space;
+       tfile->sk.sk_sndbuf = INT_MAX;
+
        file->private_data = tfile;
+       set_bit(SOCK_EXTERNALLY_ALLOCATED, &tfile->socket.flags);
+
        return 0;
 }
 
 static int tun_chr_close(struct inode *inode, struct file *file)
 {
        struct tun_file *tfile = file->private_data;
-       struct tun_struct *tun;
-
-       tun = __tun_get(tfile);
-       if (tun) {
-               struct net_device *dev = tun->dev;
-
-               tun_debug(KERN_INFO, tun, "tun_chr_close\n");
-
-               __tun_detach(tun);
-
-               /* If desirable, unregister the netdevice. */
-               if (!(tun->flags & TUN_PERSIST)) {
-                       rtnl_lock();
-                       if (dev->reg_state == NETREG_REGISTERED)
-                               unregister_netdevice(dev);
-                       rtnl_unlock();
-               }
-       }
+       struct net *net = tfile->net;
 
-       tun = tfile->tun;
-       if (tun)
-               sock_put(tun->socket.sk);
-
-       put_net(tfile->net);
-       kfree(tfile);
+       tun_detach(tfile, true);
+       put_net(net);
 
        return 0;
 }
@@ -1822,14 +2228,13 @@ static void tun_cleanup(void)
  * holding a reference to the file for as long as the socket is in use. */
 struct socket *tun_get_socket(struct file *file)
 {
-       struct tun_struct *tun;
+       struct tun_file *tfile;
        if (file->f_op != &tun_fops)
                return ERR_PTR(-EINVAL);
-       tun = tun_get(file);
-       if (!tun)
+       tfile = file->private_data;
+       if (!tfile)
                return ERR_PTR(-EBADFD);
-       tun_put(tun);
-       return &tun->socket;
+       return &tfile->socket;
 }
 EXPORT_SYMBOL_GPL(tun_get_socket);
 
index c1ae76968f47ee5fa0191d07f53c4b6eddd09078..ef976215b649330d0c6873b8185f3fefc34b1651 100644 (file)
@@ -219,6 +219,24 @@ config USB_NET_CDC_NCM
            * ST-Ericsson M343 HSPA Mobile Broadband Modem (reference design)
            * Ericsson F5521gw Mobile Broadband Module
 
+config USB_NET_CDC_MBIM
+       tristate "CDC MBIM support"
+       depends on USB_USBNET
+       select USB_WDM
+       select USB_NET_CDC_NCM
+       help
+         This driver provides support for CDC MBIM (Mobile Broadband
+         Interface Model) devices. The CDC MBIM specification is
+         available from <http://www.usb.org/>.
+
+         MBIM devices require configuration using the management
+         protocol defined by the MBIM specification.  This driver
+         provides unfiltered access to the MBIM control channel
+         through the associated /dev/cdc-wdmx character device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cdc_mbim.
+
 config USB_NET_DM9601
        tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
        depends on USB_USBNET
@@ -230,6 +248,8 @@ config USB_NET_DM9601
 config USB_NET_SMSC75XX
        tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices"
        depends on USB_USBNET
+       select BITREVERSE
+       select CRC16
        select CRC32
        help
          This option adds support for SMSC LAN95XX based USB 2.0
@@ -238,6 +258,8 @@ config USB_NET_SMSC75XX
 config USB_NET_SMSC95XX
        tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices"
        depends on USB_USBNET
+       select BITREVERSE
+       select CRC16
        select CRC32
        help
          This option adds support for SMSC LAN95XX based USB 2.0
index bf063008c1afc240a8854c75c3de42d22e7d93b9..478691326f37fc3303199a07dd9e83ae087615be 100644 (file)
@@ -31,4 +31,5 @@ obj-$(CONFIG_USB_NET_CX82310_ETH)     += cx82310_eth.o
 obj-$(CONFIG_USB_NET_CDC_NCM)  += cdc_ncm.o
 obj-$(CONFIG_USB_VL600)                += lg-vl600.o
 obj-$(CONFIG_USB_NET_QMI_WWAN) += qmi_wwan.o
+obj-$(CONFIG_USB_NET_CDC_MBIM) += cdc_mbim.o
 
index 774d9ce2dafcefa699311c8f33532cebd3187dc8..50d167330d384e76b8d3ebfe9cd15cd26dd45c87 100644 (file)
 int asix_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                  u16 size, void *data)
 {
-       void *buf;
-       int err = -ENOMEM;
-
-       netdev_dbg(dev->net, "asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
-                  cmd, value, index, size);
-
-       buf = kmalloc(size, GFP_KERNEL);
-       if (!buf)
-               goto out;
-
-       err = usb_control_msg(
-               dev->udev,
-               usb_rcvctrlpipe(dev->udev, 0),
-               cmd,
-               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value,
-               index,
-               buf,
-               size,
-               USB_CTRL_GET_TIMEOUT);
-       if (err == size)
-               memcpy(data, buf, size);
-       else if (err >= 0)
-               err = -EINVAL;
-       kfree(buf);
+       int ret;
+       ret = usbnet_read_cmd(dev, cmd,
+                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              value, index, data, size);
 
-out:
-       return err;
+       if (ret != size && ret >= 0)
+               return -EINVAL;
+       return ret;
 }
 
 int asix_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                   u16 size, void *data)
 {
-       void *buf = NULL;
-       int err = -ENOMEM;
-
-       netdev_dbg(dev->net, "asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
-                  cmd, value, index, size);
-
-       if (data) {
-               buf = kmemdup(data, size, GFP_KERNEL);
-               if (!buf)
-                       goto out;
-       }
-
-       err = usb_control_msg(
-               dev->udev,
-               usb_sndctrlpipe(dev->udev, 0),
-               cmd,
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value,
-               index,
-               buf,
-               size,
-               USB_CTRL_SET_TIMEOUT);
-       kfree(buf);
-
-out:
-       return err;
-}
-
-static void asix_async_cmd_callback(struct urb *urb)
-{
-       struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-       int status = urb->status;
-
-       if (status < 0)
-               printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
-                       status);
-
-       kfree(req);
-       usb_free_urb(urb);
+       return usbnet_write_cmd(dev, cmd,
+                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               value, index, data, size);
 }
 
 void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                          u16 size, void *data)
 {
-       struct usb_ctrlrequest *req;
-       int status;
-       struct urb *urb;
-
-       netdev_dbg(dev->net, "asix_write_cmd_async() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
-                  cmd, value, index, size);
-
-       urb = usb_alloc_urb(0, GFP_ATOMIC);
-       if (!urb) {
-               netdev_err(dev->net, "Error allocating URB in write_cmd_async!\n");
-               return;
-       }
-
-       req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-       if (!req) {
-               netdev_err(dev->net, "Failed to allocate memory for control request\n");
-               usb_free_urb(urb);
-               return;
-       }
-
-       req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-       req->bRequest = cmd;
-       req->wValue = cpu_to_le16(value);
-       req->wIndex = cpu_to_le16(index);
-       req->wLength = cpu_to_le16(size);
-
-       usb_fill_control_urb(urb, dev->udev,
-                            usb_sndctrlpipe(dev->udev, 0),
-                            (void *)req, data, size,
-                            asix_async_cmd_callback, req);
-
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status < 0) {
-               netdev_err(dev->net, "Error submitting the control message: status=%d\n",
-                          status);
-               kfree(req);
-               usb_free_urb(urb);
-       }
+       usbnet_write_cmd_async(dev, cmd,
+                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              value, index, data, size);
 }
 
 int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
index 33ab824773c5a795dc49cc91fd28e67bb3e501a5..7a6e758f48e738e4652cc11ea39cd2d913d5f4b9 100644 (file)
@@ -64,6 +64,16 @@ static void asix_status(struct usbnet *dev, struct urb *urb)
        }
 }
 
+static void asix_set_netdev_dev_addr(struct usbnet *dev, u8 *addr)
+{
+       if (is_valid_ether_addr(addr)) {
+               memcpy(dev->net->dev_addr, addr, ETH_ALEN);
+       } else {
+               netdev_info(dev->net, "invalid hw address, using random\n");
+               eth_hw_addr_random(dev->net);
+       }
+}
+
 /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
 static u32 asix_get_phyid(struct usbnet *dev)
 {
@@ -225,7 +235,8 @@ static int ax88172_bind(struct usbnet *dev, struct usb_interface *intf)
                           ret);
                goto out;
        }
-       memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+       asix_set_netdev_dev_addr(dev, buf);
 
        /* Initialize MII structure */
        dev->mii.dev = dev->net;
@@ -423,7 +434,8 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
                return ret;
        }
-       memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+       asix_set_netdev_dev_addr(dev, buf);
 
        /* Initialize MII structure */
        dev->mii.dev = dev->net;
@@ -777,7 +789,8 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
                netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret);
                return ret;
        }
-       memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+       asix_set_netdev_dev_addr(dev, buf);
 
        /* Initialize MII structure */
        dev->mii.dev = dev->net;
index c81e278629ff8595b6e246878e805ed51874a5c7..08d55b6bf272bc5293a8a8d059d54d652aca27e1 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/usb/cdc.h>
 #include <linux/usb/usbnet.h>
 #include <linux/gfp.h>
+#include <linux/if_vlan.h>
 
 
 /*
@@ -92,7 +93,7 @@ static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
 
        /* no jumbogram (16K) support for now */
 
-       dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+       dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN + VLAN_HLEN;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
 
        return 0;
index a03de71970499b7daaad750768318f4d08af6160..d0129827602b2867380ca4f8f774bfa104f2eef2 100644 (file)
@@ -592,6 +592,32 @@ static const struct usb_device_id  products [] = {
        .driver_info            = 0,
 },
 
+/* Novatel USB551L and MC551 - handled by qmi_wwan */
+{
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_PRODUCT
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = NOVATEL_VENDOR_ID,
+       .idProduct              = 0xB001,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       .driver_info = 0,
+},
+
+/* Novatel E362 - handled by qmi_wwan */
+{
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_PRODUCT
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = NOVATEL_VENDOR_ID,
+       .idProduct              = 0x9010,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
+       .driver_info = 0,
+},
+
 /*
  * WHITELIST!!!
  *
@@ -604,21 +630,6 @@ static const struct usb_device_id  products [] = {
  * because of bugs/quirks in a given product (like Zaurus, above).
  */
 {
-       /* Novatel USB551L */
-       /* This match must come *before* the generic CDC-ETHER match so that
-        * we get FLAG_WWAN set on the device, since it's descriptors are
-        * generic CDC-ETHER.
-        */
-       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
-                | USB_DEVICE_ID_MATCH_PRODUCT
-                | USB_DEVICE_ID_MATCH_INT_INFO,
-       .idVendor               = NOVATEL_VENDOR_ID,
-       .idProduct              = 0xB001,
-       .bInterfaceClass        = USB_CLASS_COMM,
-       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
-       .bInterfaceProtocol     = USB_CDC_PROTO_NONE,
-       .driver_info = (unsigned long)&wwan_info,
-}, {
        /* ZTE (Vodafone) K3805-Z */
        .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
                 | USB_DEVICE_ID_MATCH_PRODUCT
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
new file mode 100644 (file)
index 0000000..42f51c7
--- /dev/null
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2012  Smith Micro Software, Inc.
+ * Copyright (c) 2012  Bjørn Mork <bjorn@mork.no>
+ *
+ * This driver is based on and reuse most of cdc_ncm, which is
+ * Copyright (C) ST-Ericsson 2010-2012
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
+#include <linux/ip.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+#include <linux/usb/cdc-wdm.h>
+#include <linux/usb/cdc_ncm.h>
+
+/* driver specific data - must match cdc_ncm usage */
+struct cdc_mbim_state {
+       struct cdc_ncm_ctx *ctx;
+       atomic_t pmcount;
+       struct usb_driver *subdriver;
+       struct usb_interface *control;
+       struct usb_interface *data;
+};
+
+/* using a counter to merge subdriver requests with our own into a combined state */
+static int cdc_mbim_manage_power(struct usbnet *dev, int on)
+{
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       int rv = 0;
+
+       dev_dbg(&dev->intf->dev, "%s() pmcount=%d, on=%d\n", __func__, atomic_read(&info->pmcount), on);
+
+       if ((on && atomic_add_return(1, &info->pmcount) == 1) || (!on && atomic_dec_and_test(&info->pmcount))) {
+               /* need autopm_get/put here to ensure the usbcore sees the new value */
+               rv = usb_autopm_get_interface(dev->intf);
+               if (rv < 0)
+                       goto err;
+               dev->intf->needs_remote_wakeup = on;
+               usb_autopm_put_interface(dev->intf);
+       }
+err:
+       return rv;
+}
+
+static int cdc_mbim_wdm_manage_power(struct usb_interface *intf, int status)
+{
+       struct usbnet *dev = usb_get_intfdata(intf);
+
+       /* can be called while disconnecting */
+       if (!dev)
+               return 0;
+
+       return cdc_mbim_manage_power(dev, status);
+}
+
+
+static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct cdc_ncm_ctx *ctx;
+       struct usb_driver *subdriver = ERR_PTR(-ENODEV);
+       int ret = -ENODEV;
+       u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM;
+       struct cdc_mbim_state *info = (void *)&dev->data;
+
+       /* see if interface supports MBIM alternate setting */
+       if (intf->num_altsetting == 2) {
+               if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+                       usb_set_interface(dev->udev,
+                                         intf->cur_altsetting->desc.bInterfaceNumber,
+                                         CDC_NCM_COMM_ALTSETTING_MBIM);
+               data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
+       }
+
+       /* Probably NCM, defer for cdc_ncm_bind */
+       if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+               goto err;
+
+       ret = cdc_ncm_bind_common(dev, intf, data_altsetting);
+       if (ret)
+               goto err;
+
+       ctx = info->ctx;
+
+       /* The MBIM descriptor and the status endpoint are required */
+       if (ctx->mbim_desc && dev->status)
+               subdriver = usb_cdc_wdm_register(ctx->control,
+                                                &dev->status->desc,
+                                                le16_to_cpu(ctx->mbim_desc->wMaxControlMessage),
+                                                cdc_mbim_wdm_manage_power);
+       if (IS_ERR(subdriver)) {
+               ret = PTR_ERR(subdriver);
+               cdc_ncm_unbind(dev, intf);
+               goto err;
+       }
+
+       /* can't let usbnet use the interrupt endpoint */
+       dev->status = NULL;
+       info->subdriver = subdriver;
+
+       /* MBIM cannot do ARP */
+       dev->net->flags |= IFF_NOARP;
+
+       /* no need to put the VLAN tci in the packet headers */
+       dev->net->features |= NETIF_F_HW_VLAN_TX;
+err:
+       return ret;
+}
+
+static void cdc_mbim_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+
+       /* disconnect subdriver from control interface */
+       if (info->subdriver && info->subdriver->disconnect)
+               info->subdriver->disconnect(ctx->control);
+       info->subdriver = NULL;
+
+       /* let NCM unbind clean up both control and data interface */
+       cdc_ncm_unbind(dev, intf);
+}
+
+
+static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+       struct sk_buff *skb_out;
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+       __le32 sign = cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN);
+       u16 tci = 0;
+       u8 *c;
+
+       if (!ctx)
+               goto error;
+
+       if (skb) {
+               if (skb->len <= sizeof(ETH_HLEN))
+                       goto error;
+
+               /* mapping VLANs to MBIM sessions:
+                *   no tag     => IPS session <0>
+                *   1 - 255    => IPS session <vlanid>
+                *   256 - 511  => DSS session <vlanid - 256>
+                *   512 - 4095 => unsupported, drop
+                */
+               vlan_get_tag(skb, &tci);
+
+               switch (tci & 0x0f00) {
+               case 0x0000: /* VLAN ID 0 - 255 */
+                       /* verify that datagram is IPv4 or IPv6 */
+                       skb_reset_mac_header(skb);
+                       switch (eth_hdr(skb)->h_proto) {
+                       case htons(ETH_P_IP):
+                       case htons(ETH_P_IPV6):
+                               break;
+                       default:
+                               goto error;
+                       }
+                       c = (u8 *)&sign;
+                       c[3] = tci;
+                       break;
+               case 0x0100: /* VLAN ID 256 - 511 */
+                       sign = cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN);
+                       c = (u8 *)&sign;
+                       c[3] = tci;
+                       break;
+               default:
+                       netif_err(dev, tx_err, dev->net,
+                                 "unsupported tci=0x%04x\n", tci);
+                       goto error;
+               }
+               skb_pull(skb, ETH_HLEN);
+       }
+
+       spin_lock_bh(&ctx->mtx);
+       skb_out = cdc_ncm_fill_tx_frame(ctx, skb, sign);
+       spin_unlock_bh(&ctx->mtx);
+       return skb_out;
+
+error:
+       if (skb)
+               dev_kfree_skb_any(skb);
+
+       return NULL;
+}
+
+static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_t len, u16 tci)
+{
+       __be16 proto = htons(ETH_P_802_3);
+       struct sk_buff *skb = NULL;
+
+       if (tci < 256) { /* IPS session? */
+               if (len < sizeof(struct iphdr))
+                       goto err;
+
+               switch (*buf & 0xf0) {
+               case 0x40:
+                       proto = htons(ETH_P_IP);
+                       break;
+               case 0x60:
+                       proto = htons(ETH_P_IPV6);
+                       break;
+               default:
+                       goto err;
+               }
+       }
+
+       skb = netdev_alloc_skb_ip_align(dev->net,  len + ETH_HLEN);
+       if (!skb)
+               goto err;
+
+       /* add an ethernet header */
+       skb_put(skb, ETH_HLEN);
+       skb_reset_mac_header(skb);
+       eth_hdr(skb)->h_proto = proto;
+       memset(eth_hdr(skb)->h_source, 0, ETH_ALEN);
+       memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN);
+
+       /* add datagram */
+       memcpy(skb_put(skb, len), buf, len);
+
+       /* map MBIM session to VLAN */
+       if (tci)
+               vlan_put_tag(skb, tci);
+err:
+       return skb;
+}
+
+static int cdc_mbim_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+       struct sk_buff *skb;
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+       int len;
+       int nframes;
+       int x;
+       int offset;
+       struct usb_cdc_ncm_ndp16 *ndp16;
+       struct usb_cdc_ncm_dpe16 *dpe16;
+       int ndpoffset;
+       int loopcount = 50; /* arbitrary max preventing infinite loop */
+       u8 *c;
+       u16 tci;
+
+       ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+       if (ndpoffset < 0)
+               goto error;
+
+next_ndp:
+       nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+       if (nframes < 0)
+               goto error;
+
+       ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+
+       switch (ndp16->dwSignature & cpu_to_le32(0x00ffffff)) {
+       case cpu_to_le32(USB_CDC_MBIM_NDP16_IPS_SIGN):
+               c = (u8 *)&ndp16->dwSignature;
+               tci = c[3];
+               break;
+       case cpu_to_le32(USB_CDC_MBIM_NDP16_DSS_SIGN):
+               c = (u8 *)&ndp16->dwSignature;
+               tci = c[3] + 256;
+               break;
+       default:
+               netif_dbg(dev, rx_err, dev->net,
+                         "unsupported NDP signature <0x%08x>\n",
+                         le32_to_cpu(ndp16->dwSignature));
+               goto err_ndp;
+
+       }
+
+       dpe16 = ndp16->dpe16;
+       for (x = 0; x < nframes; x++, dpe16++) {
+               offset = le16_to_cpu(dpe16->wDatagramIndex);
+               len = le16_to_cpu(dpe16->wDatagramLength);
+
+               /*
+                * CDC NCM ch. 3.7
+                * All entries after first NULL entry are to be ignored
+                */
+               if ((offset == 0) || (len == 0)) {
+                       if (!x)
+                               goto err_ndp; /* empty NTB */
+                       break;
+               }
+
+               /* sanity checking */
+               if (((offset + len) > skb_in->len) || (len > ctx->rx_max)) {
+                       netif_dbg(dev, rx_err, dev->net,
+                                 "invalid frame detected (ignored) offset[%u]=%u, length=%u, skb=%p\n",
+                                 x, offset, len, skb_in);
+                       if (!x)
+                               goto err_ndp;
+                       break;
+               } else {
+                       skb = cdc_mbim_process_dgram(dev, skb_in->data + offset, len, tci);
+                       if (!skb)
+                               goto error;
+                       usbnet_skb_return(dev, skb);
+               }
+       }
+err_ndp:
+       /* are there more NDPs to process? */
+       ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+       if (ndpoffset && loopcount--)
+               goto next_ndp;
+
+       return 1;
+error:
+       return 0;
+}
+
+static int cdc_mbim_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       int ret = 0;
+       struct usbnet *dev = usb_get_intfdata(intf);
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+
+       if (ctx == NULL) {
+               ret = -1;
+               goto error;
+       }
+
+       ret = usbnet_suspend(intf, message);
+       if (ret < 0)
+               goto error;
+
+       if (intf == ctx->control && info->subdriver && info->subdriver->suspend)
+               ret = info->subdriver->suspend(intf, message);
+       if (ret < 0)
+               usbnet_resume(intf);
+
+error:
+       return ret;
+}
+
+static int cdc_mbim_resume(struct usb_interface *intf)
+{
+       int  ret = 0;
+       struct usbnet *dev = usb_get_intfdata(intf);
+       struct cdc_mbim_state *info = (void *)&dev->data;
+       struct cdc_ncm_ctx *ctx = info->ctx;
+       bool callsub = (intf == ctx->control && info->subdriver && info->subdriver->resume);
+
+       if (callsub)
+               ret = info->subdriver->resume(intf);
+       if (ret < 0)
+               goto err;
+       ret = usbnet_resume(intf);
+       if (ret < 0 && callsub && info->subdriver->suspend)
+               info->subdriver->suspend(intf, PMSG_SUSPEND);
+err:
+       return ret;
+}
+
+static const struct driver_info cdc_mbim_info = {
+       .description = "CDC MBIM",
+       .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN,
+       .bind = cdc_mbim_bind,
+       .unbind = cdc_mbim_unbind,
+       .manage_power = cdc_mbim_manage_power,
+       .rx_fixup = cdc_mbim_rx_fixup,
+       .tx_fixup = cdc_mbim_tx_fixup,
+};
+
+static const struct usb_device_id mbim_devs[] = {
+       /* This duplicate NCM entry is intentional. MBIM devices can
+        * be disguised as NCM by default, and this is necessary to
+        * allow us to bind the correct driver_info to such devices.
+        *
+        * bind() will sort out this for us, selecting the correct
+        * entry and reject the other
+        */
+       { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&cdc_mbim_info,
+       },
+       { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+         .driver_info = (unsigned long)&cdc_mbim_info,
+       },
+       {
+       },
+};
+MODULE_DEVICE_TABLE(usb, mbim_devs);
+
+static struct usb_driver cdc_mbim_driver = {
+       .name = "cdc_mbim",
+       .id_table = mbim_devs,
+       .probe = usbnet_probe,
+       .disconnect = usbnet_disconnect,
+       .suspend = cdc_mbim_suspend,
+       .resume = cdc_mbim_resume,
+       .reset_resume = cdc_mbim_resume,
+       .supports_autosuspend = 1,
+       .disable_hub_initiated_lpm = 1,
+};
+module_usb_driver(cdc_mbim_driver);
+
+MODULE_AUTHOR("Greg Suarez <gsuarez@smithmicro.com>");
+MODULE_AUTHOR("Bjørn Mork <bjorn@mork.no>");
+MODULE_DESCRIPTION("USB CDC MBIM host driver");
+MODULE_LICENSE("GPL");
index 4cd582a4f625d55d5edd8c2cd3952d5571074921..d38bc20a60e2e63fd2d056b9070cdce57f524090 100644 (file)
 #include <linux/atomic.h>
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc.h>
+#include <linux/usb/cdc_ncm.h>
 
 #define        DRIVER_VERSION                          "14-Mar-2012"
 
-/* CDC NCM subclass 3.2.1 */
-#define USB_CDC_NCM_NDP16_LENGTH_MIN           0x10
-
-/* Maximum NTB length */
-#define        CDC_NCM_NTB_MAX_SIZE_TX                 32768   /* bytes */
-#define        CDC_NCM_NTB_MAX_SIZE_RX                 32768   /* bytes */
-
-/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
-#define        CDC_NCM_MIN_DATAGRAM_SIZE               1514    /* bytes */
-
-#define        CDC_NCM_MIN_TX_PKT                      512     /* bytes */
-
-/* Default value for MaxDatagramSize */
-#define        CDC_NCM_MAX_DATAGRAM_SIZE               8192    /* bytes */
-
-/*
- * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
- * the last NULL entry.
- */
-#define        CDC_NCM_DPT_DATAGRAMS_MAX               40
-
-/* Restart the timer, if amount of datagrams is less than given value */
-#define        CDC_NCM_RESTART_TIMER_DATAGRAM_CNT      3
-#define        CDC_NCM_TIMER_PENDING_CNT               2
-#define CDC_NCM_TIMER_INTERVAL                 (400UL * NSEC_PER_USEC)
-
-/* The following macro defines the minimum header space */
-#define        CDC_NCM_MIN_HDR_SIZE \
-       (sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
-       (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
-
-struct cdc_ncm_data {
-       struct usb_cdc_ncm_nth16 nth16;
-       struct usb_cdc_ncm_ndp16 ndp16;
-       struct usb_cdc_ncm_dpe16 dpe16[CDC_NCM_DPT_DATAGRAMS_MAX + 1];
-};
-
-struct cdc_ncm_ctx {
-       struct cdc_ncm_data tx_ncm;
-       struct usb_cdc_ncm_ntb_parameters ncm_parm;
-       struct hrtimer tx_timer;
-       struct tasklet_struct bh;
-
-       const struct usb_cdc_ncm_desc *func_desc;
-       const struct usb_cdc_header_desc *header_desc;
-       const struct usb_cdc_union_desc *union_desc;
-       const struct usb_cdc_ether_desc *ether_desc;
-
-       struct net_device *netdev;
-       struct usb_device *udev;
-       struct usb_host_endpoint *in_ep;
-       struct usb_host_endpoint *out_ep;
-       struct usb_host_endpoint *status_ep;
-       struct usb_interface *intf;
-       struct usb_interface *control;
-       struct usb_interface *data;
-
-       struct sk_buff *tx_curr_skb;
-       struct sk_buff *tx_rem_skb;
-
-       spinlock_t mtx;
-       atomic_t stop;
-
-       u32 tx_timer_pending;
-       u32 tx_curr_offset;
-       u32 tx_curr_last_offset;
-       u32 tx_curr_frame_num;
-       u32 rx_speed;
-       u32 tx_speed;
-       u32 rx_max;
-       u32 tx_max;
-       u32 max_datagram_size;
-       u16 tx_max_datagrams;
-       u16 tx_remainder;
-       u16 tx_modulus;
-       u16 tx_ndp_modulus;
-       u16 tx_seq;
-       u16 rx_seq;
-       u16 connected;
-};
-
 static void cdc_ncm_txpath_bh(unsigned long param);
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@@ -158,17 +78,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
        u8 flags;
        u8 iface_no;
        int err;
+       int eth_hlen;
        u16 ntb_fmt_supported;
+       u32 min_dgram_size;
+       u32 min_hdr_size;
+       struct usbnet *dev = netdev_priv(ctx->netdev);
 
        iface_no = ctx->control->cur_altsetting->desc.bInterfaceNumber;
 
-       err = usb_control_msg(ctx->udev,
-                               usb_rcvctrlpipe(ctx->udev, 0),
-                               USB_CDC_GET_NTB_PARAMETERS,
-                               USB_TYPE_CLASS | USB_DIR_IN
-                                | USB_RECIP_INTERFACE,
-                               0, iface_no, &ctx->ncm_parm,
-                               sizeof(ctx->ncm_parm), 10000);
+       err = usbnet_read_cmd(dev, USB_CDC_GET_NTB_PARAMETERS,
+                             USB_TYPE_CLASS | USB_DIR_IN
+                             |USB_RECIP_INTERFACE,
+                             0, iface_no, &ctx->ncm_parm,
+                             sizeof(ctx->ncm_parm));
        if (err < 0) {
                pr_debug("failed GET_NTB_PARAMETERS\n");
                return 1;
@@ -184,10 +106,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
        ctx->tx_max_datagrams = le16_to_cpu(ctx->ncm_parm.wNtbOutMaxDatagrams);
        ntb_fmt_supported = le16_to_cpu(ctx->ncm_parm.bmNtbFormatsSupported);
 
-       if (ctx->func_desc != NULL)
+       eth_hlen = ETH_HLEN;
+       min_dgram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+       min_hdr_size = CDC_NCM_MIN_HDR_SIZE;
+       if (ctx->mbim_desc != NULL) {
+               flags = ctx->mbim_desc->bmNetworkCapabilities;
+               eth_hlen = 0;
+               min_dgram_size = CDC_MBIM_MIN_DATAGRAM_SIZE;
+               min_hdr_size = 0;
+       } else if (ctx->func_desc != NULL) {
                flags = ctx->func_desc->bmNetworkCapabilities;
-       else
+       } else {
                flags = 0;
+       }
 
        pr_debug("dwNtbInMaxSize=%u dwNtbOutMaxSize=%u "
                 "wNdpOutPayloadRemainder=%u wNdpOutDivisor=%u "
@@ -215,49 +146,19 @@ static u8 cdc_ncm_setup(struct cdc_ncm_ctx *ctx)
 
        /* inform device about NTB input size changes */
        if (ctx->rx_max != le32_to_cpu(ctx->ncm_parm.dwNtbInMaxSize)) {
+               __le32 dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
 
-               if (flags & USB_CDC_NCM_NCAP_NTB_INPUT_SIZE) {
-                       struct usb_cdc_ncm_ndp_input_size *ndp_in_sz;
-
-                       ndp_in_sz = kzalloc(sizeof(*ndp_in_sz), GFP_KERNEL);
-                       if (!ndp_in_sz) {
-                               err = -ENOMEM;
-                               goto size_err;
-                       }
-
-                       err = usb_control_msg(ctx->udev,
-                                       usb_sndctrlpipe(ctx->udev, 0),
-                                       USB_CDC_SET_NTB_INPUT_SIZE,
-                                       USB_TYPE_CLASS | USB_DIR_OUT
-                                        | USB_RECIP_INTERFACE,
-                                       0, iface_no, ndp_in_sz, 8, 1000);
-                       kfree(ndp_in_sz);
-               } else {
-                       __le32 *dwNtbInMaxSize;
-                       dwNtbInMaxSize = kzalloc(sizeof(*dwNtbInMaxSize),
-                                       GFP_KERNEL);
-                       if (!dwNtbInMaxSize) {
-                               err = -ENOMEM;
-                               goto size_err;
-                       }
-                       *dwNtbInMaxSize = cpu_to_le32(ctx->rx_max);
-
-                       err = usb_control_msg(ctx->udev,
-                                       usb_sndctrlpipe(ctx->udev, 0),
-                                       USB_CDC_SET_NTB_INPUT_SIZE,
-                                       USB_TYPE_CLASS | USB_DIR_OUT
-                                        | USB_RECIP_INTERFACE,
-                                       0, iface_no, dwNtbInMaxSize, 4, 1000);
-                       kfree(dwNtbInMaxSize);
-               }
-size_err:
+               err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_INPUT_SIZE,
+                                      USB_TYPE_CLASS | USB_DIR_OUT
+                                      | USB_RECIP_INTERFACE,
+                                      0, iface_no, &dwNtbInMaxSize, 4);
                if (err < 0)
                        pr_debug("Setting NTB Input Size failed\n");
        }
 
        /* verify maximum size of transmitted NTB in bytes */
        if ((ctx->tx_max <
-           (CDC_NCM_MIN_HDR_SIZE + CDC_NCM_MIN_DATAGRAM_SIZE)) ||
+           (min_hdr_size + min_dgram_size)) ||
            (ctx->tx_max > CDC_NCM_NTB_MAX_SIZE_TX)) {
                pr_debug("Using default maximum transmit length=%d\n",
                                                CDC_NCM_NTB_MAX_SIZE_TX);
@@ -299,93 +200,85 @@ size_err:
        }
 
        /* adjust TX-remainder according to NCM specification. */
-       ctx->tx_remainder = ((ctx->tx_remainder - ETH_HLEN) &
-                                               (ctx->tx_modulus - 1));
+       ctx->tx_remainder = ((ctx->tx_remainder - eth_hlen) &
+                            (ctx->tx_modulus - 1));
 
        /* additional configuration */
 
        /* set CRC Mode */
        if (flags & USB_CDC_NCM_NCAP_CRC_MODE) {
-               err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
-                               USB_CDC_SET_CRC_MODE,
-                               USB_TYPE_CLASS | USB_DIR_OUT
-                                | USB_RECIP_INTERFACE,
-                               USB_CDC_NCM_CRC_NOT_APPENDED,
-                               iface_no, NULL, 0, 1000);
+               err = usbnet_write_cmd(dev, USB_CDC_SET_CRC_MODE,
+                                      USB_TYPE_CLASS | USB_DIR_OUT
+                                      | USB_RECIP_INTERFACE,
+                                      USB_CDC_NCM_CRC_NOT_APPENDED,
+                                      iface_no, NULL, 0);
                if (err < 0)
                        pr_debug("Setting CRC mode off failed\n");
        }
 
        /* set NTB format, if both formats are supported */
        if (ntb_fmt_supported & USB_CDC_NCM_NTH32_SIGN) {
-               err = usb_control_msg(ctx->udev, usb_sndctrlpipe(ctx->udev, 0),
-                               USB_CDC_SET_NTB_FORMAT, USB_TYPE_CLASS
-                                | USB_DIR_OUT | USB_RECIP_INTERFACE,
-                               USB_CDC_NCM_NTB16_FORMAT,
-                               iface_no, NULL, 0, 1000);
+               err = usbnet_write_cmd(dev, USB_CDC_SET_NTB_FORMAT,
+                                      USB_TYPE_CLASS | USB_DIR_OUT
+                                      | USB_RECIP_INTERFACE,
+                                      USB_CDC_NCM_NTB16_FORMAT,
+                                      iface_no, NULL, 0);
                if (err < 0)
                        pr_debug("Setting NTB format to 16-bit failed\n");
        }
 
-       ctx->max_datagram_size = CDC_NCM_MIN_DATAGRAM_SIZE;
+       ctx->max_datagram_size = min_dgram_size;
 
        /* set Max Datagram Size (MTU) */
        if (flags & USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE) {
-               __le16 *max_datagram_size;
-               u16 eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
-
-               max_datagram_size = kzalloc(sizeof(*max_datagram_size),
-                               GFP_KERNEL);
-               if (!max_datagram_size) {
-                       err = -ENOMEM;
+               __le16 max_datagram_size;
+               u16 eth_max_sz;
+               if (ctx->ether_desc != NULL)
+                       eth_max_sz = le16_to_cpu(ctx->ether_desc->wMaxSegmentSize);
+               else if (ctx->mbim_desc != NULL)
+                       eth_max_sz = le16_to_cpu(ctx->mbim_desc->wMaxSegmentSize);
+               else
                        goto max_dgram_err;
-               }
 
-               err = usb_control_msg(ctx->udev, usb_rcvctrlpipe(ctx->udev, 0),
-                               USB_CDC_GET_MAX_DATAGRAM_SIZE,
-                               USB_TYPE_CLASS | USB_DIR_IN
-                                | USB_RECIP_INTERFACE,
-                               0, iface_no, max_datagram_size,
-                               2, 1000);
+               err = usbnet_read_cmd(dev, USB_CDC_GET_MAX_DATAGRAM_SIZE,
+                                     USB_TYPE_CLASS | USB_DIR_IN
+                                     | USB_RECIP_INTERFACE,
+                                     0, iface_no, &max_datagram_size, 2);
                if (err < 0) {
                        pr_debug("GET_MAX_DATAGRAM_SIZE failed, use size=%u\n",
-                                               CDC_NCM_MIN_DATAGRAM_SIZE);
+                                min_dgram_size);
                } else {
                        ctx->max_datagram_size =
-                               le16_to_cpu(*max_datagram_size);
+                               le16_to_cpu(max_datagram_size);
                        /* Check Eth descriptor value */
                        if (ctx->max_datagram_size > eth_max_sz)
                                        ctx->max_datagram_size = eth_max_sz;
 
                        if (ctx->max_datagram_size > CDC_NCM_MAX_DATAGRAM_SIZE)
-                               ctx->max_datagram_size =
-                                               CDC_NCM_MAX_DATAGRAM_SIZE;
+                               ctx->max_datagram_size = CDC_NCM_MAX_DATAGRAM_SIZE;
 
-                       if (ctx->max_datagram_size < CDC_NCM_MIN_DATAGRAM_SIZE)
-                               ctx->max_datagram_size =
-                                       CDC_NCM_MIN_DATAGRAM_SIZE;
+                       if (ctx->max_datagram_size < min_dgram_size)
+                               ctx->max_datagram_size = min_dgram_size;
 
                        /* if value changed, update device */
                        if (ctx->max_datagram_size !=
-                                       le16_to_cpu(*max_datagram_size)) {
-                               err = usb_control_msg(ctx->udev,
-                                               usb_sndctrlpipe(ctx->udev, 0),
+                                       le16_to_cpu(max_datagram_size)) {
+                               err = usbnet_write_cmd(dev,
                                                USB_CDC_SET_MAX_DATAGRAM_SIZE,
                                                USB_TYPE_CLASS | USB_DIR_OUT
                                                 | USB_RECIP_INTERFACE,
                                                0,
-                                               iface_no, max_datagram_size,
-                                               2, 1000);
+                                               iface_no, &max_datagram_size,
+                                               2);
                                if (err < 0)
                                        pr_debug("SET_MAX_DGRAM_SIZE failed\n");
                        }
                }
-               kfree(max_datagram_size);
        }
 
 max_dgram_err:
-       if (ctx->netdev->mtu != (ctx->max_datagram_size - ETH_HLEN))
-               ctx->netdev->mtu = ctx->max_datagram_size - ETH_HLEN;
+       if (ctx->netdev->mtu != (ctx->max_datagram_size - eth_hlen))
+               ctx->netdev->mtu = ctx->max_datagram_size - eth_hlen;
 
        return 0;
 }
@@ -451,7 +344,7 @@ static const struct ethtool_ops cdc_ncm_ethtool_ops = {
        .nway_reset = usbnet_nway_reset,
 };
 
-static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting)
 {
        struct cdc_ncm_ctx *ctx;
        struct usb_driver *driver;
@@ -525,6 +418,13 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
                        ctx->func_desc = (const struct usb_cdc_ncm_desc *)buf;
                        break;
 
+               case USB_CDC_MBIM_TYPE:
+                       if (buf[0] < sizeof(*(ctx->mbim_desc)))
+                               break;
+
+                       ctx->mbim_desc = (const struct usb_cdc_mbim_desc *)buf;
+                       break;
+
                default:
                        break;
                }
@@ -537,13 +437,15 @@ advance:
 
        /* check if we got everything */
        if ((ctx->control == NULL) || (ctx->data == NULL) ||
-           (ctx->ether_desc == NULL) || (ctx->control != intf))
+           ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf))))
                goto error;
 
-       /* claim interfaces, if any */
-       temp = usb_driver_claim_interface(driver, ctx->data, dev);
-       if (temp)
-               goto error;
+       /* claim data interface, if different from control */
+       if (ctx->data != ctx->control) {
+               temp = usb_driver_claim_interface(driver, ctx->data, dev);
+               if (temp)
+                       goto error;
+       }
 
        iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
 
@@ -557,7 +459,7 @@ advance:
                goto error2;
 
        /* configure data interface */
-       temp = usb_set_interface(dev->udev, iface_no, 1);
+       temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
        if (temp)
                goto error2;
 
@@ -574,11 +476,13 @@ advance:
        usb_set_intfdata(ctx->control, dev);
        usb_set_intfdata(ctx->intf, dev);
 
-       temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
-       if (temp)
-               goto error2;
+       if (ctx->ether_desc) {
+               temp = usbnet_get_ethernet_addr(dev, ctx->ether_desc->iMACAddress);
+               if (temp)
+                       goto error2;
+               dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
+       }
 
-       dev_info(&dev->udev->dev, "MAC-Address: %pM\n", dev->net->dev_addr);
 
        dev->in = usb_rcvbulkpipe(dev->udev,
                ctx->in_ep->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
@@ -587,13 +491,6 @@ advance:
        dev->status = ctx->status_ep;
        dev->rx_urb_size = ctx->rx_max;
 
-       /*
-        * We should get an event when network connection is "connected" or
-        * "disconnected". Set network connection in "disconnected" state
-        * (carrier is OFF) during attach, so the IP network stack does not
-        * start IPv6 negotiation and more.
-        */
-       netif_carrier_off(dev->net);
        ctx->tx_speed = ctx->rx_speed = 0;
        return 0;
 
@@ -607,8 +504,9 @@ error:
        dev_info(&dev->udev->dev, "bind() failure\n");
        return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_bind_common);
 
-static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
+void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
        struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
        struct usb_driver *driver = driver_of(intf);
@@ -623,6 +521,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 
        tasklet_kill(&ctx->bh);
 
+       /* handle devices with combined control and data interface */
+       if (ctx->control == ctx->data)
+               ctx->data = NULL;
+
        /* disconnect master --> disconnect slave */
        if (intf == ctx->control && ctx->data) {
                usb_set_intfdata(ctx->data, NULL);
@@ -638,52 +540,121 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
        usb_set_intfdata(ctx->intf, NULL);
        cdc_ncm_free(ctx);
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
 
-static void cdc_ncm_zero_fill(u8 *ptr, u32 first, u32 end, u32 max)
+static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-       if (first >= max)
-               return;
-       if (first >= end)
-               return;
-       if (end > max)
-               end = max;
-       memset(ptr + first, 0, end - first);
+       int ret;
+
+       /* The MBIM spec defines a NCM compatible default altsetting,
+        * which we may have matched:
+        *
+        *  "Functions that implement both NCM 1.0 and MBIM (an
+        *   “NCM/MBIM function”) according to this recommendation
+        *   shall provide two alternate settings for the
+        *   Communication Interface.  Alternate setting 0, and the
+        *   associated class and endpoint descriptors, shall be
+        *   constructed according to the rules given for the
+        *   Communication Interface in section 5 of [USBNCM10].
+        *   Alternate setting 1, and the associated class and
+        *   endpoint descriptors, shall be constructed according to
+        *   the rules given in section 6 (USB Device Model) of this
+        *   specification."
+        *
+        * Do not bind to such interfaces, allowing cdc_mbim to handle
+        * them
+        */
+#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
+       if ((intf->num_altsetting == 2) &&
+           !usb_set_interface(dev->udev,
+                              intf->cur_altsetting->desc.bInterfaceNumber,
+                              CDC_NCM_COMM_ALTSETTING_MBIM) &&
+           cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+               return -ENODEV;
+#endif
+
+       /* NCM data altsetting is always 1 */
+       ret = cdc_ncm_bind_common(dev, intf, 1);
+
+       /*
+        * We should get an event when network connection is "connected" or
+        * "disconnected". Set network connection in "disconnected" state
+        * (carrier is OFF) during attach, so the IP network stack does not
+        * start IPv6 negotiation and more.
+        */
+       netif_carrier_off(dev->net);
+       return ret;
 }
 
-static struct sk_buff *
-cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
+static void cdc_ncm_align_tail(struct sk_buff *skb, size_t modulus, size_t remainder, size_t max)
 {
+       size_t align = ALIGN(skb->len, modulus) - skb->len + remainder;
+
+       if (skb->len + align > max)
+               align = max - skb->len;
+       if (align && skb_tailroom(skb) >= align)
+               memset(skb_put(skb, align), 0, align);
+}
+
+/* return a pointer to a valid struct usb_cdc_ncm_ndp16 of type sign, possibly
+ * allocating a new one within skb
+ */
+static struct usb_cdc_ncm_ndp16 *cdc_ncm_ndp(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign, size_t reserve)
+{
+       struct usb_cdc_ncm_ndp16 *ndp16 = NULL;
+       struct usb_cdc_ncm_nth16 *nth16 = (void *)skb->data;
+       size_t ndpoffset = le16_to_cpu(nth16->wNdpIndex);
+
+       /* follow the chain of NDPs, looking for a match */
+       while (ndpoffset) {
+               ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb->data + ndpoffset);
+               if  (ndp16->dwSignature == sign)
+                       return ndp16;
+               ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+       }
+
+       /* align new NDP */
+       cdc_ncm_align_tail(skb, ctx->tx_ndp_modulus, 0, ctx->tx_max);
+
+       /* verify that there is room for the NDP and the datagram (reserve) */
+       if ((ctx->tx_max - skb->len - reserve) < CDC_NCM_NDP_SIZE)
+               return NULL;
+
+       /* link to it */
+       if (ndp16)
+               ndp16->wNextNdpIndex = cpu_to_le16(skb->len);
+       else
+               nth16->wNdpIndex = cpu_to_le16(skb->len);
+
+       /* push a new empty NDP */
+       ndp16 = (struct usb_cdc_ncm_ndp16 *)memset(skb_put(skb, CDC_NCM_NDP_SIZE), 0, CDC_NCM_NDP_SIZE);
+       ndp16->dwSignature = sign;
+       ndp16->wLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_ndp16) + sizeof(struct usb_cdc_ncm_dpe16));
+       return ndp16;
+}
+
+struct sk_buff *
+cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign)
+{
+       struct usb_cdc_ncm_nth16 *nth16;
+       struct usb_cdc_ncm_ndp16 *ndp16;
        struct sk_buff *skb_out;
-       u32 rem;
-       u32 offset;
-       u32 last_offset;
-       u16 n = 0, index;
+       u16 n = 0, index, ndplen;
        u8 ready2send = 0;
 
        /* if there is a remaining skb, it gets priority */
-       if (skb != NULL)
+       if (skb != NULL) {
                swap(skb, ctx->tx_rem_skb);
-       else
+               swap(sign, ctx->tx_rem_sign);
+       } else {
                ready2send = 1;
-
-       /*
-        * +----------------+
-        * | skb_out        |
-        * +----------------+
-        *           ^ offset
-        *        ^ last_offset
-        */
+       }
 
        /* check if we are resuming an OUT skb */
-       if (ctx->tx_curr_skb != NULL) {
-               /* pop variables */
-               skb_out = ctx->tx_curr_skb;
-               offset = ctx->tx_curr_offset;
-               last_offset = ctx->tx_curr_last_offset;
-               n = ctx->tx_curr_frame_num;
+       skb_out = ctx->tx_curr_skb;
 
-       } else {
-               /* reset variables */
+       /* allocate a new OUT skb */
+       if (!skb_out) {
                skb_out = alloc_skb((ctx->tx_max + 1), GFP_ATOMIC);
                if (skb_out == NULL) {
                        if (skb != NULL) {
@@ -692,35 +663,21 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                        }
                        goto exit_no_skb;
                }
+               /* fill out the initial 16-bit NTB header */
+               nth16 = (struct usb_cdc_ncm_nth16 *)memset(skb_put(skb_out, sizeof(struct usb_cdc_ncm_nth16)), 0, sizeof(struct usb_cdc_ncm_nth16));
+               nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
+               nth16->wHeaderLength = cpu_to_le16(sizeof(struct usb_cdc_ncm_nth16));
+               nth16->wSequence = cpu_to_le16(ctx->tx_seq++);
 
-               /* make room for NTH and NDP */
-               offset = ALIGN(sizeof(struct usb_cdc_ncm_nth16),
-                                       ctx->tx_ndp_modulus) +
-                                       sizeof(struct usb_cdc_ncm_ndp16) +
-                                       (ctx->tx_max_datagrams + 1) *
-                                       sizeof(struct usb_cdc_ncm_dpe16);
-
-               /* store last valid offset before alignment */
-               last_offset = offset;
-               /* align first Datagram offset correctly */
-               offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
-               /* zero buffer till the first IP datagram */
-               cdc_ncm_zero_fill(skb_out->data, 0, offset, offset);
-               n = 0;
+               /* count total number of frames in this NTB */
                ctx->tx_curr_frame_num = 0;
        }
 
-       for (; n < ctx->tx_max_datagrams; n++) {
-               /* check if end of transmit buffer is reached */
-               if (offset >= ctx->tx_max) {
-                       ready2send = 1;
-                       break;
-               }
-               /* compute maximum buffer size */
-               rem = ctx->tx_max - offset;
-
+       for (n = ctx->tx_curr_frame_num; n < ctx->tx_max_datagrams; n++) {
+               /* send any remaining skb first */
                if (skb == NULL) {
                        skb = ctx->tx_rem_skb;
+                       sign = ctx->tx_rem_sign;
                        ctx->tx_rem_skb = NULL;
 
                        /* check for end of skb */
@@ -728,7 +685,14 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                                break;
                }
 
-               if (skb->len > rem) {
+               /* get the appropriate NDP for this skb */
+               ndp16 = cdc_ncm_ndp(ctx, skb_out, sign, skb->len + ctx->tx_modulus + ctx->tx_remainder);
+
+               /* align beginning of next frame */
+               cdc_ncm_align_tail(skb_out,  ctx->tx_modulus, ctx->tx_remainder, ctx->tx_max);
+
+               /* check if we had enough room left for both NDP and frame */
+               if (!ndp16 || skb_out->len + skb->len > ctx->tx_max) {
                        if (n == 0) {
                                /* won't fit, MTU problem? */
                                dev_kfree_skb_any(skb);
@@ -741,31 +705,30 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                                        ctx->netdev->stats.tx_dropped++;
                                }
                                ctx->tx_rem_skb = skb;
+                               ctx->tx_rem_sign = sign;
                                skb = NULL;
                                ready2send = 1;
                        }
                        break;
                }
 
-               memcpy(((u8 *)skb_out->data) + offset, skb->data, skb->len);
-
-               ctx->tx_ncm.dpe16[n].wDatagramLength = cpu_to_le16(skb->len);
-               ctx->tx_ncm.dpe16[n].wDatagramIndex = cpu_to_le16(offset);
-
-               /* update offset */
-               offset += skb->len;
-
-               /* store last valid offset before alignment */
-               last_offset = offset;
-
-               /* align offset correctly */
-               offset = ALIGN(offset, ctx->tx_modulus) + ctx->tx_remainder;
+               /* calculate frame number withing this NDP */
+               ndplen = le16_to_cpu(ndp16->wLength);
+               index = (ndplen - sizeof(struct usb_cdc_ncm_ndp16)) / sizeof(struct usb_cdc_ncm_dpe16) - 1;
 
-               /* zero padding */
-               cdc_ncm_zero_fill(skb_out->data, last_offset, offset,
-                                                               ctx->tx_max);
+               /* OK, add this skb */
+               ndp16->dpe16[index].wDatagramLength = cpu_to_le16(skb->len);
+               ndp16->dpe16[index].wDatagramIndex = cpu_to_le16(skb_out->len);
+               ndp16->wLength = cpu_to_le16(ndplen + sizeof(struct usb_cdc_ncm_dpe16));
+               memcpy(skb_put(skb_out, skb->len), skb->data, skb->len);
                dev_kfree_skb_any(skb);
                skb = NULL;
+
+               /* send now if this NDP is full */
+               if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) {
+                       ready2send = 1;
+                       break;
+               }
        }
 
        /* free up any dangling skb */
@@ -781,16 +744,12 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                /* wait for more frames */
                /* push variables */
                ctx->tx_curr_skb = skb_out;
-               ctx->tx_curr_offset = offset;
-               ctx->tx_curr_last_offset = last_offset;
                goto exit_no_skb;
 
        } else if ((n < ctx->tx_max_datagrams) && (ready2send == 0)) {
                /* wait for more frames */
                /* push variables */
                ctx->tx_curr_skb = skb_out;
-               ctx->tx_curr_offset = offset;
-               ctx->tx_curr_last_offset = last_offset;
                /* set the pending count */
                if (n < CDC_NCM_RESTART_TIMER_DATAGRAM_CNT)
                        ctx->tx_timer_pending = CDC_NCM_TIMER_PENDING_CNT;
@@ -801,75 +760,24 @@ cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb)
                /* variables will be reset at next call */
        }
 
-       /* check for overflow */
-       if (last_offset > ctx->tx_max)
-               last_offset = ctx->tx_max;
-
-       /* revert offset */
-       offset = last_offset;
-
        /*
         * If collected data size is less or equal CDC_NCM_MIN_TX_PKT bytes,
         * we send buffers as it is. If we get more data, it would be more
         * efficient for USB HS mobile device with DMA engine to receive a full
         * size NTB, than canceling DMA transfer and receiving a short packet.
         */
-       if (offset > CDC_NCM_MIN_TX_PKT)
-               offset = ctx->tx_max;
-
-       /* final zero padding */
-       cdc_ncm_zero_fill(skb_out->data, last_offset, offset, ctx->tx_max);
-
-       /* store last offset */
-       last_offset = offset;
-
-       if (((last_offset < ctx->tx_max) && ((last_offset %
-                       le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) ||
-           (((last_offset == ctx->tx_max) && ((ctx->tx_max %
-               le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0)) &&
-               (ctx->tx_max < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)))) {
-               /* force short packet */
-               *(((u8 *)skb_out->data) + last_offset) = 0;
-               last_offset++;
-       }
-
-       /* zero the rest of the DPEs plus the last NULL entry */
-       for (; n <= CDC_NCM_DPT_DATAGRAMS_MAX; n++) {
-               ctx->tx_ncm.dpe16[n].wDatagramLength = 0;
-               ctx->tx_ncm.dpe16[n].wDatagramIndex = 0;
-       }
-
-       /* fill out 16-bit NTB header */
-       ctx->tx_ncm.nth16.dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
-       ctx->tx_ncm.nth16.wHeaderLength =
-                                       cpu_to_le16(sizeof(ctx->tx_ncm.nth16));
-       ctx->tx_ncm.nth16.wSequence = cpu_to_le16(ctx->tx_seq);
-       ctx->tx_ncm.nth16.wBlockLength = cpu_to_le16(last_offset);
-       index = ALIGN(sizeof(struct usb_cdc_ncm_nth16), ctx->tx_ndp_modulus);
-       ctx->tx_ncm.nth16.wNdpIndex = cpu_to_le16(index);
-
-       memcpy(skb_out->data, &(ctx->tx_ncm.nth16), sizeof(ctx->tx_ncm.nth16));
-       ctx->tx_seq++;
-
-       /* fill out 16-bit NDP table */
-       ctx->tx_ncm.ndp16.dwSignature =
-                               cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN);
-       rem = sizeof(ctx->tx_ncm.ndp16) + ((ctx->tx_curr_frame_num + 1) *
-                                       sizeof(struct usb_cdc_ncm_dpe16));
-       ctx->tx_ncm.ndp16.wLength = cpu_to_le16(rem);
-       ctx->tx_ncm.ndp16.wNextNdpIndex = 0; /* reserved */
-
-       memcpy(((u8 *)skb_out->data) + index,
-                                               &(ctx->tx_ncm.ndp16),
-                                               sizeof(ctx->tx_ncm.ndp16));
+       if (skb_out->len > CDC_NCM_MIN_TX_PKT)
+               /* final zero padding */
+               memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0, ctx->tx_max - skb_out->len);
 
-       memcpy(((u8 *)skb_out->data) + index + sizeof(ctx->tx_ncm.ndp16),
-                                       &(ctx->tx_ncm.dpe16),
-                                       (ctx->tx_curr_frame_num + 1) *
-                                       sizeof(struct usb_cdc_ncm_dpe16));
+       /* do we need to prevent a ZLP? */
+       if (((skb_out->len % le16_to_cpu(ctx->out_ep->desc.wMaxPacketSize)) == 0) &&
+           (skb_out->len < le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)) && skb_tailroom(skb_out))
+               *skb_put(skb_out, 1) = 0;       /* force short packet */
 
-       /* set frame length */
-       skb_put(skb_out, last_offset);
+       /* set final frame length */
+       nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
+       nth16->wBlockLength = cpu_to_le16(skb_out->len);
 
        /* return skb */
        ctx->tx_curr_skb = NULL;
@@ -882,6 +790,7 @@ exit_no_skb:
                cdc_ncm_tx_timeout_start(ctx);
        return NULL;
 }
+EXPORT_SYMBOL_GPL(cdc_ncm_fill_tx_frame);
 
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx)
 {
@@ -916,6 +825,8 @@ static void cdc_ncm_txpath_bh(unsigned long param)
                netif_tx_lock_bh(ctx->netdev);
                usbnet_start_xmit(NULL, ctx->netdev);
                netif_tx_unlock_bh(ctx->netdev);
+       } else {
+               spin_unlock_bh(&ctx->mtx);
        }
 }
 
@@ -936,7 +847,7 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
                goto error;
 
        spin_lock_bh(&ctx->mtx);
-       skb_out = cdc_ncm_fill_tx_frame(ctx, skb);
+       skb_out = cdc_ncm_fill_tx_frame(ctx, skb, cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN));
        spin_unlock_bh(&ctx->mtx);
        return skb_out;
 
@@ -947,17 +858,12 @@ error:
        return NULL;
 }
 
-static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+/* verify NTB header and return offset of first NDP, or negative error */
+int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
 {
-       struct sk_buff *skb;
-       struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
-       int len;
-       int nframes;
-       int x;
-       int offset;
        struct usb_cdc_ncm_nth16 *nth16;
-       struct usb_cdc_ncm_ndp16 *ndp16;
-       struct usb_cdc_ncm_dpe16 *dpe16;
+       int len;
+       int ret = -EINVAL;
 
        if (ctx == NULL)
                goto error;
@@ -991,20 +897,23 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
        }
        ctx->rx_seq = le16_to_cpu(nth16->wSequence);
 
-       len = le16_to_cpu(nth16->wNdpIndex);
-       if ((len + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
-               pr_debug("invalid DPT16 index <%u>\n",
-                                       le16_to_cpu(nth16->wNdpIndex));
-               goto error;
-       }
+       ret = le16_to_cpu(nth16->wNdpIndex);
+error:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_nth16);
 
-       ndp16 = (struct usb_cdc_ncm_ndp16 *)(((u8 *)skb_in->data) + len);
+/* verify NDP header and return number of datagrams, or negative error */
+int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
+{
+       struct usb_cdc_ncm_ndp16 *ndp16;
+       int ret = -EINVAL;
 
-       if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
-               pr_debug("invalid DPT16 signature <%u>\n",
-                                       le32_to_cpu(ndp16->dwSignature));
+       if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
+               pr_debug("invalid NDP offset  <%u>\n", ndpoffset);
                goto error;
        }
+       ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
 
        if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
                pr_debug("invalid DPT16 length <%u>\n",
@@ -1012,20 +921,52 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
                goto error;
        }
 
-       nframes = ((le16_to_cpu(ndp16->wLength) -
+       ret = ((le16_to_cpu(ndp16->wLength) -
                                        sizeof(struct usb_cdc_ncm_ndp16)) /
                                        sizeof(struct usb_cdc_ncm_dpe16));
-       nframes--; /* we process NDP entries except for the last one */
+       ret--; /* we process NDP entries except for the last one */
 
-       len += sizeof(struct usb_cdc_ncm_ndp16);
-
-       if ((len + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) >
+       if ((sizeof(struct usb_cdc_ncm_ndp16) + ret * (sizeof(struct usb_cdc_ncm_dpe16))) >
                                                                skb_in->len) {
-               pr_debug("Invalid nframes = %d\n", nframes);
-               goto error;
+               pr_debug("Invalid nframes = %d\n", ret);
+               ret = -EINVAL;
        }
 
-       dpe16 = (struct usb_cdc_ncm_dpe16 *)(((u8 *)skb_in->data) + len);
+error:
+       return ret;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_rx_verify_ndp16);
+
+static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
+{
+       struct sk_buff *skb;
+       struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+       int len;
+       int nframes;
+       int x;
+       int offset;
+       struct usb_cdc_ncm_ndp16 *ndp16;
+       struct usb_cdc_ncm_dpe16 *dpe16;
+       int ndpoffset;
+       int loopcount = 50; /* arbitrary max preventing infinite loop */
+
+       ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
+       if (ndpoffset < 0)
+               goto error;
+
+next_ndp:
+       nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
+       if (nframes < 0)
+               goto error;
+
+       ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
+
+       if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
+               pr_debug("invalid DPT16 signature <%u>\n",
+                        le32_to_cpu(ndp16->dwSignature));
+               goto err_ndp;
+       }
+       dpe16 = ndp16->dpe16;
 
        for (x = 0; x < nframes; x++, dpe16++) {
                offset = le16_to_cpu(dpe16->wDatagramIndex);
@@ -1037,7 +978,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
                 */
                if ((offset == 0) || (len == 0)) {
                        if (!x)
-                               goto error; /* empty NTB */
+                               goto err_ndp; /* empty NTB */
                        break;
                }
 
@@ -1048,7 +989,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
                                        "offset[%u]=%u, length=%u, skb=%p\n",
                                        x, offset, len, skb_in);
                        if (!x)
-                               goto error;
+                               goto err_ndp;
                        break;
 
                } else {
@@ -1061,6 +1002,12 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
                        usbnet_skb_return(dev, skb);
                }
        }
+err_ndp:
+       /* are there more NDPs to process? */
+       ndpoffset = le16_to_cpu(ndp16->wNextNdpIndex);
+       if (ndpoffset && loopcount--)
+               goto next_ndp;
+
        return 1;
 error:
        return 0;
@@ -1125,7 +1072,7 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb)
                 * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be
                 * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE.
                 */
-               ctx->connected = event->wValue;
+               ctx->connected = le16_to_cpu(event->wValue);
 
                printk(KERN_INFO KBUILD_MODNAME ": %s: network connection:"
                        " %sconnected\n",
@@ -1245,6 +1192,14 @@ static const struct usb_device_id cdc_devs[] = {
          .driver_info = (unsigned long) &wwan_info,
        },
 
+       /* Huawei NCM devices disguised as vendor specific */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+
        /* Generic CDC-NCM devices */
        { USB_INTERFACE_INFO(USB_CLASS_COMM,
                USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
index e0433ce6ced7aedaf7d4e39d87aeb1c39c6a42de..3f554c1149f36d2cf3221ee38e4f02507d566ba7 100644 (file)
 
 static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
-       void *buf;
-       int err = -ENOMEM;
-
-       netdev_dbg(dev->net, "dm_read() reg=0x%02x length=%d\n", reg, length);
-
-       buf = kmalloc(length, GFP_KERNEL);
-       if (!buf)
-               goto out;
-
-       err = usb_control_msg(dev->udev,
-                             usb_rcvctrlpipe(dev->udev, 0),
-                             DM_READ_REGS,
-                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                             0, reg, buf, length, USB_CTRL_SET_TIMEOUT);
-       if (err == length)
-               memcpy(data, buf, length);
-       else if (err >= 0)
+       int err;
+       err = usbnet_read_cmd(dev, DM_READ_REGS,
+                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              0, reg, data, length);
+       if(err != length && err >= 0)
                err = -EINVAL;
-       kfree(buf);
-
- out:
        return err;
 }
 
@@ -87,91 +72,29 @@ static int dm_read_reg(struct usbnet *dev, u8 reg, u8 *value)
 
 static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
-       void *buf = NULL;
-       int err = -ENOMEM;
-
-       netdev_dbg(dev->net, "dm_write() reg=0x%02x, length=%d\n", reg, length);
+       int err;
+       err = usbnet_write_cmd(dev, DM_WRITE_REGS,
+                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               0, reg, data, length);
 
-       if (data) {
-               buf = kmemdup(data, length, GFP_KERNEL);
-               if (!buf)
-                       goto out;
-       }
-
-       err = usb_control_msg(dev->udev,
-                             usb_sndctrlpipe(dev->udev, 0),
-                             DM_WRITE_REGS,
-                             USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
-                             0, reg, buf, length, USB_CTRL_SET_TIMEOUT);
-       kfree(buf);
        if (err >= 0 && err < length)
                err = -EINVAL;
- out:
        return err;
 }
 
 static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
 {
-       netdev_dbg(dev->net, "dm_write_reg() reg=0x%02x, value=0x%02x\n",
-                  reg, value);
-       return usb_control_msg(dev->udev,
-                              usb_sndctrlpipe(dev->udev, 0),
-                              DM_WRITE_REG,
-                              USB_DIR_OUT | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
-                              value, reg, NULL, 0, USB_CTRL_SET_TIMEOUT);
-}
-
-static void dm_write_async_callback(struct urb *urb)
-{
-       struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-       int status = urb->status;
-
-       if (status < 0)
-               printk(KERN_DEBUG "dm_write_async_callback() failed with %d\n",
-                      status);
-
-       kfree(req);
-       usb_free_urb(urb);
+       return usbnet_write_cmd(dev, DM_WRITE_REGS,
+                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               value, reg, NULL, 0);
 }
 
 static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value,
                                  u16 length, void *data)
 {
-       struct usb_ctrlrequest *req;
-       struct urb *urb;
-       int status;
-
-       urb = usb_alloc_urb(0, GFP_ATOMIC);
-       if (!urb) {
-               netdev_err(dev->net, "Error allocating URB in dm_write_async_helper!\n");
-               return;
-       }
-
-       req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
-       if (!req) {
-               netdev_err(dev->net, "Failed to allocate memory for control request\n");
-               usb_free_urb(urb);
-               return;
-       }
-
-       req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-       req->bRequest = length ? DM_WRITE_REGS : DM_WRITE_REG;
-       req->wValue = cpu_to_le16(value);
-       req->wIndex = cpu_to_le16(reg);
-       req->wLength = cpu_to_le16(length);
-
-       usb_fill_control_urb(urb, dev->udev,
-                            usb_sndctrlpipe(dev->udev, 0),
-                            (void *)req, data, length,
-                            dm_write_async_callback, req);
-
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status < 0) {
-               netdev_err(dev->net, "Error submitting the control message: status=%d\n",
-                          status);
-               kfree(req);
-               usb_free_urb(urb);
-       }
+       usbnet_write_cmd_async(dev, DM_WRITE_REGS,
+                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                              value, reg, data, length);
 }
 
 static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
index 8de641713d5fcbfdfac05bc6475d86c0d596bd64..ace9e74ffbdd90ece5da77dab76890d46877a344 100644 (file)
@@ -116,23 +116,8 @@ static struct sk_buff *int51x1_tx_fixup(struct usbnet *dev,
        return skb;
 }
 
-static void int51x1_async_cmd_callback(struct urb *urb)
-{
-       struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-       int status = urb->status;
-
-       if (status < 0)
-               dev_warn(&urb->dev->dev, "async callback failed with %d\n", status);
-
-       kfree(req);
-       usb_free_urb(urb);
-}
-
 static void int51x1_set_multicast(struct net_device *netdev)
 {
-       struct usb_ctrlrequest *req;
-       int status;
-       struct urb *urb;
        struct usbnet *dev = netdev_priv(netdev);
        u16 filter = PACKET_TYPE_DIRECTED | PACKET_TYPE_BROADCAST;
 
@@ -149,40 +134,9 @@ static void int51x1_set_multicast(struct net_device *netdev)
                netdev_dbg(dev->net, "receive own packets only\n");
        }
 
-       urb = usb_alloc_urb(0, GFP_ATOMIC);
-       if (!urb) {
-               netdev_warn(dev->net, "Error allocating URB\n");
-               return;
-       }
-
-       req = kmalloc(sizeof(*req), GFP_ATOMIC);
-       if (!req) {
-               netdev_warn(dev->net, "Error allocating control msg\n");
-               goto out;
-       }
-
-       req->bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
-       req->bRequest = SET_ETHERNET_PACKET_FILTER;
-       req->wValue = cpu_to_le16(filter);
-       req->wIndex = 0;
-       req->wLength = 0;
-
-       usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
-               (void *)req, NULL, 0,
-               int51x1_async_cmd_callback,
-               (void *)req);
-
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status < 0) {
-               netdev_warn(dev->net, "Error submitting control msg, sts=%d\n",
-                           status);
-               goto out1;
-       }
-       return;
-out1:
-       kfree(req);
-out:
-       usb_free_urb(urb);
+       usbnet_write_cmd_async(dev, SET_ETHERNET_PACKET_FILTER,
+                              USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+                              filter, 0, NULL, 0);
 }
 
 static const struct net_device_ops int51x1_netdev_ops = {
index a28a983d465e6d434a3272a36a9ab35a7b5b3eee..534d8becbbdc779219f26c3df0481cd07171bcc7 100644 (file)
@@ -62,6 +62,7 @@
 #define USB_PRODUCT_IPAD 0x129a
 #define USB_PRODUCT_IPHONE_4_VZW 0x129c
 #define USB_PRODUCT_IPHONE_4S  0x12a0
+#define USB_PRODUCT_IPHONE_5   0x12a8
 
 #define IPHETH_USBINTF_CLASS    255
 #define IPHETH_USBINTF_SUBCLASS 253
@@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = {
                USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
                IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
                IPHETH_USBINTF_PROTO) },
+       { USB_DEVICE_AND_INTERFACE_INFO(
+               USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5,
+               IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+               IPHETH_USBINTF_PROTO) },
        { }
 };
 MODULE_DEVICE_TABLE(usb, ipheth_table);
index cc7e72010ac383f1d0981302df50dc7f388ab40c..3f3f566afa0b7fb54a65481dbbae27ba8a168e5f 100644 (file)
@@ -124,93 +124,20 @@ static const char driver_name[] = "MOSCHIP usb-ethernet driver";
 
 static int mcs7830_get_reg(struct usbnet *dev, u16 index, u16 size, void *data)
 {
-       struct usb_device *xdev = dev->udev;
-       int ret;
-       void *buffer;
-
-       buffer = kmalloc(size, GFP_NOIO);
-       if (buffer == NULL)
-               return -ENOMEM;
-
-       ret = usb_control_msg(xdev, usb_rcvctrlpipe(xdev, 0), MCS7830_RD_BREQ,
-                             MCS7830_RD_BMREQ, 0x0000, index, buffer,
-                             size, MCS7830_CTRL_TIMEOUT);
-       memcpy(data, buffer, size);
-       kfree(buffer);
-
-       return ret;
+       return usbnet_read_cmd(dev, MCS7830_RD_BREQ, MCS7830_RD_BMREQ,
+                               0x0000, index, data, size);
 }
 
 static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, const void *data)
 {
-       struct usb_device *xdev = dev->udev;
-       int ret;
-       void *buffer;
-
-       buffer = kmemdup(data, size, GFP_NOIO);
-       if (buffer == NULL)
-               return -ENOMEM;
-
-       ret = usb_control_msg(xdev, usb_sndctrlpipe(xdev, 0), MCS7830_WR_BREQ,
-                             MCS7830_WR_BMREQ, 0x0000, index, buffer,
-                             size, MCS7830_CTRL_TIMEOUT);
-       kfree(buffer);
-       return ret;
-}
-
-static void mcs7830_async_cmd_callback(struct urb *urb)
-{
-       struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
-       int status = urb->status;
-
-       if (status < 0)
-               printk(KERN_DEBUG "%s() failed with %d\n",
-                      __func__, status);
-
-       kfree(req);
-       usb_free_urb(urb);
+       return usbnet_write_cmd(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
+                               0x0000, index, data, size);
 }
 
 static void mcs7830_set_reg_async(struct usbnet *dev, u16 index, u16 size, void *data)
 {
-       struct usb_ctrlrequest *req;
-       int ret;
-       struct urb *urb;
-
-       urb = usb_alloc_urb(0, GFP_ATOMIC);
-       if (!urb) {
-               dev_dbg(&dev->udev->dev,
-                       "Error allocating URB in write_cmd_async!\n");
-               return;
-       }
-
-       req = kmalloc(sizeof *req, GFP_ATOMIC);
-       if (!req) {
-               dev_err(&dev->udev->dev,
-                       "Failed to allocate memory for control request\n");
-               goto out;
-       }
-       req->bRequestType = MCS7830_WR_BMREQ;
-       req->bRequest = MCS7830_WR_BREQ;
-       req->wValue = 0;
-       req->wIndex = cpu_to_le16(index);
-       req->wLength = cpu_to_le16(size);
-
-       usb_fill_control_urb(urb, dev->udev,
-                            usb_sndctrlpipe(dev->udev, 0),
-                            (void *)req, data, size,
-                            mcs7830_async_cmd_callback, req);
-
-       ret = usb_submit_urb(urb, GFP_ATOMIC);
-       if (ret < 0) {
-               dev_err(&dev->udev->dev,
-                       "Error submitting the control message: ret=%d\n", ret);
-               goto out;
-       }
-       return;
-out:
-       kfree(req);
-       usb_free_urb(urb);
+       usbnet_write_cmd_async(dev, MCS7830_WR_BREQ, MCS7830_WR_BMREQ,
+                               0x0000, index, data, size);
 }
 
 static int mcs7830_hif_get_mac_address(struct usbnet *dev, unsigned char *addr)
index c062a3e8295c12d5f69158026b3055522f0f5422..93e0716a118c309f90859e4ee913d2e2e32b41e0 100644 (file)
@@ -109,13 +109,11 @@ struct nc_trailer {
 static int
 nc_vendor_read(struct usbnet *dev, u8 req, u8 regnum, u16 *retval_ptr)
 {
-       int status = usb_control_msg(dev->udev,
-               usb_rcvctrlpipe(dev->udev, 0),
-               req,
-               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               0, regnum,
-               retval_ptr, sizeof *retval_ptr,
-               USB_CTRL_GET_TIMEOUT);
+       int status = usbnet_read_cmd(dev, req,
+                                    USB_DIR_IN | USB_TYPE_VENDOR |
+                                    USB_RECIP_DEVICE,
+                                    0, regnum, retval_ptr,
+                                    sizeof *retval_ptr);
        if (status > 0)
                status = 0;
        if (!status)
@@ -133,13 +131,9 @@ nc_register_read(struct usbnet *dev, u8 regnum, u16 *retval_ptr)
 static void
 nc_vendor_write(struct usbnet *dev, u8 req, u8 regnum, u16 value)
 {
-       usb_control_msg(dev->udev,
-               usb_sndctrlpipe(dev->udev, 0),
-               req,
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               value, regnum,
-               NULL, 0,                        // data is in setup packet
-               USB_CTRL_SET_TIMEOUT);
+       usbnet_write_cmd(dev, req,
+                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                        value, regnum, NULL, 0);
 }
 
 static inline void
@@ -288,37 +282,34 @@ static inline void nc_dump_ttl(struct usbnet *dev, u16 ttl)
 static int net1080_reset(struct usbnet *dev)
 {
        u16             usbctl, status, ttl;
-       u16             *vp = kmalloc(sizeof (u16), GFP_KERNEL);
+       u16             vp;
        int             retval;
 
-       if (!vp)
-               return -ENOMEM;
-
        // nc_dump_registers(dev);
 
-       if ((retval = nc_register_read(dev, REG_STATUS, vp)) < 0) {
+       if ((retval = nc_register_read(dev, REG_STATUS, &vp)) < 0) {
                netdev_dbg(dev->net, "can't read %s-%s status: %d\n",
                           dev->udev->bus->bus_name, dev->udev->devpath, retval);
                goto done;
        }
-       status = *vp;
+       status = vp;
        nc_dump_status(dev, status);
 
-       if ((retval = nc_register_read(dev, REG_USBCTL, vp)) < 0) {
+       if ((retval = nc_register_read(dev, REG_USBCTL, &vp)) < 0) {
                netdev_dbg(dev->net, "can't read USBCTL, %d\n", retval);
                goto done;
        }
-       usbctl = *vp;
+       usbctl = vp;
        nc_dump_usbctl(dev, usbctl);
 
        nc_register_write(dev, REG_USBCTL,
                        USBCTL_FLUSH_THIS | USBCTL_FLUSH_OTHER);
 
-       if ((retval = nc_register_read(dev, REG_TTL, vp)) < 0) {
+       if ((retval = nc_register_read(dev, REG_TTL, &vp)) < 0) {
                netdev_dbg(dev->net, "can't read TTL, %d\n", retval);
                goto done;
        }
-       ttl = *vp;
+       ttl = vp;
        // nc_dump_ttl(dev, ttl);
 
        nc_register_write(dev, REG_TTL,
@@ -331,7 +322,6 @@ static int net1080_reset(struct usbnet *dev)
        retval = 0;
 
 done:
-       kfree(vp);
        return retval;
 }
 
@@ -339,13 +329,10 @@ static int net1080_check_connect(struct usbnet *dev)
 {
        int                     retval;
        u16                     status;
-       u16                     *vp = kmalloc(sizeof (u16), GFP_KERNEL);
+       u16                     vp;
 
-       if (!vp)
-               return -ENOMEM;
-       retval = nc_register_read(dev, REG_STATUS, vp);
-       status = *vp;
-       kfree(vp);
+       retval = nc_register_read(dev, REG_STATUS, &vp);
+       status = vp;
        if (retval != 0) {
                netdev_dbg(dev->net, "net1080_check_conn read - %d\n", retval);
                return retval;
@@ -355,59 +342,22 @@ static int net1080_check_connect(struct usbnet *dev)
        return 0;
 }
 
-static void nc_flush_complete(struct urb *urb)
-{
-       kfree(urb->context);
-       usb_free_urb(urb);
-}
-
 static void nc_ensure_sync(struct usbnet *dev)
 {
-       dev->frame_errors++;
-       if (dev->frame_errors > 5) {
-               struct urb              *urb;
-               struct usb_ctrlrequest  *req;
-               int                     status;
-
-               /* Send a flush */
-               urb = usb_alloc_urb(0, GFP_ATOMIC);
-               if (!urb)
-                       return;
-
-               req = kmalloc(sizeof *req, GFP_ATOMIC);
-               if (!req) {
-                       usb_free_urb(urb);
-                       return;
-               }
+       if (++dev->frame_errors <= 5)
+               return;
 
-               req->bRequestType = USB_DIR_OUT
-                       | USB_TYPE_VENDOR
-                       | USB_RECIP_DEVICE;
-               req->bRequest = REQUEST_REGISTER;
-               req->wValue = cpu_to_le16(USBCTL_FLUSH_THIS
-                               | USBCTL_FLUSH_OTHER);
-               req->wIndex = cpu_to_le16(REG_USBCTL);
-               req->wLength = cpu_to_le16(0);
-
-               /* queue an async control request, we don't need
-                * to do anything when it finishes except clean up.
-                */
-               usb_fill_control_urb(urb, dev->udev,
-                       usb_sndctrlpipe(dev->udev, 0),
-                       (unsigned char *) req,
-                       NULL, 0,
-                       nc_flush_complete, req);
-               status = usb_submit_urb(urb, GFP_ATOMIC);
-               if (status) {
-                       kfree(req);
-                       usb_free_urb(urb);
-                       return;
-               }
+       if (usbnet_write_cmd_async(dev, REQUEST_REGISTER,
+                                       USB_DIR_OUT | USB_TYPE_VENDOR |
+                                       USB_RECIP_DEVICE,
+                                       USBCTL_FLUSH_THIS |
+                                       USBCTL_FLUSH_OTHER,
+                                       REG_USBCTL, NULL, 0))
+               return;
 
-               netif_dbg(dev, rx_err, dev->net,
-                         "flush net1080; too many framing errors\n");
-               dev->frame_errors = 0;
-       }
+       netif_dbg(dev, rx_err, dev->net,
+                 "flush net1080; too many framing errors\n");
+       dev->frame_errors = 0;
 }
 
 static int net1080_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
index 4584b9a805b3b044b0261871def65c6b5cf13c03..0fcc8e65a06800a390b2aab1ab4ff1f7486cd051 100644 (file)
 static inline int
 pl_vendor_req(struct usbnet *dev, u8 req, u8 val, u8 index)
 {
-       return usb_control_msg(dev->udev,
-               usb_rcvctrlpipe(dev->udev, 0),
-               req,
-               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               val, index,
-               NULL, 0,
-               USB_CTRL_GET_TIMEOUT);
+       return usbnet_read_cmd(dev, req,
+                               USB_DIR_IN | USB_TYPE_VENDOR |
+                               USB_RECIP_DEVICE,
+                               val, index, NULL, 0);
 }
 
 static inline int
index 6883c371c59f5a2eb416466563cad5e1fbaa5b9a..1ea91f4237f053e731093fe3fc85e5897f97f5d7 100644 (file)
@@ -369,18 +369,74 @@ static const struct usb_device_id products[] = {
                USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_info,
        },
+       {       /* Novatel USB551L and MC551 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0xb001,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
+       {       /* Novatel E362 */
+               USB_DEVICE_AND_INTERFACE_INFO(0x1410, 0x9010,
+                                             USB_CLASS_COMM,
+                                             USB_CDC_SUBCLASS_ETHERNET,
+                                             USB_CDC_PROTO_NONE),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
 
        /* 3. Combined interface devices matching on interface number */
+       {QMI_FIXED_INTF(0x12d1, 0x140c, 1)},    /* Huawei E173 */
+       {QMI_FIXED_INTF(0x19d2, 0x0002, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0012, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0017, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0021, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0025, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0031, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0042, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0049, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0052, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0055, 1)},    /* ZTE (Vodafone) K3520-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0058, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x0063, 4)},    /* ZTE (Vodafone) K3565-Z */
        {QMI_FIXED_INTF(0x19d2, 0x0104, 4)},    /* ZTE (Vodafone) K4505-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0113, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0118, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0121, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0123, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0124, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0125, 6)},
+       {QMI_FIXED_INTF(0x19d2, 0x0126, 5)},
+       {QMI_FIXED_INTF(0x19d2, 0x0130, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0133, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0141, 5)},
        {QMI_FIXED_INTF(0x19d2, 0x0157, 5)},    /* ZTE MF683 */
+       {QMI_FIXED_INTF(0x19d2, 0x0158, 3)},
        {QMI_FIXED_INTF(0x19d2, 0x0167, 4)},    /* ZTE MF820D */
+       {QMI_FIXED_INTF(0x19d2, 0x0168, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x0176, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0178, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x0191, 4)},    /* ZTE EuFi890 */
+       {QMI_FIXED_INTF(0x19d2, 0x0199, 1)},    /* ZTE MF820S */
+       {QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
+       {QMI_FIXED_INTF(0x19d2, 0x0257, 3)},    /* ZTE MF821 */
        {QMI_FIXED_INTF(0x19d2, 0x0326, 4)},    /* ZTE MF821D */
        {QMI_FIXED_INTF(0x19d2, 0x1008, 4)},    /* ZTE (Vodafone) K3570-Z */
        {QMI_FIXED_INTF(0x19d2, 0x1010, 4)},    /* ZTE (Vodafone) K3571-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x1012, 4)},
        {QMI_FIXED_INTF(0x19d2, 0x1018, 3)},    /* ZTE (Vodafone) K5006-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x1021, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1245, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1247, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1252, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1254, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 3)},
+       {QMI_FIXED_INTF(0x19d2, 0x1255, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1256, 4)},
+       {QMI_FIXED_INTF(0x19d2, 0x1401, 2)},
        {QMI_FIXED_INTF(0x19d2, 0x1402, 2)},    /* ZTE MF60 */
+       {QMI_FIXED_INTF(0x19d2, 0x1424, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1425, 2)},
+       {QMI_FIXED_INTF(0x19d2, 0x1426, 2)},    /* ZTE MF91 */
        {QMI_FIXED_INTF(0x19d2, 0x2002, 4)},    /* ZTE (Vodafone) K3765-Z */
        {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)},    /* Sierra Wireless MC7700 */
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
index c27d27701aee2e2ce0d7e22f077c579da2ee1b07..18dd4257ab17eaba7115ab33fe3bef2743f38a63 100644 (file)
@@ -311,10 +311,9 @@ static int sierra_net_send_cmd(struct usbnet *dev,
        struct sierra_net_data *priv = sierra_net_get_private(dev);
        int  status;
 
-       status = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-                       USB_CDC_SEND_ENCAPSULATED_COMMAND,
-                       USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE, 0,
-                       priv->ifnum, cmd, cmdlen, USB_CTRL_SET_TIMEOUT);
+       status = usbnet_write_cmd(dev, USB_CDC_SEND_ENCAPSULATED_COMMAND,
+                                 USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE,
+                                 0, priv->ifnum, cmd, cmdlen);
 
        if (status != cmdlen && status != -ENODEV)
                netdev_err(dev->net, "Submit %s failed %d\n", cmd_name, status);
@@ -340,7 +339,7 @@ static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix)
        dev_dbg(&(priv->usbnet->udev->dev), "%s %d", __func__, ctx_ix);
        priv->tx_hdr_template[0] = 0x3F;
        priv->tx_hdr_template[1] = ctx_ix;
-       *((u16 *)&priv->tx_hdr_template[2]) =
+       *((__be16 *)&priv->tx_hdr_template[2]) =
                cpu_to_be16(SIERRA_NET_HIP_EXT_IP_OUT_ID);
 }
 
@@ -632,32 +631,22 @@ static int sierra_net_change_mtu(struct net_device *net, int new_mtu)
 static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
 {
        int result = 0;
-       u16 *attrdata;
-
-       attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL);
-       if (!attrdata)
-               return -ENOMEM;
-
-       result = usb_control_msg(
-                       dev->udev,
-                       usb_rcvctrlpipe(dev->udev, 0),
-                       /* _u8 vendor specific request */
-                       SWI_USB_REQUEST_GET_FW_ATTR,
-                       USB_DIR_IN | USB_TYPE_VENDOR,   /* __u8 request type */
-                       0x0000,         /* __u16 value not used */
-                       0x0000,         /* __u16 index  not used */
-                       attrdata,       /* char *data */
-                       sizeof(*attrdata),              /* __u16 size */
-                       USB_CTRL_SET_TIMEOUT);  /* int timeout */
-
-       if (result < 0) {
-               kfree(attrdata);
+       __le16 attrdata;
+
+       result = usbnet_read_cmd(dev,
+                               /* _u8 vendor specific request */
+                               SWI_USB_REQUEST_GET_FW_ATTR,
+                               USB_DIR_IN | USB_TYPE_VENDOR,   /* __u8 request type */
+                               0x0000,         /* __u16 value not used */
+                               0x0000,         /* __u16 index  not used */
+                               &attrdata,      /* char *data */
+                               sizeof(attrdata)        /* __u16 size */
+                               );
+
+       if (result < 0)
                return -EIO;
-       }
-
-       *datap = le16_to_cpu(*attrdata);
 
-       kfree(attrdata);
+       *datap = le16_to_cpu(attrdata);
        return result;
 }
 
index b77ae76f4aa8f96bbbcabb2d2c4eac5a837d3c29..251a3354a4b049b2299233aa90606f400e5ccf2b 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/bitrev.h>
+#include <linux/crc16.h>
 #include <linux/crc32.h>
 #include <linux/usb/usbnet.h>
 #include <linux/slab.h>
 #define USB_PRODUCT_ID_LAN7500         (0x7500)
 #define USB_PRODUCT_ID_LAN7505         (0x7505)
 #define RXW_PADDING                    2
-#define SUPPORTED_WAKE                 (WAKE_MAGIC)
+#define SUPPORTED_WAKE                 (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
+                                        WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
 
-#define check_warn(ret, fmt, args...) \
-       ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
-
-#define check_warn_return(ret, fmt, args...) \
-       ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } })
-
-#define check_warn_goto_done(ret, fmt, args...) \
-       ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } })
+#define SUSPEND_SUSPEND0               (0x01)
+#define SUSPEND_SUSPEND1               (0x02)
+#define SUSPEND_SUSPEND2               (0x04)
+#define SUSPEND_SUSPEND3               (0x08)
+#define SUSPEND_ALLMODES               (SUSPEND_SUSPEND0 | SUSPEND_SUSPEND1 | \
+                                        SUSPEND_SUSPEND2 | SUSPEND_SUSPEND3)
 
 struct smsc75xx_priv {
        struct usbnet *dev;
@@ -71,6 +72,7 @@ struct smsc75xx_priv {
        struct mutex dataport_mutex;
        spinlock_t rfe_ctl_lock;
        struct work_struct set_multicast;
+       u8 suspend_flags;
 };
 
 struct usb_context {
@@ -82,96 +84,99 @@ static bool turbo_mode = true;
 module_param(turbo_mode, bool, 0644);
 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
 
-static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
-                                         u32 *data)
+static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index,
+                                           u32 *data, int in_pm)
 {
-       u32 *buf = kmalloc(4, GFP_KERNEL);
+       u32 buf;
        int ret;
+       int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
 
        BUG_ON(!dev);
 
-       if (!buf)
-               return -ENOMEM;
-
-       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-               USB_VENDOR_REQUEST_READ_REGISTER,
-               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+       if (!in_pm)
+               fn = usbnet_read_cmd;
+       else
+               fn = usbnet_read_cmd_nopm;
 
+       ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
+                | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                0, index, &buf, 4);
        if (unlikely(ret < 0))
-               netdev_warn(dev->net,
-                       "Failed to read reg index 0x%08x: %d", index, ret);
+               netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
+                           index, ret);
 
-       le32_to_cpus(buf);
-       *data = *buf;
-       kfree(buf);
+       le32_to_cpus(&buf);
+       *data = buf;
 
        return ret;
 }
 
-static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
-                                          u32 data)
+static int __must_check __smsc75xx_write_reg(struct usbnet *dev, u32 index,
+                                            u32 data, int in_pm)
 {
-       u32 *buf = kmalloc(4, GFP_KERNEL);
+       u32 buf;
        int ret;
+       int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
 
        BUG_ON(!dev);
 
-       if (!buf)
-               return -ENOMEM;
-
-       *buf = data;
-       cpu_to_le32s(buf);
+       if (!in_pm)
+               fn = usbnet_write_cmd;
+       else
+               fn = usbnet_write_cmd_nopm;
 
-       ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-               USB_VENDOR_REQUEST_WRITE_REGISTER,
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+       buf = data;
+       cpu_to_le32s(&buf);
 
+       ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
+                | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                0, index, &buf, 4);
        if (unlikely(ret < 0))
-               netdev_warn(dev->net,
-                       "Failed to write reg index 0x%08x: %d", index, ret);
-
-       kfree(buf);
+               netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
+                           index, ret);
 
        return ret;
 }
 
-static int smsc75xx_set_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc75xx_read_reg_nopm(struct usbnet *dev, u32 index,
+                                              u32 *data)
 {
-       if (WARN_ON_ONCE(!dev))
-               return -EINVAL;
-
-       cpu_to_le32s(&feature);
-
-       return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-               USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
-               USB_CTRL_SET_TIMEOUT);
+       return __smsc75xx_read_reg(dev, index, data, 1);
 }
 
-static int smsc75xx_clear_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc75xx_write_reg_nopm(struct usbnet *dev, u32 index,
+                                               u32 data)
 {
-       if (WARN_ON_ONCE(!dev))
-               return -EINVAL;
+       return __smsc75xx_write_reg(dev, index, data, 1);
+}
 
-       cpu_to_le32s(&feature);
+static int __must_check smsc75xx_read_reg(struct usbnet *dev, u32 index,
+                                         u32 *data)
+{
+       return __smsc75xx_read_reg(dev, index, data, 0);
+}
 
-       return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-               USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
-               USB_CTRL_SET_TIMEOUT);
+static int __must_check smsc75xx_write_reg(struct usbnet *dev, u32 index,
+                                          u32 data)
+{
+       return __smsc75xx_write_reg(dev, index, data, 0);
 }
 
 /* Loop until the read is completed with timeout
  * called with phy_mutex held */
-static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
+static __must_check int __smsc75xx_phy_wait_not_busy(struct usbnet *dev,
+                                                    int in_pm)
 {
        unsigned long start_time = jiffies;
        u32 val;
        int ret;
 
        do {
-               ret = smsc75xx_read_reg(dev, MII_ACCESS, &val);
-               check_warn_return(ret, "Error reading MII_ACCESS");
+               ret = __smsc75xx_read_reg(dev, MII_ACCESS, &val, in_pm);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading MII_ACCESS\n");
+                       return ret;
+               }
 
                if (!(val & MII_ACCESS_BUSY))
                        return 0;
@@ -180,7 +185,8 @@ static int smsc75xx_phy_wait_not_busy(struct usbnet *dev)
        return -EIO;
 }
 
-static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+static int __smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
+                               int in_pm)
 {
        struct usbnet *dev = netdev_priv(netdev);
        u32 val, addr;
@@ -189,8 +195,11 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
        mutex_lock(&dev->phy_mutex);
 
        /* confirm MII not busy */
-       ret = smsc75xx_phy_wait_not_busy(dev);
-       check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_read");
+       ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "MII is busy in smsc75xx_mdio_read\n");
+               goto done;
+       }
 
        /* set the address, index & direction (read from PHY) */
        phy_id &= dev->mii.phy_id_mask;
@@ -198,14 +207,23 @@ static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
        addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
                | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
                | MII_ACCESS_READ | MII_ACCESS_BUSY;
-       ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
-       check_warn_goto_done(ret, "Error writing MII_ACCESS");
+       ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing MII_ACCESS\n");
+               goto done;
+       }
 
-       ret = smsc75xx_phy_wait_not_busy(dev);
-       check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
+       ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx);
+               goto done;
+       }
 
-       ret = smsc75xx_read_reg(dev, MII_DATA, &val);
-       check_warn_goto_done(ret, "Error reading MII_DATA");
+       ret = __smsc75xx_read_reg(dev, MII_DATA, &val, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading MII_DATA\n");
+               goto done;
+       }
 
        ret = (u16)(val & 0xFFFF);
 
@@ -214,8 +232,8 @@ done:
        return ret;
 }
 
-static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
-                               int regval)
+static void __smsc75xx_mdio_write(struct net_device *netdev, int phy_id,
+                                 int idx, int regval, int in_pm)
 {
        struct usbnet *dev = netdev_priv(netdev);
        u32 val, addr;
@@ -224,12 +242,18 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
        mutex_lock(&dev->phy_mutex);
 
        /* confirm MII not busy */
-       ret = smsc75xx_phy_wait_not_busy(dev);
-       check_warn_goto_done(ret, "MII is busy in smsc75xx_mdio_write");
+       ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "MII is busy in smsc75xx_mdio_write\n");
+               goto done;
+       }
 
        val = regval;
-       ret = smsc75xx_write_reg(dev, MII_DATA, val);
-       check_warn_goto_done(ret, "Error writing MII_DATA");
+       ret = __smsc75xx_write_reg(dev, MII_DATA, val, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing MII_DATA\n");
+               goto done;
+       }
 
        /* set the address, index & direction (write to PHY) */
        phy_id &= dev->mii.phy_id_mask;
@@ -237,16 +261,45 @@ static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
        addr = ((phy_id << MII_ACCESS_PHY_ADDR_SHIFT) & MII_ACCESS_PHY_ADDR)
                | ((idx << MII_ACCESS_REG_ADDR_SHIFT) & MII_ACCESS_REG_ADDR)
                | MII_ACCESS_WRITE | MII_ACCESS_BUSY;
-       ret = smsc75xx_write_reg(dev, MII_ACCESS, addr);
-       check_warn_goto_done(ret, "Error writing MII_ACCESS");
+       ret = __smsc75xx_write_reg(dev, MII_ACCESS, addr, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing MII_ACCESS\n");
+               goto done;
+       }
 
-       ret = smsc75xx_phy_wait_not_busy(dev);
-       check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
+       ret = __smsc75xx_phy_wait_not_busy(dev, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx);
+               goto done;
+       }
 
 done:
        mutex_unlock(&dev->phy_mutex);
 }
 
+static int smsc75xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
+                                  int idx)
+{
+       return __smsc75xx_mdio_read(netdev, phy_id, idx, 1);
+}
+
+static void smsc75xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
+                                    int idx, int regval)
+{
+       __smsc75xx_mdio_write(netdev, phy_id, idx, regval, 1);
+}
+
+static int smsc75xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+       return __smsc75xx_mdio_read(netdev, phy_id, idx, 0);
+}
+
+static void smsc75xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+                               int regval)
+{
+       __smsc75xx_mdio_write(netdev, phy_id, idx, regval, 0);
+}
+
 static int smsc75xx_wait_eeprom(struct usbnet *dev)
 {
        unsigned long start_time = jiffies;
@@ -255,7 +308,10 @@ static int smsc75xx_wait_eeprom(struct usbnet *dev)
 
        do {
                ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
-               check_warn_return(ret, "Error reading E2P_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading E2P_CMD\n");
+                       return ret;
+               }
 
                if (!(val & E2P_CMD_BUSY) || (val & E2P_CMD_TIMEOUT))
                        break;
@@ -263,7 +319,7 @@ static int smsc75xx_wait_eeprom(struct usbnet *dev)
        } while (!time_after(jiffies, start_time + HZ));
 
        if (val & (E2P_CMD_TIMEOUT | E2P_CMD_BUSY)) {
-               netdev_warn(dev->net, "EEPROM read operation timeout");
+               netdev_warn(dev->net, "EEPROM read operation timeout\n");
                return -EIO;
        }
 
@@ -278,7 +334,10 @@ static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
 
        do {
                ret = smsc75xx_read_reg(dev, E2P_CMD, &val);
-               check_warn_return(ret, "Error reading E2P_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading E2P_CMD\n");
+                       return ret;
+               }
 
                if (!(val & E2P_CMD_BUSY))
                        return 0;
@@ -286,7 +345,7 @@ static int smsc75xx_eeprom_confirm_not_busy(struct usbnet *dev)
                udelay(40);
        } while (!time_after(jiffies, start_time + HZ));
 
-       netdev_warn(dev->net, "EEPROM is busy");
+       netdev_warn(dev->net, "EEPROM is busy\n");
        return -EIO;
 }
 
@@ -306,14 +365,20 @@ static int smsc75xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
        for (i = 0; i < length; i++) {
                val = E2P_CMD_BUSY | E2P_CMD_READ | (offset & E2P_CMD_ADDR);
                ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-               check_warn_return(ret, "Error writing E2P_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing E2P_CMD\n");
+                       return ret;
+               }
 
                ret = smsc75xx_wait_eeprom(dev);
                if (ret < 0)
                        return ret;
 
                ret = smsc75xx_read_reg(dev, E2P_DATA, &val);
-               check_warn_return(ret, "Error reading E2P_DATA");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading E2P_DATA\n");
+                       return ret;
+               }
 
                data[i] = val & 0xFF;
                offset++;
@@ -338,7 +403,10 @@ static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
        /* Issue write/erase enable command */
        val = E2P_CMD_BUSY | E2P_CMD_EWEN;
        ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-       check_warn_return(ret, "Error writing E2P_CMD");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing E2P_CMD\n");
+               return ret;
+       }
 
        ret = smsc75xx_wait_eeprom(dev);
        if (ret < 0)
@@ -349,12 +417,18 @@ static int smsc75xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
                /* Fill data register */
                val = data[i];
                ret = smsc75xx_write_reg(dev, E2P_DATA, val);
-               check_warn_return(ret, "Error writing E2P_DATA");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing E2P_DATA\n");
+                       return ret;
+               }
 
                /* Send "write" command */
                val = E2P_CMD_BUSY | E2P_CMD_WRITE | (offset & E2P_CMD_ADDR);
                ret = smsc75xx_write_reg(dev, E2P_CMD, val);
-               check_warn_return(ret, "Error writing E2P_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing E2P_CMD\n");
+                       return ret;
+               }
 
                ret = smsc75xx_wait_eeprom(dev);
                if (ret < 0)
@@ -373,7 +447,10 @@ static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
        for (i = 0; i < 100; i++) {
                u32 dp_sel;
                ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
-               check_warn_return(ret, "Error reading DP_SEL");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading DP_SEL\n");
+                       return ret;
+               }
 
                if (dp_sel & DP_SEL_DPRDY)
                        return 0;
@@ -381,7 +458,7 @@ static int smsc75xx_dataport_wait_not_busy(struct usbnet *dev)
                udelay(40);
        }
 
-       netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out");
+       netdev_warn(dev->net, "smsc75xx_dataport_wait_not_busy timed out\n");
 
        return -EIO;
 }
@@ -396,28 +473,49 @@ static int smsc75xx_dataport_write(struct usbnet *dev, u32 ram_select, u32 addr,
        mutex_lock(&pdata->dataport_mutex);
 
        ret = smsc75xx_dataport_wait_not_busy(dev);
-       check_warn_goto_done(ret, "smsc75xx_dataport_write busy on entry");
+       if (ret < 0) {
+               netdev_warn(dev->net, "smsc75xx_dataport_write busy on entry\n");
+               goto done;
+       }
 
        ret = smsc75xx_read_reg(dev, DP_SEL, &dp_sel);
-       check_warn_goto_done(ret, "Error reading DP_SEL");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading DP_SEL\n");
+               goto done;
+       }
 
        dp_sel &= ~DP_SEL_RSEL;
        dp_sel |= ram_select;
        ret = smsc75xx_write_reg(dev, DP_SEL, dp_sel);
-       check_warn_goto_done(ret, "Error writing DP_SEL");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing DP_SEL\n");
+               goto done;
+       }
 
        for (i = 0; i < length; i++) {
                ret = smsc75xx_write_reg(dev, DP_ADDR, addr + i);
-               check_warn_goto_done(ret, "Error writing DP_ADDR");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing DP_ADDR\n");
+                       goto done;
+               }
 
                ret = smsc75xx_write_reg(dev, DP_DATA, buf[i]);
-               check_warn_goto_done(ret, "Error writing DP_DATA");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing DP_DATA\n");
+                       goto done;
+               }
 
                ret = smsc75xx_write_reg(dev, DP_CMD, DP_CMD_WRITE);
-               check_warn_goto_done(ret, "Error writing DP_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing DP_CMD\n");
+                       goto done;
+               }
 
                ret = smsc75xx_dataport_wait_not_busy(dev);
-               check_warn_goto_done(ret, "smsc75xx_dataport_write timeout");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "smsc75xx_dataport_write timeout\n");
+                       goto done;
+               }
        }
 
 done:
@@ -438,14 +536,15 @@ static void smsc75xx_deferred_multicast_write(struct work_struct *param)
        struct usbnet *dev = pdata->dev;
        int ret;
 
-       netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x",
-               pdata->rfe_ctl);
+       netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n",
+                 pdata->rfe_ctl);
 
        smsc75xx_dataport_write(dev, DP_SEL_VHF, DP_SEL_VHF_VLAN_LEN,
                DP_SEL_VHF_HASH_LEN, pdata->multicast_hash_table);
 
        ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-       check_warn(ret, "Error writing RFE_CRL");
+       if (ret < 0)
+               netdev_warn(dev->net, "Error writing RFE_CRL\n");
 }
 
 static void smsc75xx_set_multicast(struct net_device *netdev)
@@ -465,15 +564,15 @@ static void smsc75xx_set_multicast(struct net_device *netdev)
                pdata->multicast_hash_table[i] = 0;
 
        if (dev->net->flags & IFF_PROMISC) {
-               netif_dbg(dev, drv, dev->net, "promiscuous mode enabled");
+               netif_dbg(dev, drv, dev->net, "promiscuous mode enabled\n");
                pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_AU;
        } else if (dev->net->flags & IFF_ALLMULTI) {
-               netif_dbg(dev, drv, dev->net, "receive all multicast enabled");
+               netif_dbg(dev, drv, dev->net, "receive all multicast enabled\n");
                pdata->rfe_ctl |= RFE_CTL_AM | RFE_CTL_DPF;
        } else if (!netdev_mc_empty(dev->net)) {
                struct netdev_hw_addr *ha;
 
-               netif_dbg(dev, drv, dev->net, "receive multicast hash filter");
+               netif_dbg(dev, drv, dev->net, "receive multicast hash filter\n");
 
                pdata->rfe_ctl |= RFE_CTL_MHF | RFE_CTL_DPF;
 
@@ -483,7 +582,7 @@ static void smsc75xx_set_multicast(struct net_device *netdev)
                                (1 << (bitnum % 32));
                }
        } else {
-               netif_dbg(dev, drv, dev->net, "receive own packets only");
+               netif_dbg(dev, drv, dev->net, "receive own packets only\n");
                pdata->rfe_ctl |= RFE_CTL_DPF;
        }
 
@@ -511,18 +610,24 @@ static int smsc75xx_update_flowcontrol(struct usbnet *dev, u8 duplex,
                if (cap & FLOW_CTRL_RX)
                        flow |= FLOW_RX_FCEN;
 
-               netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s",
-                       (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
-                       (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+               netif_dbg(dev, link, dev->net, "rx pause %s, tx pause %s\n",
+                         (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+                         (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
        } else {
-               netif_dbg(dev, link, dev->net, "half duplex");
+               netif_dbg(dev, link, dev->net, "half duplex\n");
        }
 
        ret = smsc75xx_write_reg(dev, FLOW, flow);
-       check_warn_return(ret, "Error writing FLOW");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing FLOW\n");
+               return ret;
+       }
 
        ret = smsc75xx_write_reg(dev, FCT_FLOW, fct_flow);
-       check_warn_return(ret, "Error writing FCT_FLOW");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing FCT_FLOW\n");
+               return ret;
+       }
 
        return 0;
 }
@@ -539,16 +644,18 @@ static int smsc75xx_link_reset(struct usbnet *dev)
                PHY_INT_SRC_CLEAR_ALL);
 
        ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
-       check_warn_return(ret, "Error writing INT_STS");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing INT_STS\n");
+               return ret;
+       }
 
        mii_check_media(mii, 1, 1);
        mii_ethtool_gset(&dev->mii, &ecmd);
        lcladv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE);
        rmtadv = smsc75xx_mdio_read(dev->net, mii->phy_id, MII_LPA);
 
-       netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x"
-                 " rmtadv: %04x", ethtool_cmd_speed(&ecmd),
-                 ecmd.duplex, lcladv, rmtadv);
+       netif_dbg(dev, link, dev->net, "speed: %u duplex: %d lcladv: %04x rmtadv: %04x\n",
+                 ethtool_cmd_speed(&ecmd), ecmd.duplex, lcladv, rmtadv);
 
        return smsc75xx_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
 }
@@ -558,21 +665,21 @@ static void smsc75xx_status(struct usbnet *dev, struct urb *urb)
        u32 intdata;
 
        if (urb->actual_length != 4) {
-               netdev_warn(dev->net,
-                       "unexpected urb length %d", urb->actual_length);
+               netdev_warn(dev->net, "unexpected urb length %d\n",
+                           urb->actual_length);
                return;
        }
 
        memcpy(&intdata, urb->transfer_buffer, 4);
        le32_to_cpus(&intdata);
 
-       netif_dbg(dev, link, dev->net, "intdata: 0x%08X", intdata);
+       netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
 
        if (intdata & INT_ENP_PHY_INT)
                usbnet_defer_kevent(dev, EVENT_LINK_RESET);
        else
-               netdev_warn(dev->net,
-                       "unexpected interrupt, intdata=0x%08X", intdata);
+               netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
+                           intdata);
 }
 
 static int smsc75xx_ethtool_get_eeprom_len(struct net_device *net)
@@ -596,8 +703,8 @@ static int smsc75xx_ethtool_set_eeprom(struct net_device *netdev,
        struct usbnet *dev = netdev_priv(netdev);
 
        if (ee->magic != LAN75XX_EEPROM_MAGIC) {
-               netdev_warn(dev->net,
-                       "EEPROM: magic value mismatch: 0x%x", ee->magic);
+               netdev_warn(dev->net, "EEPROM: magic value mismatch: 0x%x\n",
+                           ee->magic);
                return -EINVAL;
        }
 
@@ -619,9 +726,15 @@ static int smsc75xx_ethtool_set_wol(struct net_device *net,
 {
        struct usbnet *dev = netdev_priv(net);
        struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       int ret;
 
        pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
-       return 0;
+
+       ret = device_set_wakeup_enable(&dev->udev->dev, pdata->wolopts);
+       if (ret < 0)
+               netdev_warn(dev->net, "device_set_wakeup_enable error %d\n", ret);
+
+       return ret;
 }
 
 static const struct ethtool_ops smsc75xx_ethtool_ops = {
@@ -657,14 +770,14 @@ static void smsc75xx_init_mac_address(struct usbnet *dev)
                if (is_valid_ether_addr(dev->net->dev_addr)) {
                        /* eeprom values are valid so use them */
                        netif_dbg(dev, ifup, dev->net,
-                               "MAC address read from EEPROM");
+                                 "MAC address read from EEPROM\n");
                        return;
                }
        }
 
        /* no eeprom, or eeprom values are invalid. generate random MAC */
        eth_hw_addr_random(dev->net);
-       netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr");
+       netif_dbg(dev, ifup, dev->net, "MAC address set to eth_random_addr\n");
 }
 
 static int smsc75xx_set_mac_address(struct usbnet *dev)
@@ -674,19 +787,29 @@ static int smsc75xx_set_mac_address(struct usbnet *dev)
        u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8;
 
        int ret = smsc75xx_write_reg(dev, RX_ADDRH, addr_hi);
-       check_warn_return(ret, "Failed to write RX_ADDRH: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write RX_ADDRH: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_write_reg(dev, RX_ADDRL, addr_lo);
-       check_warn_return(ret, "Failed to write RX_ADDRL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write RX_ADDRL: %d\n", ret);
+               return ret;
+       }
 
        addr_hi |= ADDR_FILTX_FB_VALID;
        ret = smsc75xx_write_reg(dev, ADDR_FILTX, addr_hi);
-       check_warn_return(ret, "Failed to write ADDR_FILTX: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write ADDR_FILTX: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_write_reg(dev, ADDR_FILTX + 4, addr_lo);
-       check_warn_return(ret, "Failed to write ADDR_FILTX+4: %d", ret);
+       if (ret < 0)
+               netdev_warn(dev->net, "Failed to write ADDR_FILTX+4: %d\n", ret);
 
-       return 0;
+       return ret;
 }
 
 static int smsc75xx_phy_initialize(struct usbnet *dev)
@@ -708,12 +831,15 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
        do {
                msleep(10);
                bmcr = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
-               check_warn_return(bmcr, "Error reading MII_BMCR");
+               if (bmcr < 0) {
+                       netdev_warn(dev->net, "Error reading MII_BMCR\n");
+                       return bmcr;
+               }
                timeout++;
        } while ((bmcr & BMCR_RESET) && (timeout < 100));
 
        if (timeout >= 100) {
-               netdev_warn(dev->net, "timeout on PHY Reset");
+               netdev_warn(dev->net, "timeout on PHY Reset\n");
                return -EIO;
        }
 
@@ -725,14 +851,18 @@ static int smsc75xx_phy_initialize(struct usbnet *dev)
 
        /* read and write to clear phy interrupt status */
        ret = smsc75xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
-       check_warn_return(ret, "Error reading PHY_INT_SRC");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+               return ret;
+       }
+
        smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_SRC, 0xffff);
 
        smsc75xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
                PHY_INT_MASK_DEFAULT);
        mii_nway_restart(&dev->mii);
 
-       netif_dbg(dev, ifup, dev->net, "phy initialised successfully");
+       netif_dbg(dev, ifup, dev->net, "phy initialised successfully\n");
        return 0;
 }
 
@@ -743,14 +873,20 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
        bool rxenabled;
 
        ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
-       check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
+               return ret;
+       }
 
        rxenabled = ((buf & MAC_RX_RXEN) != 0);
 
        if (rxenabled) {
                buf &= ~MAC_RX_RXEN;
                ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-               check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+                       return ret;
+               }
        }
 
        /* add 4 to size for FCS */
@@ -758,12 +894,18 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
        buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT) & MAC_RX_MAX_SIZE);
 
        ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-       check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+               return ret;
+       }
 
        if (rxenabled) {
                buf |= MAC_RX_RXEN;
                ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-               check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+                       return ret;
+               }
        }
 
        return 0;
@@ -774,7 +916,10 @@ static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
        struct usbnet *dev = netdev_priv(netdev);
 
        int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
-       check_warn_return(ret, "Failed to set mac rx frame length");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to set mac rx frame length\n");
+               return ret;
+       }
 
        return usbnet_change_mtu(netdev, new_mtu);
 }
@@ -799,19 +944,26 @@ static int smsc75xx_set_features(struct net_device *netdev,
        /* it's racing here! */
 
        ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-       check_warn_return(ret, "Error writing RFE_CTL");
+       if (ret < 0)
+               netdev_warn(dev->net, "Error writing RFE_CTL\n");
 
-       return 0;
+       return ret;
 }
 
-static int smsc75xx_wait_ready(struct usbnet *dev)
+static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm)
 {
        int timeout = 0;
 
        do {
                u32 buf;
-               int ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
-               check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+               int ret;
+
+               ret = __smsc75xx_read_reg(dev, PMT_CTL, &buf, in_pm);
+
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
+                       return ret;
+               }
 
                if (buf & PMT_CTL_DEV_RDY)
                        return 0;
@@ -820,7 +972,7 @@ static int smsc75xx_wait_ready(struct usbnet *dev)
                timeout++;
        } while (timeout < 100);
 
-       netdev_warn(dev->net, "timeout waiting for device ready");
+       netdev_warn(dev->net, "timeout waiting for device ready\n");
        return -EIO;
 }
 
@@ -830,79 +982,112 @@ static int smsc75xx_reset(struct usbnet *dev)
        u32 buf;
        int ret = 0, timeout;
 
-       netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset");
+       netif_dbg(dev, ifup, dev->net, "entering smsc75xx_reset\n");
 
-       ret = smsc75xx_wait_ready(dev);
-       check_warn_return(ret, "device not ready in smsc75xx_reset");
+       ret = smsc75xx_wait_ready(dev, 0);
+       if (ret < 0) {
+               netdev_warn(dev->net, "device not ready in smsc75xx_reset\n");
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-       check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+               return ret;
+       }
 
        buf |= HW_CFG_LRST;
 
        ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-       check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
+               return ret;
+       }
 
        timeout = 0;
        do {
                msleep(10);
                ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-               check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+                       return ret;
+               }
                timeout++;
        } while ((buf & HW_CFG_LRST) && (timeout < 100));
 
        if (timeout >= 100) {
-               netdev_warn(dev->net, "timeout on completion of Lite Reset");
+               netdev_warn(dev->net, "timeout on completion of Lite Reset\n");
                return -EIO;
        }
 
-       netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY");
+       netif_dbg(dev, ifup, dev->net, "Lite reset complete, resetting PHY\n");
 
        ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
-       check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
+               return ret;
+       }
 
        buf |= PMT_CTL_PHY_RST;
 
        ret = smsc75xx_write_reg(dev, PMT_CTL, buf);
-       check_warn_return(ret, "Failed to write PMT_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write PMT_CTL: %d\n", ret);
+               return ret;
+       }
 
        timeout = 0;
        do {
                msleep(10);
                ret = smsc75xx_read_reg(dev, PMT_CTL, &buf);
-               check_warn_return(ret, "Failed to read PMT_CTL: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret);
+                       return ret;
+               }
                timeout++;
        } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100));
 
        if (timeout >= 100) {
-               netdev_warn(dev->net, "timeout waiting for PHY Reset");
+               netdev_warn(dev->net, "timeout waiting for PHY Reset\n");
                return -EIO;
        }
 
-       netif_dbg(dev, ifup, dev->net, "PHY reset complete");
-
-       smsc75xx_init_mac_address(dev);
+       netif_dbg(dev, ifup, dev->net, "PHY reset complete\n");
 
        ret = smsc75xx_set_mac_address(dev);
-       check_warn_return(ret, "Failed to set mac address");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to set mac address\n");
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "MAC Address: %pM", dev->net->dev_addr);
+       netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n",
+                 dev->net->dev_addr);
 
        ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-       check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
+                 buf);
 
        buf |= HW_CFG_BIR;
 
        ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-       check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net,  "Failed to write HW_CFG: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-       check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after "
-                       "writing HW_CFG_BIR: 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG after writing HW_CFG_BIR: 0x%08x\n",
+                 buf);
 
        if (!turbo_mode) {
                buf = 0;
@@ -915,99 +1100,157 @@ static int smsc75xx_reset(struct usbnet *dev)
                dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
        }
 
-       netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld",
-               (ulong)dev->rx_urb_size);
+       netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
+                 (ulong)dev->rx_urb_size);
 
        ret = smsc75xx_write_reg(dev, BURST_CAP, buf);
-       check_warn_return(ret, "Failed to write BURST_CAP: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, BURST_CAP, &buf);
-       check_warn_return(ret, "Failed to read BURST_CAP: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret);
+               return ret;
+       }
 
        netif_dbg(dev, ifup, dev->net,
-               "Read Value from BURST_CAP after writing: 0x%08x", buf);
+                 "Read Value from BURST_CAP after writing: 0x%08x\n", buf);
 
        ret = smsc75xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
-       check_warn_return(ret, "Failed to write BULK_IN_DLY: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write BULK_IN_DLY: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, BULK_IN_DLY, &buf);
-       check_warn_return(ret, "Failed to read BULK_IN_DLY: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret);
+               return ret;
+       }
 
        netif_dbg(dev, ifup, dev->net,
-               "Read Value from BULK_IN_DLY after writing: 0x%08x", buf);
+                 "Read Value from BULK_IN_DLY after writing: 0x%08x\n", buf);
 
        if (turbo_mode) {
                ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-               check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+                       return ret;
+               }
 
-               netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x", buf);
+               netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n", buf);
 
                buf |= (HW_CFG_MEF | HW_CFG_BCE);
 
                ret = smsc75xx_write_reg(dev, HW_CFG, buf);
-               check_warn_return(ret, "Failed to write HW_CFG: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
+                       return ret;
+               }
 
                ret = smsc75xx_read_reg(dev, HW_CFG, &buf);
-               check_warn_return(ret, "Failed to read HW_CFG: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+                       return ret;
+               }
 
-               netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x", buf);
+               netif_dbg(dev, ifup, dev->net, "HW_CFG: 0x%08x\n", buf);
        }
 
        /* set FIFO sizes */
        buf = (MAX_RX_FIFO_SIZE - 512) / 512;
        ret = smsc75xx_write_reg(dev, FCT_RX_FIFO_END, buf);
-       check_warn_return(ret, "Failed to write FCT_RX_FIFO_END: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write FCT_RX_FIFO_END: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "FCT_RX_FIFO_END set to 0x%08x\n", buf);
 
        buf = (MAX_TX_FIFO_SIZE - 512) / 512;
        ret = smsc75xx_write_reg(dev, FCT_TX_FIFO_END, buf);
-       check_warn_return(ret, "Failed to write FCT_TX_FIFO_END: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write FCT_TX_FIFO_END: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "FCT_TX_FIFO_END set to 0x%08x\n", buf);
 
        ret = smsc75xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL);
-       check_warn_return(ret, "Failed to write INT_STS: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write INT_STS: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, ID_REV, &buf);
-       check_warn_return(ret, "Failed to read ID_REV: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", buf);
 
        ret = smsc75xx_read_reg(dev, E2P_CMD, &buf);
-       check_warn_return(ret, "Failed to read E2P_CMD: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read E2P_CMD: %d\n", ret);
+               return ret;
+       }
 
        /* only set default GPIO/LED settings if no EEPROM is detected */
        if (!(buf & E2P_CMD_LOADED)) {
                ret = smsc75xx_read_reg(dev, LED_GPIO_CFG, &buf);
-               check_warn_return(ret, "Failed to read LED_GPIO_CFG: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to read LED_GPIO_CFG: %d\n", ret);
+                       return ret;
+               }
 
                buf &= ~(LED_GPIO_CFG_LED2_FUN_SEL | LED_GPIO_CFG_LED10_FUN_SEL);
                buf |= LED_GPIO_CFG_LEDGPIO_EN | LED_GPIO_CFG_LED2_FUN_SEL;
 
                ret = smsc75xx_write_reg(dev, LED_GPIO_CFG, buf);
-               check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to write LED_GPIO_CFG: %d\n", ret);
+                       return ret;
+               }
        }
 
        ret = smsc75xx_write_reg(dev, FLOW, 0);
-       check_warn_return(ret, "Failed to write FLOW: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_write_reg(dev, FCT_FLOW, 0);
-       check_warn_return(ret, "Failed to write FCT_FLOW: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write FCT_FLOW: %d\n", ret);
+               return ret;
+       }
 
        /* Don't need rfe_ctl_lock during initialisation */
        ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
-       check_warn_return(ret, "Failed to read RFE_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read RFE_CTL: %d\n", ret);
+               return ret;
+       }
 
        pdata->rfe_ctl |= RFE_CTL_AB | RFE_CTL_DPF;
 
        ret = smsc75xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-       check_warn_return(ret, "Failed to write RFE_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write RFE_CTL: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, RFE_CTL, &pdata->rfe_ctl);
-       check_warn_return(ret, "Failed to read RFE_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read RFE_CTL: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x", pdata->rfe_ctl);
+       netif_dbg(dev, ifup, dev->net, "RFE_CTL set to 0x%08x\n",
+                 pdata->rfe_ctl);
 
        /* Enable or disable checksum offload engines */
        smsc75xx_set_features(dev->net, dev->net->features);
@@ -1015,69 +1258,111 @@ static int smsc75xx_reset(struct usbnet *dev)
        smsc75xx_set_multicast(dev->net);
 
        ret = smsc75xx_phy_initialize(dev);
-       check_warn_return(ret, "Failed to initialize PHY: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to initialize PHY: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, INT_EP_CTL, &buf);
-       check_warn_return(ret, "Failed to read INT_EP_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret);
+               return ret;
+       }
 
        /* enable PHY interrupts */
        buf |= INT_ENP_PHY_INT;
 
        ret = smsc75xx_write_reg(dev, INT_EP_CTL, buf);
-       check_warn_return(ret, "Failed to write INT_EP_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret);
+               return ret;
+       }
 
        /* allow mac to detect speed and duplex from phy */
        ret = smsc75xx_read_reg(dev, MAC_CR, &buf);
-       check_warn_return(ret, "Failed to read MAC_CR: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret);
+               return ret;
+       }
 
        buf |= (MAC_CR_ADD | MAC_CR_ASD);
        ret = smsc75xx_write_reg(dev, MAC_CR, buf);
-       check_warn_return(ret, "Failed to write MAC_CR: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, MAC_TX, &buf);
-       check_warn_return(ret, "Failed to read MAC_TX: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read MAC_TX: %d\n", ret);
+               return ret;
+       }
 
        buf |= MAC_TX_TXEN;
 
        ret = smsc75xx_write_reg(dev, MAC_TX, buf);
-       check_warn_return(ret, "Failed to write MAC_TX: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write MAC_TX: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "MAC_TX set to 0x%08x\n", buf);
 
        ret = smsc75xx_read_reg(dev, FCT_TX_CTL, &buf);
-       check_warn_return(ret, "Failed to read FCT_TX_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read FCT_TX_CTL: %d\n", ret);
+               return ret;
+       }
 
        buf |= FCT_TX_CTL_EN;
 
        ret = smsc75xx_write_reg(dev, FCT_TX_CTL, buf);
-       check_warn_return(ret, "Failed to write FCT_TX_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write FCT_TX_CTL: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n", buf);
 
        ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
-       check_warn_return(ret, "Failed to set max rx frame length");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to set max rx frame length\n");
+               return ret;
+       }
 
        ret = smsc75xx_read_reg(dev, MAC_RX, &buf);
-       check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
+               return ret;
+       }
 
        buf |= MAC_RX_RXEN;
 
        ret = smsc75xx_write_reg(dev, MAC_RX, buf);
-       check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "MAC_RX set to 0x%08x\n", buf);
 
        ret = smsc75xx_read_reg(dev, FCT_RX_CTL, &buf);
-       check_warn_return(ret, "Failed to read FCT_RX_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read FCT_RX_CTL: %d\n", ret);
+               return ret;
+       }
 
        buf |= FCT_RX_CTL_EN;
 
        ret = smsc75xx_write_reg(dev, FCT_RX_CTL, buf);
-       check_warn_return(ret, "Failed to write FCT_RX_CTL: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write FCT_RX_CTL: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x", buf);
+       netif_dbg(dev, ifup, dev->net, "FCT_RX_CTL set to 0x%08x\n", buf);
 
-       netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0");
+       netif_dbg(dev, ifup, dev->net, "smsc75xx_reset, return 0\n");
        return 0;
 }
 
@@ -1102,14 +1387,17 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
        printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
 
        ret = usbnet_get_endpoints(dev, intf);
-       check_warn_return(ret, "usbnet_get_endpoints failed: %d", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret);
+               return ret;
+       }
 
        dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc75xx_priv),
                GFP_KERNEL);
 
        pdata = (struct smsc75xx_priv *)(dev->data[0]);
        if (!pdata) {
-               netdev_warn(dev->net, "Unable to allocate smsc75xx_priv");
+               netdev_warn(dev->net, "Unable to allocate smsc75xx_priv\n");
                return -ENOMEM;
        }
 
@@ -1132,8 +1420,20 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
                NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXCSUM;
 
+       ret = smsc75xx_wait_ready(dev, 0);
+       if (ret < 0) {
+               netdev_warn(dev->net, "device not ready in smsc75xx_bind\n");
+               return ret;
+       }
+
+       smsc75xx_init_mac_address(dev);
+
        /* Init all registers */
        ret = smsc75xx_reset(dev);
+       if (ret < 0) {
+               netdev_warn(dev->net, "smsc75xx_reset error %d\n", ret);
+               return ret;
+       }
 
        dev->net->netdev_ops = &smsc75xx_netdev_ops;
        dev->net->ethtool_ops = &smsc75xx_ethtool_ops;
@@ -1147,172 +1447,647 @@ static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
        struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
        if (pdata) {
-               netif_dbg(dev, ifdown, dev->net, "free pdata");
+               netif_dbg(dev, ifdown, dev->net, "free pdata\n");
                kfree(pdata);
                pdata = NULL;
                dev->data[0] = 0;
        }
 }
 
+static u16 smsc_crc(const u8 *buffer, size_t len)
+{
+       return bitrev16(crc16(0xFFFF, buffer, len));
+}
+
+static int smsc75xx_write_wuff(struct usbnet *dev, int filter, u32 wuf_cfg,
+                              u32 wuf_mask1)
+{
+       int cfg_base = WUF_CFGX + filter * 4;
+       int mask_base = WUF_MASKX + filter * 16;
+       int ret;
+
+       ret = smsc75xx_write_reg(dev, cfg_base, wuf_cfg);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing WUF_CFGX\n");
+               return ret;
+       }
+
+       ret = smsc75xx_write_reg(dev, mask_base, wuf_mask1);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing WUF_MASKX\n");
+               return ret;
+       }
+
+       ret = smsc75xx_write_reg(dev, mask_base + 4, 0);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing WUF_MASKX\n");
+               return ret;
+       }
+
+       ret = smsc75xx_write_reg(dev, mask_base + 8, 0);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing WUF_MASKX\n");
+               return ret;
+       }
+
+       ret = smsc75xx_write_reg(dev, mask_base + 12, 0);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing WUF_MASKX\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int smsc75xx_enter_suspend0(struct usbnet *dev)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       u32 val;
+       int ret;
+
+       ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PMT_CTL\n");
+               return ret;
+       }
+
+       val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_PHY_RST));
+       val |= PMT_CTL_SUS_MODE_0 | PMT_CTL_WOL_EN | PMT_CTL_WUPS;
+
+       ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PMT_CTL\n");
+               return ret;
+       }
+
+       pdata->suspend_flags |= SUSPEND_SUSPEND0;
+
+       return 0;
+}
+
+static int smsc75xx_enter_suspend1(struct usbnet *dev)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       u32 val;
+       int ret;
+
+       ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PMT_CTL\n");
+               return ret;
+       }
+
+       val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+       val |= PMT_CTL_SUS_MODE_1;
+
+       ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PMT_CTL\n");
+               return ret;
+       }
+
+       /* clear wol status, enable energy detection */
+       val &= ~PMT_CTL_WUPS;
+       val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
+
+       ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PMT_CTL\n");
+               return ret;
+       }
+
+       pdata->suspend_flags |= SUSPEND_SUSPEND1;
+
+       return 0;
+}
+
+static int smsc75xx_enter_suspend2(struct usbnet *dev)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       u32 val;
+       int ret;
+
+       ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PMT_CTL\n");
+               return ret;
+       }
+
+       val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+       val |= PMT_CTL_SUS_MODE_2;
+
+       ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PMT_CTL\n");
+               return ret;
+       }
+
+       pdata->suspend_flags |= SUSPEND_SUSPEND2;
+
+       return 0;
+}
+
+static int smsc75xx_enter_suspend3(struct usbnet *dev)
+{
+       struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       u32 val;
+       int ret;
+
+       ret = smsc75xx_read_reg_nopm(dev, FCT_RX_CTL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading FCT_RX_CTL\n");
+               return ret;
+       }
+
+       if (val & FCT_RX_CTL_RXUSED) {
+               netdev_dbg(dev->net, "rx fifo not empty in autosuspend\n");
+               return -EBUSY;
+       }
+
+       ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PMT_CTL\n");
+               return ret;
+       }
+
+       val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
+       val |= PMT_CTL_SUS_MODE_3 | PMT_CTL_RES_CLR_WKP_EN;
+
+       ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PMT_CTL\n");
+               return ret;
+       }
+
+       /* clear wol status */
+       val &= ~PMT_CTL_WUPS;
+       val |= PMT_CTL_WUPS_WOL;
+
+       ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PMT_CTL\n");
+               return ret;
+       }
+
+       pdata->suspend_flags |= SUSPEND_SUSPEND3;
+
+       return 0;
+}
+
+static int smsc75xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
+{
+       struct mii_if_info *mii = &dev->mii;
+       int ret;
+
+       netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
+
+       /* read to clear */
+       ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+               return ret;
+       }
+
+       /* enable interrupt source */
+       ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PHY_INT_MASK\n");
+               return ret;
+       }
+
+       ret |= mask;
+
+       smsc75xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
+
+       return 0;
+}
+
+static int smsc75xx_link_ok_nopm(struct usbnet *dev)
+{
+       struct mii_if_info *mii = &dev->mii;
+       int ret;
+
+       /* first, a dummy read, needed to latch some MII phys */
+       ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading MII_BMSR\n");
+               return ret;
+       }
+
+       ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading MII_BMSR\n");
+               return ret;
+       }
+
+       return !!(ret & BMSR_LSTATUS);
+}
+
+static int smsc75xx_autosuspend(struct usbnet *dev, u32 link_up)
+{
+       int ret;
+
+       if (!netif_running(dev->net)) {
+               /* interface is ifconfig down so fully power down hw */
+               netdev_dbg(dev->net, "autosuspend entering SUSPEND2\n");
+               return smsc75xx_enter_suspend2(dev);
+       }
+
+       if (!link_up) {
+               /* link is down so enter EDPD mode */
+               netdev_dbg(dev->net, "autosuspend entering SUSPEND1\n");
+
+               /* enable PHY wakeup events for if cable is attached */
+               ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+                       PHY_INT_MASK_ANEG_COMP);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+                       return ret;
+               }
+
+               netdev_info(dev->net, "entering SUSPEND1 mode\n");
+               return smsc75xx_enter_suspend1(dev);
+       }
+
+       /* enable PHY wakeup events so we remote wakeup if cable is pulled */
+       ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+               PHY_INT_MASK_LINK_DOWN);
+       if (ret < 0) {
+               netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+               return ret;
+       }
+
+       netdev_dbg(dev->net, "autosuspend entering SUSPEND3\n");
+       return smsc75xx_enter_suspend3(dev);
+}
+
 static int smsc75xx_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct usbnet *dev = usb_get_intfdata(intf);
        struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       u32 val, link_up;
        int ret;
-       u32 val;
 
        ret = usbnet_suspend(intf, message);
-       check_warn_return(ret, "usbnet_suspend error");
+       if (ret < 0) {
+               netdev_warn(dev->net, "usbnet_suspend error\n");
+               return ret;
+       }
 
-       /* if no wol options set, enter lowest power SUSPEND2 mode */
-       if (!(pdata->wolopts & SUPPORTED_WAKE)) {
-               netdev_info(dev->net, "entering SUSPEND2 mode");
+       if (pdata->suspend_flags) {
+               netdev_warn(dev->net, "error during last resume\n");
+               pdata->suspend_flags = 0;
+       }
+
+       /* determine if link is up using only _nopm functions */
+       link_up = smsc75xx_link_ok_nopm(dev);
+
+       if (message.event == PM_EVENT_AUTO_SUSPEND) {
+               ret = smsc75xx_autosuspend(dev, link_up);
+               goto done;
+       }
+
+       /* if we get this far we're not autosuspending */
+       /* if no wol options set, or if link is down and we're not waking on
+        * PHY activity, enter lowest power SUSPEND2 mode
+        */
+       if (!(pdata->wolopts & SUPPORTED_WAKE) ||
+               !(link_up || (pdata->wolopts & WAKE_PHY))) {
+               netdev_info(dev->net, "entering SUSPEND2 mode\n");
 
                /* disable energy detect (link up) & wake up events */
-               ret = smsc75xx_read_reg(dev, WUCSR, &val);
-               check_warn_return(ret, "Error reading WUCSR");
+               ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
 
                val &= ~(WUCSR_MPEN | WUCSR_WUEN);
 
-               ret = smsc75xx_write_reg(dev, WUCSR, val);
-               check_warn_return(ret, "Error writing WUCSR");
+               ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
 
-               ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-               check_warn_return(ret, "Error reading PMT_CTL");
+               ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading PMT_CTL\n");
+                       goto done;
+               }
 
                val &= ~(PMT_CTL_ED_EN | PMT_CTL_WOL_EN);
 
-               ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-               check_warn_return(ret, "Error writing PMT_CTL");
+               ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing PMT_CTL\n");
+                       goto done;
+               }
 
-               /* enter suspend2 mode */
-               ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-               check_warn_return(ret, "Error reading PMT_CTL");
+               ret = smsc75xx_enter_suspend2(dev);
+               goto done;
+       }
 
-               val &= ~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST);
-               val |= PMT_CTL_SUS_MODE_2;
+       if (pdata->wolopts & WAKE_PHY) {
+               ret = smsc75xx_enable_phy_wakeup_interrupts(dev,
+                       (PHY_INT_MASK_ANEG_COMP | PHY_INT_MASK_LINK_DOWN));
+               if (ret < 0) {
+                       netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+                       goto done;
+               }
 
-               ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-               check_warn_return(ret, "Error writing PMT_CTL");
+               /* if link is down then configure EDPD and enter SUSPEND1,
+                * otherwise enter SUSPEND0 below
+                */
+               if (!link_up) {
+                       struct mii_if_info *mii = &dev->mii;
+                       netdev_info(dev->net, "entering SUSPEND1 mode\n");
+
+                       /* enable energy detect power-down mode */
+                       ret = smsc75xx_mdio_read_nopm(dev->net, mii->phy_id,
+                               PHY_MODE_CTRL_STS);
+                       if (ret < 0) {
+                               netdev_warn(dev->net, "Error reading PHY_MODE_CTRL_STS\n");
+                               goto done;
+                       }
 
-               return 0;
+                       ret |= MODE_CTRL_STS_EDPWRDOWN;
+
+                       smsc75xx_mdio_write_nopm(dev->net, mii->phy_id,
+                               PHY_MODE_CTRL_STS, ret);
+
+                       /* enter SUSPEND1 mode */
+                       ret = smsc75xx_enter_suspend1(dev);
+                       goto done;
+               }
        }
 
-       if (pdata->wolopts & WAKE_MAGIC) {
-               /* clear any pending magic packet status */
-               ret = smsc75xx_read_reg(dev, WUCSR, &val);
-               check_warn_return(ret, "Error reading WUCSR");
+       if (pdata->wolopts & (WAKE_MCAST | WAKE_ARP)) {
+               int i, filter = 0;
 
-               val |= WUCSR_MPR;
+               /* disable all filters */
+               for (i = 0; i < WUF_NUM; i++) {
+                       ret = smsc75xx_write_reg_nopm(dev, WUF_CFGX + i * 4, 0);
+                       if (ret < 0) {
+                               netdev_warn(dev->net, "Error writing WUF_CFGX\n");
+                               goto done;
+                       }
+               }
 
-               ret = smsc75xx_write_reg(dev, WUCSR, val);
-               check_warn_return(ret, "Error writing WUCSR");
-       }
+               if (pdata->wolopts & WAKE_MCAST) {
+                       const u8 mcast[] = {0x01, 0x00, 0x5E};
+                       netdev_info(dev->net, "enabling multicast detection\n");
 
-       /* enable/disable magic packup wake */
-       ret = smsc75xx_read_reg(dev, WUCSR, &val);
-       check_warn_return(ret, "Error reading WUCSR");
+                       val = WUF_CFGX_EN | WUF_CFGX_ATYPE_MULTICAST
+                               | smsc_crc(mcast, 3);
+                       ret = smsc75xx_write_wuff(dev, filter++, val, 0x0007);
+                       if (ret < 0) {
+                               netdev_warn(dev->net, "Error writing wakeup filter\n");
+                               goto done;
+                       }
+               }
 
-       if (pdata->wolopts & WAKE_MAGIC) {
-               netdev_info(dev->net, "enabling magic packet wakeup");
-               val |= WUCSR_MPEN;
+               if (pdata->wolopts & WAKE_ARP) {
+                       const u8 arp[] = {0x08, 0x06};
+                       netdev_info(dev->net, "enabling ARP detection\n");
+
+                       val = WUF_CFGX_EN | WUF_CFGX_ATYPE_ALL | (0x0C << 16)
+                               | smsc_crc(arp, 2);
+                       ret = smsc75xx_write_wuff(dev, filter++, val, 0x0003);
+                       if (ret < 0) {
+                               netdev_warn(dev->net, "Error writing wakeup filter\n");
+                               goto done;
+                       }
+               }
+
+               /* clear any pending pattern match packet status */
+               ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
+
+               val |= WUCSR_WUFR;
+
+               ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
+
+               netdev_info(dev->net, "enabling packet match detection\n");
+               ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
+
+               val |= WUCSR_WUEN;
+
+               ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
        } else {
-               netdev_info(dev->net, "disabling magic packet wakeup");
-               val &= ~WUCSR_MPEN;
+               netdev_info(dev->net, "disabling packet match detection\n");
+               ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
+
+               val &= ~WUCSR_WUEN;
+
+               ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
        }
 
-       ret = smsc75xx_write_reg(dev, WUCSR, val);
-       check_warn_return(ret, "Error writing WUCSR");
+       /* disable magic, bcast & unicast wakeup sources */
+       ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading WUCSR\n");
+               goto done;
+       }
 
-       /* enable wol wakeup source */
-       ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-       check_warn_return(ret, "Error reading PMT_CTL");
+       val &= ~(WUCSR_MPEN | WUCSR_BCST_EN | WUCSR_PFDA_EN);
 
-       val |= PMT_CTL_WOL_EN;
+       ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing WUCSR\n");
+               goto done;
+       }
 
-       ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-       check_warn_return(ret, "Error writing PMT_CTL");
+       if (pdata->wolopts & WAKE_PHY) {
+               netdev_info(dev->net, "enabling PHY wakeup\n");
 
-       /* enable receiver */
-       ret = smsc75xx_read_reg(dev, MAC_RX, &val);
-       check_warn_return(ret, "Failed to read MAC_RX: %d", ret);
+               ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading PMT_CTL\n");
+                       goto done;
+               }
 
-       val |= MAC_RX_RXEN;
+               /* clear wol status, enable energy detection */
+               val &= ~PMT_CTL_WUPS;
+               val |= (PMT_CTL_WUPS_ED | PMT_CTL_ED_EN);
 
-       ret = smsc75xx_write_reg(dev, MAC_RX, val);
-       check_warn_return(ret, "Failed to write MAC_RX: %d", ret);
+               ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing PMT_CTL\n");
+                       goto done;
+               }
+       }
 
-       /* some wol options are enabled, so enter SUSPEND0 */
-       netdev_info(dev->net, "entering SUSPEND0 mode");
+       if (pdata->wolopts & WAKE_MAGIC) {
+               netdev_info(dev->net, "enabling magic packet wakeup\n");
+               ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
 
-       ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-       check_warn_return(ret, "Error reading PMT_CTL");
+               /* clear any pending magic packet status */
+               val |= WUCSR_MPR | WUCSR_MPEN;
 
-       val &= (~(PMT_CTL_SUS_MODE | PMT_CTL_WUPS | PMT_CTL_PHY_RST));
-       val |= PMT_CTL_SUS_MODE_0;
+               ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
+       }
 
-       ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-       check_warn_return(ret, "Error writing PMT_CTL");
+       if (pdata->wolopts & WAKE_BCAST) {
+               netdev_info(dev->net, "enabling broadcast detection\n");
+               ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
 
-       /* clear wol status */
-       val &= ~PMT_CTL_WUPS;
-       val |= PMT_CTL_WUPS_WOL;
-       ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-       check_warn_return(ret, "Error writing PMT_CTL");
+               val |= WUCSR_BCAST_FR | WUCSR_BCST_EN;
 
-       /* read back PMT_CTL */
-       ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-       check_warn_return(ret, "Error reading PMT_CTL");
+               ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
+       }
 
-       smsc75xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+       if (pdata->wolopts & WAKE_UCAST) {
+               netdev_info(dev->net, "enabling unicast detection\n");
+               ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
 
-       return 0;
+               val |= WUCSR_WUFR | WUCSR_PFDA_EN;
+
+               ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
+       }
+
+       /* enable receiver to enable frame reception */
+       ret = smsc75xx_read_reg_nopm(dev, MAC_RX, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read MAC_RX: %d\n", ret);
+               goto done;
+       }
+
+       val |= MAC_RX_RXEN;
+
+       ret = smsc75xx_write_reg_nopm(dev, MAC_RX, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write MAC_RX: %d\n", ret);
+               goto done;
+       }
+
+       /* some wol options are enabled, so enter SUSPEND0 */
+       netdev_info(dev->net, "entering SUSPEND0 mode\n");
+       ret = smsc75xx_enter_suspend0(dev);
+
+done:
+       if (ret)
+               usbnet_resume(intf);
+       return ret;
 }
 
 static int smsc75xx_resume(struct usb_interface *intf)
 {
        struct usbnet *dev = usb_get_intfdata(intf);
        struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]);
+       u8 suspend_flags = pdata->suspend_flags;
        int ret;
        u32 val;
 
-       if (pdata->wolopts & WAKE_MAGIC) {
-               netdev_info(dev->net, "resuming from SUSPEND0");
+       netdev_dbg(dev->net, "resume suspend_flags=0x%02x\n", suspend_flags);
 
-               smsc75xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+       /* do this first to ensure it's cleared even in error case */
+       pdata->suspend_flags = 0;
 
-               /* Disable magic packup wake */
-               ret = smsc75xx_read_reg(dev, WUCSR, &val);
-               check_warn_return(ret, "Error reading WUCSR");
+       if (suspend_flags & SUSPEND_ALLMODES) {
+               /* Disable wakeup sources */
+               ret = smsc75xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       return ret;
+               }
 
-               val &= ~WUCSR_MPEN;
+               val &= ~(WUCSR_WUEN | WUCSR_MPEN | WUCSR_PFDA_EN
+                       | WUCSR_BCST_EN);
 
-               ret = smsc75xx_write_reg(dev, WUCSR, val);
-               check_warn_return(ret, "Error writing WUCSR");
+               ret = smsc75xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       return ret;
+               }
 
                /* clear wake-up status */
-               ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-               check_warn_return(ret, "Error reading PMT_CTL");
+               ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading PMT_CTL\n");
+                       return ret;
+               }
 
                val &= ~PMT_CTL_WOL_EN;
                val |= PMT_CTL_WUPS;
 
-               ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-               check_warn_return(ret, "Error writing PMT_CTL");
-       } else {
-               netdev_info(dev->net, "resuming from SUSPEND2");
+               ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing PMT_CTL\n");
+                       return ret;
+               }
+       }
 
-               ret = smsc75xx_read_reg(dev, PMT_CTL, &val);
-               check_warn_return(ret, "Error reading PMT_CTL");
+       if (suspend_flags & SUSPEND_SUSPEND2) {
+               netdev_info(dev->net, "resuming from SUSPEND2\n");
+
+               ret = smsc75xx_read_reg_nopm(dev, PMT_CTL, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading PMT_CTL\n");
+                       return ret;
+               }
 
                val |= PMT_CTL_PHY_PWRUP;
 
-               ret = smsc75xx_write_reg(dev, PMT_CTL, val);
-               check_warn_return(ret, "Error writing PMT_CTL");
+               ret = smsc75xx_write_reg_nopm(dev, PMT_CTL, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing PMT_CTL\n");
+                       return ret;
+               }
        }
 
-       ret = smsc75xx_wait_ready(dev);
-       check_warn_return(ret, "device not ready in smsc75xx_resume");
+       ret = smsc75xx_wait_ready(dev, 1);
+       if (ret < 0) {
+               netdev_warn(dev->net, "device not ready in smsc75xx_resume\n");
+               return ret;
+       }
 
        return usbnet_resume(intf);
 }
@@ -1352,7 +2127,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
                if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
                        netif_dbg(dev, rx_err, dev->net,
-                               "Error rx_cmd_a=0x%08x", rx_cmd_a);
+                                 "Error rx_cmd_a=0x%08x\n", rx_cmd_a);
                        dev->net->stats.rx_errors++;
                        dev->net->stats.rx_dropped++;
 
@@ -1364,7 +2139,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
                        if (unlikely(size > (ETH_FRAME_LEN + 12))) {
                                netif_dbg(dev, rx_err, dev->net,
-                                       "size err rx_cmd_a=0x%08x", rx_cmd_a);
+                                         "size err rx_cmd_a=0x%08x\n",
+                                         rx_cmd_a);
                                return 0;
                        }
 
@@ -1381,7 +2157,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
                        ax_skb = skb_clone(skb, GFP_ATOMIC);
                        if (unlikely(!ax_skb)) {
-                               netdev_warn(dev->net, "Error allocating skb");
+                               netdev_warn(dev->net, "Error allocating skb\n");
                                return 0;
                        }
 
@@ -1406,7 +2182,7 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        }
 
        if (unlikely(skb->len < 0)) {
-               netdev_warn(dev->net, "invalid rx length<0 %d", skb->len);
+               netdev_warn(dev->net, "invalid rx length<0 %d\n", skb->len);
                return 0;
        }
 
@@ -1454,6 +2230,12 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev,
        return skb;
 }
 
+static int smsc75xx_manage_power(struct usbnet *dev, int on)
+{
+       dev->intf->needs_remote_wakeup = on;
+       return 0;
+}
+
 static const struct driver_info smsc75xx_info = {
        .description    = "smsc75xx USB 2.0 Gigabit Ethernet",
        .bind           = smsc75xx_bind,
@@ -1463,6 +2245,7 @@ static const struct driver_info smsc75xx_info = {
        .rx_fixup       = smsc75xx_rx_fixup,
        .tx_fixup       = smsc75xx_tx_fixup,
        .status         = smsc75xx_status,
+       .manage_power   = smsc75xx_manage_power,
        .flags          = FLAG_ETHER | FLAG_SEND_ZLP | FLAG_LINK_INTR,
 };
 
@@ -1490,6 +2273,7 @@ static struct usb_driver smsc75xx_driver = {
        .reset_resume   = smsc75xx_resume,
        .disconnect     = usbnet_disconnect,
        .disable_hub_initiated_lpm = 1,
+       .supports_autosuspend = 1,
 };
 
 module_usb_driver(smsc75xx_driver);
index 7479a5761d0d6b35c9a275ae470e49dc959de366..9b736701f854e33ae4b8ee4391f5f2135625da45 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/usb.h>
+#include <linux/bitrev.h>
+#include <linux/crc16.h>
 #include <linux/crc32.h>
 #include <linux/usb/usbnet.h>
 #include <linux/slab.h>
 #define SMSC95XX_INTERNAL_PHY_ID       (1)
 #define SMSC95XX_TX_OVERHEAD           (8)
 #define SMSC95XX_TX_OVERHEAD_CSUM      (12)
-#define SUPPORTED_WAKE                 (WAKE_MAGIC)
+#define SUPPORTED_WAKE                 (WAKE_PHY | WAKE_UCAST | WAKE_BCAST | \
+                                        WAKE_MCAST | WAKE_ARP | WAKE_MAGIC)
 
-#define check_warn(ret, fmt, args...) \
-       ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
-
-#define check_warn_return(ret, fmt, args...) \
-       ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); return ret; } })
-
-#define check_warn_goto_done(ret, fmt, args...) \
-       ({ if (ret < 0) { netdev_warn(dev->net, fmt, ##args); goto done; } })
+#define FEATURE_8_WAKEUP_FILTERS       (0x01)
+#define FEATURE_PHY_NLP_CROSSOVER      (0x02)
+#define FEATURE_AUTOSUSPEND            (0x04)
 
 struct smsc95xx_priv {
        u32 mac_cr;
@@ -63,105 +61,107 @@ struct smsc95xx_priv {
        u32 hash_lo;
        u32 wolopts;
        spinlock_t mac_cr_lock;
-};
-
-struct usb_context {
-       struct usb_ctrlrequest req;
-       struct usbnet *dev;
+       u8 features;
 };
 
 static bool turbo_mode = true;
 module_param(turbo_mode, bool, 0644);
 MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction");
 
-static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
-                                         u32 *data)
+static int __must_check __smsc95xx_read_reg(struct usbnet *dev, u32 index,
+                                           u32 *data, int in_pm)
 {
-       u32 *buf = kmalloc(4, GFP_KERNEL);
+       u32 buf;
        int ret;
+       int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16);
 
        BUG_ON(!dev);
 
-       if (!buf)
-               return -ENOMEM;
-
-       ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
-               USB_VENDOR_REQUEST_READ_REGISTER,
-               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               00, index, buf, 4, USB_CTRL_GET_TIMEOUT);
+       if (!in_pm)
+               fn = usbnet_read_cmd;
+       else
+               fn = usbnet_read_cmd_nopm;
 
+       ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN
+                | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                0, index, &buf, 4);
        if (unlikely(ret < 0))
-               netdev_warn(dev->net, "Failed to read register index 0x%08x\n", index);
+               netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n",
+                           index, ret);
 
-       le32_to_cpus(buf);
-       *data = *buf;
-       kfree(buf);
+       le32_to_cpus(&buf);
+       *data = buf;
 
        return ret;
 }
 
-static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
-                                          u32 data)
+static int __must_check __smsc95xx_write_reg(struct usbnet *dev, u32 index,
+                                            u32 data, int in_pm)
 {
-       u32 *buf = kmalloc(4, GFP_KERNEL);
+       u32 buf;
        int ret;
+       int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16);
 
        BUG_ON(!dev);
 
-       if (!buf)
-               return -ENOMEM;
-
-       *buf = data;
-       cpu_to_le32s(buf);
+       if (!in_pm)
+               fn = usbnet_write_cmd;
+       else
+               fn = usbnet_write_cmd_nopm;
 
-       ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-               USB_VENDOR_REQUEST_WRITE_REGISTER,
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               00, index, buf, 4, USB_CTRL_SET_TIMEOUT);
+       buf = data;
+       cpu_to_le32s(&buf);
 
+       ret = fn(dev, USB_VENDOR_REQUEST_WRITE_REGISTER, USB_DIR_OUT
+                | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                0, index, &buf, 4);
        if (unlikely(ret < 0))
-               netdev_warn(dev->net, "Failed to write register index 0x%08x\n", index);
-
-       kfree(buf);
+               netdev_warn(dev->net, "Failed to write reg index 0x%08x: %d\n",
+                           index, ret);
 
        return ret;
 }
 
-static int smsc95xx_set_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc95xx_read_reg_nopm(struct usbnet *dev, u32 index,
+                                              u32 *data)
 {
-       if (WARN_ON_ONCE(!dev))
-               return -EINVAL;
-
-       cpu_to_le32s(&feature);
-
-       return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-               USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
-               USB_CTRL_SET_TIMEOUT);
+       return __smsc95xx_read_reg(dev, index, data, 1);
 }
 
-static int smsc95xx_clear_feature(struct usbnet *dev, u32 feature)
+static int __must_check smsc95xx_write_reg_nopm(struct usbnet *dev, u32 index,
+                                               u32 data)
 {
-       if (WARN_ON_ONCE(!dev))
-               return -EINVAL;
+       return __smsc95xx_write_reg(dev, index, data, 1);
+}
 
-       cpu_to_le32s(&feature);
+static int __must_check smsc95xx_read_reg(struct usbnet *dev, u32 index,
+                                         u32 *data)
+{
+       return __smsc95xx_read_reg(dev, index, data, 0);
+}
 
-       return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
-               USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, feature, 0, NULL, 0,
-               USB_CTRL_SET_TIMEOUT);
+static int __must_check smsc95xx_write_reg(struct usbnet *dev, u32 index,
+                                          u32 data)
+{
+       return __smsc95xx_write_reg(dev, index, data, 0);
 }
 
 /* Loop until the read is completed with timeout
  * called with phy_mutex held */
-static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev)
+static int __must_check __smsc95xx_phy_wait_not_busy(struct usbnet *dev,
+                                                    int in_pm)
 {
        unsigned long start_time = jiffies;
        u32 val;
        int ret;
 
        do {
-               ret = smsc95xx_read_reg(dev, MII_ADDR, &val);
-               check_warn_return(ret, "Error reading MII_ACCESS");
+               ret = __smsc95xx_read_reg(dev, MII_ADDR, &val, in_pm);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading MII_ACCESS\n");
+                       return ret;
+               }
+
                if (!(val & MII_BUSY_))
                        return 0;
        } while (!time_after(jiffies, start_time + HZ));
@@ -169,7 +169,8 @@ static int __must_check smsc95xx_phy_wait_not_busy(struct usbnet *dev)
        return -EIO;
 }
 
-static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+static int __smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx,
+                               int in_pm)
 {
        struct usbnet *dev = netdev_priv(netdev);
        u32 val, addr;
@@ -178,21 +179,33 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
        mutex_lock(&dev->phy_mutex);
 
        /* confirm MII not busy */
-       ret = smsc95xx_phy_wait_not_busy(dev);
-       check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_read");
+       ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_read\n");
+               goto done;
+       }
 
        /* set the address, index & direction (read from PHY) */
        phy_id &= dev->mii.phy_id_mask;
        idx &= dev->mii.reg_num_mask;
-       addr = (phy_id << 11) | (idx << 6) | MII_READ_;
-       ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
-       check_warn_goto_done(ret, "Error writing MII_ADDR");
+       addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
+       ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing MII_ADDR\n");
+               goto done;
+       }
 
-       ret = smsc95xx_phy_wait_not_busy(dev);
-       check_warn_goto_done(ret, "Timed out reading MII reg %02X", idx);
+       ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Timed out reading MII reg %02X\n", idx);
+               goto done;
+       }
 
-       ret = smsc95xx_read_reg(dev, MII_DATA, &val);
-       check_warn_goto_done(ret, "Error reading MII_DATA");
+       ret = __smsc95xx_read_reg(dev, MII_DATA, &val, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading MII_DATA\n");
+               goto done;
+       }
 
        ret = (u16)(val & 0xFFFF);
 
@@ -201,8 +214,8 @@ done:
        return ret;
 }
 
-static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
-                               int regval)
+static void __smsc95xx_mdio_write(struct net_device *netdev, int phy_id,
+                                 int idx, int regval, int in_pm)
 {
        struct usbnet *dev = netdev_priv(netdev);
        u32 val, addr;
@@ -211,27 +224,62 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
        mutex_lock(&dev->phy_mutex);
 
        /* confirm MII not busy */
-       ret = smsc95xx_phy_wait_not_busy(dev);
-       check_warn_goto_done(ret, "MII is busy in smsc95xx_mdio_write");
+       ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "MII is busy in smsc95xx_mdio_write\n");
+               goto done;
+       }
 
        val = regval;
-       ret = smsc95xx_write_reg(dev, MII_DATA, val);
-       check_warn_goto_done(ret, "Error writing MII_DATA");
+       ret = __smsc95xx_write_reg(dev, MII_DATA, val, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing MII_DATA\n");
+               goto done;
+       }
 
        /* set the address, index & direction (write to PHY) */
        phy_id &= dev->mii.phy_id_mask;
        idx &= dev->mii.reg_num_mask;
-       addr = (phy_id << 11) | (idx << 6) | MII_WRITE_;
-       ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
-       check_warn_goto_done(ret, "Error writing MII_ADDR");
+       addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
+       ret = __smsc95xx_write_reg(dev, MII_ADDR, addr, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing MII_ADDR\n");
+               goto done;
+       }
 
-       ret = smsc95xx_phy_wait_not_busy(dev);
-       check_warn_goto_done(ret, "Timed out writing MII reg %02X", idx);
+       ret = __smsc95xx_phy_wait_not_busy(dev, in_pm);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Timed out writing MII reg %02X\n", idx);
+               goto done;
+       }
 
 done:
        mutex_unlock(&dev->phy_mutex);
 }
 
+static int smsc95xx_mdio_read_nopm(struct net_device *netdev, int phy_id,
+                                  int idx)
+{
+       return __smsc95xx_mdio_read(netdev, phy_id, idx, 1);
+}
+
+static void smsc95xx_mdio_write_nopm(struct net_device *netdev, int phy_id,
+                                    int idx, int regval)
+{
+       __smsc95xx_mdio_write(netdev, phy_id, idx, regval, 1);
+}
+
+static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
+{
+       return __smsc95xx_mdio_read(netdev, phy_id, idx, 0);
+}
+
+static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
+                               int regval)
+{
+       __smsc95xx_mdio_write(netdev, phy_id, idx, regval, 0);
+}
+
 static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
 {
        unsigned long start_time = jiffies;
@@ -240,7 +288,11 @@ static int __must_check smsc95xx_wait_eeprom(struct usbnet *dev)
 
        do {
                ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
-               check_warn_return(ret, "Error reading E2P_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading E2P_CMD\n");
+                       return ret;
+               }
+
                if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_))
                        break;
                udelay(40);
@@ -262,7 +314,10 @@ static int __must_check smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev)
 
        do {
                ret = smsc95xx_read_reg(dev, E2P_CMD, &val);
-               check_warn_return(ret, "Error reading E2P_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading E2P_CMD\n");
+                       return ret;
+               }
 
                if (!(val & E2P_CMD_BUSY_))
                        return 0;
@@ -290,14 +345,20 @@ static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length,
        for (i = 0; i < length; i++) {
                val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_);
                ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-               check_warn_return(ret, "Error writing E2P_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing E2P_CMD\n");
+                       return ret;
+               }
 
                ret = smsc95xx_wait_eeprom(dev);
                if (ret < 0)
                        return ret;
 
                ret = smsc95xx_read_reg(dev, E2P_DATA, &val);
-               check_warn_return(ret, "Error reading E2P_DATA");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading E2P_DATA\n");
+                       return ret;
+               }
 
                data[i] = val & 0xFF;
                offset++;
@@ -322,7 +383,10 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
        /* Issue write/erase enable command */
        val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_;
        ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-       check_warn_return(ret, "Error writing E2P_DATA");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing E2P_DATA\n");
+               return ret;
+       }
 
        ret = smsc95xx_wait_eeprom(dev);
        if (ret < 0)
@@ -333,12 +397,18 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
                /* Fill data register */
                val = data[i];
                ret = smsc95xx_write_reg(dev, E2P_DATA, val);
-               check_warn_return(ret, "Error writing E2P_DATA");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing E2P_DATA\n");
+                       return ret;
+               }
 
                /* Send "write" command */
                val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_);
                ret = smsc95xx_write_reg(dev, E2P_CMD, val);
-               check_warn_return(ret, "Error writing E2P_CMD");
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing E2P_CMD\n");
+                       return ret;
+               }
 
                ret = smsc95xx_wait_eeprom(dev);
                if (ret < 0)
@@ -350,60 +420,24 @@ static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length,
        return 0;
 }
 
-static void smsc95xx_async_cmd_callback(struct urb *urb)
-{
-       struct usb_context *usb_context = urb->context;
-       struct usbnet *dev = usb_context->dev;
-       int status = urb->status;
-
-       check_warn(status, "async callback failed with %d\n", status);
-
-       kfree(usb_context);
-       usb_free_urb(urb);
-}
-
 static int __must_check smsc95xx_write_reg_async(struct usbnet *dev, u16 index,
-                                                u32 *data)
+                                                u32 data)
 {
-       struct usb_context *usb_context;
-       int status;
-       struct urb *urb;
        const u16 size = 4;
+       u32 buf;
+       int ret;
 
-       urb = usb_alloc_urb(0, GFP_ATOMIC);
-       if (!urb) {
-               netdev_warn(dev->net, "Error allocating URB\n");
-               return -ENOMEM;
-       }
-
-       usb_context = kmalloc(sizeof(struct usb_context), GFP_ATOMIC);
-       if (usb_context == NULL) {
-               netdev_warn(dev->net, "Error allocating control msg\n");
-               usb_free_urb(urb);
-               return -ENOMEM;
-       }
-
-       usb_context->req.bRequestType =
-               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
-       usb_context->req.bRequest = USB_VENDOR_REQUEST_WRITE_REGISTER;
-       usb_context->req.wValue = 00;
-       usb_context->req.wIndex = cpu_to_le16(index);
-       usb_context->req.wLength = cpu_to_le16(size);
-
-       usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
-               (void *)&usb_context->req, data, size,
-               smsc95xx_async_cmd_callback,
-               (void *)usb_context);
-
-       status = usb_submit_urb(urb, GFP_ATOMIC);
-       if (status < 0) {
-               netdev_warn(dev->net, "Error submitting control msg, sts=%d\n",
-                           status);
-               kfree(usb_context);
-               usb_free_urb(urb);
-       }
+       buf = data;
+       cpu_to_le32s(&buf);
 
-       return status;
+       ret = usbnet_write_cmd_async(dev, USB_VENDOR_REQUEST_WRITE_REGISTER,
+                                    USB_DIR_OUT | USB_TYPE_VENDOR |
+                                    USB_RECIP_DEVICE,
+                                    0, index, &buf, size);
+       if (ret < 0)
+               netdev_warn(dev->net, "Error write async cmd, sts=%d\n",
+                           ret);
+       return ret;
 }
 
 /* returns hash bit number for given MAC address
@@ -460,14 +494,17 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
        spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
 
        /* Initiate async writes, as we can't wait for completion here */
-       ret = smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi);
-       check_warn(ret, "failed to initiate async write to HASHH");
+       ret = smsc95xx_write_reg_async(dev, HASHH, pdata->hash_hi);
+       if (ret < 0)
+               netdev_warn(dev->net, "failed to initiate async write to HASHH\n");
 
-       ret = smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo);
-       check_warn(ret, "failed to initiate async write to HASHL");
+       ret = smsc95xx_write_reg_async(dev, HASHL, pdata->hash_lo);
+       if (ret < 0)
+               netdev_warn(dev->net, "failed to initiate async write to HASHL\n");
 
-       ret = smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
-       check_warn(ret, "failed to initiate async write to MAC_CR");
+       ret = smsc95xx_write_reg_async(dev, MAC_CR, pdata->mac_cr);
+       if (ret < 0)
+               netdev_warn(dev->net, "failed to initiate async write to MAC_CR\n");
 }
 
 static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
@@ -476,7 +513,10 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
        u32 flow, afc_cfg = 0;
 
        int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg);
-       check_warn_return(ret, "Error reading AFC_CFG");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading AFC_CFG\n");
+               return ret;
+       }
 
        if (duplex == DUPLEX_FULL) {
                u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
@@ -501,12 +541,16 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
        }
 
        ret = smsc95xx_write_reg(dev, FLOW, flow);
-       check_warn_return(ret, "Error writing FLOW");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing FLOW\n");
+               return ret;
+       }
 
        ret = smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
-       check_warn_return(ret, "Error writing AFC_CFG");
+       if (ret < 0)
+               netdev_warn(dev->net, "Error writing AFC_CFG\n");
 
-       return 0;
+       return ret;
 }
 
 static int smsc95xx_link_reset(struct usbnet *dev)
@@ -520,10 +564,16 @@ static int smsc95xx_link_reset(struct usbnet *dev)
 
        /* clear interrupt status */
        ret = smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC);
-       check_warn_return(ret, "Error reading PHY_INT_SRC");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+               return ret;
+       }
 
        ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
-       check_warn_return(ret, "Error writing INT_STS");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing INT_STS\n");
+               return ret;
+       }
 
        mii_check_media(mii, 1, 1);
        mii_ethtool_gset(&dev->mii, &ecmd);
@@ -545,12 +595,16 @@ static int smsc95xx_link_reset(struct usbnet *dev)
        spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
 
        ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
-       check_warn_return(ret, "Error writing MAC_CR");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing MAC_CR\n");
+               return ret;
+       }
 
        ret = smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv);
-       check_warn_return(ret, "Error updating PHY flow control");
+       if (ret < 0)
+               netdev_warn(dev->net, "Error updating PHY flow control\n");
 
-       return 0;
+       return ret;
 }
 
 static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
@@ -584,7 +638,10 @@ static int smsc95xx_set_features(struct net_device *netdev,
        int ret;
 
        ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
-       check_warn_return(ret, "Failed to read COE_CR: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read COE_CR: %d\n", ret);
+               return ret;
+       }
 
        if (features & NETIF_F_HW_CSUM)
                read_buf |= Tx_COE_EN_;
@@ -597,7 +654,10 @@ static int smsc95xx_set_features(struct net_device *netdev,
                read_buf &= ~Rx_COE_EN_;
 
        ret = smsc95xx_write_reg(dev, COE_CR, read_buf);
-       check_warn_return(ret, "Failed to write COE_CR: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write COE_CR: %d\n", ret);
+               return ret;
+       }
 
        netif_dbg(dev, hw, dev->net, "COE_CR = 0x%08x\n", read_buf);
        return 0;
@@ -635,7 +695,7 @@ static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev,
 static int smsc95xx_ethtool_getregslen(struct net_device *netdev)
 {
        /* all smsc95xx registers */
-       return COE_CR - ID_REV + 1;
+       return COE_CR - ID_REV + sizeof(u32);
 }
 
 static void
@@ -677,9 +737,15 @@ static int smsc95xx_ethtool_set_wol(struct net_device *net,
 {
        struct usbnet *dev = netdev_priv(net);
        struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+       int ret;
 
        pdata->wolopts = wolinfo->wolopts & SUPPORTED_WAKE;
-       return 0;
+
+       ret = device_set_wakeup_enable(&dev->udev->dev, pdata->wolopts);
+       if (ret < 0)
+               netdev_warn(dev->net, "device_set_wakeup_enable error %d\n", ret);
+
+       return ret;
 }
 
 static const struct ethtool_ops smsc95xx_ethtool_ops = {
@@ -734,12 +800,16 @@ static int smsc95xx_set_mac_address(struct usbnet *dev)
        int ret;
 
        ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
-       check_warn_return(ret, "Failed to write ADDRL: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write ADDRL: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc95xx_write_reg(dev, ADDRH, addr_hi);
-       check_warn_return(ret, "Failed to write ADDRH: %d\n", ret);
+       if (ret < 0)
+               netdev_warn(dev->net, "Failed to write ADDRH: %d\n", ret);
 
-       return 0;
+       return ret;
 }
 
 /* starts the TX path */
@@ -755,17 +825,21 @@ static int smsc95xx_start_tx_path(struct usbnet *dev)
        spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
 
        ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
-       check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
+               return ret;
+       }
 
        /* Enable Tx at SCSRs */
        ret = smsc95xx_write_reg(dev, TX_CFG, TX_CFG_ON_);
-       check_warn_return(ret, "Failed to write TX_CFG: %d\n", ret);
+       if (ret < 0)
+               netdev_warn(dev->net, "Failed to write TX_CFG: %d\n", ret);
 
-       return 0;
+       return ret;
 }
 
 /* Starts the Receive path */
-static int smsc95xx_start_rx_path(struct usbnet *dev)
+static int smsc95xx_start_rx_path(struct usbnet *dev, int in_pm)
 {
        struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
        unsigned long flags;
@@ -775,10 +849,11 @@ static int smsc95xx_start_rx_path(struct usbnet *dev)
        pdata->mac_cr |= MAC_CR_RXEN_;
        spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
 
-       ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
-       check_warn_return(ret, "Failed to write MAC_CR: %d\n", ret);
+       ret = __smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr, in_pm);
+       if (ret < 0)
+               netdev_warn(dev->net, "Failed to write MAC_CR: %d\n", ret);
 
-       return 0;
+       return ret;
 }
 
 static int smsc95xx_phy_initialize(struct usbnet *dev)
@@ -813,7 +888,10 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
 
        /* read to clear */
        ret = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC);
-       check_warn_return(ret, "Failed to read PHY_INT_SRC during init");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read PHY_INT_SRC during init\n");
+               return ret;
+       }
 
        smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK,
                PHY_INT_MASK_DEFAULT_);
@@ -832,13 +910,19 @@ static int smsc95xx_reset(struct usbnet *dev)
        netif_dbg(dev, ifup, dev->net, "entering smsc95xx_reset\n");
 
        ret = smsc95xx_write_reg(dev, HW_CFG, HW_CFG_LRST_);
-       check_warn_return(ret, "Failed to write HW_CFG_LRST_ bit in HW_CFG\n");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write HW_CFG_LRST_ bit in HW_CFG\n");
+               return ret;
+       }
 
        timeout = 0;
        do {
                msleep(10);
                ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-               check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+                       return ret;
+               }
                timeout++;
        } while ((read_buf & HW_CFG_LRST_) && (timeout < 100));
 
@@ -848,13 +932,19 @@ static int smsc95xx_reset(struct usbnet *dev)
        }
 
        ret = smsc95xx_write_reg(dev, PM_CTRL, PM_CTL_PHY_RST_);
-       check_warn_return(ret, "Failed to write PM_CTRL: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write PM_CTRL: %d\n", ret);
+               return ret;
+       }
 
        timeout = 0;
        do {
                msleep(10);
                ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf);
-               check_warn_return(ret, "Failed to read PM_CTRL: %d\n", ret);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Failed to read PM_CTRL: %d\n", ret);
+                       return ret;
+               }
                timeout++;
        } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100));
 
@@ -867,22 +957,32 @@ static int smsc95xx_reset(struct usbnet *dev)
        if (ret < 0)
                return ret;
 
-       netif_dbg(dev, ifup, dev->net,
-                 "MAC Address: %pM\n", dev->net->dev_addr);
+       netif_dbg(dev, ifup, dev->net, "MAC Address: %pM\n",
+                 dev->net->dev_addr);
 
        ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-       check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net,
-                 "Read Value from HW_CFG : 0x%08x\n", read_buf);
+       netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG : 0x%08x\n",
+                 read_buf);
 
        read_buf |= HW_CFG_BIR_;
 
        ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
-       check_warn_return(ret, "Failed to write HW_CFG_BIR_ bit in HW_CFG\n");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write HW_CFG_BIR_ bit in HW_CFG\n");
+               return ret;
+       }
 
        ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-       check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+               return ret;
+       }
+
        netif_dbg(dev, ifup, dev->net,
                  "Read Value from HW_CFG after writing HW_CFG_BIR_: 0x%08x\n",
                  read_buf);
@@ -898,34 +998,49 @@ static int smsc95xx_reset(struct usbnet *dev)
                dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
        }
 
-       netif_dbg(dev, ifup, dev->net,
-                 "rx_urb_size=%ld\n", (ulong)dev->rx_urb_size);
+       netif_dbg(dev, ifup, dev->net, "rx_urb_size=%ld\n",
+                 (ulong)dev->rx_urb_size);
 
        ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
-       check_warn_return(ret, "Failed to write BURST_CAP: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write BURST_CAP: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf);
-       check_warn_return(ret, "Failed to read BURST_CAP: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read BURST_CAP: %d\n", ret);
+               return ret;
+       }
 
        netif_dbg(dev, ifup, dev->net,
                  "Read Value from BURST_CAP after writing: 0x%08x\n",
                  read_buf);
 
        ret = smsc95xx_write_reg(dev, BULK_IN_DLY, DEFAULT_BULK_IN_DELAY);
-       check_warn_return(ret, "Failed to write BULK_IN_DLY: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write BULK_IN_DLY: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf);
-       check_warn_return(ret, "Failed to read BULK_IN_DLY: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read BULK_IN_DLY: %d\n", ret);
+               return ret;
+       }
 
        netif_dbg(dev, ifup, dev->net,
                  "Read Value from BULK_IN_DLY after writing: 0x%08x\n",
                  read_buf);
 
        ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-       check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+               return ret;
+       }
 
-       netif_dbg(dev, ifup, dev->net,
-                 "Read Value from HW_CFG: 0x%08x\n", read_buf);
+       netif_dbg(dev, ifup, dev->net, "Read Value from HW_CFG: 0x%08x\n",
+                 read_buf);
 
        if (turbo_mode)
                read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_);
@@ -936,66 +1051,111 @@ static int smsc95xx_reset(struct usbnet *dev)
        read_buf |= NET_IP_ALIGN << 9;
 
        ret = smsc95xx_write_reg(dev, HW_CFG, read_buf);
-       check_warn_return(ret, "Failed to write HW_CFG: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write HW_CFG: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
-       check_warn_return(ret, "Failed to read HW_CFG: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read HW_CFG: %d\n", ret);
+               return ret;
+       }
 
        netif_dbg(dev, ifup, dev->net,
                  "Read Value from HW_CFG after writing: 0x%08x\n", read_buf);
 
        ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
-       check_warn_return(ret, "Failed to write INT_STS: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write INT_STS: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc95xx_read_reg(dev, ID_REV, &read_buf);
-       check_warn_return(ret, "Failed to read ID_REV: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
+               return ret;
+       }
        netif_dbg(dev, ifup, dev->net, "ID_REV = 0x%08x\n", read_buf);
 
        /* Configure GPIO pins as LED outputs */
        write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
                LED_GPIO_CFG_FDX_LED;
        ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
-       check_warn_return(ret, "Failed to write LED_GPIO_CFG: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write LED_GPIO_CFG: %d\n", ret);
+               return ret;
+       }
 
        /* Init Tx */
        ret = smsc95xx_write_reg(dev, FLOW, 0);
-       check_warn_return(ret, "Failed to write FLOW: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write FLOW: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc95xx_write_reg(dev, AFC_CFG, AFC_CFG_DEFAULT);
-       check_warn_return(ret, "Failed to write AFC_CFG: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write AFC_CFG: %d\n", ret);
+               return ret;
+       }
 
        /* Don't need mac_cr_lock during initialisation */
        ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr);
-       check_warn_return(ret, "Failed to read MAC_CR: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read MAC_CR: %d\n", ret);
+               return ret;
+       }
 
        /* Init Rx */
        /* Set Vlan */
        ret = smsc95xx_write_reg(dev, VLAN1, (u32)ETH_P_8021Q);
-       check_warn_return(ret, "Failed to write VLAN1: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write VLAN1: %d\n", ret);
+               return ret;
+       }
 
        /* Enable or disable checksum offload engines */
        ret = smsc95xx_set_features(dev->net, dev->net->features);
-       check_warn_return(ret, "Failed to set checksum offload features");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to set checksum offload features\n");
+               return ret;
+       }
 
        smsc95xx_set_multicast(dev->net);
 
        ret = smsc95xx_phy_initialize(dev);
-       check_warn_return(ret, "Failed to init PHY");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to init PHY\n");
+               return ret;
+       }
 
        ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf);
-       check_warn_return(ret, "Failed to read INT_EP_CTL: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read INT_EP_CTL: %d\n", ret);
+               return ret;
+       }
 
        /* enable PHY interrupts */
        read_buf |= INT_EP_CTL_PHY_INT_;
 
        ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf);
-       check_warn_return(ret, "Failed to write INT_EP_CTL: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to write INT_EP_CTL: %d\n", ret);
+               return ret;
+       }
 
        ret = smsc95xx_start_tx_path(dev);
-       check_warn_return(ret, "Failed to start TX path");
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to start TX path\n");
+               return ret;
+       }
 
-       ret = smsc95xx_start_rx_path(dev);
-       check_warn_return(ret, "Failed to start RX path");
+       ret = smsc95xx_start_rx_path(dev, 0);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to start RX path\n");
+               return ret;
+       }
 
        netif_dbg(dev, ifup, dev->net, "smsc95xx_reset, return 0\n");
        return 0;
@@ -1017,12 +1177,16 @@ static const struct net_device_ops smsc95xx_netdev_ops = {
 static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        struct smsc95xx_priv *pdata = NULL;
+       u32 val;
        int ret;
 
        printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n");
 
        ret = usbnet_get_endpoints(dev, intf);
-       check_warn_return(ret, "usbnet_get_endpoints failed: %d\n", ret);
+       if (ret < 0) {
+               netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret);
+               return ret;
+       }
 
        dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv),
                GFP_KERNEL);
@@ -1047,6 +1211,22 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
        /* Init all registers */
        ret = smsc95xx_reset(dev);
 
+       /* detect device revision as different features may be available */
+       ret = smsc95xx_read_reg(dev, ID_REV, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Failed to read ID_REV: %d\n", ret);
+               return ret;
+       }
+       val >>= 16;
+
+       if ((val == ID_REV_CHIP_ID_9500A_) || (val == ID_REV_CHIP_ID_9530_) ||
+           (val == ID_REV_CHIP_ID_89530_) || (val == ID_REV_CHIP_ID_9730_))
+               pdata->features = (FEATURE_8_WAKEUP_FILTERS |
+                       FEATURE_PHY_NLP_CROSSOVER |
+                       FEATURE_AUTOSUSPEND);
+       else if (val == ID_REV_CHIP_ID_9512_)
+               pdata->features = FEATURE_8_WAKEUP_FILTERS;
+
        dev->net->netdev_ops = &smsc95xx_netdev_ops;
        dev->net->ethtool_ops = &smsc95xx_ethtool_ops;
        dev->net->flags |= IFF_MULTICAST;
@@ -1066,113 +1246,448 @@ static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf)
        }
 }
 
+static u32 smsc_crc(const u8 *buffer, size_t len, int filter)
+{
+       u32 crc = bitrev16(crc16(0xFFFF, buffer, len));
+       return crc << ((filter % 2) * 16);
+}
+
+static int smsc95xx_enable_phy_wakeup_interrupts(struct usbnet *dev, u16 mask)
+{
+       struct mii_if_info *mii = &dev->mii;
+       int ret;
+
+       netdev_dbg(dev->net, "enabling PHY wakeup interrupts\n");
+
+       /* read to clear */
+       ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_SRC);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PHY_INT_SRC\n");
+               return ret;
+       }
+
+       /* enable interrupt source */
+       ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_INT_MASK);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PHY_INT_MASK\n");
+               return ret;
+       }
+
+       ret |= mask;
+
+       smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_INT_MASK, ret);
+
+       return 0;
+}
+
+static int smsc95xx_link_ok_nopm(struct usbnet *dev)
+{
+       struct mii_if_info *mii = &dev->mii;
+       int ret;
+
+       /* first, a dummy read, needed to latch some MII phys */
+       ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading MII_BMSR\n");
+               return ret;
+       }
+
+       ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, MII_BMSR);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading MII_BMSR\n");
+               return ret;
+       }
+
+       return !!(ret & BMSR_LSTATUS);
+}
+
+static int smsc95xx_enter_suspend0(struct usbnet *dev)
+{
+       struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+       u32 val;
+       int ret;
+
+       ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PM_CTRL\n");
+               return ret;
+       }
+
+       val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
+       val |= PM_CTL_SUS_MODE_0;
+
+       ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PM_CTRL\n");
+               return ret;
+       }
+
+       /* clear wol status */
+       val &= ~PM_CTL_WUPS_;
+       val |= PM_CTL_WUPS_WOL_;
+
+       /* enable energy detection */
+       if (pdata->wolopts & WAKE_PHY)
+               val |= PM_CTL_WUPS_ED_;
+
+       ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PM_CTRL\n");
+               return ret;
+       }
+
+       /* read back PM_CTRL */
+       ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+       if (ret < 0)
+               netdev_warn(dev->net, "Error reading PM_CTRL\n");
+
+       return ret;
+}
+
+static int smsc95xx_enter_suspend1(struct usbnet *dev)
+{
+       struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+       struct mii_if_info *mii = &dev->mii;
+       u32 val;
+       int ret;
+
+       /* reconfigure link pulse detection timing for
+        * compatibility with non-standard link partners
+        */
+       if (pdata->features & FEATURE_PHY_NLP_CROSSOVER)
+               smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_EDPD_CONFIG,
+                       PHY_EDPD_CONFIG_DEFAULT);
+
+       /* enable energy detect power-down mode */
+       ret = smsc95xx_mdio_read_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PHY_MODE_CTRL_STS\n");
+               return ret;
+       }
+
+       ret |= MODE_CTRL_STS_EDPWRDOWN_;
+
+       smsc95xx_mdio_write_nopm(dev->net, mii->phy_id, PHY_MODE_CTRL_STS, ret);
+
+       /* enter SUSPEND1 mode */
+       ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PM_CTRL\n");
+               return ret;
+       }
+
+       val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+       val |= PM_CTL_SUS_MODE_1;
+
+       ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PM_CTRL\n");
+               return ret;
+       }
+
+       /* clear wol status, enable energy detection */
+       val &= ~PM_CTL_WUPS_;
+       val |= (PM_CTL_WUPS_ED_ | PM_CTL_ED_EN_);
+
+       ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+       if (ret < 0)
+               netdev_warn(dev->net, "Error writing PM_CTRL\n");
+
+       return ret;
+}
+
+static int smsc95xx_enter_suspend2(struct usbnet *dev)
+{
+       u32 val;
+       int ret;
+
+       ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PM_CTRL\n");
+               return ret;
+       }
+
+       val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
+       val |= PM_CTL_SUS_MODE_2;
+
+       ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+       if (ret < 0)
+               netdev_warn(dev->net, "Error writing PM_CTRL\n");
+
+       return ret;
+}
+
 static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct usbnet *dev = usb_get_intfdata(intf);
        struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+       u32 val, link_up;
        int ret;
-       u32 val;
 
        ret = usbnet_suspend(intf, message);
-       check_warn_return(ret, "usbnet_suspend error");
+       if (ret < 0) {
+               netdev_warn(dev->net, "usbnet_suspend error\n");
+               return ret;
+       }
 
-       /* if no wol options set, enter lowest power SUSPEND2 mode */
-       if (!(pdata->wolopts & SUPPORTED_WAKE)) {
-               netdev_info(dev->net, "entering SUSPEND2 mode");
+       /* determine if link is up using only _nopm functions */
+       link_up = smsc95xx_link_ok_nopm(dev);
+
+       /* if no wol options set, or if link is down and we're not waking on
+        * PHY activity, enter lowest power SUSPEND2 mode
+        */
+       if (!(pdata->wolopts & SUPPORTED_WAKE) ||
+               !(link_up || (pdata->wolopts & WAKE_PHY))) {
+               netdev_info(dev->net, "entering SUSPEND2 mode\n");
 
                /* disable energy detect (link up) & wake up events */
-               ret = smsc95xx_read_reg(dev, WUCSR, &val);
-               check_warn_return(ret, "Error reading WUCSR");
+               ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
 
                val &= ~(WUCSR_MPEN_ | WUCSR_WAKE_EN_);
 
-               ret = smsc95xx_write_reg(dev, WUCSR, val);
-               check_warn_return(ret, "Error writing WUCSR");
+               ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
 
-               ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-               check_warn_return(ret, "Error reading PM_CTRL");
+               ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading PM_CTRL\n");
+                       goto done;
+               }
 
                val &= ~(PM_CTL_ED_EN_ | PM_CTL_WOL_EN_);
 
-               ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-               check_warn_return(ret, "Error writing PM_CTRL");
+               ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing PM_CTRL\n");
+                       goto done;
+               }
 
-               /* enter suspend2 mode */
-               ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-               check_warn_return(ret, "Error reading PM_CTRL");
+               ret = smsc95xx_enter_suspend2(dev);
+               goto done;
+       }
 
-               val &= ~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_);
-               val |= PM_CTL_SUS_MODE_2;
+       if (pdata->wolopts & WAKE_PHY) {
+               ret = smsc95xx_enable_phy_wakeup_interrupts(dev,
+                       (PHY_INT_MASK_ANEG_COMP_ | PHY_INT_MASK_LINK_DOWN_));
+               if (ret < 0) {
+                       netdev_warn(dev->net, "error enabling PHY wakeup ints\n");
+                       goto done;
+               }
+
+               /* if link is down then configure EDPD and enter SUSPEND1,
+                * otherwise enter SUSPEND0 below
+                */
+               if (!link_up) {
+                       netdev_info(dev->net, "entering SUSPEND1 mode\n");
+                       ret = smsc95xx_enter_suspend1(dev);
+                       goto done;
+               }
+       }
 
-               ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-               check_warn_return(ret, "Error writing PM_CTRL");
+       if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
+               u32 *filter_mask = kzalloc(sizeof(u32) * 32, GFP_KERNEL);
+               u32 command[2];
+               u32 offset[2];
+               u32 crc[4];
+               int wuff_filter_count =
+                       (pdata->features & FEATURE_8_WAKEUP_FILTERS) ?
+                       LAN9500A_WUFF_NUM : LAN9500_WUFF_NUM;
+               int i, filter = 0;
+
+               if (!filter_mask) {
+                       netdev_warn(dev->net, "Unable to allocate filter_mask\n");
+                       ret = -ENOMEM;
+                       goto done;
+               }
 
-               return 0;
+               memset(command, 0, sizeof(command));
+               memset(offset, 0, sizeof(offset));
+               memset(crc, 0, sizeof(crc));
+
+               if (pdata->wolopts & WAKE_BCAST) {
+                       const u8 bcast[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+                       netdev_info(dev->net, "enabling broadcast detection\n");
+                       filter_mask[filter * 4] = 0x003F;
+                       filter_mask[filter * 4 + 1] = 0x00;
+                       filter_mask[filter * 4 + 2] = 0x00;
+                       filter_mask[filter * 4 + 3] = 0x00;
+                       command[filter/4] |= 0x05UL << ((filter % 4) * 8);
+                       offset[filter/4] |= 0x00 << ((filter % 4) * 8);
+                       crc[filter/2] |= smsc_crc(bcast, 6, filter);
+                       filter++;
+               }
+
+               if (pdata->wolopts & WAKE_MCAST) {
+                       const u8 mcast[] = {0x01, 0x00, 0x5E};
+                       netdev_info(dev->net, "enabling multicast detection\n");
+                       filter_mask[filter * 4] = 0x0007;
+                       filter_mask[filter * 4 + 1] = 0x00;
+                       filter_mask[filter * 4 + 2] = 0x00;
+                       filter_mask[filter * 4 + 3] = 0x00;
+                       command[filter/4] |= 0x09UL << ((filter % 4) * 8);
+                       offset[filter/4] |= 0x00  << ((filter % 4) * 8);
+                       crc[filter/2] |= smsc_crc(mcast, 3, filter);
+                       filter++;
+               }
+
+               if (pdata->wolopts & WAKE_ARP) {
+                       const u8 arp[] = {0x08, 0x06};
+                       netdev_info(dev->net, "enabling ARP detection\n");
+                       filter_mask[filter * 4] = 0x0003;
+                       filter_mask[filter * 4 + 1] = 0x00;
+                       filter_mask[filter * 4 + 2] = 0x00;
+                       filter_mask[filter * 4 + 3] = 0x00;
+                       command[filter/4] |= 0x05UL << ((filter % 4) * 8);
+                       offset[filter/4] |= 0x0C << ((filter % 4) * 8);
+                       crc[filter/2] |= smsc_crc(arp, 2, filter);
+                       filter++;
+               }
+
+               if (pdata->wolopts & WAKE_UCAST) {
+                       netdev_info(dev->net, "enabling unicast detection\n");
+                       filter_mask[filter * 4] = 0x003F;
+                       filter_mask[filter * 4 + 1] = 0x00;
+                       filter_mask[filter * 4 + 2] = 0x00;
+                       filter_mask[filter * 4 + 3] = 0x00;
+                       command[filter/4] |= 0x01UL << ((filter % 4) * 8);
+                       offset[filter/4] |= 0x00 << ((filter % 4) * 8);
+                       crc[filter/2] |= smsc_crc(dev->net->dev_addr, ETH_ALEN, filter);
+                       filter++;
+               }
+
+               for (i = 0; i < (wuff_filter_count * 4); i++) {
+                       ret = smsc95xx_write_reg_nopm(dev, WUFF, filter_mask[i]);
+                       if (ret < 0) {
+                               netdev_warn(dev->net, "Error writing WUFF\n");
+                               kfree(filter_mask);
+                               goto done;
+                       }
+               }
+               kfree(filter_mask);
+
+               for (i = 0; i < (wuff_filter_count / 4); i++) {
+                       ret = smsc95xx_write_reg_nopm(dev, WUFF, command[i]);
+                       if (ret < 0) {
+                               netdev_warn(dev->net, "Error writing WUFF\n");
+                               goto done;
+                       }
+               }
+
+               for (i = 0; i < (wuff_filter_count / 4); i++) {
+                       ret = smsc95xx_write_reg_nopm(dev, WUFF, offset[i]);
+                       if (ret < 0) {
+                               netdev_warn(dev->net, "Error writing WUFF\n");
+                               goto done;
+                       }
+               }
+
+               for (i = 0; i < (wuff_filter_count / 2); i++) {
+                       ret = smsc95xx_write_reg_nopm(dev, WUFF, crc[i]);
+                       if (ret < 0) {
+                               netdev_warn(dev->net, "Error writing WUFF\n");
+                               goto done;
+                       }
+               }
+
+               /* clear any pending pattern match packet status */
+               ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
+
+               val |= WUCSR_WUFR_;
+
+               ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
        }
 
        if (pdata->wolopts & WAKE_MAGIC) {
                /* clear any pending magic packet status */
-               ret = smsc95xx_read_reg(dev, WUCSR, &val);
-               check_warn_return(ret, "Error reading WUCSR");
+               ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       goto done;
+               }
 
                val |= WUCSR_MPR_;
 
-               ret = smsc95xx_write_reg(dev, WUCSR, val);
-               check_warn_return(ret, "Error writing WUCSR");
+               ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       goto done;
+               }
+       }
+
+       /* enable/disable wakeup sources */
+       ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading WUCSR\n");
+               goto done;
        }
 
-       /* enable/disable magic packup wake */
-       ret = smsc95xx_read_reg(dev, WUCSR, &val);
-       check_warn_return(ret, "Error reading WUCSR");
+       if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
+               netdev_info(dev->net, "enabling pattern match wakeup\n");
+               val |= WUCSR_WAKE_EN_;
+       } else {
+               netdev_info(dev->net, "disabling pattern match wakeup\n");
+               val &= ~WUCSR_WAKE_EN_;
+       }
 
        if (pdata->wolopts & WAKE_MAGIC) {
-               netdev_info(dev->net, "enabling magic packet wakeup");
+               netdev_info(dev->net, "enabling magic packet wakeup\n");
                val |= WUCSR_MPEN_;
        } else {
-               netdev_info(dev->net, "disabling magic packet wakeup");
+               netdev_info(dev->net, "disabling magic packet wakeup\n");
                val &= ~WUCSR_MPEN_;
        }
 
-       ret = smsc95xx_write_reg(dev, WUCSR, val);
-       check_warn_return(ret, "Error writing WUCSR");
+       ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing WUCSR\n");
+               goto done;
+       }
 
        /* enable wol wakeup source */
-       ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-       check_warn_return(ret, "Error reading PM_CTRL");
+       ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error reading PM_CTRL\n");
+               goto done;
+       }
 
        val |= PM_CTL_WOL_EN_;
 
-       ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-       check_warn_return(ret, "Error writing PM_CTRL");
-
-       /* enable receiver */
-       smsc95xx_start_rx_path(dev);
-
-       /* some wol options are enabled, so enter SUSPEND0 */
-       netdev_info(dev->net, "entering SUSPEND0 mode");
-
-       ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-       check_warn_return(ret, "Error reading PM_CTRL");
-
-       val &= (~(PM_CTL_SUS_MODE_ | PM_CTL_WUPS_ | PM_CTL_PHY_RST_));
-       val |= PM_CTL_SUS_MODE_0;
-
-       ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-       check_warn_return(ret, "Error writing PM_CTRL");
+       /* phy energy detect wakeup source */
+       if (pdata->wolopts & WAKE_PHY)
+               val |= PM_CTL_ED_EN_;
 
-       /* clear wol status */
-       val &= ~PM_CTL_WUPS_;
-       val |= PM_CTL_WUPS_WOL_;
-       ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-       check_warn_return(ret, "Error writing PM_CTRL");
+       ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+       if (ret < 0) {
+               netdev_warn(dev->net, "Error writing PM_CTRL\n");
+               goto done;
+       }
 
-       /* read back PM_CTRL */
-       ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-       check_warn_return(ret, "Error reading PM_CTRL");
+       /* enable receiver to enable frame reception */
+       smsc95xx_start_rx_path(dev, 1);
 
-       smsc95xx_set_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
+       /* some wol options are enabled, so enter SUSPEND0 */
+       netdev_info(dev->net, "entering SUSPEND0 mode\n");
+       ret = smsc95xx_enter_suspend0(dev);
 
-       return 0;
+done:
+       if (ret)
+               usbnet_resume(intf);
+       return ret;
 }
 
 static int smsc95xx_resume(struct usb_interface *intf)
@@ -1184,33 +1699,44 @@ static int smsc95xx_resume(struct usb_interface *intf)
 
        BUG_ON(!dev);
 
-       if (pdata->wolopts & WAKE_MAGIC) {
-               smsc95xx_clear_feature(dev, USB_DEVICE_REMOTE_WAKEUP);
-
-               /* Disable magic packup wake */
-               ret = smsc95xx_read_reg(dev, WUCSR, &val);
-               check_warn_return(ret, "Error reading WUCSR");
+       if (pdata->wolopts) {
+               /* clear wake-up sources */
+               ret = smsc95xx_read_reg_nopm(dev, WUCSR, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading WUCSR\n");
+                       return ret;
+               }
 
-               val &= ~WUCSR_MPEN_;
+               val &= ~(WUCSR_WAKE_EN_ | WUCSR_MPEN_);
 
-               ret = smsc95xx_write_reg(dev, WUCSR, val);
-               check_warn_return(ret, "Error writing WUCSR");
+               ret = smsc95xx_write_reg_nopm(dev, WUCSR, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing WUCSR\n");
+                       return ret;
+               }
 
                /* clear wake-up status */
-               ret = smsc95xx_read_reg(dev, PM_CTRL, &val);
-               check_warn_return(ret, "Error reading PM_CTRL");
+               ret = smsc95xx_read_reg_nopm(dev, PM_CTRL, &val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error reading PM_CTRL\n");
+                       return ret;
+               }
 
                val &= ~PM_CTL_WOL_EN_;
                val |= PM_CTL_WUPS_;
 
-               ret = smsc95xx_write_reg(dev, PM_CTRL, val);
-               check_warn_return(ret, "Error writing PM_CTRL");
+               ret = smsc95xx_write_reg_nopm(dev, PM_CTRL, val);
+               if (ret < 0) {
+                       netdev_warn(dev->net, "Error writing PM_CTRL\n");
+                       return ret;
+               }
        }
 
-       return usbnet_resume(intf);
-       check_warn_return(ret, "usbnet_resume error");
+       ret = usbnet_resume(intf);
+       if (ret < 0)
+               netdev_warn(dev->net, "usbnet_resume error\n");
 
-       return 0;
+       return ret;
 }
 
 static void smsc95xx_rx_csum_offload(struct sk_buff *skb)
@@ -1344,6 +1870,7 @@ static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
                } else {
                        u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
                        skb_push(skb, 4);
+                       cpu_to_le32s(&csum_preamble);
                        memcpy(skb->data, &csum_preamble, 4);
                }
        }
index 2ff9815aa27c5e9e098dd587e8291398f2dce25f..f360ee372554d5b1ce40c789aac44a6d066fc730 100644 (file)
 #define ID_REV_CHIP_ID_MASK_           (0xFFFF0000)
 #define ID_REV_CHIP_REV_MASK_          (0x0000FFFF)
 #define ID_REV_CHIP_ID_9500_           (0x9500)
+#define ID_REV_CHIP_ID_9500A_          (0x9E00)
+#define ID_REV_CHIP_ID_9512_           (0xEC00)
+#define ID_REV_CHIP_ID_9530_           (0x9530)
+#define ID_REV_CHIP_ID_89530_          (0x9E08)
+#define ID_REV_CHIP_ID_9730_           (0x9730)
 
 #define INT_STS                                (0x08)
 #define INT_STS_TX_STOP_               (0x00020000)
 #define VLAN2                          (0x124)
 
 #define WUFF                           (0x128)
+#define LAN9500_WUFF_NUM               (4)
+#define LAN9500A_WUFF_NUM              (8)
 
 #define WUCSR                          (0x12C)
+#define WUCSR_WFF_PTR_RST_             (0x80000000)
 #define WUCSR_GUE_                     (0x00000200)
 #define WUCSR_WUFR_                    (0x00000040)
 #define WUCSR_MPR_                     (0x00000020)
 
 /* Vendor-specific PHY Definitions */
 
+/* EDPD NLP / crossover time configuration (LAN9500A only) */
+#define PHY_EDPD_CONFIG                        (16)
+#define PHY_EDPD_CONFIG_TX_NLP_EN_     ((u16)0x8000)
+#define PHY_EDPD_CONFIG_TX_NLP_1000_   ((u16)0x0000)
+#define PHY_EDPD_CONFIG_TX_NLP_768_    ((u16)0x2000)
+#define PHY_EDPD_CONFIG_TX_NLP_512_    ((u16)0x4000)
+#define PHY_EDPD_CONFIG_TX_NLP_256_    ((u16)0x6000)
+#define PHY_EDPD_CONFIG_RX_1_NLP_      ((u16)0x1000)
+#define PHY_EDPD_CONFIG_RX_NLP_64_     ((u16)0x0000)
+#define PHY_EDPD_CONFIG_RX_NLP_256_    ((u16)0x0400)
+#define PHY_EDPD_CONFIG_RX_NLP_512_    ((u16)0x0800)
+#define PHY_EDPD_CONFIG_RX_NLP_1000_   ((u16)0x0C00)
+#define PHY_EDPD_CONFIG_EXT_CROSSOVER_ ((u16)0x0001)
+#define PHY_EDPD_CONFIG_DEFAULT                (PHY_EDPD_CONFIG_TX_NLP_EN_ | \
+                                        PHY_EDPD_CONFIG_TX_NLP_768_ | \
+                                        PHY_EDPD_CONFIG_RX_1_NLP_)
+
 /* Mode Control/Status Register */
 #define PHY_MODE_CTRL_STS              (17)
 #define MODE_CTRL_STS_EDPWRDOWN_       ((u16)0x2000)
index f9819d10b1f9d41f864dc710e6799ffed9f9d5f0..c04110ba677f5febcac3876a411646845b3a9ab3 100644 (file)
@@ -359,10 +359,12 @@ static enum skb_state defer_bh(struct usbnet *dev, struct sk_buff *skb,
 void usbnet_defer_kevent (struct usbnet *dev, int work)
 {
        set_bit (work, &dev->flags);
-       if (!schedule_work (&dev->kevent))
-               netdev_err(dev->net, "kevent %d may have been dropped\n", work);
-       else
+       if (!schedule_work (&dev->kevent)) {
+               if (net_ratelimit())
+                       netdev_err(dev->net, "kevent %d may have been dropped\n", work);
+       } else {
                netdev_dbg(dev->net, "kevent %d scheduled\n", work);
+       }
 }
 EXPORT_SYMBOL_GPL(usbnet_defer_kevent);
 
@@ -1158,6 +1160,7 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb,
                usb_anchor_urb(urb, &dev->deferred);
                /* no use to process more packets */
                netif_stop_queue(net);
+               usb_put_urb(urb);
                spin_unlock_irqrestore(&dev->txq.lock, flags);
                netdev_dbg(dev->net, "Delaying transmission for resumption\n");
                goto deferred;
@@ -1310,6 +1313,8 @@ void usbnet_disconnect (struct usb_interface *intf)
 
        cancel_work_sync(&dev->kevent);
 
+       usb_scuttle_anchored_urbs(&dev->deferred);
+
        if (dev->driver_info->unbind)
                dev->driver_info->unbind (dev, intf);
 
@@ -1610,6 +1615,202 @@ void usbnet_device_suggests_idle(struct usbnet *dev)
 }
 EXPORT_SYMBOL(usbnet_device_suggests_idle);
 
+/*-------------------------------------------------------------------------*/
+static int __usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+                            u16 value, u16 index, void *data, u16 size)
+{
+       void *buf = NULL;
+       int err = -ENOMEM;
+
+       netdev_dbg(dev->net, "usbnet_read_cmd cmd=0x%02x reqtype=%02x"
+                  " value=0x%04x index=0x%04x size=%d\n",
+                  cmd, reqtype, value, index, size);
+
+       if (data) {
+               buf = kmalloc(size, GFP_KERNEL);
+               if (!buf)
+                       goto out;
+       }
+
+       err = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+                             cmd, reqtype, value, index, buf, size,
+                             USB_CTRL_GET_TIMEOUT);
+       if (err > 0 && err <= size)
+               memcpy(data, buf, err);
+       kfree(buf);
+out:
+       return err;
+}
+
+static int __usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+                             u16 value, u16 index, const void *data,
+                             u16 size)
+{
+       void *buf = NULL;
+       int err = -ENOMEM;
+
+       netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
+                  " value=0x%04x index=0x%04x size=%d\n",
+                  cmd, reqtype, value, index, size);
+
+       if (data) {
+               buf = kmemdup(data, size, GFP_KERNEL);
+               if (!buf)
+                       goto out;
+       }
+
+       err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+                             cmd, reqtype, value, index, buf, size,
+                             USB_CTRL_SET_TIMEOUT);
+       kfree(buf);
+
+out:
+       return err;
+}
+
+/*
+ * The function can't be called inside suspend/resume callback,
+ * otherwise deadlock will be caused.
+ */
+int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+                   u16 value, u16 index, void *data, u16 size)
+{
+       int ret;
+
+       if (usb_autopm_get_interface(dev->intf) < 0)
+               return -ENODEV;
+       ret = __usbnet_read_cmd(dev, cmd, reqtype, value, index,
+                               data, size);
+       usb_autopm_put_interface(dev->intf);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usbnet_read_cmd);
+
+/*
+ * The function can't be called inside suspend/resume callback,
+ * otherwise deadlock will be caused.
+ */
+int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+                    u16 value, u16 index, const void *data, u16 size)
+{
+       int ret;
+
+       if (usb_autopm_get_interface(dev->intf) < 0)
+               return -ENODEV;
+       ret = __usbnet_write_cmd(dev, cmd, reqtype, value, index,
+                                data, size);
+       usb_autopm_put_interface(dev->intf);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd);
+
+/*
+ * The function can be called inside suspend/resume callback safely
+ * and should only be called by suspend/resume callback generally.
+ */
+int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+                         u16 value, u16 index, void *data, u16 size)
+{
+       return __usbnet_read_cmd(dev, cmd, reqtype, value, index,
+                                data, size);
+}
+EXPORT_SYMBOL_GPL(usbnet_read_cmd_nopm);
+
+/*
+ * The function can be called inside suspend/resume callback safely
+ * and should only be called by suspend/resume callback generally.
+ */
+int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+                         u16 value, u16 index, const void *data,
+                         u16 size)
+{
+       return __usbnet_write_cmd(dev, cmd, reqtype, value, index,
+                                 data, size);
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd_nopm);
+
+static void usbnet_async_cmd_cb(struct urb *urb)
+{
+       struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+       int status = urb->status;
+
+       if (status < 0)
+               dev_dbg(&urb->dev->dev, "%s failed with %d",
+                       __func__, status);
+
+       kfree(req);
+       usb_free_urb(urb);
+}
+
+/*
+ * The caller must make sure that device can't be put into suspend
+ * state until the control URB completes.
+ */
+int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
+                          u16 value, u16 index, const void *data, u16 size)
+{
+       struct usb_ctrlrequest *req = NULL;
+       struct urb *urb;
+       int err = -ENOMEM;
+       void *buf = NULL;
+
+       netdev_dbg(dev->net, "usbnet_write_cmd cmd=0x%02x reqtype=%02x"
+                  " value=0x%04x index=0x%04x size=%d\n",
+                  cmd, reqtype, value, index, size);
+
+       urb = usb_alloc_urb(0, GFP_ATOMIC);
+       if (!urb) {
+               netdev_err(dev->net, "Error allocating URB in"
+                          " %s!\n", __func__);
+               goto fail;
+       }
+
+       if (data) {
+               buf = kmemdup(data, size, GFP_ATOMIC);
+               if (!buf) {
+                       netdev_err(dev->net, "Error allocating buffer"
+                                  " in %s!\n", __func__);
+                       goto fail_free;
+               }
+       }
+
+       req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_ATOMIC);
+       if (!req) {
+               netdev_err(dev->net, "Failed to allocate memory for %s\n",
+                          __func__);
+               goto fail_free_buf;
+       }
+
+       req->bRequestType = reqtype;
+       req->bRequest = cmd;
+       req->wValue = cpu_to_le16(value);
+       req->wIndex = cpu_to_le16(index);
+       req->wLength = cpu_to_le16(size);
+
+       usb_fill_control_urb(urb, dev->udev,
+                            usb_sndctrlpipe(dev->udev, 0),
+                            (void *)req, buf, size,
+                            usbnet_async_cmd_cb, req);
+       urb->transfer_flags |= URB_FREE_BUFFER;
+
+       err = usb_submit_urb(urb, GFP_ATOMIC);
+       if (err < 0) {
+               netdev_err(dev->net, "Error submitting the control"
+                          " message: status=%d\n", err);
+               goto fail_free;
+       }
+       return 0;
+
+fail_free_buf:
+       kfree(buf);
+fail_free:
+       kfree(req);
+       usb_free_urb(urb);
+fail:
+       return err;
+
+}
+EXPORT_SYMBOL_GPL(usbnet_write_cmd_async);
 /*-------------------------------------------------------------------------*/
 
 static int __init usbnet_init(void)
index e522ff70444cd0d7e8f1ce34132055e438ded7ce..95814d9747ef1988657ccd72bc01d56501bc7b37 100644 (file)
@@ -264,6 +264,7 @@ static void veth_setup(struct net_device *dev)
        ether_setup(dev);
 
        dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+       dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
 
        dev->netdev_ops = &veth_netdev_ops;
        dev->ethtool_ops = &veth_ethtool_ops;
@@ -339,7 +340,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
        if (IS_ERR(net))
                return PTR_ERR(net);
 
-       peer = rtnl_create_link(src_net, net, ifname, &veth_link_ops, tbp);
+       peer = rtnl_create_link(net, ifname, &veth_link_ops, tbp);
        if (IS_ERR(peer)) {
                put_net(net);
                return PTR_ERR(peer);
index cbf8b06253528e9e5557c31e844581d7334d7e21..68d64f0313eaa38d3324213f536e820365f16f93 100644 (file)
@@ -51,15 +51,51 @@ struct virtnet_stats {
        u64 rx_packets;
 };
 
+/* Internal representation of a send virtqueue */
+struct send_queue {
+       /* Virtqueue associated with this send _queue */
+       struct virtqueue *vq;
+
+       /* TX: fragments + linear part + virtio header */
+       struct scatterlist sg[MAX_SKB_FRAGS + 2];
+
+       /* Name of the send queue: output.$index */
+       char name[40];
+};
+
+/* Internal representation of a receive virtqueue */
+struct receive_queue {
+       /* Virtqueue associated with this receive_queue */
+       struct virtqueue *vq;
+
+       struct napi_struct napi;
+
+       /* Number of input buffers, and max we've ever had. */
+       unsigned int num, max;
+
+       /* Chain pages by the private ptr. */
+       struct page *pages;
+
+       /* RX: fragments + linear part + virtio header */
+       struct scatterlist sg[MAX_SKB_FRAGS + 2];
+
+       /* Name of this receive queue: input.$index */
+       char name[40];
+};
+
 struct virtnet_info {
        struct virtio_device *vdev;
-       struct virtqueue *rvq, *svq, *cvq;
+       struct virtqueue *cvq;
        struct net_device *dev;
-       struct napi_struct napi;
+       struct send_queue *sq;
+       struct receive_queue *rq;
        unsigned int status;
 
-       /* Number of input buffers, and max we've ever had. */
-       unsigned int num, max;
+       /* Max # of queue pairs supported by the device */
+       u16 max_queue_pairs;
+
+       /* # of queue pairs currently used by the driver */
+       u16 curr_queue_pairs;
 
        /* I like... big packets and I cannot lie! */
        bool big_packets;
@@ -67,6 +103,9 @@ struct virtnet_info {
        /* Host will merge rx buffers for big packets (shake it! shake it!) */
        bool mergeable_rx_bufs;
 
+       /* Has control virtqueue */
+       bool has_cvq;
+
        /* enable config space updates */
        bool config_enable;
 
@@ -82,12 +121,8 @@ struct virtnet_info {
        /* Lock for config space updates */
        struct mutex config_lock;
 
-       /* Chain pages by the private ptr. */
-       struct page *pages;
-
-       /* fragments + linear part + virtio header */
-       struct scatterlist rx_sg[MAX_SKB_FRAGS + 2];
-       struct scatterlist tx_sg[MAX_SKB_FRAGS + 2];
+       /* Does the affinity hint is set for virtqueues? */
+       bool affinity_hint_set;
 };
 
 struct skb_vnet_hdr {
@@ -108,6 +143,29 @@ struct padded_vnet_hdr {
        char padding[6];
 };
 
+/* Converting between virtqueue no. and kernel tx/rx queue no.
+ * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
+ */
+static int vq2txq(struct virtqueue *vq)
+{
+       return (virtqueue_get_queue_index(vq) - 1) / 2;
+}
+
+static int txq2vq(int txq)
+{
+       return txq * 2 + 1;
+}
+
+static int vq2rxq(struct virtqueue *vq)
+{
+       return virtqueue_get_queue_index(vq) / 2;
+}
+
+static int rxq2vq(int rxq)
+{
+       return rxq * 2;
+}
+
 static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
 {
        return (struct skb_vnet_hdr *)skb->cb;
@@ -117,22 +175,22 @@ static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb)
  * private is used to chain pages for big packets, put the whole
  * most recent used list in the beginning for reuse
  */
-static void give_pages(struct virtnet_info *vi, struct page *page)
+static void give_pages(struct receive_queue *rq, struct page *page)
 {
        struct page *end;
 
-       /* Find end of list, sew whole thing into vi->pages. */
+       /* Find end of list, sew whole thing into vi->rq.pages. */
        for (end = page; end->private; end = (struct page *)end->private);
-       end->private = (unsigned long)vi->pages;
-       vi->pages = page;
+       end->private = (unsigned long)rq->pages;
+       rq->pages = page;
 }
 
-static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
+static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask)
 {
-       struct page *p = vi->pages;
+       struct page *p = rq->pages;
 
        if (p) {
-               vi->pages = (struct page *)p->private;
+               rq->pages = (struct page *)p->private;
                /* clear private here, it is used to chain pages */
                p->private = 0;
        } else
@@ -140,15 +198,15 @@ static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
        return p;
 }
 
-static void skb_xmit_done(struct virtqueue *svq)
+static void skb_xmit_done(struct virtqueue *vq)
 {
-       struct virtnet_info *vi = svq->vdev->priv;
+       struct virtnet_info *vi = vq->vdev->priv;
 
        /* Suppress further interrupts. */
-       virtqueue_disable_cb(svq);
+       virtqueue_disable_cb(vq);
 
        /* We were probably waiting for more output buffers. */
-       netif_wake_queue(vi->dev);
+       netif_wake_subqueue(vi->dev, vq2txq(vq));
 }
 
 static void set_skb_frag(struct sk_buff *skb, struct page *page,
@@ -167,9 +225,10 @@ static void set_skb_frag(struct sk_buff *skb, struct page *page,
 }
 
 /* Called from bottom half context */
-static struct sk_buff *page_to_skb(struct virtnet_info *vi,
+static struct sk_buff *page_to_skb(struct receive_queue *rq,
                                   struct page *page, unsigned int len)
 {
+       struct virtnet_info *vi = rq->vq->vdev->priv;
        struct sk_buff *skb;
        struct skb_vnet_hdr *hdr;
        unsigned int copy, hdr_len, offset;
@@ -212,8 +271,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
         * the case of a broken device.
         */
        if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) {
-               if (net_ratelimit())
-                       pr_debug("%s: too much data\n", skb->dev->name);
+               net_dbg_ratelimited("%s: too much data\n", skb->dev->name);
                dev_kfree_skb(skb);
                return NULL;
        }
@@ -225,12 +283,12 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi,
        }
 
        if (page)
-               give_pages(vi, page);
+               give_pages(rq, page);
 
        return skb;
 }
 
-static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
+static int receive_mergeable(struct receive_queue *rq, struct sk_buff *skb)
 {
        struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
        struct page *page;
@@ -244,7 +302,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
                        skb->dev->stats.rx_length_errors++;
                        return -EINVAL;
                }
-               page = virtqueue_get_buf(vi->rvq, &len);
+               page = virtqueue_get_buf(rq->vq, &len);
                if (!page) {
                        pr_debug("%s: rx error: %d buffers missing\n",
                                 skb->dev->name, hdr->mhdr.num_buffers);
@@ -257,14 +315,15 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb)
 
                set_skb_frag(skb, page, 0, &len);
 
-               --vi->num;
+               --rq->num;
        }
        return 0;
 }
 
-static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
+static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len)
 {
-       struct virtnet_info *vi = netdev_priv(dev);
+       struct virtnet_info *vi = rq->vq->vdev->priv;
+       struct net_device *dev = vi->dev;
        struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
        struct sk_buff *skb;
        struct page *page;
@@ -274,7 +333,7 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
                pr_debug("%s: short packet %i\n", dev->name, len);
                dev->stats.rx_length_errors++;
                if (vi->mergeable_rx_bufs || vi->big_packets)
-                       give_pages(vi, buf);
+                       give_pages(rq, buf);
                else
                        dev_kfree_skb(buf);
                return;
@@ -286,14 +345,14 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
                skb_trim(skb, len);
        } else {
                page = buf;
-               skb = page_to_skb(vi, page, len);
+               skb = page_to_skb(rq, page, len);
                if (unlikely(!skb)) {
                        dev->stats.rx_dropped++;
-                       give_pages(vi, page);
+                       give_pages(rq, page);
                        return;
                }
                if (vi->mergeable_rx_bufs)
-                       if (receive_mergeable(vi, skb)) {
+                       if (receive_mergeable(rq, skb)) {
                                dev_kfree_skb(skb);
                                return;
                        }
@@ -333,9 +392,8 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
                        skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
                        break;
                default:
-                       if (net_ratelimit())
-                               printk(KERN_WARNING "%s: bad gso type %u.\n",
-                                      dev->name, hdr->hdr.gso_type);
+                       net_warn_ratelimited("%s: bad gso type %u.\n",
+                                            dev->name, hdr->hdr.gso_type);
                        goto frame_err;
                }
 
@@ -344,9 +402,7 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len)
 
                skb_shinfo(skb)->gso_size = hdr->hdr.gso_size;
                if (skb_shinfo(skb)->gso_size == 0) {
-                       if (net_ratelimit())
-                               printk(KERN_WARNING "%s: zero gso size.\n",
-                                      dev->name);
+                       net_warn_ratelimited("%s: zero gso size.\n", dev->name);
                        goto frame_err;
                }
 
@@ -363,8 +419,9 @@ frame_err:
        dev_kfree_skb(skb);
 }
 
-static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_small(struct receive_queue *rq, gfp_t gfp)
 {
+       struct virtnet_info *vi = rq->vq->vdev->priv;
        struct sk_buff *skb;
        struct skb_vnet_hdr *hdr;
        int err;
@@ -376,77 +433,77 @@ static int add_recvbuf_small(struct virtnet_info *vi, gfp_t gfp)
        skb_put(skb, MAX_PACKET_LEN);
 
        hdr = skb_vnet_hdr(skb);
-       sg_set_buf(vi->rx_sg, &hdr->hdr, sizeof hdr->hdr);
+       sg_set_buf(rq->sg, &hdr->hdr, sizeof hdr->hdr);
 
-       skb_to_sgvec(skb, vi->rx_sg + 1, 0, skb->len);
+       skb_to_sgvec(skb, rq->sg + 1, 0, skb->len);
 
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 2, skb, gfp);
+       err = virtqueue_add_buf(rq->vq, rq->sg, 0, 2, skb, gfp);
        if (err < 0)
                dev_kfree_skb(skb);
 
        return err;
 }
 
-static int add_recvbuf_big(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_big(struct receive_queue *rq, gfp_t gfp)
 {
        struct page *first, *list = NULL;
        char *p;
        int i, err, offset;
 
-       /* page in vi->rx_sg[MAX_SKB_FRAGS + 1] is list tail */
+       /* page in rq->sg[MAX_SKB_FRAGS + 1] is list tail */
        for (i = MAX_SKB_FRAGS + 1; i > 1; --i) {
-               first = get_a_page(vi, gfp);
+               first = get_a_page(rq, gfp);
                if (!first) {
                        if (list)
-                               give_pages(vi, list);
+                               give_pages(rq, list);
                        return -ENOMEM;
                }
-               sg_set_buf(&vi->rx_sg[i], page_address(first), PAGE_SIZE);
+               sg_set_buf(&rq->sg[i], page_address(first), PAGE_SIZE);
 
                /* chain new page in list head to match sg */
                first->private = (unsigned long)list;
                list = first;
        }
 
-       first = get_a_page(vi, gfp);
+       first = get_a_page(rq, gfp);
        if (!first) {
-               give_pages(vi, list);
+               give_pages(rq, list);
                return -ENOMEM;
        }
        p = page_address(first);
 
-       /* vi->rx_sg[0], vi->rx_sg[1] share the same page */
-       /* a separated vi->rx_sg[0] for virtio_net_hdr only due to QEMU bug */
-       sg_set_buf(&vi->rx_sg[0], p, sizeof(struct virtio_net_hdr));
+       /* rq->sg[0], rq->sg[1] share the same page */
+       /* a separated rq->sg[0] for virtio_net_hdr only due to QEMU bug */
+       sg_set_buf(&rq->sg[0], p, sizeof(struct virtio_net_hdr));
 
-       /* vi->rx_sg[1] for data packet, from offset */
+       /* rq->sg[1] for data packet, from offset */
        offset = sizeof(struct padded_vnet_hdr);
-       sg_set_buf(&vi->rx_sg[1], p + offset, PAGE_SIZE - offset);
+       sg_set_buf(&rq->sg[1], p + offset, PAGE_SIZE - offset);
 
        /* chain first in list head */
        first->private = (unsigned long)list;
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, MAX_SKB_FRAGS + 2,
+       err = virtqueue_add_buf(rq->vq, rq->sg, 0, MAX_SKB_FRAGS + 2,
                                first, gfp);
        if (err < 0)
-               give_pages(vi, first);
+               give_pages(rq, first);
 
        return err;
 }
 
-static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
+static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp)
 {
        struct page *page;
        int err;
 
-       page = get_a_page(vi, gfp);
+       page = get_a_page(rq, gfp);
        if (!page)
                return -ENOMEM;
 
-       sg_init_one(vi->rx_sg, page_address(page), PAGE_SIZE);
+       sg_init_one(rq->sg, page_address(page), PAGE_SIZE);
 
-       err = virtqueue_add_buf(vi->rvq, vi->rx_sg, 0, 1, page, gfp);
+       err = virtqueue_add_buf(rq->vq, rq->sg, 0, 1, page, gfp);
        if (err < 0)
-               give_pages(vi, page);
+               give_pages(rq, page);
 
        return err;
 }
@@ -458,97 +515,108 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi, gfp_t gfp)
  * before we're receiving packets, or from refill_work which is
  * careful to disable receiving (using napi_disable).
  */
-static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp)
+static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp)
 {
+       struct virtnet_info *vi = rq->vq->vdev->priv;
        int err;
        bool oom;
 
        do {
                if (vi->mergeable_rx_bufs)
-                       err = add_recvbuf_mergeable(vi, gfp);
+                       err = add_recvbuf_mergeable(rq, gfp);
                else if (vi->big_packets)
-                       err = add_recvbuf_big(vi, gfp);
+                       err = add_recvbuf_big(rq, gfp);
                else
-                       err = add_recvbuf_small(vi, gfp);
+                       err = add_recvbuf_small(rq, gfp);
 
                oom = err == -ENOMEM;
                if (err < 0)
                        break;
-               ++vi->num;
+               ++rq->num;
        } while (err > 0);
-       if (unlikely(vi->num > vi->max))
-               vi->max = vi->num;
-       virtqueue_kick(vi->rvq);
+       if (unlikely(rq->num > rq->max))
+               rq->max = rq->num;
+       virtqueue_kick(rq->vq);
        return !oom;
 }
 
 static void skb_recv_done(struct virtqueue *rvq)
 {
        struct virtnet_info *vi = rvq->vdev->priv;
+       struct receive_queue *rq = &vi->rq[vq2rxq(rvq)];
+
        /* Schedule NAPI, Suppress further interrupts if successful. */
-       if (napi_schedule_prep(&vi->napi)) {
+       if (napi_schedule_prep(&rq->napi)) {
                virtqueue_disable_cb(rvq);
-               __napi_schedule(&vi->napi);
+               __napi_schedule(&rq->napi);
        }
 }
 
-static void virtnet_napi_enable(struct virtnet_info *vi)
+static void virtnet_napi_enable(struct receive_queue *rq)
 {
-       napi_enable(&vi->napi);
+       napi_enable(&rq->napi);
 
        /* If all buffers were filled by other side before we napi_enabled, we
         * won't get another interrupt, so process any outstanding packets
         * now.  virtnet_poll wants re-enable the queue, so we disable here.
         * We synchronize against interrupts via NAPI_STATE_SCHED */
-       if (napi_schedule_prep(&vi->napi)) {
-               virtqueue_disable_cb(vi->rvq);
+       if (napi_schedule_prep(&rq->napi)) {
+               virtqueue_disable_cb(rq->vq);
                local_bh_disable();
-               __napi_schedule(&vi->napi);
+               __napi_schedule(&rq->napi);
                local_bh_enable();
        }
 }
 
 static void refill_work(struct work_struct *work)
 {
-       struct virtnet_info *vi;
+       struct virtnet_info *vi =
+               container_of(work, struct virtnet_info, refill.work);
        bool still_empty;
+       int i;
 
-       vi = container_of(work, struct virtnet_info, refill.work);
-       napi_disable(&vi->napi);
-       still_empty = !try_fill_recv(vi, GFP_KERNEL);
-       virtnet_napi_enable(vi);
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               struct receive_queue *rq = &vi->rq[i];
 
-       /* In theory, this can happen: if we don't get any buffers in
-        * we will *never* try to fill again. */
-       if (still_empty)
-               schedule_delayed_work(&vi->refill, HZ/2);
+               napi_disable(&rq->napi);
+               still_empty = !try_fill_recv(rq, GFP_KERNEL);
+               virtnet_napi_enable(rq);
+
+               /* In theory, this can happen: if we don't get any buffers in
+                * we will *never* try to fill again.
+                */
+               if (still_empty)
+                       schedule_delayed_work(&vi->refill, HZ/2);
+       }
 }
 
 static int virtnet_poll(struct napi_struct *napi, int budget)
 {
-       struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi);
+       struct receive_queue *rq =
+               container_of(napi, struct receive_queue, napi);
+       struct virtnet_info *vi = rq->vq->vdev->priv;
        void *buf;
        unsigned int len, received = 0;
 
 again:
        while (received < budget &&
-              (buf = virtqueue_get_buf(vi->rvq, &len)) != NULL) {
-               receive_buf(vi->dev, buf, len);
-               --vi->num;
+              (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
+               receive_buf(rq, buf, len);
+               --rq->num;
                received++;
        }
 
-       if (vi->num < vi->max / 2) {
-               if (!try_fill_recv(vi, GFP_ATOMIC))
+       if (rq->num < rq->max / 2) {
+               if (!try_fill_recv(rq, GFP_ATOMIC))
                        schedule_delayed_work(&vi->refill, 0);
        }
 
        /* Out of packets? */
        if (received < budget) {
                napi_complete(napi);
-               if (unlikely(!virtqueue_enable_cb(vi->rvq)) &&
+               if (unlikely(!virtqueue_enable_cb(rq->vq)) &&
                    napi_schedule_prep(napi)) {
-                       virtqueue_disable_cb(vi->rvq);
+                       virtqueue_disable_cb(rq->vq);
                        __napi_schedule(napi);
                        goto again;
                }
@@ -557,13 +625,29 @@ again:
        return received;
 }
 
-static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
+static int virtnet_open(struct net_device *dev)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+       int i;
+
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               /* Make sure we have some buffers: if oom use wq. */
+               if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+                       schedule_delayed_work(&vi->refill, 0);
+               virtnet_napi_enable(&vi->rq[i]);
+       }
+
+       return 0;
+}
+
+static unsigned int free_old_xmit_skbs(struct send_queue *sq)
 {
        struct sk_buff *skb;
        unsigned int len, tot_sgs = 0;
+       struct virtnet_info *vi = sq->vq->vdev->priv;
        struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 
-       while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) {
+       while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
                pr_debug("Sent skb %p\n", skb);
 
                u64_stats_update_begin(&stats->tx_syncp);
@@ -577,10 +661,11 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
        return tot_sgs;
 }
 
-static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
+static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
 {
        struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb);
        const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
+       struct virtnet_info *vi = sq->vq->vdev->priv;
 
        pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
 
@@ -615,44 +700,47 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
 
        /* Encode metadata header at front. */
        if (vi->mergeable_rx_bufs)
-               sg_set_buf(vi->tx_sg, &hdr->mhdr, sizeof hdr->mhdr);
+               sg_set_buf(sq->sg, &hdr->mhdr, sizeof hdr->mhdr);
        else
-               sg_set_buf(vi->tx_sg, &hdr->hdr, sizeof hdr->hdr);
+               sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr);
 
-       hdr->num_sg = skb_to_sgvec(skb, vi->tx_sg + 1, 0, skb->len) + 1;
-       return virtqueue_add_buf(vi->svq, vi->tx_sg, hdr->num_sg,
+       hdr->num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1;
+       return virtqueue_add_buf(sq->vq, sq->sg, hdr->num_sg,
                                 0, skb, GFP_ATOMIC);
 }
 
 static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
+       int qnum = skb_get_queue_mapping(skb);
+       struct send_queue *sq = &vi->sq[qnum];
        int capacity;
 
        /* Free up any pending old buffers before queueing new ones. */
-       free_old_xmit_skbs(vi);
+       free_old_xmit_skbs(sq);
 
        /* Try to transmit */
-       capacity = xmit_skb(vi, skb);
+       capacity = xmit_skb(sq, skb);
 
        /* This can happen with OOM and indirect buffers. */
        if (unlikely(capacity < 0)) {
                if (likely(capacity == -ENOMEM)) {
                        if (net_ratelimit())
                                dev_warn(&dev->dev,
-                                        "TX queue failure: out of memory\n");
+                                        "TXQ (%d) failure: out of memory\n",
+                                        qnum);
                } else {
                        dev->stats.tx_fifo_errors++;
                        if (net_ratelimit())
                                dev_warn(&dev->dev,
-                                        "Unexpected TX queue failure: %d\n",
-                                        capacity);
+                                        "Unexpected TXQ (%d) failure: %d\n",
+                                        qnum, capacity);
                }
                dev->stats.tx_dropped++;
                kfree_skb(skb);
                return NETDEV_TX_OK;
        }
-       virtqueue_kick(vi->svq);
+       virtqueue_kick(sq->vq);
 
        /* Don't wait up for transmitted skbs to be freed. */
        skb_orphan(skb);
@@ -661,13 +749,13 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
        /* Apparently nice girls don't return TX_BUSY; stop the queue
         * before it gets out of hand.  Naturally, this wastes entries. */
        if (capacity < 2+MAX_SKB_FRAGS) {
-               netif_stop_queue(dev);
-               if (unlikely(!virtqueue_enable_cb_delayed(vi->svq))) {
+               netif_stop_subqueue(dev, qnum);
+               if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
                        /* More just got used, free them then recheck. */
-                       capacity += free_old_xmit_skbs(vi);
+                       capacity += free_old_xmit_skbs(sq);
                        if (capacity >= 2+MAX_SKB_FRAGS) {
-                               netif_start_queue(dev);
-                               virtqueue_disable_cb(vi->svq);
+                               netif_start_subqueue(dev, qnum);
+                               virtqueue_disable_cb(sq->vq);
                        }
                }
        }
@@ -734,23 +822,13 @@ static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev,
 static void virtnet_netpoll(struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
+       int i;
 
-       napi_schedule(&vi->napi);
+       for (i = 0; i < vi->curr_queue_pairs; i++)
+               napi_schedule(&vi->rq[i].napi);
 }
 #endif
 
-static int virtnet_open(struct net_device *dev)
-{
-       struct virtnet_info *vi = netdev_priv(dev);
-
-       /* Make sure we have some buffers: if oom use wq. */
-       if (!try_fill_recv(vi, GFP_KERNEL))
-               schedule_delayed_work(&vi->refill, 0);
-
-       virtnet_napi_enable(vi);
-       return 0;
-}
-
 /*
  * Send command via the control virtqueue and check status.  Commands
  * supported by the hypervisor, as indicated by feature bits, should
@@ -806,13 +884,39 @@ static void virtnet_ack_link_announce(struct virtnet_info *vi)
        rtnl_unlock();
 }
 
+static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs)
+{
+       struct scatterlist sg;
+       struct virtio_net_ctrl_mq s;
+       struct net_device *dev = vi->dev;
+
+       if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ))
+               return 0;
+
+       s.virtqueue_pairs = queue_pairs;
+       sg_init_one(&sg, &s, sizeof(s));
+
+       if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ,
+                                 VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg, 1, 0)){
+               dev_warn(&dev->dev, "Fail to set num of queue pairs to %d\n",
+                        queue_pairs);
+               return -EINVAL;
+       } else
+               vi->curr_queue_pairs = queue_pairs;
+
+       return 0;
+}
+
 static int virtnet_close(struct net_device *dev)
 {
        struct virtnet_info *vi = netdev_priv(dev);
+       int i;
 
        /* Make sure refill_work doesn't re-enable napi! */
        cancel_delayed_work_sync(&vi->refill);
-       napi_disable(&vi->napi);
+
+       for (i = 0; i < vi->max_queue_pairs; i++)
+               napi_disable(&vi->rq[i].napi);
 
        return 0;
 }
@@ -919,16 +1023,43 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
        return 0;
 }
 
+static void virtnet_set_affinity(struct virtnet_info *vi, bool set)
+{
+       int i;
+
+       /* In multiqueue mode, when the number of cpu is equal to the number of
+        * queue pairs, we let the queue pairs to be private to one cpu by
+        * setting the affinity hint to eliminate the contention.
+        */
+       if ((vi->curr_queue_pairs == 1 ||
+            vi->max_queue_pairs != num_online_cpus()) && set) {
+               if (vi->affinity_hint_set)
+                       set = false;
+               else
+                       return;
+       }
+
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               int cpu = set ? i : -1;
+               virtqueue_set_affinity(vi->rq[i].vq, cpu);
+               virtqueue_set_affinity(vi->sq[i].vq, cpu);
+       }
+
+       if (set)
+               vi->affinity_hint_set = true;
+       else
+               vi->affinity_hint_set = false;
+}
+
 static void virtnet_get_ringparam(struct net_device *dev,
                                struct ethtool_ringparam *ring)
 {
        struct virtnet_info *vi = netdev_priv(dev);
 
-       ring->rx_max_pending = virtqueue_get_vring_size(vi->rvq);
-       ring->tx_max_pending = virtqueue_get_vring_size(vi->svq);
+       ring->rx_max_pending = virtqueue_get_vring_size(vi->rq[0].vq);
+       ring->tx_max_pending = virtqueue_get_vring_size(vi->sq[0].vq);
        ring->rx_pending = ring->rx_max_pending;
        ring->tx_pending = ring->tx_max_pending;
-
 }
 
 
@@ -944,10 +1075,53 @@ static void virtnet_get_drvinfo(struct net_device *dev,
 
 }
 
+/* TODO: Eliminate OOO packets during switching */
+static int virtnet_set_channels(struct net_device *dev,
+                               struct ethtool_channels *channels)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+       u16 queue_pairs = channels->combined_count;
+       int err;
+
+       /* We don't support separate rx/tx channels.
+        * We don't allow setting 'other' channels.
+        */
+       if (channels->rx_count || channels->tx_count || channels->other_count)
+               return -EINVAL;
+
+       if (queue_pairs > vi->max_queue_pairs)
+               return -EINVAL;
+
+       err = virtnet_set_queues(vi, queue_pairs);
+       if (!err) {
+               netif_set_real_num_tx_queues(dev, queue_pairs);
+               netif_set_real_num_rx_queues(dev, queue_pairs);
+
+               virtnet_set_affinity(vi, true);
+       }
+
+       return err;
+}
+
+static void virtnet_get_channels(struct net_device *dev,
+                                struct ethtool_channels *channels)
+{
+       struct virtnet_info *vi = netdev_priv(dev);
+
+       channels->combined_count = vi->curr_queue_pairs;
+       channels->max_combined = vi->max_queue_pairs;
+       channels->max_other = 0;
+       channels->rx_count = 0;
+       channels->tx_count = 0;
+       channels->other_count = 0;
+}
+
 static const struct ethtool_ops virtnet_ethtool_ops = {
        .get_drvinfo = virtnet_get_drvinfo,
        .get_link = ethtool_op_get_link,
        .get_ringparam = virtnet_get_ringparam,
+       .set_channels = virtnet_set_channels,
+       .get_channels = virtnet_get_channels,
 };
 
 #define MIN_MTU 68
@@ -961,6 +1135,21 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
+/* To avoid contending a lock hold by a vcpu who would exit to host, select the
+ * txq based on the processor id.
+ * TODO: handle cpu hotplug.
+ */
+static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+       int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
+                 smp_processor_id();
+
+       while (unlikely(txq >= dev->real_num_tx_queues))
+               txq -= dev->real_num_tx_queues;
+
+       return txq;
+}
+
 static const struct net_device_ops virtnet_netdev = {
        .ndo_open            = virtnet_open,
        .ndo_stop            = virtnet_close,
@@ -972,6 +1161,7 @@ static const struct net_device_ops virtnet_netdev = {
        .ndo_get_stats64     = virtnet_stats,
        .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
        .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
+       .ndo_select_queue     = virtnet_select_queue,
 #ifdef CONFIG_NET_POLL_CONTROLLER
        .ndo_poll_controller = virtnet_netpoll,
 #endif
@@ -1007,10 +1197,10 @@ static void virtnet_config_changed_work(struct work_struct *work)
 
        if (vi->status & VIRTIO_NET_S_LINK_UP) {
                netif_carrier_on(vi->dev);
-               netif_wake_queue(vi->dev);
+               netif_tx_wake_all_queues(vi->dev);
        } else {
                netif_carrier_off(vi->dev);
-               netif_stop_queue(vi->dev);
+               netif_tx_stop_all_queues(vi->dev);
        }
 done:
        mutex_unlock(&vi->config_lock);
@@ -1023,41 +1213,203 @@ static void virtnet_config_changed(struct virtio_device *vdev)
        schedule_work(&vi->config_work);
 }
 
-static int init_vqs(struct virtnet_info *vi)
+static void virtnet_free_queues(struct virtnet_info *vi)
 {
-       struct virtqueue *vqs[3];
-       vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done, NULL};
-       const char *names[] = { "input", "output", "control" };
-       int nvqs, err;
+       kfree(vi->rq);
+       kfree(vi->sq);
+}
 
-       /* We expect two virtqueues, receive then send,
-        * and optionally control. */
-       nvqs = virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
+static void free_receive_bufs(struct virtnet_info *vi)
+{
+       int i;
 
-       err = vi->vdev->config->find_vqs(vi->vdev, nvqs, vqs, callbacks, names);
-       if (err)
-               return err;
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               while (vi->rq[i].pages)
+                       __free_pages(get_a_page(&vi->rq[i], GFP_KERNEL), 0);
+       }
+}
 
-       vi->rvq = vqs[0];
-       vi->svq = vqs[1];
+static void free_unused_bufs(struct virtnet_info *vi)
+{
+       void *buf;
+       int i;
 
-       if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
-               vi->cvq = vqs[2];
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               struct virtqueue *vq = vi->sq[i].vq;
+               while ((buf = virtqueue_detach_unused_buf(vq)) != NULL)
+                       dev_kfree_skb(buf);
+       }
 
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               struct virtqueue *vq = vi->rq[i].vq;
+
+               while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
+                       if (vi->mergeable_rx_bufs || vi->big_packets)
+                               give_pages(&vi->rq[i], buf);
+                       else
+                               dev_kfree_skb(buf);
+                       --vi->rq[i].num;
+               }
+               BUG_ON(vi->rq[i].num != 0);
+       }
+}
+
+static void virtnet_del_vqs(struct virtnet_info *vi)
+{
+       struct virtio_device *vdev = vi->vdev;
+
+       virtnet_set_affinity(vi, false);
+
+       vdev->config->del_vqs(vdev);
+
+       virtnet_free_queues(vi);
+}
+
+static int virtnet_find_vqs(struct virtnet_info *vi)
+{
+       vq_callback_t **callbacks;
+       struct virtqueue **vqs;
+       int ret = -ENOMEM;
+       int i, total_vqs;
+       const char **names;
+
+       /* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
+        * possible N-1 RX/TX queue pairs used in multiqueue mode, followed by
+        * possible control vq.
+        */
+       total_vqs = vi->max_queue_pairs * 2 +
+                   virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ);
+
+       /* Allocate space for find_vqs parameters */
+       vqs = kzalloc(total_vqs * sizeof(*vqs), GFP_KERNEL);
+       if (!vqs)
+               goto err_vq;
+       callbacks = kmalloc(total_vqs * sizeof(*callbacks), GFP_KERNEL);
+       if (!callbacks)
+               goto err_callback;
+       names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL);
+       if (!names)
+               goto err_names;
+
+       /* Parameters for control virtqueue, if any */
+       if (vi->has_cvq) {
+               callbacks[total_vqs - 1] = NULL;
+               names[total_vqs - 1] = "control";
+       }
+
+       /* Allocate/initialize parameters for send/receive virtqueues */
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               callbacks[rxq2vq(i)] = skb_recv_done;
+               callbacks[txq2vq(i)] = skb_xmit_done;
+               sprintf(vi->rq[i].name, "input.%d", i);
+               sprintf(vi->sq[i].name, "output.%d", i);
+               names[rxq2vq(i)] = vi->rq[i].name;
+               names[txq2vq(i)] = vi->sq[i].name;
+       }
+
+       ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks,
+                                        names);
+       if (ret)
+               goto err_find;
+
+       if (vi->has_cvq) {
+               vi->cvq = vqs[total_vqs - 1];
                if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
                        vi->dev->features |= NETIF_F_HW_VLAN_FILTER;
        }
+
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               vi->rq[i].vq = vqs[rxq2vq(i)];
+               vi->sq[i].vq = vqs[txq2vq(i)];
+       }
+
+       kfree(names);
+       kfree(callbacks);
+       kfree(vqs);
+
+       return 0;
+
+err_find:
+       kfree(names);
+err_names:
+       kfree(callbacks);
+err_callback:
+       kfree(vqs);
+err_vq:
+       return ret;
+}
+
+static int virtnet_alloc_queues(struct virtnet_info *vi)
+{
+       int i;
+
+       vi->sq = kzalloc(sizeof(*vi->sq) * vi->max_queue_pairs, GFP_KERNEL);
+       if (!vi->sq)
+               goto err_sq;
+       vi->rq = kzalloc(sizeof(*vi->rq) * vi->max_queue_pairs, GFP_KERNEL);
+       if (!vi->rq)
+               goto err_rq;
+
+       INIT_DELAYED_WORK(&vi->refill, refill_work);
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               vi->rq[i].pages = NULL;
+               netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll,
+                              napi_weight);
+
+               sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg));
+               sg_init_table(vi->sq[i].sg, ARRAY_SIZE(vi->sq[i].sg));
+       }
+
        return 0;
+
+err_rq:
+       kfree(vi->sq);
+err_sq:
+       return -ENOMEM;
+}
+
+static int init_vqs(struct virtnet_info *vi)
+{
+       int ret;
+
+       /* Allocate send & receive queues */
+       ret = virtnet_alloc_queues(vi);
+       if (ret)
+               goto err;
+
+       ret = virtnet_find_vqs(vi);
+       if (ret)
+               goto err_free;
+
+       virtnet_set_affinity(vi, true);
+       return 0;
+
+err_free:
+       virtnet_free_queues(vi);
+err:
+       return ret;
 }
 
 static int virtnet_probe(struct virtio_device *vdev)
 {
-       int err;
+       int i, err;
        struct net_device *dev;
        struct virtnet_info *vi;
+       u16 max_queue_pairs;
+
+       /* Find if host supports multiqueue virtio_net device */
+       err = virtio_config_val(vdev, VIRTIO_NET_F_MQ,
+                               offsetof(struct virtio_net_config,
+                               max_virtqueue_pairs), &max_queue_pairs);
+
+       /* We need at least 2 queue's */
+       if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN ||
+           max_queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX ||
+           !virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ))
+               max_queue_pairs = 1;
 
        /* Allocate ourselves a network device with room for our info */
-       dev = alloc_etherdev(sizeof(struct virtnet_info));
+       dev = alloc_etherdev_mq(sizeof(struct virtnet_info), max_queue_pairs);
        if (!dev)
                return -ENOMEM;
 
@@ -1103,22 +1455,17 @@ static int virtnet_probe(struct virtio_device *vdev)
 
        /* Set up our device-specific information */
        vi = netdev_priv(dev);
-       netif_napi_add(dev, &vi->napi, virtnet_poll, napi_weight);
        vi->dev = dev;
        vi->vdev = vdev;
        vdev->priv = vi;
-       vi->pages = NULL;
        vi->stats = alloc_percpu(struct virtnet_stats);
        err = -ENOMEM;
        if (vi->stats == NULL)
                goto free;
 
-       INIT_DELAYED_WORK(&vi->refill, refill_work);
        mutex_init(&vi->config_lock);
        vi->config_enable = true;
        INIT_WORK(&vi->config_work, virtnet_config_changed_work);
-       sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
-       sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
 
        /* If we can receive ANY GSO packets, we must allocate large ones. */
        if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
@@ -1129,10 +1476,21 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
                vi->mergeable_rx_bufs = true;
 
+       if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ))
+               vi->has_cvq = true;
+
+       /* Use single tx/rx queue pair as default */
+       vi->curr_queue_pairs = 1;
+       vi->max_queue_pairs = max_queue_pairs;
+
+       /* Allocate/initialize the rx/tx queues, and invoke find_vqs */
        err = init_vqs(vi);
        if (err)
                goto free_stats;
 
+       netif_set_real_num_tx_queues(dev, 1);
+       netif_set_real_num_rx_queues(dev, 1);
+
        err = register_netdev(dev);
        if (err) {
                pr_debug("virtio_net: registering device failed\n");
@@ -1140,12 +1498,15 @@ static int virtnet_probe(struct virtio_device *vdev)
        }
 
        /* Last of all, set up some receive buffers. */
-       try_fill_recv(vi, GFP_KERNEL);
-
-       /* If we didn't even get one input buffer, we're useless. */
-       if (vi->num == 0) {
-               err = -ENOMEM;
-               goto unregister;
+       for (i = 0; i < vi->max_queue_pairs; i++) {
+               try_fill_recv(&vi->rq[i], GFP_KERNEL);
+
+               /* If we didn't even get one input buffer, we're useless. */
+               if (vi->rq[i].num == 0) {
+                       free_unused_bufs(vi);
+                       err = -ENOMEM;
+                       goto free_recv_bufs;
+               }
        }
 
        /* Assume link up if device can't report link status,
@@ -1158,13 +1519,17 @@ static int virtnet_probe(struct virtio_device *vdev)
                netif_carrier_on(dev);
        }
 
-       pr_debug("virtnet: registered device %s\n", dev->name);
+       pr_debug("virtnet: registered device %s with %d RX and TX vq's\n",
+                dev->name, max_queue_pairs);
+
        return 0;
 
-unregister:
+free_recv_bufs:
+       free_receive_bufs(vi);
        unregister_netdev(dev);
 free_vqs:
-       vdev->config->del_vqs(vdev);
+       cancel_delayed_work_sync(&vi->refill);
+       virtnet_del_vqs(vi);
 free_stats:
        free_percpu(vi->stats);
 free:
@@ -1172,28 +1537,6 @@ free:
        return err;
 }
 
-static void free_unused_bufs(struct virtnet_info *vi)
-{
-       void *buf;
-       while (1) {
-               buf = virtqueue_detach_unused_buf(vi->svq);
-               if (!buf)
-                       break;
-               dev_kfree_skb(buf);
-       }
-       while (1) {
-               buf = virtqueue_detach_unused_buf(vi->rvq);
-               if (!buf)
-                       break;
-               if (vi->mergeable_rx_bufs || vi->big_packets)
-                       give_pages(vi, buf);
-               else
-                       dev_kfree_skb(buf);
-               --vi->num;
-       }
-       BUG_ON(vi->num != 0);
-}
-
 static void remove_vq_common(struct virtnet_info *vi)
 {
        vi->vdev->config->reset(vi->vdev);
@@ -1201,13 +1544,12 @@ static void remove_vq_common(struct virtnet_info *vi)
        /* Free unused buffers in both send and recv, if any. */
        free_unused_bufs(vi);
 
-       vi->vdev->config->del_vqs(vi->vdev);
+       free_receive_bufs(vi);
 
-       while (vi->pages)
-               __free_pages(get_a_page(vi, GFP_KERNEL), 0);
+       virtnet_del_vqs(vi);
 }
 
-static void __devexit virtnet_remove(struct virtio_device *vdev)
+static void virtnet_remove(struct virtio_device *vdev)
 {
        struct virtnet_info *vi = vdev->priv;
 
@@ -1230,6 +1572,7 @@ static void __devexit virtnet_remove(struct virtio_device *vdev)
 static int virtnet_freeze(struct virtio_device *vdev)
 {
        struct virtnet_info *vi = vdev->priv;
+       int i;
 
        /* Prevent config work handler from accessing the device */
        mutex_lock(&vi->config_lock);
@@ -1240,7 +1583,10 @@ static int virtnet_freeze(struct virtio_device *vdev)
        cancel_delayed_work_sync(&vi->refill);
 
        if (netif_running(vi->dev))
-               napi_disable(&vi->napi);
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       napi_disable(&vi->rq[i].napi);
+                       netif_napi_del(&vi->rq[i].napi);
+               }
 
        remove_vq_common(vi);
 
@@ -1252,24 +1598,28 @@ static int virtnet_freeze(struct virtio_device *vdev)
 static int virtnet_restore(struct virtio_device *vdev)
 {
        struct virtnet_info *vi = vdev->priv;
-       int err;
+       int err, i;
 
        err = init_vqs(vi);
        if (err)
                return err;
 
        if (netif_running(vi->dev))
-               virtnet_napi_enable(vi);
+               for (i = 0; i < vi->max_queue_pairs; i++)
+                       virtnet_napi_enable(&vi->rq[i]);
 
        netif_device_attach(vi->dev);
 
-       if (!try_fill_recv(vi, GFP_KERNEL))
-               schedule_delayed_work(&vi->refill, 0);
+       for (i = 0; i < vi->max_queue_pairs; i++)
+               if (!try_fill_recv(&vi->rq[i], GFP_KERNEL))
+                       schedule_delayed_work(&vi->refill, 0);
 
        mutex_lock(&vi->config_lock);
        vi->config_enable = true;
        mutex_unlock(&vi->config_lock);
 
+       virtnet_set_queues(vi, vi->curr_queue_pairs);
+
        return 0;
 }
 #endif
@@ -1287,7 +1637,7 @@ static unsigned int features[] = {
        VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
        VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
        VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
-       VIRTIO_NET_F_GUEST_ANNOUNCE,
+       VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,
 };
 
 static struct virtio_driver virtio_net_driver = {
@@ -1297,7 +1647,7 @@ static struct virtio_driver virtio_net_driver = {
        .driver.owner = THIS_MODULE,
        .id_table =     id_table,
        .probe =        virtnet_probe,
-       .remove =       __devexit_p(virtnet_remove),
+       .remove =       virtnet_remove,
        .config_changed = virtnet_config_changed,
 #ifdef CONFIG_PM
        .freeze =       virtnet_freeze,
index ce9d4f2c9776e08d1b543f18de8cb7100fe43a86..dc8913c6238c965b0905ef7ad6784bf669f06388 100644 (file)
@@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
 
        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+               u32 buf_size;
 
-               tbi = tq->buf_info + tq->tx_ring.next2fill;
-               tbi->map_type = VMXNET3_MAP_PAGE;
-               tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
-                                                0, skb_frag_size(frag),
-                                                DMA_TO_DEVICE);
+               buf_offset = 0;
+               len = skb_frag_size(frag);
+               while (len) {
+                       tbi = tq->buf_info + tq->tx_ring.next2fill;
+                       if (len < VMXNET3_MAX_TX_BUF_SIZE) {
+                               buf_size = len;
+                               dw2 |= len;
+                       } else {
+                               buf_size = VMXNET3_MAX_TX_BUF_SIZE;
+                               /* spec says that for TxDesc.len, 0 == 2^14 */
+                       }
+                       tbi->map_type = VMXNET3_MAP_PAGE;
+                       tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag,
+                                                        buf_offset, buf_size,
+                                                        DMA_TO_DEVICE);
 
-               tbi->len = skb_frag_size(frag);
+                       tbi->len = buf_size;
 
-               gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
-               BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
+                       gdesc = tq->tx_ring.base + tq->tx_ring.next2fill;
+                       BUG_ON(gdesc->txd.gen == tq->tx_ring.gen);
 
-               gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
-               gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag));
-               gdesc->dword[3] = 0;
+                       gdesc->txd.addr = cpu_to_le64(tbi->dma_addr);
+                       gdesc->dword[2] = cpu_to_le32(dw2);
+                       gdesc->dword[3] = 0;
 
-               dev_dbg(&adapter->netdev->dev,
-                       "txd[%u]: 0x%llu %u %u\n",
-                       tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
-                       le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
-               vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
-               dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+                       dev_dbg(&adapter->netdev->dev,
+                               "txd[%u]: 0x%llu %u %u\n",
+                               tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr),
+                               le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]);
+                       vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
+                       dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT;
+
+                       len -= buf_size;
+                       buf_offset += buf_size;
+               }
        }
 
        ctx->eop_txd = gdesc;
@@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,
        }
 }
 
+static int txd_estimate(const struct sk_buff *skb)
+{
+       int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1;
+       int i;
+
+       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+               const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i];
+
+               count += VMXNET3_TXD_NEEDED(skb_frag_size(frag));
+       }
+       return count;
+}
 
 /*
  * Transmits a pkt thru a given tq
@@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
        union Vmxnet3_GenericDesc tempTxDesc;
 #endif
 
-       /* conservatively estimate # of descriptors to use */
-       count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) +
-               skb_shinfo(skb)->nr_frags + 1;
+       count = txd_estimate(skb);
 
        ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP));
 
@@ -1069,10 +1094,10 @@ vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
-               BUG_ON(skb->queue_mapping > adapter->num_tx_queues);
-               return vmxnet3_tq_xmit(skb,
-                                      &adapter->tx_queue[skb->queue_mapping],
-                                      adapter, netdev);
+       BUG_ON(skb->queue_mapping > adapter->num_tx_queues);
+       return vmxnet3_tq_xmit(skb,
+                              &adapter->tx_queue[skb->queue_mapping],
+                              adapter, netdev);
 }
 
 
@@ -1218,8 +1243,8 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
                        skb_reserve(new_skb, NET_IP_ALIGN);
                        rbi->skb = new_skb;
                        rbi->dma_addr = pci_map_single(adapter->pdev,
-                                       rbi->skb->data, rbi->len,
-                                       PCI_DMA_FROMDEVICE);
+                                                      rbi->skb->data, rbi->len,
+                                                      PCI_DMA_FROMDEVICE);
                        rxd->addr = cpu_to_le64(rbi->dma_addr);
                        rxd->len = rbi->len;
 
@@ -1306,14 +1331,14 @@ rcd_done:
                /* if needed, update the register */
                if (unlikely(rq->shared->updateRxProd)) {
                        VMXNET3_WRITE_BAR0_REG(adapter,
-                               rxprod_reg[ring_idx] + rq->qid * 8,
-                               ring->next2fill);
+                                              rxprod_reg[ring_idx] + rq->qid * 8,
+                                              ring->next2fill);
                        rq->uncommitted[ring_idx] = 0;
                }
 
                vmxnet3_comp_ring_adv_next2proc(&rq->comp_ring);
                vmxnet3_getRxComp(rcd,
-                    &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
+                                 &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp);
        }
 
        return num_rxd;
@@ -1897,7 +1922,7 @@ vmxnet3_free_irqs(struct vmxnet3_adapter *adapter)
                free_irq(adapter->pdev->irq, adapter->netdev);
                break;
        default:
-               BUG_ON(true);
+               BUG();
        }
 }
 
@@ -2860,7 +2885,7 @@ vmxnet3_reset_work(struct work_struct *data)
 }
 
 
-static int __devinit
+static int
 vmxnet3_probe_device(struct pci_dev *pdev,
                     const struct pci_device_id *id)
 {
@@ -2924,11 +2949,11 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
        spin_lock_init(&adapter->cmd_lock);
        adapter->shared = pci_alloc_consistent(adapter->pdev,
-                         sizeof(struct Vmxnet3_DriverShared),
-                         &adapter->shared_pa);
+                                              sizeof(struct Vmxnet3_DriverShared),
+                                              &adapter->shared_pa);
        if (!adapter->shared) {
                printk(KERN_ERR "Failed to allocate memory for %s\n",
-                       pci_name(pdev));
+                      pci_name(pdev));
                err = -ENOMEM;
                goto err_alloc_shared;
        }
@@ -2939,16 +2964,16 @@ vmxnet3_probe_device(struct pci_dev *pdev,
        size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues;
        size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues;
        adapter->tqd_start = pci_alloc_consistent(adapter->pdev, size,
-                            &adapter->queue_desc_pa);
+                                                 &adapter->queue_desc_pa);
 
        if (!adapter->tqd_start) {
                printk(KERN_ERR "Failed to allocate memory for %s\n",
-                       pci_name(pdev));
+                      pci_name(pdev));
                err = -ENOMEM;
                goto err_alloc_queue_desc;
        }
        adapter->rqd_start = (struct Vmxnet3_RxQueueDesc *)(adapter->tqd_start +
-                                                       adapter->num_tx_queues);
+                                                           adapter->num_tx_queues);
 
        adapter->pm_conf = kmalloc(sizeof(struct Vmxnet3_PMConf), GFP_KERNEL);
        if (adapter->pm_conf == NULL) {
@@ -2994,7 +3019,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
        adapter->dev_number = atomic_read(&devices_found);
 
-        adapter->share_intr = irq_share_mode;
+       adapter->share_intr = irq_share_mode;
        if (adapter->share_intr == VMXNET3_INTR_BUDDYSHARE &&
            adapter->num_tx_queues != adapter->num_rx_queues)
                adapter->share_intr = VMXNET3_INTR_DONTSHARE;
@@ -3040,7 +3065,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
        if (err) {
                printk(KERN_ERR "Failed to register adapter %s\n",
-                       pci_name(pdev));
+                      pci_name(pdev));
                goto err_register;
        }
 
@@ -3071,7 +3096,7 @@ err_alloc_shared:
 }
 
 
-static void __devexit
+static void
 vmxnet3_remove_device(struct pci_dev *pdev)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
@@ -3277,7 +3302,7 @@ static struct pci_driver vmxnet3_driver = {
        .name           = vmxnet3_driver_name,
        .id_table       = vmxnet3_pciid_table,
        .probe          = vmxnet3_probe_device,
-       .remove         = __devexit_p(vmxnet3_remove_device),
+       .remove         = vmxnet3_remove_device,
 #ifdef CONFIG_PM
        .driver.pm      = &vmxnet3_pm_ops,
 #endif
index 607976c001626a75afbf590411bf6ec1bbff26c0..3b3fdf648ea741267800a2b49eee87d835d2370a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * VXLAN: Virtual eXtensiable Local Area Network
+ * VXLAN: Virtual eXtensible Local Area Network
  *
  * Copyright (c) 2012 Vyatta Inc.
  *
@@ -29,6 +29,8 @@
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
 #include <linux/hash.h>
+#include <net/arp.h>
+#include <net/ndisc.h>
 #include <net/ip.h>
 #include <net/icmp.h>
 #include <net/udp.h>
@@ -50,8 +52,8 @@
 
 #define VXLAN_N_VID    (1u << 24)
 #define VXLAN_VID_MASK (VXLAN_N_VID - 1)
-/* VLAN + IP header + UDP + VXLAN */
-#define VXLAN_HEADROOM (4 + 20 + 8 + 8)
+/* IP header + UDP + VXLAN + Ethernet header */
+#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
 
 #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
 
@@ -110,18 +112,23 @@ struct vxlan_dev {
        __u16             port_max;
        __u8              tos;          /* TOS override */
        __u8              ttl;
-       bool              learn;
+       u32               flags;        /* VXLAN_F_* below */
 
        unsigned long     age_interval;
        struct timer_list age_timer;
        spinlock_t        hash_lock;
        unsigned int      addrcnt;
        unsigned int      addrmax;
-       unsigned int      addrexceeded;
 
        struct hlist_head fdb_head[FDB_HASH_SIZE];
 };
 
+#define VXLAN_F_LEARN  0x01
+#define VXLAN_F_PROXY  0x02
+#define VXLAN_F_RSC    0x04
+#define VXLAN_F_L2MISS 0x08
+#define VXLAN_F_L3MISS 0x10
+
 /* salt for hash table */
 static u32 vxlan_salt __read_mostly;
 
@@ -155,6 +162,7 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
        struct nda_cacheinfo ci;
        struct nlmsghdr *nlh;
        struct ndmsg *ndm;
+       bool send_ip, send_eth;
 
        nlh = nlmsg_put(skb, portid, seq, type, sizeof(*ndm), flags);
        if (nlh == NULL)
@@ -162,16 +170,24 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
 
        ndm = nlmsg_data(nlh);
        memset(ndm, 0, sizeof(*ndm));
-       ndm->ndm_family = AF_BRIDGE;
+
+       send_eth = send_ip = true;
+
+       if (type == RTM_GETNEIGH) {
+               ndm->ndm_family = AF_INET;
+               send_ip = fdb->remote_ip != 0;
+               send_eth = !is_zero_ether_addr(fdb->eth_addr);
+       } else
+               ndm->ndm_family = AF_BRIDGE;
        ndm->ndm_state = fdb->state;
        ndm->ndm_ifindex = vxlan->dev->ifindex;
        ndm->ndm_flags = NTF_SELF;
        ndm->ndm_type = NDA_DST;
 
-       if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
+       if (send_eth && nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->eth_addr))
                goto nla_put_failure;
 
-       if (nla_put_be32(skb, NDA_DST, fdb->remote_ip))
+       if (send_ip && nla_put_be32(skb, NDA_DST, fdb->remote_ip))
                goto nla_put_failure;
 
        ci.ndm_used      = jiffies_to_clock_t(now - fdb->used);
@@ -223,6 +239,29 @@ errout:
                rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
 }
 
+static void vxlan_ip_miss(struct net_device *dev, __be32 ipa)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct vxlan_fdb f;
+
+       memset(&f, 0, sizeof f);
+       f.state = NUD_STALE;
+       f.remote_ip = ipa; /* goes to NDA_DST */
+
+       vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
+}
+
+static void vxlan_fdb_miss(struct vxlan_dev *vxlan, const u8 eth_addr[ETH_ALEN])
+{
+       struct vxlan_fdb        f;
+
+       memset(&f, 0, sizeof f);
+       f.state = NUD_STALE;
+       memcpy(f.eth_addr, eth_addr, ETH_ALEN);
+
+       vxlan_fdb_notify(vxlan, &f, RTM_GETNEIGH);
+}
+
 /* Hash Ethernet address */
 static u32 eth_hash(const unsigned char *addr)
 {
@@ -552,6 +591,8 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                goto drop;
        }
 
+       skb_reset_mac_header(skb);
+
        /* Re-examine inner Ethernet packet */
        oip = ip_hdr(skb);
        skb->protocol = eth_type_trans(skb, vxlan->dev);
@@ -561,12 +602,22 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                               vxlan->dev->dev_addr) == 0)
                goto drop;
 
-       if (vxlan->learn)
+       if (vxlan->flags & VXLAN_F_LEARN)
                vxlan_snoop(skb->dev, oip->saddr, eth_hdr(skb)->h_source);
 
        __skb_tunnel_rx(skb, vxlan->dev);
        skb_reset_network_header(skb);
-       skb->ip_summed = CHECKSUM_NONE;
+
+       /* If the NIC driver gave us an encapsulated packet with
+        * CHECKSUM_UNNECESSARY and Rx checksum feature is enabled,
+        * leave the CHECKSUM_UNNECESSARY, the device checksummed it
+        * for us. Otherwise force the upper layers to verify it.
+        */
+       if (skb->ip_summed != CHECKSUM_UNNECESSARY || !skb->encapsulation ||
+           !(vxlan->dev->features & NETIF_F_RXCSUM))
+               skb->ip_summed = CHECKSUM_NONE;
+
+       skb->encapsulation = 0;
 
        err = IP_ECN_decapsulate(oip, skb);
        if (unlikely(err)) {
@@ -600,6 +651,117 @@ drop:
        return 0;
 }
 
+static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct arphdr *parp;
+       u8 *arpptr, *sha;
+       __be32 sip, tip;
+       struct neighbour *n;
+
+       if (dev->flags & IFF_NOARP)
+               goto out;
+
+       if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
+               dev->stats.tx_dropped++;
+               goto out;
+       }
+       parp = arp_hdr(skb);
+
+       if ((parp->ar_hrd != htons(ARPHRD_ETHER) &&
+            parp->ar_hrd != htons(ARPHRD_IEEE802)) ||
+           parp->ar_pro != htons(ETH_P_IP) ||
+           parp->ar_op != htons(ARPOP_REQUEST) ||
+           parp->ar_hln != dev->addr_len ||
+           parp->ar_pln != 4)
+               goto out;
+       arpptr = (u8 *)parp + sizeof(struct arphdr);
+       sha = arpptr;
+       arpptr += dev->addr_len;        /* sha */
+       memcpy(&sip, arpptr, sizeof(sip));
+       arpptr += sizeof(sip);
+       arpptr += dev->addr_len;        /* tha */
+       memcpy(&tip, arpptr, sizeof(tip));
+
+       if (ipv4_is_loopback(tip) ||
+           ipv4_is_multicast(tip))
+               goto out;
+
+       n = neigh_lookup(&arp_tbl, &tip, dev);
+
+       if (n) {
+               struct vxlan_dev *vxlan = netdev_priv(dev);
+               struct vxlan_fdb *f;
+               struct sk_buff  *reply;
+
+               if (!(n->nud_state & NUD_CONNECTED)) {
+                       neigh_release(n);
+                       goto out;
+               }
+
+               f = vxlan_find_mac(vxlan, n->ha);
+               if (f && f->remote_ip == 0) {
+                       /* bridge-local neighbor */
+                       neigh_release(n);
+                       goto out;
+               }
+
+               reply = arp_create(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
+                               n->ha, sha);
+
+               neigh_release(n);
+
+               skb_reset_mac_header(reply);
+               __skb_pull(reply, skb_network_offset(reply));
+               reply->ip_summed = CHECKSUM_UNNECESSARY;
+               reply->pkt_type = PACKET_HOST;
+
+               if (netif_rx_ni(reply) == NET_RX_DROP)
+                       dev->stats.rx_dropped++;
+       } else if (vxlan->flags & VXLAN_F_L3MISS)
+               vxlan_ip_miss(dev, tip);
+out:
+       consume_skb(skb);
+       return NETDEV_TX_OK;
+}
+
+static bool route_shortcircuit(struct net_device *dev, struct sk_buff *skb)
+{
+       struct vxlan_dev *vxlan = netdev_priv(dev);
+       struct neighbour *n;
+       struct iphdr *pip;
+
+       if (is_multicast_ether_addr(eth_hdr(skb)->h_dest))
+               return false;
+
+       n = NULL;
+       switch (ntohs(eth_hdr(skb)->h_proto)) {
+       case ETH_P_IP:
+               if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+                       return false;
+               pip = ip_hdr(skb);
+               n = neigh_lookup(&arp_tbl, &pip->daddr, dev);
+               break;
+       default:
+               return false;
+       }
+
+       if (n) {
+               bool diff;
+
+               diff = compare_ether_addr(eth_hdr(skb)->h_dest, n->ha) != 0;
+               if (diff) {
+                       memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
+                               dev->addr_len);
+                       memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len);
+               }
+               neigh_release(n);
+               return diff;
+       } else if (vxlan->flags & VXLAN_F_L3MISS)
+               vxlan_ip_miss(dev, pip->daddr);
+       return false;
+}
+
 /* Extract dsfield from inner protocol */
 static inline u8 vxlan_get_dsfield(const struct iphdr *iph,
                                   const struct sk_buff *skb)
@@ -622,22 +784,6 @@ static inline u8 vxlan_ecn_encap(u8 tos,
        return INET_ECN_encapsulate(tos, inner);
 }
 
-static __be32 vxlan_find_dst(struct vxlan_dev *vxlan, struct sk_buff *skb)
-{
-       const struct ethhdr *eth = (struct ethhdr *) skb->data;
-       const struct vxlan_fdb *f;
-
-       if (is_multicast_ether_addr(eth->h_dest))
-               return vxlan->gaddr;
-
-       f = vxlan_find_mac(vxlan, eth->h_dest);
-       if (f)
-               return f->remote_ip;
-       else
-               return vxlan->gaddr;
-
-}
-
 static void vxlan_sock_free(struct sk_buff *skb)
 {
        sock_put(skb->sk);
@@ -684,6 +830,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct rtable *rt;
        const struct iphdr *old_iph;
+       struct ethhdr *eth;
        struct iphdr *iph;
        struct vxlanhdr *vxh;
        struct udphdr *uh;
@@ -694,10 +841,55 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        __be16 df = 0;
        __u8 tos, ttl;
        int err;
+       bool did_rsc = false;
+       const struct vxlan_fdb *f;
+
+       skb_reset_mac_header(skb);
+       eth = eth_hdr(skb);
+
+       if ((vxlan->flags & VXLAN_F_PROXY) && ntohs(eth->h_proto) == ETH_P_ARP)
+               return arp_reduce(dev, skb);
+       else if ((vxlan->flags&VXLAN_F_RSC) && ntohs(eth->h_proto) == ETH_P_IP)
+               did_rsc = route_shortcircuit(dev, skb);
 
-       dst = vxlan_find_dst(vxlan, skb);
-       if (!dst)
+       f = vxlan_find_mac(vxlan, eth->h_dest);
+       if (f == NULL) {
+               did_rsc = false;
+               dst = vxlan->gaddr;
+               if (!dst && (vxlan->flags & VXLAN_F_L2MISS) &&
+                   !is_multicast_ether_addr(eth->h_dest))
+                       vxlan_fdb_miss(vxlan, eth->h_dest);
+       } else
+               dst = f->remote_ip;
+
+       if (!dst) {
+               if (did_rsc) {
+                       __skb_pull(skb, skb_network_offset(skb));
+                       skb->ip_summed = CHECKSUM_NONE;
+                       skb->pkt_type = PACKET_HOST;
+
+                       /* short-circuited back to local bridge */
+                       if (netif_rx(skb) == NET_RX_SUCCESS) {
+                               struct vxlan_stats *stats =
+                                               this_cpu_ptr(vxlan->stats);
+
+                               u64_stats_update_begin(&stats->syncp);
+                               stats->tx_packets++;
+                               stats->tx_bytes += pkt_len;
+                               u64_stats_update_end(&stats->syncp);
+                       } else {
+                               dev->stats.tx_errors++;
+                               dev->stats.tx_aborted_errors++;
+                       }
+                       return NETDEV_TX_OK;
+               }
                goto drop;
+       }
+
+       if (!skb->encapsulation) {
+               skb_reset_inner_headers(skb);
+               skb->encapsulation = 1;
+       }
 
        /* Need space for new headers (invalidates iph ptr) */
        if (skb_cow_head(skb, VXLAN_HEADROOM))
@@ -769,8 +961,9 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
 
        vxlan_set_owner(dev, skb);
 
-       /* See __IPTUNNEL_XMIT */
-       skb->ip_summed = CHECKSUM_NONE;
+       /* See iptunnel_xmit() */
+       if (skb->ip_summed != CHECKSUM_PARTIAL)
+               skb->ip_summed = CHECKSUM_NONE;
        ip_select_ident(iph, &rt->dst, NULL);
 
        err = ip_local_out(skb);
@@ -816,7 +1009,7 @@ static void vxlan_cleanup(unsigned long arg)
                                = container_of(p, struct vxlan_fdb, hlist);
                        unsigned long timeout;
 
-                       if (f->state == NUD_PERMANENT)
+                       if (f->state & NUD_PERMANENT)
                                continue;
 
                        timeout = f->used + vxlan->age_interval * HZ;
@@ -991,6 +1184,10 @@ static void vxlan_setup(struct net_device *dev)
        dev->tx_queue_len = 0;
        dev->features   |= NETIF_F_LLTX;
        dev->features   |= NETIF_F_NETNS_LOCAL;
+       dev->features   |= NETIF_F_SG | NETIF_F_HW_CSUM;
+       dev->features   |= NETIF_F_RXCSUM;
+
+       dev->hw_features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
        dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
 
        spin_lock_init(&vxlan->hash_lock);
@@ -1020,6 +1217,10 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
        [IFLA_VXLAN_AGEING]     = { .type = NLA_U32 },
        [IFLA_VXLAN_LIMIT]      = { .type = NLA_U32 },
        [IFLA_VXLAN_PORT_RANGE] = { .len  = sizeof(struct ifla_vxlan_port_range) },
+       [IFLA_VXLAN_PROXY]      = { .type = NLA_U8 },
+       [IFLA_VXLAN_RSC]        = { .type = NLA_U8 },
+       [IFLA_VXLAN_L2MISS]     = { .type = NLA_U8 },
+       [IFLA_VXLAN_L3MISS]     = { .type = NLA_U8 },
 };
 
 static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -1102,19 +1303,38 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 
                if (!tb[IFLA_MTU])
                        dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
+
+               /* update header length based on lower device */
+               dev->hard_header_len = lowerdev->hard_header_len +
+                                      VXLAN_HEADROOM;
        }
 
        if (data[IFLA_VXLAN_TOS])
                vxlan->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);
 
+       if (data[IFLA_VXLAN_TTL])
+               vxlan->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
+
        if (!data[IFLA_VXLAN_LEARNING] || nla_get_u8(data[IFLA_VXLAN_LEARNING]))
-               vxlan->learn = true;
+               vxlan->flags |= VXLAN_F_LEARN;
 
        if (data[IFLA_VXLAN_AGEING])
                vxlan->age_interval = nla_get_u32(data[IFLA_VXLAN_AGEING]);
        else
                vxlan->age_interval = FDB_AGE_DEFAULT;
 
+       if (data[IFLA_VXLAN_PROXY] && nla_get_u8(data[IFLA_VXLAN_PROXY]))
+               vxlan->flags |= VXLAN_F_PROXY;
+
+       if (data[IFLA_VXLAN_RSC] && nla_get_u8(data[IFLA_VXLAN_RSC]))
+               vxlan->flags |= VXLAN_F_RSC;
+
+       if (data[IFLA_VXLAN_L2MISS] && nla_get_u8(data[IFLA_VXLAN_L2MISS]))
+               vxlan->flags |= VXLAN_F_L2MISS;
+
+       if (data[IFLA_VXLAN_L3MISS] && nla_get_u8(data[IFLA_VXLAN_L3MISS]))
+               vxlan->flags |= VXLAN_F_L3MISS;
+
        if (data[IFLA_VXLAN_LIMIT])
                vxlan->addrmax = nla_get_u32(data[IFLA_VXLAN_LIMIT]);
 
@@ -1151,6 +1371,10 @@ static size_t vxlan_get_size(const struct net_device *dev)
                nla_total_size(sizeof(__u8)) +  /* IFLA_VXLAN_TTL */
                nla_total_size(sizeof(__u8)) +  /* IFLA_VXLAN_TOS */
                nla_total_size(sizeof(__u8)) +  /* IFLA_VXLAN_LEARNING */
+               nla_total_size(sizeof(__u8)) +  /* IFLA_VXLAN_PROXY */
+               nla_total_size(sizeof(__u8)) +  /* IFLA_VXLAN_RSC */
+               nla_total_size(sizeof(__u8)) +  /* IFLA_VXLAN_L2MISS */
+               nla_total_size(sizeof(__u8)) +  /* IFLA_VXLAN_L3MISS */
                nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_AGEING */
                nla_total_size(sizeof(__u32)) + /* IFLA_VXLAN_LIMIT */
                nla_total_size(sizeof(struct ifla_vxlan_port_range)) +
@@ -1179,7 +1403,15 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
 
        if (nla_put_u8(skb, IFLA_VXLAN_TTL, vxlan->ttl) ||
            nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->tos) ||
-           nla_put_u8(skb, IFLA_VXLAN_LEARNING, vxlan->learn) ||
+           nla_put_u8(skb, IFLA_VXLAN_LEARNING,
+                       !!(vxlan->flags & VXLAN_F_LEARN)) ||
+           nla_put_u8(skb, IFLA_VXLAN_PROXY,
+                       !!(vxlan->flags & VXLAN_F_PROXY)) ||
+           nla_put_u8(skb, IFLA_VXLAN_RSC, !!(vxlan->flags & VXLAN_F_RSC)) ||
+           nla_put_u8(skb, IFLA_VXLAN_L2MISS,
+                       !!(vxlan->flags & VXLAN_F_L2MISS)) ||
+           nla_put_u8(skb, IFLA_VXLAN_L3MISS,
+                       !!(vxlan->flags & VXLAN_F_L3MISS)) ||
            nla_put_u32(skb, IFLA_VXLAN_AGEING, vxlan->age_interval) ||
            nla_put_u32(skb, IFLA_VXLAN_LIMIT, vxlan->addrmax))
                goto nla_put_failure;
index eac709bed7ae54473067d334e76fb4484f4f478b..df70248e2fdafe36e09d1c026e4c034094165264 100644 (file)
@@ -52,9 +52,9 @@ endif
 
 quiet_cmd_build_wanxlfw = BLD FW  $@
       cmd_build_wanxlfw = \
-       $(CPP) -Wp,-MD,$(depfile) -I$(srctree)/include $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
+       $(CPP) -D__ASSEMBLY__ -Wp,-MD,$(depfile) -I$(srctree)/include/uapi $< | $(AS68K) -m68360 -o $(obj)/wanxlfw.o; \
        $(LD68K) --oformat binary -Ttext 0x1000 $(obj)/wanxlfw.o -o $(obj)/wanxlfw.bin; \
-       hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x  ,//g;1s/^/static u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
+       hexdump -ve '"\n" 16/1 "0x%02X,"' $(obj)/wanxlfw.bin | sed 's/0x  ,//g;1s/^/static const u8 firmware[]={/;$$s/,$$/\n};\n/' >$(obj)/wanxlfw.inc; \
        rm -f $(obj)/wanxlfw.bin $(obj)/wanxlfw.o
 
 $(obj)/wanxlfw.inc:    $(src)/wanxlfw.S
index ef36cafd44b72138436ce3175dd5dfca7d184082..851dc7b7e8b0a650482df9b86d2abf50d666e67a 100644 (file)
@@ -707,8 +707,7 @@ static void dscc4_free1(struct pci_dev *pdev)
        kfree(ppriv);
 }
 
-static int __devinit dscc4_init_one(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int dscc4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct dscc4_pci_priv *priv;
        struct dscc4_dev_priv *dpriv;
@@ -1968,7 +1967,7 @@ err_out:
        return -ENOMEM;
 }
 
-static void __devexit dscc4_remove_one(struct pci_dev *pdev)
+static void dscc4_remove_one(struct pci_dev *pdev)
 {
        struct dscc4_pci_priv *ppriv;
        struct dscc4_dev_priv *root;
@@ -2053,7 +2052,7 @@ static struct pci_driver dscc4_driver = {
        .name           = DRV_NAME,
        .id_table       = dscc4_pci_tbl,
        .probe          = dscc4_init_one,
-       .remove         = __devexit_p(dscc4_remove_one),
+       .remove         = dscc4_remove_one,
 };
 
 module_pci_driver(dscc4_driver);
index b6271325f8035c33ebaabf5e172f9ef9725780ba..56941d6547eb33388535ead21ffb808354027de2 100644 (file)
@@ -2361,7 +2361,7 @@ fst_start_xmit(struct sk_buff *skb, struct net_device *dev)
  *      via a printk and leave the corresponding interface and all that follow
  *      disabled.
  */
-static char *type_strings[] __devinitdata = {
+static char *type_strings[] = {
        "no hardware",          /* Should never be seen */
        "FarSync T2P",
        "FarSync T4P",
@@ -2371,7 +2371,7 @@ static char *type_strings[] __devinitdata = {
        "FarSync TE1"
 };
 
-static void __devinit
+static void
 fst_init_card(struct fst_card_info *card)
 {
        int i;
@@ -2415,7 +2415,7 @@ static const struct net_device_ops fst_ops = {
  *      Initialise card when detected.
  *      Returns 0 to indicate success, or errno otherwise.
  */
-static int __devinit
+static int
 fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        static int no_of_cards_added = 0;
@@ -2615,7 +2615,7 @@ fst_add_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 /*
  *      Cleanup and close down a card
  */
-static void __devexit
+static void
 fst_remove_one(struct pci_dev *pdev)
 {
        struct fst_card_info *card;
@@ -2652,7 +2652,7 @@ static struct pci_driver fst_driver = {
         .name          = FST_NAME,
         .id_table      = fst_pci_dev_id,
         .probe         = fst_add_one,
-        .remove        = __devexit_p(fst_remove_one),
+        .remove        = fst_remove_one,
         .suspend       = NULL,
         .resume        = NULL,
 };
index cf4903355a34eb78b6bbdd488b9c35849f0afe97..62f01b74cbd65d1f6899f37dfe21a99735bcce74 100644 (file)
@@ -676,8 +676,7 @@ static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev)
 
 
 #ifdef NEED_DETECT_RAM
-static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
-                                   u32 ramsize)
+static u32 sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize)
 {
        /* Round RAM size to 32 bits, fill from end to start */
        u32 i = ramsize &= ~3;
@@ -705,7 +704,7 @@ static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
 #endif /* NEED_DETECT_RAM */
 
 
-static void __devinit sca_init(card_t *card, int wait_states)
+static void sca_init(card_t *card, int wait_states)
 {
        sca_out(wait_states, WCRL, card); /* Wait Control */
        sca_out(wait_states, WCRM, card);
index e2779faa6c4f9c651cc115dae455dd72423f19c9..6269a09c736950c98d7df37ec4261d548d53f1c6 100644 (file)
@@ -605,8 +605,7 @@ static netdev_tx_t sca_xmit(struct sk_buff *skb, struct net_device *dev)
 }
 
 
-static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
-                                   u32 ramsize)
+static u32 sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize)
 {
        /* Round RAM size to 32 bits, fill from end to start */
        u32 i = ramsize &= ~3;
@@ -625,7 +624,7 @@ static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
 }
 
 
-static void __devinit sca_init(card_t *card, int wait_states)
+static void sca_init(card_t *card, int wait_states)
 {
        sca_out(wait_states, WCRL, card); /* Wait Control */
        sca_out(wait_states, WCRM, card);
index 3f575afd8cfcb03f283df0932f6fb33bb1495cca..b617622526b43e4abe43789435999d46e769d1d9 100644 (file)
@@ -969,10 +969,12 @@ static int init_hdlc_queues(struct port *port)
 {
        int i;
 
-       if (!ports_open)
-               if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-                                                POOL_ALLOC_SIZE, 32, 0)))
+       if (!ports_open) {
+               dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+                                          POOL_ALLOC_SIZE, 32, 0);
+               if (!dma_pool)
                        return -ENOMEM;
+       }
 
        if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
                                              &port->desc_tab_phys)))
@@ -1324,7 +1326,7 @@ static const struct net_device_ops hss_hdlc_ops = {
        .ndo_do_ioctl   = hss_hdlc_ioctl,
 };
 
-static int __devinit hss_init_one(struct platform_device *pdev)
+static int hss_init_one(struct platform_device *pdev)
 {
        struct port *port;
        struct net_device *dev;
@@ -1375,7 +1377,7 @@ err_free:
        return err;
 }
 
-static int __devexit hss_remove_one(struct platform_device *pdev)
+static int hss_remove_one(struct platform_device *pdev)
 {
        struct port *port = platform_get_drvdata(pdev);
 
index f5d533a706eacc690d87a7260e9b0189ccad3800..7ef435bab42550ee4f220333e192be158634e875 100644 (file)
@@ -816,8 +816,7 @@ static const struct net_device_ops lmc_ops = {
        .ndo_get_stats  = lmc_get_stats,
 };
 
-static int __devinit lmc_init_one(struct pci_dev *pdev,
-                                 const struct pci_device_id *ent)
+static int lmc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        lmc_softc_t *sc;
        struct net_device *dev;
@@ -986,7 +985,7 @@ err_req_io:
 /*
  * Called from pci when removing module.
  */
-static void __devexit lmc_remove_one(struct pci_dev *pdev)
+static void lmc_remove_one(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
@@ -1733,7 +1732,7 @@ static struct pci_driver lmc_driver = {
        .name           = "lmc",
        .id_table       = lmc_pci_tbl,
        .probe          = lmc_init_one,
-       .remove         = __devexit_p(lmc_remove_one),
+       .remove         = lmc_remove_one,
 };
 
 module_pci_driver(lmc_driver);
index 5fe246e060d7b8288f933e8f83856eade0e37271..53efc57fcacebd776ff810108a48e619c79eca03 100644 (file)
@@ -297,8 +297,8 @@ static const struct net_device_ops pc300_ops = {
        .ndo_do_ioctl   = pc300_ioctl,
 };
 
-static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent)
+static int pc300_pci_init_one(struct pci_dev *pdev,
+                             const struct pci_device_id *ent)
 {
        card_t *card;
        u32 __iomem *p;
index 9659fcaa34ed5001f973f62ed600aebc4e314885..ddbce54040e2ca5e0a49c3fbde8b77528499c792 100644 (file)
@@ -276,8 +276,8 @@ static const struct net_device_ops pci200_ops = {
        .ndo_do_ioctl   = pci200_ioctl,
 };
 
-static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
-                                        const struct pci_device_id *ent)
+static int pci200_pci_init_one(struct pci_dev *pdev,
+                              const struct pci_device_id *ent)
 {
        card_t *card;
        u32 __iomem *p;
index feb7541b33fbb8191928581eaaacc024dc193e5c..6a24a5a70cc7d4459e04e0348882f0324dd4fad3 100644 (file)
@@ -557,8 +557,8 @@ static const struct net_device_ops wanxl_ops = {
        .ndo_get_stats  = wanxl_get_stats,
 };
 
-static int __devinit wanxl_pci_init_one(struct pci_dev *pdev,
-                                       const struct pci_device_id *ent)
+static int wanxl_pci_init_one(struct pci_dev *pdev,
+                             const struct pci_device_id *ent)
 {
        card_t *card;
        u32 ramsize, stat;
index 73aae2bf2f1c886180b5074085acd610c0415cab..21565d59ec7b5f5351608a5fbcf7e22de3475fb7 100644 (file)
@@ -35,6 +35,7 @@
 */
 
 #include <linux/hdlc.h>
+#include <linux/hdlc/ioctl.h>
 #include "wanxl.h"
 
 /* memory addresses and offsets */
index 192251adf986c97579539025055f91c592f189bd..282eedec675ee17fae313655797716ad1617eec0 100644 (file)
@@ -382,7 +382,7 @@ static void cancel_transfers(struct b43legacy_pioqueue *queue)
 {
        struct b43legacy_pio_txpacket *packet, *tmp_packet;
 
-       tasklet_disable(&queue->txtask);
+       tasklet_kill(&queue->txtask);
 
        list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
                free_txpacket(packet, 0);
index caa011008cd0c9fe11b38507e7f550552bd93170..c26e28b4bd9f985a4d7c6d3307d969bb671bf6f7 100644 (file)
@@ -452,29 +452,85 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
        /* Grant backend access to each skb fragment page. */
        for (i = 0; i < frags; i++) {
                skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+               struct page *page = skb_frag_page(frag);
 
-               tx->flags |= XEN_NETTXF_more_data;
+               len = skb_frag_size(frag);
+               offset = frag->page_offset;
 
-               id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
-               np->tx_skbs[id].skb = skb_get(skb);
-               tx = RING_GET_REQUEST(&np->tx, prod++);
-               tx->id = id;
-               ref = gnttab_claim_grant_reference(&np->gref_tx_head);
-               BUG_ON((signed short)ref < 0);
+               /* Data must not cross a page boundary. */
+               BUG_ON(len + offset > PAGE_SIZE<<compound_order(page));
 
-               mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag)));
-               gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
-                                               mfn, GNTMAP_readonly);
+               /* Skip unused frames from start of page */
+               page += offset >> PAGE_SHIFT;
+               offset &= ~PAGE_MASK;
 
-               tx->gref = np->grant_tx_ref[id] = ref;
-               tx->offset = frag->page_offset;
-               tx->size = skb_frag_size(frag);
-               tx->flags = 0;
+               while (len > 0) {
+                       unsigned long bytes;
+
+                       BUG_ON(offset >= PAGE_SIZE);
+
+                       bytes = PAGE_SIZE - offset;
+                       if (bytes > len)
+                               bytes = len;
+
+                       tx->flags |= XEN_NETTXF_more_data;
+
+                       id = get_id_from_freelist(&np->tx_skb_freelist,
+                                                 np->tx_skbs);
+                       np->tx_skbs[id].skb = skb_get(skb);
+                       tx = RING_GET_REQUEST(&np->tx, prod++);
+                       tx->id = id;
+                       ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+                       BUG_ON((signed short)ref < 0);
+
+                       mfn = pfn_to_mfn(page_to_pfn(page));
+                       gnttab_grant_foreign_access_ref(ref,
+                                                       np->xbdev->otherend_id,
+                                                       mfn, GNTMAP_readonly);
+
+                       tx->gref = np->grant_tx_ref[id] = ref;
+                       tx->offset = offset;
+                       tx->size = bytes;
+                       tx->flags = 0;
+
+                       offset += bytes;
+                       len -= bytes;
+
+                       /* Next frame */
+                       if (offset == PAGE_SIZE && len) {
+                               BUG_ON(!PageCompound(page));
+                               page++;
+                               offset = 0;
+                       }
+               }
        }
 
        np->tx.req_prod_pvt = prod;
 }
 
+/*
+ * Count how many ring slots are required to send the frags of this
+ * skb. Each frag might be a compound page.
+ */
+static int xennet_count_skb_frag_slots(struct sk_buff *skb)
+{
+       int i, frags = skb_shinfo(skb)->nr_frags;
+       int pages = 0;
+
+       for (i = 0; i < frags; i++) {
+               skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+               unsigned long size = skb_frag_size(frag);
+               unsigned long offset = frag->page_offset;
+
+               /* Skip unused frames from start of page */
+               offset &= ~PAGE_MASK;
+
+               pages += PFN_UP(offset + size);
+       }
+
+       return pages;
+}
+
 static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        unsigned short id;
@@ -487,23 +543,23 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        grant_ref_t ref;
        unsigned long mfn;
        int notify;
-       int frags = skb_shinfo(skb)->nr_frags;
+       int slots;
        unsigned int offset = offset_in_page(data);
        unsigned int len = skb_headlen(skb);
        unsigned long flags;
 
-       frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
-       if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
-               printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
-                      frags);
-               dump_stack();
+       slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
+               xennet_count_skb_frag_slots(skb);
+       if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
+               net_alert_ratelimited(
+                       "xennet: skb rides the rocket: %d slots\n", slots);
                goto drop;
        }
 
        spin_lock_irqsave(&np->tx_lock, flags);
 
        if (unlikely(!netif_carrier_ok(dev) ||
-                    (frags > 1 && !xennet_can_sg(dev)) ||
+                    (slots > 1 && !xennet_can_sg(dev)) ||
                     netif_needs_gso(skb, netif_skb_features(skb)))) {
                spin_unlock_irqrestore(&np->tx_lock, flags);
                goto drop;
@@ -1255,7 +1311,7 @@ static const struct net_device_ops xennet_netdev_ops = {
 #endif
 };
 
-static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev)
+static struct net_device *xennet_create_dev(struct xenbus_device *dev)
 {
        int i, err;
        struct net_device *netdev;
@@ -1351,8 +1407,8 @@ static struct net_device * __devinit xennet_create_dev(struct xenbus_device *dev
  * structures and the ring buffers for communication with the backend, and
  * inform the backend of the appropriate details for those.
  */
-static int __devinit netfront_probe(struct xenbus_device *dev,
-                                   const struct xenbus_device_id *id)
+static int netfront_probe(struct xenbus_device *dev,
+                         const struct xenbus_device_id *id)
 {
        int err;
        struct net_device *netdev;
@@ -1911,7 +1967,7 @@ static const struct xenbus_device_id netfront_ids[] = {
 };
 
 
-static int __devexit xennet_remove(struct xenbus_device *dev)
+static int xennet_remove(struct xenbus_device *dev)
 {
        struct netfront_info *info = dev_get_drvdata(&dev->dev);
 
@@ -1934,7 +1990,7 @@ static int __devexit xennet_remove(struct xenbus_device *dev)
 
 static DEFINE_XENBUS_DRIVER(netfront, ,
        .probe = netfront_probe,
-       .remove = __devexit_p(xennet_remove),
+       .remove = xennet_remove,
        .resume = netfront_resume,
        .otherend_changed = netback_changed,
 );
index 72e496f1e9b082d576f439c442a07721330f1928..0125524c08c48437080c5842657bb913a937455e 100644 (file)
@@ -37,9 +37,9 @@ struct of_bus {
        int             (*match)(struct device_node *parent);
        void            (*count_cells)(struct device_node *child,
                                       int *addrc, int *sizec);
-       u64             (*map)(u32 *addr, const __be32 *range,
+       u64             (*map)(__be32 *addr, const __be32 *range,
                                int na, int ns, int pna);
-       int             (*translate)(u32 *addr, u64 offset, int na);
+       int             (*translate)(__be32 *addr, u64 offset, int na);
        unsigned int    (*get_flags)(const __be32 *addr);
 };
 
@@ -56,7 +56,7 @@ static void of_bus_default_count_cells(struct device_node *dev,
                *sizec = of_n_size_cells(dev);
 }
 
-static u64 of_bus_default_map(u32 *addr, const __be32 *range,
+static u64 of_bus_default_map(__be32 *addr, const __be32 *range,
                int na, int ns, int pna)
 {
        u64 cp, s, da;
@@ -82,7 +82,7 @@ static u64 of_bus_default_map(u32 *addr, const __be32 *range,
        return da - cp;
 }
 
-static int of_bus_default_translate(u32 *addr, u64 offset, int na)
+static int of_bus_default_translate(__be32 *addr, u64 offset, int na)
 {
        u64 a = of_read_number(addr, na);
        memset(addr, 0, na * 4);
@@ -138,7 +138,7 @@ static unsigned int of_bus_pci_get_flags(const __be32 *addr)
        return flags;
 }
 
-static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns,
+static u64 of_bus_pci_map(__be32 *addr, const __be32 *range, int na, int ns,
                int pna)
 {
        u64 cp, s, da;
@@ -165,7 +165,7 @@ static u64 of_bus_pci_map(u32 *addr, const __be32 *range, int na, int ns,
        return da - cp;
 }
 
-static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
+static int of_bus_pci_translate(__be32 *addr, u64 offset, int na)
 {
        return of_bus_default_translate(addr + 1, offset, na - 1);
 }
@@ -247,7 +247,7 @@ static void of_bus_isa_count_cells(struct device_node *child,
                *sizec = 1;
 }
 
-static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns,
+static u64 of_bus_isa_map(__be32 *addr, const __be32 *range, int na, int ns,
                int pna)
 {
        u64 cp, s, da;
@@ -270,7 +270,7 @@ static u64 of_bus_isa_map(u32 *addr, const __be32 *range, int na, int ns,
        return da - cp;
 }
 
-static int of_bus_isa_translate(u32 *addr, u64 offset, int na)
+static int of_bus_isa_translate(__be32 *addr, u64 offset, int na)
 {
        return of_bus_default_translate(addr + 1, offset, na - 1);
 }
@@ -338,7 +338,7 @@ static struct of_bus *of_match_bus(struct device_node *np)
 }
 
 static int of_translate_one(struct device_node *parent, struct of_bus *bus,
-                           struct of_bus *pbus, u32 *addr,
+                           struct of_bus *pbus, __be32 *addr,
                            int na, int ns, int pna, const char *rprop)
 {
        const __be32 *ranges;
@@ -409,12 +409,12 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus,
  * that can be mapped to a cpu physical address). This is not really specified
  * that way, but this is traditionally the way IBM at least do things
  */
-u64 __of_translate_address(struct device_node *dev, const __be32 *in_addr,
-                          const char *rprop)
+static u64 __of_translate_address(struct device_node *dev,
+                                 const __be32 *in_addr, const char *rprop)
 {
        struct device_node *parent = NULL;
        struct of_bus *bus, *pbus;
-       u32 addr[OF_MAX_ADDR_CELLS];
+       __be32 addr[OF_MAX_ADDR_CELLS];
        int na, ns, pna, pns;
        u64 result = OF_BAD_ADDR;
 
index a23ec7779997b553269ad7af6e36a2580f98375c..a3c1c5aae6a9eaa5de0ecd0dd0335771ac8f7fab 100644 (file)
@@ -192,11 +192,13 @@ int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
                        /* Compare specifiers */
                        match = 1;
                        for (i = 0; i < addrsize && match; ++i) {
-                               u32 mask = imask ? imask[i] : 0xffffffffu;
+                               __be32 mask = imask ? imask[i]
+                                                   : cpu_to_be32(0xffffffffu);
                                match = ((addr[i] ^ imap[i]) & mask) == 0;
                        }
                        for (; i < (addrsize + intsize) && match; ++i) {
-                               u32 mask = imask ? imask[i] : 0xffffffffu;
+                               __be32 mask = imask ? imask[i]
+                                                   : cpu_to_be32(0xffffffffu);
                                match =
                                   ((intspec[i-addrsize] ^ imap[i]) & mask) == 0;
                        }
@@ -465,7 +467,7 @@ void __init of_irq_init(const struct of_device_id *matches)
                        pr_debug("of_irq_init: init %s @ %p, parent %p\n",
                                 match->compatible,
                                 desc->dev, desc->interrupt_parent);
-                       irq_init_cb = match->data;
+                       irq_init_cb = (of_irq_init_cb_t)match->data;
                        ret = irq_init_cb(desc->dev, desc->interrupt_parent);
                        if (ret) {
                                kfree(desc);
index 9bdeaf30b17dd5a197f373f9baa18401338ef3d8..b80891b438168491b6434afb2086b4f2424ffc7e 100644 (file)
@@ -76,7 +76,7 @@ void of_device_make_bus_id(struct device *dev)
 {
        static atomic_t bus_no_reg_magic;
        struct device_node *node = dev->of_node;
-       const u32 *reg;
+       const __be32 *reg;
        u64 addr;
        const __be32 *addrp;
        int magic;
index 6241fd05bd4108cde7ff14366eb169a00cb80138..a543746fb354d99913cac3323b99b6f5aa71dbc9 100644 (file)
@@ -320,10 +320,7 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
                } else
                        next = dev->bus_list.next;
 
-               /* Run device routines with the device locked */
-               device_lock(&dev->dev);
                retval = cb(dev, userdata);
-               device_unlock(&dev->dev);
                if (retval)
                        break;
        }
index 94c6e2aa03d658defb5d30b0f2fbb1f8383cf9d0..6c94fc9489e709b2ad5f42817d8f29ef21c9a9b6 100644 (file)
@@ -398,6 +398,8 @@ static void pci_device_shutdown(struct device *dev)
        struct pci_dev *pci_dev = to_pci_dev(dev);
        struct pci_driver *drv = pci_dev->driver;
 
+       pm_runtime_resume(dev);
+
        if (drv && drv->shutdown)
                drv->shutdown(pci_dev);
        pci_msi_shutdown(pci_dev);
@@ -408,16 +410,6 @@ static void pci_device_shutdown(struct device *dev)
         * continue to do DMA
         */
        pci_disable_device(pci_dev);
-
-       /*
-        * Devices may be enabled to wake up by runtime PM, but they need not
-        * be supposed to wake up the system from its "power off" state (e.g.
-        * ACPI S5).  Therefore disable wakeup for all devices that aren't
-        * supposed to wake up the system at this point.  The state argument
-        * will be ignored by pci_enable_wake().
-        */
-       if (!device_may_wakeup(dev))
-               pci_enable_wake(pci_dev, PCI_UNKNOWN, false);
 }
 
 #ifdef CONFIG_PM
index 02d107b152818e948cc3e561d276bf24126ac997..f39378d9da1500056a90f4816f742e9e5ee9626f 100644 (file)
@@ -458,40 +458,6 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 struct device_attribute vga_attr = __ATTR_RO(boot_vga);
 
-static void
-pci_config_pm_runtime_get(struct pci_dev *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device *parent = dev->parent;
-
-       if (parent)
-               pm_runtime_get_sync(parent);
-       pm_runtime_get_noresume(dev);
-       /*
-        * pdev->current_state is set to PCI_D3cold during suspending,
-        * so wait until suspending completes
-        */
-       pm_runtime_barrier(dev);
-       /*
-        * Only need to resume devices in D3cold, because config
-        * registers are still accessible for devices suspended but
-        * not in D3cold.
-        */
-       if (pdev->current_state == PCI_D3cold)
-               pm_runtime_resume(dev);
-}
-
-static void
-pci_config_pm_runtime_put(struct pci_dev *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct device *parent = dev->parent;
-
-       pm_runtime_put(dev);
-       if (parent)
-               pm_runtime_put_sync(parent);
-}
-
 static ssize_t
 pci_read_config(struct file *filp, struct kobject *kobj,
                struct bin_attribute *bin_attr,
index 54858838f09867f142886edcac6b4dab9c049531..aabf64798bda7d2ebdca2697f23c7e29bfbae620 100644 (file)
@@ -1858,6 +1858,38 @@ bool pci_dev_run_wake(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_dev_run_wake);
 
+void pci_config_pm_runtime_get(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       if (parent)
+               pm_runtime_get_sync(parent);
+       pm_runtime_get_noresume(dev);
+       /*
+        * pdev->current_state is set to PCI_D3cold during suspending,
+        * so wait until suspending completes
+        */
+       pm_runtime_barrier(dev);
+       /*
+        * Only need to resume devices in D3cold, because config
+        * registers are still accessible for devices suspended but
+        * not in D3cold.
+        */
+       if (pdev->current_state == PCI_D3cold)
+               pm_runtime_resume(dev);
+}
+
+void pci_config_pm_runtime_put(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       pm_runtime_put(dev);
+       if (parent)
+               pm_runtime_put_sync(parent);
+}
+
 /**
  * pci_pm_init - Initialize PM functions of given PCI device
  * @dev: PCI device to handle.
index bacbcba69cf386dd2971b8b94e6ddd383888b471..fd92aab9904b92a694dadf685291220121661905 100644 (file)
@@ -72,6 +72,8 @@ extern void pci_disable_enabled_device(struct pci_dev *dev);
 extern int pci_finish_runtime_suspend(struct pci_dev *dev);
 extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
 extern void pci_wakeup_bus(struct pci_bus *bus);
+extern void pci_config_pm_runtime_get(struct pci_dev *dev);
+extern void pci_config_pm_runtime_put(struct pci_dev *dev);
 extern void pci_pm_init(struct pci_dev *dev);
 extern void platform_pci_wakeup_init(struct pci_dev *dev);
 extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
index 06bad96af415b052b4eb9a90d83f7c04c70b108a..af4e31cd3a3b6b1f895a36afaf4bb874b3e1fb66 100644 (file)
@@ -213,6 +213,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        dev->error_state = result_data->state;
 
        if (!dev->driver ||
@@ -231,12 +232,14 @@ static int report_error_detected(struct pci_dev *dev, void *data)
                                   dev->driver ?
                                   "no AER-aware driver" : "no driver");
                }
-               return 0;
+               goto out;
        }
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->error_detected(dev, result_data->state);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -247,14 +250,17 @@ static int report_mmio_enabled(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->mmio_enabled)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->mmio_enabled(dev);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -265,14 +271,17 @@ static int report_slot_reset(struct pci_dev *dev, void *data)
        struct aer_broadcast_data *result_data;
        result_data = (struct aer_broadcast_data *) data;
 
+       device_lock(&dev->dev);
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->slot_reset)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        vote = err_handler->slot_reset(dev);
        result_data->result = merge_result(result_data->result, vote);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
@@ -280,15 +289,18 @@ static int report_resume(struct pci_dev *dev, void *data)
 {
        const struct pci_error_handlers *err_handler;
 
+       device_lock(&dev->dev);
        dev->error_state = pci_channel_io_normal;
 
        if (!dev->driver ||
                !dev->driver->err_handler ||
                !dev->driver->err_handler->resume)
-               return 0;
+               goto out;
 
        err_handler = dev->driver->err_handler;
        err_handler->resume(dev);
+out:
+       device_unlock(&dev->dev);
        return 0;
 }
 
index d03a7a39b2d85e14baef54a8255e787094528229..ed129b4146246144de63db421ff04d28d5d7de27 100644 (file)
@@ -272,7 +272,8 @@ static int get_port_device_capability(struct pci_dev *dev)
        }
 
        /* Hot-Plug Capable */
-       if (cap_mask & PCIE_PORT_SERVICE_HP) {
+       if ((cap_mask & PCIE_PORT_SERVICE_HP) &&
+           dev->pcie_flags_reg & PCI_EXP_FLAGS_SLOT) {
                pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &reg32);
                if (reg32 & PCI_EXP_SLTCAP_HPC) {
                        services |= PCIE_PORT_SERVICE_HP;
index eb907a8faf2a9b6e325033005127b0b40904930a..9b8505ccc56d5ef87a09105f5847d19a441ec704 100644 (file)
@@ -76,6 +76,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
        if (!access_ok(VERIFY_WRITE, buf, cnt))
                return -EINVAL;
 
+       pci_config_pm_runtime_get(dev);
+
        if ((pos & 1) && cnt) {
                unsigned char val;
                pci_user_read_config_byte(dev, pos, &val);
@@ -121,6 +123,8 @@ proc_bus_pci_read(struct file *file, char __user *buf, size_t nbytes, loff_t *pp
                cnt--;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        *ppos = pos;
        return nbytes;
 }
@@ -146,6 +150,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
        if (!access_ok(VERIFY_READ, buf, cnt))
                return -EINVAL;
 
+       pci_config_pm_runtime_get(dev);
+
        if ((pos & 1) && cnt) {
                unsigned char val;
                __get_user(val, buf);
@@ -191,6 +197,8 @@ proc_bus_pci_write(struct file *file, const char __user *buf, size_t nbytes, lof
                cnt--;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        *ppos = pos;
        i_size_write(ino, dp->size);
        return nbytes;
index b066273b6b4f4dc5a87ee9c37ee589938f8b0d39..7dd879ce514df8cffdf23de397923fb96e878eef 100644 (file)
@@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
        sharpsl_pcmcia_init_reset(skt);
 }
 
-static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = {
+static struct pcmcia_low_level sharpsl_pcmcia_ops = {
        .owner                  = THIS_MODULE,
        .hw_init                = sharpsl_pcmcia_hw_init,
        .socket_state           = sharpsl_pcmcia_socket_state,
index 7bf914df6e91a6129d23f5d12828b8228a8c2775..aeecf0f72cad50c633953e4ffd9617709239095b 100644 (file)
@@ -178,12 +178,14 @@ config PINCTRL_COH901
          ports of 8 GPIO pins each.
 
 config PINCTRL_SAMSUNG
-       bool "Samsung pinctrl driver"
+       bool
+       depends on OF && GPIOLIB
        select PINMUX
        select PINCONF
 
 config PINCTRL_EXYNOS4
        bool "Pinctrl driver data for Exynos4 SoC"
+       depends on OF && GPIOLIB
        select PINCTRL_SAMSUNG
 
 config PINCTRL_MVEBU
index 0f1ec9e8ff14b02448877cb4f4872f45baeeccd3..2e39c04fc16bb4be31dba8800477aafed2e64441 100644 (file)
@@ -1061,8 +1061,10 @@ static int pinctrl_groups_show(struct seq_file *s, void *what)
                        seq_printf(s, "group: %s\n", gname);
                        for (i = 0; i < num_pins; i++) {
                                pname = pin_get_name(pctldev, pins[i]);
-                               if (WARN_ON(!pname))
+                               if (WARN_ON(!pname)) {
+                                       mutex_unlock(&pinctrl_mutex);
                                        return -EINVAL;
+                               }
                                seq_printf(s, "pin %d (%s)\n", pins[i], pname);
                        }
                        seq_puts(s, "\n");
index 43f474cdc11082717c881b757c6bcaf104bcbb97..baee2cc46a17a7c5c328f98c7eaa25f8f10d8fba 100644 (file)
@@ -537,8 +537,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
        seq_puts(s, "Pin config settings per pin group\n");
        seq_puts(s, "Format: group (name): configs\n");
 
-       mutex_lock(&pinctrl_mutex);
-
        while (selector < ngroups) {
                const char *gname = pctlops->get_group_name(pctldev, selector);
 
@@ -549,8 +547,6 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
                selector++;
        }
 
-       mutex_unlock(&pinctrl_mutex);
-
        return 0;
 }
 
index a4adee633fa91f5d3f09ccf3d03d29053d114da5..7e9be18ec2d2b92922373f7f62d8543d43febf50 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
 #include <linux/irqdomain.h>
-#include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of.h>
@@ -960,7 +959,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev)
                return err;
        }
 
-       pc->base = devm_request_and_ioremap(&pdev->dev, &iomem);
+       pc->base = devm_request_and_ioremap(dev, &iomem);
        if (!pc->base)
                return -EADDRNOTAVAIL;
 
@@ -1032,7 +1031,7 @@ static int __devinit bcm2835_pinctrl_probe(struct platform_device *pdev)
        pc->pctl_dev = pinctrl_register(&bcm2835_pinctrl_desc, dev, pc);
        if (!pc->pctl_dev) {
                gpiochip_remove(&pc->gpio_chip);
-               return PTR_ERR(pc->pctl_dev);
+               return -EINVAL;
        }
 
        pc->gpio_range = bcm2835_pinctrl_gpio_range;
index fec9c30133d43b2731a9fe8d765ba05106d5eda1..cf82d9ce4deeccc8c19c6104103fee84854c945a 100644 (file)
 #include <linux/pinctrl/pinconf.h>
 /* Since we request GPIOs from ourself */
 #include <linux/pinctrl/consumer.h>
+/*
+ * For the U8500 archs, use the PRCMU register interface, for the older
+ * Nomadik, provide some stubs. The functions using these will only be
+ * called on the U8500 series.
+ */
+#ifdef CONFIG_ARCH_U8500
 #include <linux/mfd/dbx500-prcmu.h>
+#else
+static inline u32 prcmu_read(unsigned int reg) {
+       return 0;
+}
+static inline void prcmu_write(unsigned int reg, u32 value) {}
+static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
+#endif
 
 #include <asm/mach/irq.h>
 
@@ -1043,7 +1056,7 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
        struct nmk_gpio_chip *nmk_chip =
                container_of(chip, struct nmk_gpio_chip, chip);
 
-       return irq_find_mapping(nmk_chip->domain, offset);
+       return irq_create_mapping(nmk_chip->domain, offset);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -1268,6 +1281,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
        struct clk *clk;
        int secondary_irq;
        void __iomem *base;
+       int irq_start = 0;
        int irq;
        int ret;
 
@@ -1371,19 +1385,11 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
 
        platform_set_drvdata(dev, nmk_chip);
 
-       if (np) {
-               /* The DT case will just grab a set of IRQ numbers */
-               nmk_chip->domain = irq_domain_add_linear(np, NMK_GPIO_PER_CHIP,
-                               &nmk_gpio_irq_simple_ops, nmk_chip);
-       } else {
-               /* Non-DT legacy mode, use hardwired IRQ numbers */
-               int irq_start;
-
+       if (!np)
                irq_start = NOMADIK_GPIO_TO_IRQ(pdata->first_gpio);
-               nmk_chip->domain = irq_domain_add_simple(NULL,
+       nmk_chip->domain = irq_domain_add_simple(np,
                                NMK_GPIO_PER_CHIP, irq_start,
                                &nmk_gpio_irq_simple_ops, nmk_chip);
-       }
        if (!nmk_chip->domain) {
                dev_err(&dev->dev, "failed to create irqdomain\n");
                ret = -ENOSYS;
index dd108a94acf95028929a5c2b82a3fdaf7a906267..861cd5f04d5e12ba2aa497cc39934a56b0680a7b 100644 (file)
@@ -513,7 +513,7 @@ static int samsung_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
  * Parse the pin names listed in the 'samsung,pins' property and convert it
  * into a list of gpio numbers are create a pin group from it.
  */
-static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
+static int __devinit samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
                        struct device_node *cfg_np, struct pinctrl_desc *pctl,
                        unsigned int **pin_list, unsigned int *npins)
 {
@@ -560,7 +560,7 @@ static int __init samsung_pinctrl_parse_dt_pins(struct platform_device *pdev,
  * from device node of the pin-controller. A pin group is formed with all
  * the pins listed in the "samsung,pins" property.
  */
-static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev,
+static int __devinit samsung_pinctrl_parse_dt(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
        struct device *dev = &pdev->dev;
@@ -655,7 +655,7 @@ static int __init samsung_pinctrl_parse_dt(struct platform_device *pdev,
 }
 
 /* register the pinctrl interface with the pinctrl subsystem */
-static int __init samsung_pinctrl_register(struct platform_device *pdev,
+static int __devinit samsung_pinctrl_register(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
        struct pinctrl_desc *ctrldesc = &drvdata->pctl;
@@ -729,7 +729,7 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev,
 }
 
 /* register the gpiolib interface with the gpiolib subsystem */
-static int __init samsung_gpiolib_register(struct platform_device *pdev,
+static int __devinit samsung_gpiolib_register(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
        struct gpio_chip *gc;
@@ -762,7 +762,7 @@ static int __init samsung_gpiolib_register(struct platform_device *pdev,
 }
 
 /* unregister the gpiolib interface with the gpiolib subsystem */
-static int __init samsung_gpiolib_unregister(struct platform_device *pdev,
+static int __devinit samsung_gpiolib_unregister(struct platform_device *pdev,
                                struct samsung_pinctrl_drv_data *drvdata)
 {
        int ret = gpiochip_remove(drvdata->gc);
index 675497c15149f2e3725cdb9f1031d78dc1859750..9ecacf3d0a759715db3d1081677747b51905626f 100644 (file)
@@ -1323,41 +1323,6 @@ static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int gpio)
        return &sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE];
 }
 
-void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode)
-{
-       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(gpio);
-       int idx = sirfsoc_gpio_to_offset(gpio);
-       u32 val, offset;
-       unsigned long flags;
-
-       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
-
-       spin_lock_irqsave(&sgpio_lock, flags);
-
-       val = readl(bank->chip.regs + offset);
-
-       switch (mode) {
-       case SIRFSOC_GPIO_PULL_NONE:
-               val &= ~SIRFSOC_GPIO_CTL_PULL_MASK;
-               break;
-       case SIRFSOC_GPIO_PULL_UP:
-               val |= SIRFSOC_GPIO_CTL_PULL_MASK;
-               val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
-               break;
-       case SIRFSOC_GPIO_PULL_DOWN:
-               val |= SIRFSOC_GPIO_CTL_PULL_MASK;
-               val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
-               break;
-       default:
-               break;
-       }
-
-       writel(val, bank->chip.regs + offset);
-
-       spin_unlock_irqrestore(&sgpio_lock, flags);
-}
-EXPORT_SYMBOL(sirfsoc_gpio_set_pull);
-
 static inline struct sirfsoc_gpio_bank *sirfsoc_irqchip_to_bank(struct gpio_chip *chip)
 {
        return container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank, chip);
index 729b686c3ad2338e2d4878ed0e1623674ba87f3f..7da0b371fd652a04ac7d55ecf89c55c915d19f8b 100644 (file)
@@ -464,7 +464,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx,
                *bank = g->drv_bank;
                *reg = g->drv_reg;
                *bit = g->lpmd_bit;
-               *width = 1;
+               *width = 2;
                break;
        case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH:
                *bank = g->drv_bank;
index 0386fdf0da16441ecc874b1710e55a929d44325a..7894f14c70590058726a6c07da4286e1640058db 100644 (file)
@@ -3345,10 +3345,10 @@ static const struct tegra_function tegra30_functions[] = {
        FUNCTION(vi_alt3),
 };
 
-#define MUXCTL_REG_A   0x3000
-#define PINGROUP_REG_A 0x868
+#define DRV_PINGROUP_REG_A     0x868   /* bank 0 */
+#define PINGROUP_REG_A         0x3000  /* bank 1 */
 
-#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A)
+#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A)
 #define PINGROUP_REG_N(r) -1
 
 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior)  \
@@ -3364,25 +3364,25 @@ static const struct tegra_function tegra30_functions[] = {
                },                                              \
                .func_safe = TEGRA_MUX_ ## f_safe,              \
                .mux_reg = PINGROUP_REG_Y(r),                   \
-               .mux_bank = 0,                                  \
+               .mux_bank = 1,                                  \
                .mux_bit = 0,                                   \
                .pupd_reg = PINGROUP_REG_Y(r),                  \
-               .pupd_bank = 0,                                 \
+               .pupd_bank = 1,                                 \
                .pupd_bit = 2,                                  \
                .tri_reg = PINGROUP_REG_Y(r),                   \
-               .tri_bank = 0,                                  \
+               .tri_bank = 1,                                  \
                .tri_bit = 4,                                   \
                .einput_reg = PINGROUP_REG_Y(r),                \
-               .einput_bank = 0,                               \
+               .einput_bank = 1,                               \
                .einput_bit = 5,                                \
                .odrain_reg = PINGROUP_REG_##od(r),             \
-               .odrain_bank = 0,                               \
+               .odrain_bank = 1,                               \
                .odrain_bit = 6,                                \
                .lock_reg = PINGROUP_REG_Y(r),                  \
-               .lock_bank = 0,                                 \
+               .lock_bank = 1,                                 \
                .lock_bit = 7,                                  \
                .ioreset_reg = PINGROUP_REG_##ior(r),           \
-               .ioreset_bank = 0,                              \
+               .ioreset_bank = 1,                              \
                .ioreset_bit = 8,                               \
                .drv_reg = -1,                                  \
        }
@@ -3401,8 +3401,8 @@ static const struct tegra_function tegra30_functions[] = {
                .odrain_reg = -1,                               \
                .lock_reg = -1,                                 \
                .ioreset_reg = -1,                              \
-               .drv_reg = ((r) - PINGROUP_REG_A),              \
-               .drv_bank = 1,                                  \
+               .drv_reg = ((r) - DRV_PINGROUP_REG_A),          \
+               .drv_bank = 0,                                  \
                .hsm_bit = hsm_b,                               \
                .schmitt_bit = schmitt_b,                       \
                .lpmd_bit = lpmd_b,                             \
index f8d917d40c92c9ae23ff6fd1d108f60db8c8e3dd..b9bcaec6622381ca3461212cad85144b857e1b48 100644 (file)
@@ -17,8 +17,6 @@
 #include <linux/ioport.h>
 #include <linux/io.h>
 #include <linux/device.h>
-#include <linux/module.h>
-#include <linux/io.h>
 #include <linux/platform_device.h>
 
 #include "pinctrl-lantiq.h"
index 5d4f44f462f0962b26b955d877f3a0ceb0285c7a..b1fd6ee33c6ceed614e3a5ccf1cb096049069710 100644 (file)
@@ -244,7 +244,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
                        else
                                temp = ~muxreg->val;
 
-                       val |= temp;
+                       val |= muxreg->mask & temp;
                        pmx_writel(pmx, val, muxreg->reg);
                }
        }
index d6cca8c81b92cf9cd9cb63f9d972965e46670249..0436fc7895d6226a8c0cd4943fad2201b03ad4b5 100644 (file)
@@ -25,8 +25,8 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
 };
 
 /* registers */
-#define PERIP_CFG                                      0x32C
-       #define MCIF_SEL_SHIFT                          3
+#define PERIP_CFG                                      0x3B0
+       #define MCIF_SEL_SHIFT                          5
        #define MCIF_SEL_SD                             (0x1 << MCIF_SEL_SHIFT)
        #define MCIF_SEL_CF                             (0x2 << MCIF_SEL_SHIFT)
        #define MCIF_SEL_XD                             (0x3 << MCIF_SEL_SHIFT)
@@ -164,6 +164,10 @@ static const struct pinctrl_pin_desc spear1310_pins[] = {
        #define PMX_SSP0_CS0_MASK                       (1 << 29)
        #define PMX_SSP0_CS1_2_MASK                     (1 << 30)
 
+#define PAD_DIRECTION_SEL_0                            0x65C
+#define PAD_DIRECTION_SEL_1                            0x660
+#define PAD_DIRECTION_SEL_2                            0x664
+
 /* combined macros */
 #define PMX_GMII_MASK          (PMX_GMIICLK_MASK |                     \
                                PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK |  \
@@ -237,6 +241,10 @@ static struct spear_muxreg i2c0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2C0_MASK,
                .val = PMX_I2C0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2C0_MASK,
+               .val = PMX_I2C0_MASK,
        },
 };
 
@@ -269,6 +277,10 @@ static struct spear_muxreg ssp0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SSP0_MASK,
                .val = PMX_SSP0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SSP0_MASK,
+               .val = PMX_SSP0_MASK,
        },
 };
 
@@ -294,6 +306,10 @@ static struct spear_muxreg ssp0_cs0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_SSP0_CS0_MASK,
                .val = PMX_SSP0_CS0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_SSP0_CS0_MASK,
+               .val = PMX_SSP0_CS0_MASK,
        },
 };
 
@@ -319,6 +335,10 @@ static struct spear_muxreg ssp0_cs1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_SSP0_CS1_2_MASK,
                .val = PMX_SSP0_CS1_2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_SSP0_CS1_2_MASK,
+               .val = PMX_SSP0_CS1_2_MASK,
        },
 };
 
@@ -352,6 +372,10 @@ static struct spear_muxreg i2s0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK,
                .val = PMX_I2S0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK,
+               .val = PMX_I2S0_MASK,
        },
 };
 
@@ -384,6 +408,10 @@ static struct spear_muxreg i2s1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_I2S1_MASK,
                .val = PMX_I2S1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_I2S1_MASK,
+               .val = PMX_I2S1_MASK,
        },
 };
 
@@ -418,6 +446,10 @@ static struct spear_muxreg clcd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = PMX_CLCD1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -443,6 +475,10 @@ static struct spear_muxreg clcd_high_res_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_CLCD2_MASK,
                .val = PMX_CLCD2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_CLCD2_MASK,
+               .val = PMX_CLCD2_MASK,
        },
 };
 
@@ -461,7 +497,7 @@ static struct spear_pingroup clcd_high_res_pingroup = {
        .nmodemuxs = ARRAY_SIZE(clcd_high_res_modemux),
 };
 
-static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res" };
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_high_res_grp" };
 static struct spear_function clcd_function = {
        .name = "clcd",
        .groups = clcd_grps,
@@ -479,6 +515,14 @@ static struct spear_muxreg arm_gpio_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_EGPIO_1_GRP_MASK,
                .val = PMX_EGPIO_1_GRP_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_EGPIO_0_GRP_MASK,
+               .val = PMX_EGPIO_0_GRP_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_EGPIO_1_GRP_MASK,
+               .val = PMX_EGPIO_1_GRP_MASK,
        },
 };
 
@@ -511,6 +555,10 @@ static struct spear_muxreg smi_2_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SMI_MASK,
                .val = PMX_SMI_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
        },
 };
 
@@ -539,6 +587,14 @@ static struct spear_muxreg smi_4_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
                .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
+               .val = PMX_SMINCS2_MASK | PMX_SMINCS3_MASK,
        },
 };
 
@@ -573,6 +629,10 @@ static struct spear_muxreg gmii_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_GMII_MASK,
                .val = PMX_GMII_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_GMII_MASK,
+               .val = PMX_GMII_MASK,
        },
 };
 
@@ -615,6 +675,18 @@ static struct spear_muxreg rgmii_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_RGMII_REG2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_RGMII_REG0_MASK,
+               .val = PMX_RGMII_REG0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_RGMII_REG1_MASK,
+               .val = PMX_RGMII_REG1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_RGMII_REG2_MASK,
+               .val = PMX_RGMII_REG2_MASK,
        },
 };
 
@@ -649,6 +721,10 @@ static struct spear_muxreg smii_0_1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_SMII_0_1_2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_SMII_0_1_2_MASK,
+               .val = PMX_SMII_0_1_2_MASK,
        },
 };
 
@@ -681,6 +757,10 @@ static struct spear_muxreg ras_mii_txclk_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NFCE2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NFCE2_MASK,
+               .val = PMX_NFCE2_MASK,
        },
 };
 
@@ -721,6 +801,14 @@ static struct spear_muxreg nand_8bit_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND8BIT_1_MASK,
                .val = PMX_NAND8BIT_1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_NAND8BIT_0_MASK,
+               .val = PMX_NAND8BIT_0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND8BIT_1_MASK,
+               .val = PMX_NAND8BIT_1_MASK,
        },
 };
 
@@ -747,6 +835,10 @@ static struct spear_muxreg nand_16bit_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND16BIT_1_MASK,
                .val = PMX_NAND16BIT_1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND16BIT_1_MASK,
+               .val = PMX_NAND16BIT_1_MASK,
        },
 };
 
@@ -772,6 +864,10 @@ static struct spear_muxreg nand_4_chips_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NAND_4CHIPS_MASK,
                .val = PMX_NAND_4CHIPS_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NAND_4CHIPS_MASK,
+               .val = PMX_NAND_4CHIPS_MASK,
        },
 };
 
@@ -833,6 +929,10 @@ static struct spear_muxreg keyboard_rowcol6_8_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL68_MASK,
                .val = PMX_KBD_ROWCOL68_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL68_MASK,
+               .val = PMX_KBD_ROWCOL68_MASK,
        },
 };
 
@@ -866,6 +966,10 @@ static struct spear_muxreg uart0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_UART0_MASK,
                .val = PMX_UART0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_UART0_MASK,
+               .val = PMX_UART0_MASK,
        },
 };
 
@@ -891,6 +995,10 @@ static struct spear_muxreg uart0_modem_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_UART0_MODEM_MASK,
                .val = PMX_UART0_MODEM_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_UART0_MODEM_MASK,
+               .val = PMX_UART0_MODEM_MASK,
        },
 };
 
@@ -923,6 +1031,10 @@ static struct spear_muxreg gpt0_tmr0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT0_TMR0_MASK,
                .val = PMX_GPT0_TMR0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT0_TMR0_MASK,
+               .val = PMX_GPT0_TMR0_MASK,
        },
 };
 
@@ -948,6 +1060,10 @@ static struct spear_muxreg gpt0_tmr1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT0_TMR1_MASK,
                .val = PMX_GPT0_TMR1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT0_TMR1_MASK,
+               .val = PMX_GPT0_TMR1_MASK,
        },
 };
 
@@ -980,6 +1096,10 @@ static struct spear_muxreg gpt1_tmr0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT1_TMR0_MASK,
                .val = PMX_GPT1_TMR0_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT1_TMR0_MASK,
+               .val = PMX_GPT1_TMR0_MASK,
        },
 };
 
@@ -1005,6 +1125,10 @@ static struct spear_muxreg gpt1_tmr1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_GPT1_TMR1_MASK,
                .val = PMX_GPT1_TMR1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_GPT1_TMR1_MASK,
+               .val = PMX_GPT1_TMR1_MASK,
        },
 };
 
@@ -1049,6 +1173,20 @@ static const unsigned mcif_pins[] = { 86, 87, 88, 89, 90, 91, 92, 93, 213, 214,
                .reg = PAD_FUNCTION_EN_2,                       \
                .mask = PMX_MCIFALL_2_MASK,                     \
                .val = PMX_MCIFALL_2_MASK,                      \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_0,                     \
+               .mask = PMX_MCI_DATA8_15_MASK,                  \
+               .val = PMX_MCI_DATA8_15_MASK,                   \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_1,                     \
+               .mask = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK | \
+                       PMX_NFWPRT2_MASK,                       \
+               .val = PMX_MCIFALL_1_MASK | PMX_NFWPRT1_MASK |  \
+                       PMX_NFWPRT2_MASK,                       \
+       }, {                                                    \
+               .reg = PAD_DIRECTION_SEL_2,                     \
+               .mask = PMX_MCIFALL_2_MASK,                     \
+               .val = PMX_MCIFALL_2_MASK,                      \
        }
 
 /* sdhci device */
@@ -1154,6 +1292,10 @@ static struct spear_muxreg touch_xy_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_TOUCH_XY_MASK,
                .val = PMX_TOUCH_XY_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_TOUCH_XY_MASK,
+               .val = PMX_TOUCH_XY_MASK,
        },
 };
 
@@ -1187,6 +1329,10 @@ static struct spear_muxreg uart1_dis_i2c_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2C0_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2C0_MASK,
+               .val = PMX_I2C0_MASK,
        },
 };
 
@@ -1213,6 +1359,12 @@ static struct spear_muxreg uart1_dis_sd_muxreg[] = {
                .mask = PMX_MCIDATA1_MASK |
                        PMX_MCIDATA2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_MCIDATA1_MASK |
+                       PMX_MCIDATA2_MASK,
+               .val = PMX_MCIDATA1_MASK |
+                       PMX_MCIDATA2_MASK,
        },
 };
 
@@ -1246,6 +1398,10 @@ static struct spear_muxreg uart2_3_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK,
+               .val = PMX_I2S0_MASK,
        },
 };
 
@@ -1278,6 +1434,10 @@ static struct spear_muxreg uart4_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_I2S0_MASK | PMX_CLCD1_MASK,
+               .val = PMX_I2S0_MASK | PMX_CLCD1_MASK,
        },
 };
 
@@ -1310,6 +1470,10 @@ static struct spear_muxreg uart5_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1344,6 +1508,10 @@ static struct spear_muxreg rs485_0_1_tdm_0_1_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1376,6 +1544,10 @@ static struct spear_muxreg i2c_1_2_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK,
+               .val = PMX_CLCD1_MASK,
        },
 };
 
@@ -1409,6 +1581,10 @@ static struct spear_muxreg i2c3_dis_smi_clcd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_CLCD1_MASK | PMX_SMI_MASK,
+               .val = PMX_CLCD1_MASK | PMX_SMI_MASK,
        },
 };
 
@@ -1435,6 +1611,10 @@ static struct spear_muxreg i2c3_dis_sd_i2s0_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
+               .val = PMX_I2S1_MASK | PMX_MCIDATA3_MASK,
        },
 };
 
@@ -1469,6 +1649,10 @@ static struct spear_muxreg i2c_4_5_dis_smi_muxreg[] = {
                .reg = PAD_FUNCTION_EN_0,
                .mask = PMX_SMI_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_SMI_MASK,
+               .val = PMX_SMI_MASK,
        },
 };
 
@@ -1499,6 +1683,14 @@ static struct spear_muxreg i2c4_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCIDATA5_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_MCIDATA4_MASK,
+               .val = PMX_MCIDATA4_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIDATA5_MASK,
+               .val = PMX_MCIDATA5_MASK,
        },
 };
 
@@ -1526,6 +1718,12 @@ static struct spear_muxreg i2c5_dis_sd_muxreg[] = {
                .mask = PMX_MCIDATA6_MASK |
                        PMX_MCIDATA7_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIDATA6_MASK |
+                       PMX_MCIDATA7_MASK,
+               .val = PMX_MCIDATA6_MASK |
+                       PMX_MCIDATA7_MASK,
        },
 };
 
@@ -1560,6 +1758,10 @@ static struct spear_muxreg i2c_6_7_dis_kbd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL25_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK,
        },
 };
 
@@ -1587,6 +1789,12 @@ static struct spear_muxreg i2c6_dis_sd_muxreg[] = {
                .mask = PMX_MCIIORDRE_MASK |
                        PMX_MCIIOWRWE_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIIORDRE_MASK |
+                       PMX_MCIIOWRWE_MASK,
+               .val = PMX_MCIIORDRE_MASK |
+                       PMX_MCIIOWRWE_MASK,
        },
 };
 
@@ -1613,6 +1821,12 @@ static struct spear_muxreg i2c7_dis_sd_muxreg[] = {
                .mask = PMX_MCIRESETCF_MASK |
                        PMX_MCICS0CE_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIRESETCF_MASK |
+                       PMX_MCICS0CE_MASK,
+               .val = PMX_MCIRESETCF_MASK |
+                       PMX_MCICS0CE_MASK,
        },
 };
 
@@ -1651,6 +1865,14 @@ static struct spear_muxreg can0_dis_nor_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_NFRSTPWDWN3_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_NFRSTPWDWN2_MASK,
+               .val = PMX_NFRSTPWDWN2_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_NFRSTPWDWN3_MASK,
+               .val = PMX_NFRSTPWDWN3_MASK,
        },
 };
 
@@ -1677,6 +1899,10 @@ static struct spear_muxreg can0_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
+               .val = PMX_MCICFINTR_MASK | PMX_MCIIORDY_MASK,
        },
 };
 
@@ -1711,6 +1937,10 @@ static struct spear_muxreg can1_dis_sd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_2,
                .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
+               .val = PMX_MCICS1_MASK | PMX_MCIDMAACK_MASK,
        },
 };
 
@@ -1737,6 +1967,10 @@ static struct spear_muxreg can1_dis_kbd_muxreg[] = {
                .reg = PAD_FUNCTION_EN_1,
                .mask = PMX_KBD_ROWCOL25_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK,
        },
 };
 
@@ -1763,29 +1997,64 @@ static struct spear_function can1_function = {
        .ngroups = ARRAY_SIZE(can1_grps),
 };
 
-/* Pad multiplexing for pci device */
-static const unsigned pci_sata_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
+/* Pad multiplexing for (ras-ip) pci device */
+static const unsigned pci_pins[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 18,
        19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
        37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
        55, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99 };
-#define PCI_SATA_MUXREG                                \
-       {                                       \
-               .reg = PAD_FUNCTION_EN_0,       \
-               .mask = PMX_MCI_DATA8_15_MASK,  \
-               .val = 0,                       \
-       }, {                                    \
-               .reg = PAD_FUNCTION_EN_1,       \
-               .mask = PMX_PCI_REG1_MASK,      \
-               .val = 0,                       \
-       }, {                                    \
-               .reg = PAD_FUNCTION_EN_2,       \
-               .mask = PMX_PCI_REG2_MASK,      \
-               .val = 0,                       \
-       }
 
-/* pad multiplexing for pcie0 device */
+static struct spear_muxreg pci_muxreg[] = {
+       {
+               .reg = PAD_FUNCTION_EN_0,
+               .mask = PMX_MCI_DATA8_15_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_1,
+               .mask = PMX_PCI_REG1_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_2,
+               .mask = PMX_PCI_REG2_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_0,
+               .mask = PMX_MCI_DATA8_15_MASK,
+               .val = PMX_MCI_DATA8_15_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_PCI_REG1_MASK,
+               .val = PMX_PCI_REG1_MASK,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_PCI_REG2_MASK,
+               .val = PMX_PCI_REG2_MASK,
+       },
+};
+
+static struct spear_modemux pci_modemux[] = {
+       {
+               .muxregs = pci_muxreg,
+               .nmuxregs = ARRAY_SIZE(pci_muxreg),
+       },
+};
+
+static struct spear_pingroup pci_pingroup = {
+       .name = "pci_grp",
+       .pins = pci_pins,
+       .npins = ARRAY_SIZE(pci_pins),
+       .modemuxs = pci_modemux,
+       .nmodemuxs = ARRAY_SIZE(pci_modemux),
+};
+
+static const char *const pci_grps[] = { "pci_grp" };
+static struct spear_function pci_function = {
+       .name = "pci",
+       .groups = pci_grps,
+       .ngroups = ARRAY_SIZE(pci_grps),
+};
+
+/* pad multiplexing for (fix-part) pcie0 device */
 static struct spear_muxreg pcie0_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(0),
@@ -1802,15 +2071,12 @@ static struct spear_modemux pcie0_modemux[] = {
 
 static struct spear_pingroup pcie0_pingroup = {
        .name = "pcie0_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie0_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie0_modemux),
 };
 
-/* pad multiplexing for pcie1 device */
+/* pad multiplexing for (fix-part) pcie1 device */
 static struct spear_muxreg pcie1_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(1),
@@ -1827,15 +2093,12 @@ static struct spear_modemux pcie1_modemux[] = {
 
 static struct spear_pingroup pcie1_pingroup = {
        .name = "pcie1_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie1_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie1_modemux),
 };
 
-/* pad multiplexing for pcie2 device */
+/* pad multiplexing for (fix-part) pcie2 device */
 static struct spear_muxreg pcie2_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = PCIE_CFG_VAL(2),
@@ -1852,22 +2115,20 @@ static struct spear_modemux pcie2_modemux[] = {
 
 static struct spear_pingroup pcie2_pingroup = {
        .name = "pcie2_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = pcie2_modemux,
        .nmodemuxs = ARRAY_SIZE(pcie2_modemux),
 };
 
-static const char *const pci_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp" };
-static struct spear_function pci_function = {
-       .name = "pci",
-       .groups = pci_grps,
-       .ngroups = ARRAY_SIZE(pci_grps),
+static const char *const pcie_grps[] = { "pcie0_grp", "pcie1_grp", "pcie2_grp"
+};
+static struct spear_function pcie_function = {
+       .name = "pci_express",
+       .groups = pcie_grps,
+       .ngroups = ARRAY_SIZE(pcie_grps),
 };
 
 /* pad multiplexing for sata0 device */
 static struct spear_muxreg sata0_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(0),
@@ -1884,15 +2145,12 @@ static struct spear_modemux sata0_modemux[] = {
 
 static struct spear_pingroup sata0_pingroup = {
        .name = "sata0_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata0_modemux,
        .nmodemuxs = ARRAY_SIZE(sata0_modemux),
 };
 
 /* pad multiplexing for sata1 device */
 static struct spear_muxreg sata1_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(1),
@@ -1909,15 +2167,12 @@ static struct spear_modemux sata1_modemux[] = {
 
 static struct spear_pingroup sata1_pingroup = {
        .name = "sata1_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata1_modemux,
        .nmodemuxs = ARRAY_SIZE(sata1_modemux),
 };
 
 /* pad multiplexing for sata2 device */
 static struct spear_muxreg sata2_muxreg[] = {
-       PCI_SATA_MUXREG,
        {
                .reg = PCIE_SATA_CFG,
                .mask = SATA_CFG_VAL(2),
@@ -1934,8 +2189,6 @@ static struct spear_modemux sata2_modemux[] = {
 
 static struct spear_pingroup sata2_pingroup = {
        .name = "sata2_grp",
-       .pins = pci_sata_pins,
-       .npins = ARRAY_SIZE(pci_sata_pins),
        .modemuxs = sata2_modemux,
        .nmodemuxs = ARRAY_SIZE(sata2_modemux),
 };
@@ -1957,6 +2210,14 @@ static struct spear_muxreg ssp1_dis_kbd_muxreg[] = {
                        PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
                        PMX_NFCE2_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_1,
+               .mask = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+                       PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+                       PMX_NFCE2_MASK,
+               .val = PMX_KBD_ROWCOL25_MASK | PMX_KBD_COL1_MASK |
+                       PMX_KBD_COL0_MASK | PMX_NFIO8_15_MASK | PMX_NFCE1_MASK |
+                       PMX_NFCE2_MASK,
        },
 };
 
@@ -1983,6 +2244,12 @@ static struct spear_muxreg ssp1_dis_sd_muxreg[] = {
                .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
                        PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+                       PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
+               .val = PMX_MCIADDR0ALE_MASK | PMX_MCIADDR2_MASK |
+                       PMX_MCICECF_MASK | PMX_MCICEXD_MASK,
        },
 };
 
@@ -2017,6 +2284,12 @@ static struct spear_muxreg gpt64_muxreg[] = {
                .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
                        | PMX_MCILEDS_MASK,
                .val = 0,
+       }, {
+               .reg = PAD_DIRECTION_SEL_2,
+               .mask = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+                       | PMX_MCILEDS_MASK,
+               .val = PMX_MCICDCF1_MASK | PMX_MCICDCF2_MASK | PMX_MCICDXD_MASK
+                       | PMX_MCILEDS_MASK,
        },
 };
 
@@ -2093,6 +2366,7 @@ static struct spear_pingroup *spear1310_pingroups[] = {
        &can0_dis_sd_pingroup,
        &can1_dis_sd_pingroup,
        &can1_dis_kbd_pingroup,
+       &pci_pingroup,
        &pcie0_pingroup,
        &pcie1_pingroup,
        &pcie2_pingroup,
@@ -2138,6 +2412,7 @@ static struct spear_function *spear1310_functions[] = {
        &can0_function,
        &can1_function,
        &pci_function,
+       &pcie_function,
        &sata_function,
        &ssp1_function,
        &gpt64_function,
index a0eb057e55bd3f91e390364a9187ee1f4e0768ab..0606b8cf3f2c10923014917d190d3f5ef73cd0aa 100644 (file)
@@ -213,7 +213,7 @@ static const struct pinctrl_pin_desc spear1340_pins[] = {
  * Pad multiplexing for making all pads as gpio's. This is done to override the
  * values passed from bootloader and start from scratch.
  */
-static const unsigned pads_as_gpio_pins[] = { 251 };
+static const unsigned pads_as_gpio_pins[] = { 12, 88, 89, 251 };
 static struct spear_muxreg pads_as_gpio_muxreg[] = {
        {
                .reg = PAD_FUNCTION_EN_1,
@@ -1692,7 +1692,43 @@ static struct spear_pingroup clcd_pingroup = {
        .nmodemuxs = ARRAY_SIZE(clcd_modemux),
 };
 
-static const char *const clcd_grps[] = { "clcd_grp" };
+/* Disable cld runtime to save panel damage */
+static struct spear_muxreg clcd_sleep_muxreg[] = {
+       {
+               .reg = PAD_SHARED_IP_EN_1,
+               .mask = ARM_TRACE_MASK | MIPHY_DBG_MASK,
+               .val = 0,
+       }, {
+               .reg = PAD_FUNCTION_EN_5,
+               .mask = CLCD_REG4_MASK | CLCD_AND_ARM_TRACE_REG4_MASK,
+               .val = 0x0,
+       }, {
+               .reg = PAD_FUNCTION_EN_6,
+               .mask = CLCD_AND_ARM_TRACE_REG5_MASK,
+               .val = 0x0,
+       }, {
+               .reg = PAD_FUNCTION_EN_7,
+               .mask = CLCD_AND_ARM_TRACE_REG6_MASK,
+               .val = 0x0,
+       },
+};
+
+static struct spear_modemux clcd_sleep_modemux[] = {
+       {
+               .muxregs = clcd_sleep_muxreg,
+               .nmuxregs = ARRAY_SIZE(clcd_sleep_muxreg),
+       },
+};
+
+static struct spear_pingroup clcd_sleep_pingroup = {
+       .name = "clcd_sleep_grp",
+       .pins = clcd_pins,
+       .npins = ARRAY_SIZE(clcd_pins),
+       .modemuxs = clcd_sleep_modemux,
+       .nmodemuxs = ARRAY_SIZE(clcd_sleep_modemux),
+};
+
+static const char *const clcd_grps[] = { "clcd_grp", "clcd_sleep_grp" };
 static struct spear_function clcd_function = {
        .name = "clcd",
        .groups = clcd_grps,
@@ -1893,6 +1929,7 @@ static struct spear_pingroup *spear1340_pingroups[] = {
        &sdhci_pingroup,
        &cf_pingroup,
        &xd_pingroup,
+       &clcd_sleep_pingroup,
        &clcd_pingroup,
        &arm_trace_pingroup,
        &miphy_dbg_pingroup,
index 020b1e0bdb3ee77c0e4fd254e91467c3436604e9..ca47b0e50780c52b884c7155349ad107fd098a93 100644 (file)
@@ -2239,6 +2239,10 @@ static struct spear_muxreg pwm2_pin_34_muxreg[] = {
                .reg = PMX_CONFIG_REG,
                .mask = PMX_SSP_CS_MASK,
                .val = 0,
+       }, {
+               .reg = MODE_CONFIG_REG,
+               .mask = PMX_PWM_MASK,
+               .val = PMX_PWM_MASK,
        }, {
                .reg = IP_SEL_PAD_30_39_REG,
                .mask = PMX_PL_34_MASK,
@@ -2956,9 +2960,9 @@ static struct spear_function mii2_function = {
 };
 
 /* Pad multiplexing for cadence mii 1_2 as smii or rmii device */
-static const unsigned smii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
+static const unsigned rmii0_1_pins[] = { 10, 11, 13, 14, 15, 16, 17, 18, 19, 20,
        21, 22, 23, 24, 25, 26, 27 };
-static const unsigned rmii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
+static const unsigned smii0_1_pins[] = { 10, 11, 21, 22, 23, 24, 25, 26, 27 };
 static struct spear_muxreg mii0_1_muxreg[] = {
        {
                .reg = PMX_CONFIG_REG,
index 31f44347f17ccfd32e3ca0f0913d85b2998aaa05..7860b36053c4523f69a5861f9fd832afae0983e8 100644 (file)
@@ -15,6 +15,7 @@
 #include "pinctrl-spear.h"
 
 /* pad mux declarations */
+#define PMX_PWM_MASK           (1 << 16)
 #define PMX_FIRDA_MASK         (1 << 14)
 #define PMX_I2C_MASK           (1 << 13)
 #define PMX_SSP_CS_MASK                (1 << 12)
index 258ca596e1bcce7fc0af5229fddd7b0bfef4174a..982d16b5a846f0e1575fca4d101c91f32fa93ba4 100644 (file)
@@ -6,7 +6,6 @@ menu "PPS support"
 
 config PPS
        tristate "PPS support"
-       depends on EXPERIMENTAL
        ---help---
          PPS (Pulse Per Second) is a special pulse provided by some GPS
          antennae. Userland can use it to get a high-precision time
index ffdf712f9a67c7e725b790ff3fed54fc43985901..1ea6f1dbbedd0323fe726b1364b930befff7df0e 100644 (file)
@@ -4,13 +4,9 @@
 
 menu "PTP clock support"
 
-comment "Enable Device Drivers -> PPS to see the PTP clock options."
-       depends on PPS=n
-
 config PTP_1588_CLOCK
        tristate "PTP clock support"
-       depends on EXPERIMENTAL
-       depends on PPS
+       select PPS
        help
          The IEEE 1588 standard defines a method to precisely
          synchronize distributed clocks over Ethernet networks. The
@@ -29,8 +25,9 @@ config PTP_1588_CLOCK
 
 config PTP_1588_CLOCK_GIANFAR
        tristate "Freescale eTSEC as PTP clock"
-       depends on PTP_1588_CLOCK
        depends on GIANFAR
+       select PTP_1588_CLOCK
+       default y
        help
          This driver adds support for using the eTSEC as a PTP
          clock. This clock is only useful if your PTP programs are
@@ -42,8 +39,9 @@ config PTP_1588_CLOCK_GIANFAR
 
 config PTP_1588_CLOCK_IXP46X
        tristate "Intel IXP46x as PTP clock"
-       depends on PTP_1588_CLOCK
        depends on IXP4XX_ETH
+       select PTP_1588_CLOCK
+       default y
        help
          This driver adds support for using the IXP46X as a PTP
          clock. This clock is only useful if your PTP programs are
@@ -54,13 +52,13 @@ config PTP_1588_CLOCK_IXP46X
          will be called ptp_ixp46x.
 
 comment "Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks."
-       depends on PTP_1588_CLOCK && (PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n)
+       depends on PHYLIB=n || NETWORK_PHY_TIMESTAMPING=n
 
 config DP83640_PHY
        tristate "Driver for the National Semiconductor DP83640 PHYTER"
-       depends on PTP_1588_CLOCK
        depends on NETWORK_PHY_TIMESTAMPING
        depends on PHYLIB
+       select PTP_1588_CLOCK
        ---help---
          Supports the DP83640 PHYTER with IEEE 1588 features.
 
@@ -74,8 +72,7 @@ config DP83640_PHY
 
 config PTP_1588_CLOCK_PCH
        tristate "Intel PCH EG20T as PTP clock"
-       depends on PTP_1588_CLOCK
-       depends on PCH_GBE
+       select PTP_1588_CLOCK
        help
          This driver adds support for using the PCH EG20T as a PTP
          clock. The hardware supports time stamping of PTP packets
index e7f301da290286153180fc5f1a9e02cdd9bb5f01..34a0c607318eb2173e4d1e44cb16aff2c889164d 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/posix-clock.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 
 #include "ptp_private.h"
 
@@ -33,9 +34,13 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
 {
        struct ptp_clock_caps caps;
        struct ptp_clock_request req;
+       struct ptp_sys_offset *sysoff = NULL;
        struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
        struct ptp_clock_info *ops = ptp->info;
+       struct ptp_clock_time *pct;
+       struct timespec ts;
        int enable, err = 0;
+       unsigned int i;
 
        switch (cmd) {
 
@@ -88,10 +93,45 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
                err = ops->enable(ops, &req, enable);
                break;
 
+       case PTP_SYS_OFFSET:
+               sysoff = kmalloc(sizeof(*sysoff), GFP_KERNEL);
+               if (!sysoff) {
+                       err = -ENOMEM;
+                       break;
+               }
+               if (copy_from_user(sysoff, (void __user *)arg,
+                                  sizeof(*sysoff))) {
+                       err = -EFAULT;
+                       break;
+               }
+               if (sysoff->n_samples > PTP_MAX_SAMPLES) {
+                       err = -EINVAL;
+                       break;
+               }
+               pct = &sysoff->ts[0];
+               for (i = 0; i < sysoff->n_samples; i++) {
+                       getnstimeofday(&ts);
+                       pct->sec = ts.tv_sec;
+                       pct->nsec = ts.tv_nsec;
+                       pct++;
+                       ptp->info->gettime(ptp->info, &ts);
+                       pct->sec = ts.tv_sec;
+                       pct->nsec = ts.tv_nsec;
+                       pct++;
+               }
+               getnstimeofday(&ts);
+               pct->sec = ts.tv_sec;
+               pct->nsec = ts.tv_nsec;
+               if (copy_to_user((void __user *)arg, sysoff, sizeof(*sysoff)))
+                       err = -EFAULT;
+               break;
+
        default:
                err = -ENOTTY;
                break;
        }
+
+       kfree(sysoff);
        return err;
 }
 
@@ -104,20 +144,23 @@ unsigned int ptp_poll(struct posix_clock *pc, struct file *fp, poll_table *wait)
        return queue_cnt(&ptp->tsevq) ? POLLIN : 0;
 }
 
+#define EXTTS_BUFSIZE (PTP_BUF_TIMESTAMPS * sizeof(struct ptp_extts_event))
+
 ssize_t ptp_read(struct posix_clock *pc,
                 uint rdflags, char __user *buf, size_t cnt)
 {
        struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
        struct timestamp_event_queue *queue = &ptp->tsevq;
-       struct ptp_extts_event event[PTP_BUF_TIMESTAMPS];
+       struct ptp_extts_event *event;
        unsigned long flags;
        size_t qcnt, i;
+       int result;
 
        if (cnt % sizeof(struct ptp_extts_event) != 0)
                return -EINVAL;
 
-       if (cnt > sizeof(event))
-               cnt = sizeof(event);
+       if (cnt > EXTTS_BUFSIZE)
+               cnt = EXTTS_BUFSIZE;
 
        cnt = cnt / sizeof(struct ptp_extts_event);
 
@@ -135,6 +178,12 @@ ssize_t ptp_read(struct posix_clock *pc,
                return -ENODEV;
        }
 
+       event = kmalloc(EXTTS_BUFSIZE, GFP_KERNEL);
+       if (!event) {
+               mutex_unlock(&ptp->tsevq_mux);
+               return -ENOMEM;
+       }
+
        spin_lock_irqsave(&queue->lock, flags);
 
        qcnt = queue_cnt(queue);
@@ -153,8 +202,10 @@ ssize_t ptp_read(struct posix_clock *pc,
 
        mutex_unlock(&ptp->tsevq_mux);
 
+       result = cnt;
        if (copy_to_user(buf, event, cnt))
-               return -EFAULT;
+               result = -EFAULT;
 
-       return cnt;
+       kfree(event);
+       return result;
 }
index c17ae22567e0494c381bf023c13e48dfc729aa8b..0c6fcb461faf7bb10df865bd3e49a5bd905313df 100644 (file)
@@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
 /**
  * rio_map_inb_region -- Map inbound memory region.
  * @mport: Master port.
- * @lstart: physical address of memory region to be mapped
+ * @local: physical address of memory region to be mapped
  * @rbase: RIO base address assigned to this window
  * @size: Size of the memory region
  * @rflags: Flags for mapping.
index 5c4829cba6a62de6168c6bb3c4913812e5e8b4e1..e872c8be080ed427a2e546efffee50c12acdd9fe 100644 (file)
@@ -1381,22 +1381,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
-/**
- * regulator_put - "free" the regulator source
- * @regulator: regulator source
- *
- * Note: drivers must ensure that all regulator_enable calls made on this
- * regulator source are balanced by regulator_disable calls prior to calling
- * this function.
- */
-void regulator_put(struct regulator *regulator)
+/* Locks held by regulator_put() */
+static void _regulator_put(struct regulator *regulator)
 {
        struct regulator_dev *rdev;
 
        if (regulator == NULL || IS_ERR(regulator))
                return;
 
-       mutex_lock(&regulator_list_mutex);
        rdev = regulator->rdev;
 
        debugfs_remove_recursive(regulator->debugfs);
@@ -1412,6 +1404,20 @@ void regulator_put(struct regulator *regulator)
        rdev->exclusive = 0;
 
        module_put(rdev->owner);
+}
+
+/**
+ * regulator_put - "free" the regulator source
+ * @regulator: regulator source
+ *
+ * Note: drivers must ensure that all regulator_enable calls made on this
+ * regulator source are balanced by regulator_disable calls prior to calling
+ * this function.
+ */
+void regulator_put(struct regulator *regulator)
+{
+       mutex_lock(&regulator_list_mutex);
+       _regulator_put(regulator);
        mutex_unlock(&regulator_list_mutex);
 }
 EXPORT_SYMBOL_GPL(regulator_put);
@@ -1974,7 +1980,7 @@ int regulator_is_supported_voltage(struct regulator *regulator,
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
                ret = regulator_get_voltage(regulator);
                if (ret >= 0)
-                       return (min_uV >= ret && ret <= max_uV);
+                       return (min_uV <= ret && ret <= max_uV);
                else
                        return ret;
        }
@@ -3365,7 +3371,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
                if (ret != 0) {
                        rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
                                 config->ena_gpio, ret);
-                       goto clean;
+                       goto wash;
                }
 
                rdev->ena_gpio = config->ena_gpio;
@@ -3445,10 +3451,11 @@ unset_supplies:
 
 scrub:
        if (rdev->supply)
-               regulator_put(rdev->supply);
+               _regulator_put(rdev->supply);
        if (rdev->ena_gpio)
                gpio_free(rdev->ena_gpio);
        kfree(rdev->constraints);
+wash:
        device_unregister(&rdev->dev);
        /* device core frees rdev */
        rdev = ERR_PTR(ret);
index 891cd6c61d0ae76112ccc0f6b6da3876d21569ad..4eed51044c5dd331f576fc1b1b71655e5f932366 100644 (file)
@@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev)
        if (imxdi->ioaddr == NULL)
                return -ENOMEM;
 
+       spin_lock_init(&imxdi->irq_lock);
+
        imxdi->irq = platform_get_irq(pdev, 0);
        if (imxdi->irq < 0)
                return imxdi->irq;
index 9ffb6d5f17aa0523473215db57edeccda1391a70..4ed343e4eb4155718cc31084eb6902a2ee84f570 100644 (file)
@@ -44,7 +44,6 @@
 #define RAW3215_NR_CCWS            3
 #define RAW3215_TIMEOUT            HZ/10     /* time for delayed output */
 
-#define RAW3215_FIXED      1         /* 3215 console device is not be freed */
 #define RAW3215_WORKING            4         /* set if a request is being worked on */
 #define RAW3215_THROTTLED   8        /* set if reading is disabled */
 #define RAW3215_STOPPED            16        /* set if writing is disabled */
@@ -339,8 +338,10 @@ static void raw3215_wakeup(unsigned long data)
        struct tty_struct *tty;
 
        tty = tty_port_tty_get(&raw->port);
-       tty_wakeup(tty);
-       tty_kref_put(tty);
+       if (tty) {
+               tty_wakeup(tty);
+               tty_kref_put(tty);
+       }
 }
 
 /*
@@ -629,8 +630,7 @@ static void raw3215_shutdown(struct raw3215_info *raw)
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
 
-       if (!(raw->port.flags & ASYNC_INITIALIZED) ||
-                       (raw->flags & RAW3215_FIXED))
+       if (!(raw->port.flags & ASYNC_INITIALIZED))
                return;
        /* Wait for outstanding requests, then free irq */
        spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
@@ -926,8 +926,6 @@ static int __init con3215_init(void)
        dev_set_drvdata(&cdev->dev, raw);
        cdev->handler = raw3215_irq;
 
-       raw->flags |= RAW3215_FIXED;
-
        /* Request the console irq */
        if (raw3215_startup(raw) != 0) {
                raw3215_free_info(raw);
index b4d572f65f079d93650cebd8ff5f7bb39bcb75d2..fd00afd8b850da2abaa916ba485dccd748939319 100644 (file)
@@ -377,7 +377,11 @@ static int css_evaluate_new_subchannel(struct subchannel_id schid, int slow)
                /* Will be done on the slow path. */
                return -EAGAIN;
        }
-       if (stsch_err(schid, &schib) || !css_sch_is_valid(&schib)) {
+       if (stsch_err(schid, &schib)) {
+               /* Subchannel is not provided. */
+               return -ENXIO;
+       }
+       if (!css_sch_is_valid(&schib)) {
                /* Unusable - ignore. */
                return 0;
        }
@@ -536,6 +540,7 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data)
                case -ENOMEM:
                case -EIO:
                        /* These should abort looping */
+                       idset_sch_del_subseq(slow_subchannel_set, schid);
                        break;
                default:
                        rc = 0;
index 33bb4d891e161174d01b8f6e0d6433883d5fb495..4af3dfe70ef53d075bb7cc96ea1064801ac777c6 100644 (file)
@@ -112,9 +112,6 @@ extern int for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *);
 extern void css_reiterate_subchannels(void);
 void css_update_ssd_info(struct subchannel *sch);
 
-#define __MAX_SUBCHANNEL 65535
-#define __MAX_SSID 3
-
 struct channel_subsystem {
        u8 cssid;
        int valid;
index fc916f5d731412c7146465d3ff29277979b69189..fd3143c291c6a630933d608c6c6e455b2be04a0d 100644 (file)
@@ -1424,7 +1424,7 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
        }
        if (device_is_disconnected(cdev))
                return IO_SCH_REPROBE;
-       if (cdev->online)
+       if (cdev->online && !cdev->private->flags.resuming)
                return IO_SCH_VERIFY;
        if (cdev->private->state == DEV_STATE_NOT_OPER)
                return IO_SCH_UNREG_ATTACH;
@@ -1469,12 +1469,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
                rc = 0;
                goto out_unlock;
        case IO_SCH_VERIFY:
-               if (cdev->private->flags.resuming == 1) {
-                       if (cio_enable_subchannel(sch, (u32)(addr_t)sch)) {
-                               ccw_device_set_notoper(cdev);
-                               break;
-                       }
-               }
                /* Trigger path verification. */
                io_subchannel_verify(sch);
                rc = 0;
index e6d5f8c49524d05f78f6548a2937b1747bd7ffe6..65d13e38803f9dddc11079b9a00176e7b94116d2 100644 (file)
@@ -1,9 +1,10 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
 #include <linux/vmalloc.h>
+#include <linux/bitmap.h>
 #include <linux/bitops.h>
 #include "idset.h"
 #include "css.h"
@@ -89,6 +90,14 @@ void idset_sch_del(struct idset *set, struct subchannel_id schid)
        idset_del(set, schid.ssid, schid.sch_no);
 }
 
+/* Clear ids starting from @schid up to end of subchannel set. */
+void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid)
+{
+       int pos = schid.ssid * set->num_id + schid.sch_no;
+
+       bitmap_clear(set->bitmap, pos, set->num_id - schid.sch_no);
+}
+
 int idset_sch_contains(struct idset *set, struct subchannel_id schid)
 {
        return idset_contains(set, schid.ssid, schid.sch_no);
@@ -111,20 +120,12 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid)
 
 int idset_is_empty(struct idset *set)
 {
-       int bitnum;
-
-       bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id);
-       if (bitnum >= set->num_ssid * set->num_id)
-               return 1;
-       return 0;
+       return bitmap_empty(set->bitmap, set->num_ssid * set->num_id);
 }
 
 void idset_add_set(struct idset *to, struct idset *from)
 {
-       unsigned long i, len;
+       int len = min(to->num_ssid * to->num_id, from->num_ssid * from->num_id);
 
-       len = min(__BITOPS_WORDS(to->num_ssid * to->num_id),
-                 __BITOPS_WORDS(from->num_ssid * from->num_id));
-       for (i = 0; i < len ; i++)
-               to->bitmap[i] |= from->bitmap[i];
+       bitmap_or(to->bitmap, to->bitmap, from->bitmap, len);
 }
index 3d943f03591e1b2180cc6fdd9c92e54c99a0d0e4..06d3bc01bb0934a52198349da2657e8787c46c13 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007
+ *    Copyright IBM Corp. 2007, 2012
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
@@ -17,6 +17,7 @@ void idset_fill(struct idset *set);
 struct idset *idset_sch_new(void);
 void idset_sch_add(struct idset *set, struct subchannel_id id);
 void idset_sch_del(struct idset *set, struct subchannel_id id);
+void idset_sch_del_subseq(struct idset *set, struct subchannel_id schid);
 int idset_sch_contains(struct idset *set, struct subchannel_id id);
 int idset_sch_get_first(struct idset *set, struct subchannel_id *id);
 int idset_is_empty(struct idset *set);
index a0a4afe537d079038e02b74e7606b66b0cedcee4..5c70a6599578d6940faff2e1791e89ef4d4b769b 100644 (file)
@@ -3018,10 +3018,8 @@ claw_remove_device(struct ccwgroup_device *cgdev)
 {
        struct claw_privbk *priv;
 
-       BUG_ON(!cgdev);
        CLAW_DBF_TEXT_(2, setup, "%s", dev_name(&cgdev->dev));
        priv = dev_get_drvdata(&cgdev->dev);
-       BUG_ON(!priv);
        dev_info(&cgdev->dev, " will be removed.\n");
        if (cgdev->state == CCWGROUP_ONLINE)
                claw_shutdown_device(cgdev);
index 98ea9cc6f1aaba9f442ecb4b46724c0f3f5ccd7b..817b68925dddbd5c097129e6da6be7f41c77bdc8 100644 (file)
@@ -1691,8 +1691,6 @@ static void ctcm_remove_device(struct ccwgroup_device *cgdev)
 {
        struct ctcm_priv *priv = dev_get_drvdata(&cgdev->dev);
 
-       BUG_ON(priv == NULL);
-
        CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO,
                        "removing device %p, proto : %d",
                        cgdev, priv->protocol);
index 05b734a2b5b7ae09f33f2a7307948e232e4f253f..2dbc77b5137bacb4e3d283ed6b0eea4fa45c8395 100644 (file)
@@ -1367,7 +1367,6 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg)
        struct mpc_group *grp;
        struct channel *wch;
 
-       BUG_ON(dev == NULL);
        CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name);
 
        priv  = dev->ml_priv;
@@ -1472,8 +1471,6 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg)
        struct channel *wch;
        struct channel *rch;
 
-       BUG_ON(dev == NULL);
-
        priv = dev->ml_priv;
        grp = priv->mpcg;
        wch = priv->channel[CTCM_WRITE];
index fa7adad6f9ba07f6e1948d775898866fbfe9d019..480fbeab0256ab3406feffd0dd93a2b70dc666c8 100644 (file)
@@ -933,6 +933,7 @@ int qeth_hdr_chk_and_bounce(struct sk_buff *, int);
 int qeth_configure_cq(struct qeth_card *, enum qeth_cq);
 int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);
 int qeth_query_ipassists(struct qeth_card *, enum qeth_prot_versions prot);
+void qeth_trace_features(struct qeth_card *);
 
 /* exports for OSN */
 int qeth_osn_assist(struct net_device *, void *, int);
index 3e25d31504560a79b75b782a45153190a7694ffa..638a57f4d8a11cc1ad040914f7991f2a780fefd9 100644 (file)
@@ -73,13 +73,13 @@ static inline const char *qeth_get_cardname(struct qeth_card *card)
        if (card->info.guestlan) {
                switch (card->info.type) {
                case QETH_CARD_TYPE_OSD:
-                       return " Guest LAN QDIO";
+                       return " Virtual NIC QDIO";
                case QETH_CARD_TYPE_IQD:
-                       return " Guest LAN Hiper";
+                       return " Virtual NIC Hiper";
                case QETH_CARD_TYPE_OSM:
-                       return " Guest LAN QDIO - OSM";
+                       return " Virtual NIC QDIO - OSM";
                case QETH_CARD_TYPE_OSX:
-                       return " Guest LAN QDIO - OSX";
+                       return " Virtual NIC QDIO - OSX";
                default:
                        return " unknown";
                }
@@ -108,13 +108,13 @@ const char *qeth_get_cardname_short(struct qeth_card *card)
        if (card->info.guestlan) {
                switch (card->info.type) {
                case QETH_CARD_TYPE_OSD:
-                       return "GuestLAN QDIO";
+                       return "Virt.NIC QDIO";
                case QETH_CARD_TYPE_IQD:
-                       return "GuestLAN Hiper";
+                       return "Virt.NIC Hiper";
                case QETH_CARD_TYPE_OSM:
-                       return "GuestLAN OSM";
+                       return "Virt.NIC OSM";
                case QETH_CARD_TYPE_OSX:
-                       return "GuestLAN OSX";
+                       return "Virt.NIC OSX";
                default:
                        return "unknown";
                }
@@ -383,7 +383,7 @@ static inline void qeth_cleanup_handled_pending(struct qeth_qdio_out_q *q,
                                qeth_release_skbs(c);
 
                                c = f->next_pending;
-                               BUG_ON(head->next_pending != f);
+                               WARN_ON_ONCE(head->next_pending != f);
                                head->next_pending = c;
                                kmem_cache_free(qeth_qdio_outbuf_cache, f);
                        } else {
@@ -415,13 +415,12 @@ static inline void qeth_qdio_handle_aob(struct qeth_card *card,
        buffer = (struct qeth_qdio_out_buffer *) aob->user1;
        QETH_CARD_TEXT_(card, 5, "%lx", aob->user1);
 
-       BUG_ON(buffer == NULL);
-
        if (atomic_cmpxchg(&buffer->state, QETH_QDIO_BUF_PRIMED,
                           QETH_QDIO_BUF_IN_CQ) == QETH_QDIO_BUF_PRIMED) {
                notification = TX_NOTIFY_OK;
        } else {
-               BUG_ON(atomic_read(&buffer->state) != QETH_QDIO_BUF_PENDING);
+               WARN_ON_ONCE(atomic_read(&buffer->state) !=
+                                                       QETH_QDIO_BUF_PENDING);
                atomic_set(&buffer->state, QETH_QDIO_BUF_IN_CQ);
                notification = TX_NOTIFY_DELAYED_OK;
        }
@@ -1131,7 +1130,7 @@ static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
                notify_general_error = 1;
 
        /* release may never happen from within CQ tasklet scope */
-       BUG_ON(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
+       WARN_ON_ONCE(atomic_read(&buf->state) == QETH_QDIO_BUF_IN_CQ);
 
        skb = skb_dequeue(&buf->skb_list);
        while (skb) {
@@ -2280,7 +2279,6 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
                unsigned long data)
 {
        struct qeth_cmd_buffer *iob;
-       int rc = 0;
 
        QETH_DBF_TEXT(SETUP, 2, "ulpstpcb");
 
@@ -2296,7 +2294,7 @@ static int qeth_ulp_setup_cb(struct qeth_card *card, struct qeth_reply *reply,
                iob->rc = -EMLINK;
        }
        QETH_DBF_TEXT_(SETUP, 2, "  rc%d", iob->rc);
-       return rc;
+       return 0;
 }
 
 static int qeth_ulp_setup(struct qeth_card *card)
@@ -2401,7 +2399,7 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
                card->qdio.out_qs[i]->queue_no = i;
                /* give outbound qeth_qdio_buffers their qdio_buffers */
                for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; ++j) {
-                       BUG_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
+                       WARN_ON(card->qdio.out_qs[i]->bufs[j] != NULL);
                        if (qeth_init_qdio_out_buf(card->qdio.out_qs[i], j))
                                goto out_freeoutqbufs;
                }
@@ -2942,16 +2940,33 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
        QETH_DBF_TEXT(SETUP, 2, "qipasscb");
 
        cmd = (struct qeth_ipa_cmd *) data;
+
+       switch (cmd->hdr.return_code) {
+       case IPA_RC_NOTSUPP:
+       case IPA_RC_L2_UNSUPPORTED_CMD:
+               QETH_DBF_TEXT(SETUP, 2, "ipaunsup");
+               card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
+               card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
+               return -0;
+       default:
+               if (cmd->hdr.return_code) {
+                       QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled "
+                                               "rc=%d\n",
+                                               dev_name(&card->gdev->dev),
+                                               cmd->hdr.return_code);
+                       return 0;
+               }
+       }
+
        if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
                card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
-       } else {
+       } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) {
                card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
-       }
-       QETH_DBF_TEXT(SETUP, 2, "suppenbl");
-       QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported);
-       QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled);
+       } else
+               QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected"
+                                       "\n", dev_name(&card->gdev->dev));
        return 0;
 }
 
@@ -3549,7 +3564,7 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
                if (queue->bufstates &&
                    (queue->bufstates[bidx].flags &
                     QDIO_OUTBUF_STATE_FLAG_PENDING) != 0) {
-                       BUG_ON(card->options.cq != QETH_CQ_ENABLED);
+                       WARN_ON_ONCE(card->options.cq != QETH_CQ_ENABLED);
 
                        if (atomic_cmpxchg(&buffer->state,
                                           QETH_QDIO_BUF_PRIMED,
@@ -3563,7 +3578,6 @@ void qeth_qdio_output_handler(struct ccw_device *ccwdev,
                        QETH_CARD_TEXT(queue->card, 5, "aob");
                        QETH_CARD_TEXT_(queue->card, 5, "%lx",
                                        virt_to_phys(buffer->aob));
-                       BUG_ON(bidx < 0 || bidx >= QDIO_MAX_BUFFERS_PER_Q);
                        if (qeth_init_qdio_out_buf(queue, bidx)) {
                                QETH_CARD_TEXT(card, 2, "outofbuf");
                                qeth_schedule_recovery(card);
@@ -4711,6 +4725,19 @@ static void qeth_core_free_card(struct qeth_card *card)
        kfree(card);
 }
 
+void qeth_trace_features(struct qeth_card *card)
+{
+       QETH_CARD_TEXT(card, 2, "features");
+       QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.supported_funcs);
+       QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa4.enabled_funcs);
+       QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.supported_funcs);
+       QETH_CARD_TEXT_(card, 2, "%x", card->options.ipa6.enabled_funcs);
+       QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.supported_funcs);
+       QETH_CARD_TEXT_(card, 2, "%x", card->options.adp.enabled_funcs);
+       QETH_CARD_TEXT_(card, 2, "%x", card->info.diagass_support);
+}
+EXPORT_SYMBOL_GPL(qeth_trace_features);
+
 static struct ccw_device_id qeth_ids[] = {
        {CCW_DEVICE_DEVTYPE(0x1731, 0x01, 0x1732, 0x01),
                                        .driver_info = QETH_CARD_TYPE_OSD},
index 2db409330c217f4d38f9d67bde47ba91fddc98ad..73195553f84b168442918a0c6697d9ef090999c2 100644 (file)
@@ -411,7 +411,7 @@ static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
        unsigned int len;
 
        *done = 0;
-       BUG_ON(!budget);
+       WARN_ON_ONCE(!budget);
        while (budget) {
                skb = qeth_core_get_next_skb(card,
                        &card->qdio.in_q->bufs[card->rx.b_index],
@@ -626,10 +626,13 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
        QETH_DBF_TEXT(SETUP, 2, "doL2init");
        QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
 
-       rc = qeth_query_setadapterparms(card);
-       if (rc) {
-               QETH_DBF_MESSAGE(2, "could not query adapter parameters on "
-                       "device %s: x%x\n", CARD_BUS_ID(card), rc);
+       if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
+               rc = qeth_query_setadapterparms(card);
+               if (rc) {
+                       QETH_DBF_MESSAGE(2, "could not query adapter "
+                               "parameters on device %s: x%x\n",
+                               CARD_BUS_ID(card), rc);
+               }
        }
 
        if (card->info.type == QETH_CARD_TYPE_IQD ||
@@ -676,7 +679,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
                return -ERESTARTSYS;
        }
        rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
-       if (!rc)
+       if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND))
                rc = qeth_l2_send_setmac(card, addr->sa_data);
        return rc ? -EINVAL : 0;
 }
@@ -970,7 +973,6 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
        int rc = 0;
        enum qeth_card_states recover_flag;
 
-       BUG_ON(!card);
        mutex_lock(&card->discipline_mutex);
        mutex_lock(&card->conf_mutex);
        QETH_DBF_TEXT(SETUP, 2, "setonlin");
@@ -983,6 +985,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)
                rc = -ENODEV;
                goto out_remove;
        }
+       qeth_trace_features(card);
 
        if (!card->dev && qeth_l2_setup_netdev(card)) {
                rc = -ENODEV;
@@ -1141,11 +1144,12 @@ static int qeth_l2_recover(void *ptr)
                dev_info(&card->gdev->dev,
                        "Device successfully recovered!\n");
        else {
-               rtnl_lock();
-               dev_close(card->dev);
-               rtnl_unlock();
-               dev_warn(&card->gdev->dev, "The qeth device driver "
-                       "failed to recover an error on the device\n");
+               if (rtnl_trylock()) {
+                       dev_close(card->dev);
+                       rtnl_unlock();
+                       dev_warn(&card->gdev->dev, "The qeth device driver "
+                               "failed to recover an error on the device\n");
+               }
        }
        qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
        qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
index 4cd310cb5bdf8f1c070cc1193294928015834a94..6e5eef01e66784b4eaa3e9357d81c7e89b96e47e 100644 (file)
@@ -1939,7 +1939,7 @@ static int qeth_l3_process_inbound_buffer(struct qeth_card *card,
        __u16 magic;
 
        *done = 0;
-       BUG_ON(!budget);
+       WARN_ON_ONCE(!budget);
        while (budget) {
                skb = qeth_core_get_next_skb(card,
                        &card->qdio.in_q->bufs[card->rx.b_index],
@@ -3334,7 +3334,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
        int rc = 0;
        enum qeth_card_states recover_flag;
 
-       BUG_ON(!card);
        mutex_lock(&card->discipline_mutex);
        mutex_lock(&card->conf_mutex);
        QETH_DBF_TEXT(SETUP, 2, "setonlin");
@@ -3347,6 +3346,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
                rc = -ENODEV;
                goto out_remove;
        }
+       qeth_trace_features(card);
 
        if (!card->dev && qeth_l3_setup_netdev(card)) {
                rc = -ENODEV;
@@ -3510,11 +3510,12 @@ static int qeth_l3_recover(void *ptr)
                dev_info(&card->gdev->dev,
                        "Device successfully recovered!\n");
        else {
-               rtnl_lock();
-               dev_close(card->dev);
-               rtnl_unlock();
-               dev_warn(&card->gdev->dev, "The qeth device driver "
-                       "failed to recover an error on the device\n");
+               if (rtnl_trylock()) {
+                       dev_close(card->dev);
+                       rtnl_unlock();
+                       dev_warn(&card->gdev->dev, "The qeth device driver "
+                               "failed to recover an error on the device\n");
+               }
        }
        qeth_clear_thread_start_bit(card, QETH_RECOVER_THREAD);
        qeth_clear_thread_running_bit(card, QETH_RECOVER_THREAD);
@@ -3713,9 +3714,9 @@ static void qeth_l3_unregister_notifiers(void)
 {
 
        QETH_DBF_TEXT(SETUP, 5, "unregnot");
-       BUG_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
+       WARN_ON(unregister_inetaddr_notifier(&qeth_l3_ip_notifier));
 #ifdef CONFIG_QETH_IPV6
-       BUG_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
+       WARN_ON(unregister_inet6addr_notifier(&qeth_l3_ip6_notifier));
 #endif /* QETH_IPV6 */
 }
 
index 207b7d7424435ccefd62700a07cd424a0e732c40..d8f990b6b332c62f41c90b747347c71f56ef1709 100644 (file)
@@ -157,7 +157,7 @@ static int smsg_pm_restore_thaw(struct device *dev)
 #ifdef CONFIG_PM_DEBUG
        printk(KERN_WARNING "smsg_pm_restore_thaw\n");
 #endif
-       if (smsg_path && iucv_path_connected) {
+       if (smsg_path && !iucv_path_connected) {
                memset(smsg_path, 0, sizeof(*smsg_path));
                smsg_path->msglim = 255;
                smsg_path->flags = 0;
index 6206a666a8ec6d76a5ecba29f5069d77be339b61..737554c37d9ec1ea2f794bf026d4ee96bb5f0c1b 100644 (file)
@@ -179,6 +179,7 @@ static void print_SCp(struct scsi_pointer *SCp, const char *prefix, const char *
                SCp->buffers_residual, suffix);
 }
 
+#ifdef CHECK_STRUCTURE
 static void fas216_dumpinfo(FAS216_Info *info)
 {
        static int used = 0;
@@ -223,7 +224,6 @@ static void fas216_dumpinfo(FAS216_Info *info)
                info->internal_done, info->magic_end);
 }
 
-#ifdef CHECK_STRUCTURE
 static void __fas216_checkmagic(FAS216_Info *info, const char *func)
 {
        int corruption = 0;
index d25f944b59c27a42e1c034a3e85b75a68326f5e9..fc6a5aabf66eadf9a90d2e6c11e2cc45018d6f8a 100644 (file)
@@ -21,6 +21,7 @@
 /*#define PSEUDO_DMA*/
 
 #define OAKSCSI_PUBLIC_RELEASE 1
+#define DONT_USE_INTR
 
 #define priv(host)                     ((struct NCR5380_hostdata *)(host)->hostdata)
 #define NCR5380_local_declare()                void __iomem *_base
index c1bafc3f3fb19bad3a1587c85345ef2c4fa9545f..9594ab62702b1786d51d7ac80f7e10b365b6ce61 100644 (file)
@@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq,
                                                                      frame_index,
                                                                      (void **)&frame_buffer);
 
-                       sci_controller_copy_sata_response(&ireq->stp.req,
+                       sci_controller_copy_sata_response(&ireq->stp.rsp,
                                                               frame_header,
                                                               frame_buffer);
 
index bd4708a422cd78b09fd8594ded593af775343398..20fd974f903afd5d4ae15c95db2549d49db52849 100644 (file)
@@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)
 int
 qla24xx_disable_vp(scsi_qla_host_t *vha)
 {
+       unsigned long flags;
        int ret;
 
        ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL);
@@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)
        atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
 
        /* Remove port id from vp target map */
+       spin_lock_irqsave(&vha->hw->vport_slock, flags);
        qlt_update_vp_map(vha, RESET_AL_PA);
+       spin_unlock_irqrestore(&vha->hw->vport_slock, flags);
 
        qla2x00_mark_vp_devices_dead(vha);
        atomic_set(&vha->vp_state, VP_FAILED);
index 0e09d8f433d1683e61ba61074d7c67b71919d970..62aa5584f64478d286e373414dd8b119315a5204 100644 (file)
@@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,
        int pmap_len;
        fc_port_t *fcport;
        int global_resets;
+       unsigned long flags;
 
 retry:
        global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count);
@@ -625,10 +626,10 @@ retry:
            sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,
            fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id);
 
-       sess->s_id = fcport->d_id;
-       sess->loop_id = fcport->loop_id;
-       sess->conf_compl_supported = !!(fcport->flags &
-           FCF_CONF_COMP_SUPPORTED);
+       spin_lock_irqsave(&ha->hardware_lock, flags);
+       ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                               (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        res = true;
 
@@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(
                                qlt_undelete_sess(sess);
 
                        kref_get(&sess->se_sess->sess_kref);
-                       sess->s_id = fcport->d_id;
-                       sess->loop_id = fcport->loop_id;
-                       sess->conf_compl_supported = !!(fcport->flags &
-                           FCF_CONF_COMP_SUPPORTED);
+                       ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                                               (fcport->flags & FCF_CONF_COMP_SUPPORTED));
+
                        if (sess->local && !local)
                                sess->local = 0;
                        spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(
         */
        kref_get(&sess->se_sess->sess_kref);
 
-       sess->conf_compl_supported = !!(fcport->flags &
-           FCF_CONF_COMP_SUPPORTED);
+       sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);
        BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));
        memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name));
 
@@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
                        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,
                            "Reappeared sess %p\n", sess);
                }
-               sess->s_id = fcport->d_id;
-               sess->loop_id = fcport->loop_id;
-               sess->conf_compl_supported = !!(fcport->flags &
-                   FCF_CONF_COMP_SUPPORTED);
+               ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id,
+                                       (fcport->flags & FCF_CONF_COMP_SUPPORTED));
        }
 
        if (sess && sess->local) {
index 170af1571214095fe82db73fa52f520c16a8197b..bad749561ec2ae4fe57e3ea28763ec627f0b18f1 100644 (file)
@@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {
 
        int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
                                        void *, uint8_t *, uint16_t);
+       void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
        struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
                                                const uint16_t);
        struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *,
index 2358c16c4c8ea8a0cdb85c33c2c97a5b4e65c400..3d74f2f39ae18954ac825f4599b689d770f494cf 100644 (file)
@@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)
                                struct tcm_qla2xxx_tpg, se_tpg);
        struct tcm_qla2xxx_lport *lport = tpg->lport;
 
-       return &lport->lport_name[0];
+       return lport->lport_naa_name;
 }
 
 static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg)
@@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(
        return 0;
 }
 
+static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id,
+                                   uint16_t loop_id, bool conf_compl_supported)
+{
+       struct qla_tgt *tgt = sess->tgt;
+       struct qla_hw_data *ha = tgt->ha;
+       struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr;
+       struct se_node_acl *se_nacl = sess->se_sess->se_node_acl;
+       struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
+                       struct tcm_qla2xxx_nacl, se_node_acl);
+       u32 key;
+
+
+       if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24)
+               pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n",
+                       sess,
+                       sess->port_name[0], sess->port_name[1],
+                       sess->port_name[2], sess->port_name[3],
+                       sess->port_name[4], sess->port_name[5],
+                       sess->port_name[6], sess->port_name[7],
+                       sess->loop_id, loop_id,
+                       sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+                       s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+
+       if (sess->loop_id != loop_id) {
+               /*
+                * Because we can shuffle loop IDs around and we
+                * update different sessions non-atomically, we might
+                * have overwritten this session's old loop ID
+                * already, and we might end up overwriting some other
+                * session that will be updated later.  So we have to
+                * be extra careful and we can't warn about those things...
+                */
+               if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl)
+                       lport->lport_loopid_map[sess->loop_id].se_nacl = NULL;
+
+               lport->lport_loopid_map[loop_id].se_nacl = se_nacl;
+
+               sess->loop_id = loop_id;
+       }
+
+       if (sess->s_id.b24 != s_id.b24) {
+               key = (((u32) sess->s_id.b.domain << 16) |
+                      ((u32) sess->s_id.b.area   <<  8) |
+                      ((u32) sess->s_id.b.al_pa));
+
+               if (btree_lookup32(&lport->lport_fcport_map, key))
+                       WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl,
+                            "Found wrong se_nacl when updating s_id %x:%x:%x\n",
+                            sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+               else
+                       WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n",
+                            sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa);
+
+               key = (((u32) s_id.b.domain << 16) |
+                      ((u32) s_id.b.area   <<  8) |
+                      ((u32) s_id.b.al_pa));
+
+               if (btree_lookup32(&lport->lport_fcport_map, key)) {
+                       WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n",
+                            s_id.b.domain, s_id.b.area, s_id.b.al_pa);
+                       btree_update32(&lport->lport_fcport_map, key, se_nacl);
+               } else {
+                       btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC);
+               }
+
+               sess->s_id = s_id;
+               nacl->nport_id = key;
+       }
+
+       sess->conf_compl_supported = conf_compl_supported;
+}
+
 /*
  * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
  */
@@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
        .free_cmd               = tcm_qla2xxx_free_cmd,
        .free_mcmd              = tcm_qla2xxx_free_mcmd,
        .free_session           = tcm_qla2xxx_free_session,
+       .update_sess            = tcm_qla2xxx_update_sess,
        .check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,
        .find_sess_by_s_id      = tcm_qla2xxx_find_sess_by_s_id,
        .find_sess_by_loop_id   = tcm_qla2xxx_find_sess_by_loop_id,
@@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(
        lport->lport_wwpn = wwpn;
        tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,
                                wwpn);
+       sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);
 
        ret = tcm_qla2xxx_init_lport(lport);
        if (ret != 0)
@@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(
        lport->lport_npiv_wwnn = npiv_wwnn;
        tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],
                        TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn);
+       sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);
 
 /* FIXME: tcm_qla2xxx_npiv_make_lport */
        ret = -ENOSYS;
index 8254981033524466bc372ac4bbd067aa5d19cc5b..9ba075fe9781f0148dca9aa73b6525e554a91154 100644 (file)
@@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {
        u64 lport_npiv_wwnn;
        /* ASCII formatted WWPN for FC Target Lport */
        char lport_name[TCM_QLA2XXX_NAMELEN];
+       /* ASCII formatted naa WWPN for VPD page 83 etc */
+       char lport_naa_name[TCM_QLA2XXX_NAMELEN];
        /* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */
        char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];
        /* map for fc_port pointers in 24-bit FC Port ID space */
index b191dd549207db3ac2c25fd16e3b6a87559cb047..71fddbc60f181feb15bbd30994f16dc5b35d4831 100644 (file)
@@ -1294,26 +1294,19 @@ static struct scsi_host_template qpti_template = {
 static const struct of_device_id qpti_match[];
 static int __devinit qpti_sbus_probe(struct platform_device *op)
 {
-       const struct of_device_id *match;
-       struct scsi_host_template *tpnt;
        struct device_node *dp = op->dev.of_node;
        struct Scsi_Host *host;
        struct qlogicpti *qpti;
        static int nqptis;
        const char *fcode;
 
-       match = of_match_device(qpti_match, &op->dev);
-       if (!match)
-               return -EINVAL;
-       tpnt = match->data;
-
        /* Sometimes Antares cards come up not completely
         * setup, and we get a report of a zero IRQ.
         */
        if (op->archdata.irqs[0] == 0)
                return -ENODEV;
 
-       host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti));
+       host = scsi_host_alloc(&qpti_template, sizeof(struct qlogicpti));
        if (!host)
                return -ENOMEM;
 
@@ -1445,19 +1438,15 @@ static int __devexit qpti_sbus_remove(struct platform_device *op)
 static const struct of_device_id qpti_match[] = {
        {
                .name = "ptisp",
-               .data = &qpti_template,
        },
        {
                .name = "PTI,ptisp",
-               .data = &qpti_template,
        },
        {
                .name = "QLGC,isp",
-               .data = &qpti_template,
        },
        {
                .name = "SUNW,isp",
-               .data = &qpti_template,
        },
        {},
 };
index 2936b447cae93bc544fc054c862ecd6d1abb92c6..2c0d0ec8150b62d62d8ca3ca9ecc777a950a7c0a 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/cpu.h>
 #include <linux/mutex.h>
 #include <linux/async.h>
+#include <asm/unaligned.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -1061,6 +1062,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
 }
 EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
 
+/**
+ * scsi_report_opcode - Find out if a given command opcode is supported
+ * @sdev:      scsi device to query
+ * @buffer:    scratch buffer (must be at least 20 bytes long)
+ * @len:       length of buffer
+ * @opcode:    opcode for command to look up
+ *
+ * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
+ * opcode. Returns 0 if RSOC fails or if the command opcode is
+ * unsupported. Returns 1 if the device claims to support the command.
+ */
+int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+                      unsigned int len, unsigned char opcode)
+{
+       unsigned char cmd[16];
+       struct scsi_sense_hdr sshdr;
+       int result;
+
+       if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
+               return 0;
+
+       memset(cmd, 0, 16);
+       cmd[0] = MAINTENANCE_IN;
+       cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
+       cmd[2] = 1;             /* One command format */
+       cmd[3] = opcode;
+       put_unaligned_be32(len, &cmd[6]);
+       memset(buffer, 0, len);
+
+       result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+                                 &sshdr, 30 * HZ, 3, NULL);
+
+       if (result && scsi_sense_valid(&sshdr) &&
+           sshdr.sense_key == ILLEGAL_REQUEST &&
+           (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
+               return 0;
+
+       if ((buffer[1] & 3) == 3) /* Command supported */
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL(scsi_report_opcode);
+
 /**
  * scsi_device_get  -  get an additional reference to a scsi_device
  * @sdev:      device to get a reference to
index da36a3a81a9ee2206f753a04d4fbbe91b883e00a..9032e910bca3044055ed23310b38c126318736bb 100644 (file)
@@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                action = ACTION_FAIL;
                                error = -EILSEQ;
                        /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
-                       } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
-                                  (cmd->cmnd[0] == UNMAP ||
-                                   cmd->cmnd[0] == WRITE_SAME_16 ||
-                                   cmd->cmnd[0] == WRITE_SAME)) {
-                               description = "Discard failure";
+                       } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+                               switch (cmd->cmnd[0]) {
+                               case UNMAP:
+                                       description = "Discard failure";
+                                       break;
+                               case WRITE_SAME:
+                               case WRITE_SAME_16:
+                                       if (cmd->cmnd[1] & 0x8)
+                                               description = "Discard failure";
+                                       else
+                                               description =
+                                                       "Write same failure";
+                                       break;
+                               default:
+                                       description = "Invalid command failure";
+                                       break;
+                               }
                                action = ACTION_FAIL;
                                error = -EREMOTEIO;
                        } else
index 12f6fdfc11474a9363ae6c641959832d2c1d6440..352bc77b7c886fb80c057019c3edc2d5b95b7d7e 100644 (file)
@@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 #endif
 
 static void sd_config_discard(struct scsi_disk *, unsigned int);
+static void sd_config_write_same(struct scsi_disk *);
 static int  sd_revalidate_disk(struct gendisk *);
 static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
@@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev,
        return err ? err : count;
 }
 
+static ssize_t
+sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+       return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks);
+}
+
+static ssize_t
+sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+       struct scsi_device *sdp = sdkp->device;
+       unsigned long max;
+       int err;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (sdp->type != TYPE_DISK)
+               return -EINVAL;
+
+       err = kstrtoul(buf, 10, &max);
+
+       if (err)
+               return err;
+
+       if (max == 0)
+               sdp->no_write_same = 1;
+       else if (max <= SD_MAX_WS16_BLOCKS)
+               sdkp->max_ws_blocks = max;
+
+       sd_config_write_same(sdkp);
+
+       return count;
+}
+
 static struct device_attribute sd_disk_attrs[] = {
        __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
               sd_store_cache_type),
@@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = {
        __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
        __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
               sd_store_provisioning_mode),
+       __ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR,
+              sd_show_write_same_blocks, sd_store_write_same_blocks),
        __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
               sd_show_max_medium_access_timeouts,
               sd_store_max_medium_access_timeouts),
@@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
                return;
 
        case SD_LBP_UNMAP:
-               max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff);
+               max_blocks = min_not_zero(sdkp->max_unmap_blocks,
+                                         (u32)SD_MAX_WS16_BLOCKS);
                break;
 
        case SD_LBP_WS16:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS16_BLOCKS);
                break;
 
        case SD_LBP_WS10:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS10_BLOCKS);
                break;
 
        case SD_LBP_ZERO:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS10_BLOCKS);
                q->limits.discard_zeroes_data = 1;
                break;
        }
@@ -583,29 +629,26 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
 }
 
 /**
- * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device
+ * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device
  * @sdp: scsi device to operate one
  * @rq: Request to prepare
  *
  * Will issue either UNMAP or WRITE SAME(16) depending on preference
  * indicated by target device.
  **/
-static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
+static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 {
        struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
-       struct bio *bio = rq->bio;
-       sector_t sector = bio->bi_sector;
-       unsigned int nr_sectors = bio_sectors(bio);
+       sector_t sector = blk_rq_pos(rq);
+       unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
        unsigned int len;
        int ret;
        char *buf;
        struct page *page;
 
-       if (sdkp->device->sector_size == 4096) {
-               sector >>= 3;
-               nr_sectors >>= 3;
-       }
-
+       sector >>= ilog2(sdp->sector_size) - 9;
+       nr_sectors >>= ilog2(sdp->sector_size) - 9;
        rq->timeout = SD_TIMEOUT;
 
        memset(rq->cmd, 0, rq->cmd_len);
@@ -660,6 +703,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
        blk_add_request_payload(rq, page, len);
        ret = scsi_setup_blk_pc_cmnd(sdp, rq);
        rq->buffer = page_address(page);
+       rq->__data_len = nr_bytes;
 
 out:
        if (ret != BLKPREP_OK) {
@@ -669,6 +713,83 @@ out:
        return ret;
 }
 
+static void sd_config_write_same(struct scsi_disk *sdkp)
+{
+       struct request_queue *q = sdkp->disk->queue;
+       unsigned int logical_block_size = sdkp->device->sector_size;
+       unsigned int blocks = 0;
+
+       if (sdkp->device->no_write_same) {
+               sdkp->max_ws_blocks = 0;
+               goto out;
+       }
+
+       /* Some devices can not handle block counts above 0xffff despite
+        * supporting WRITE SAME(16). Consequently we default to 64k
+        * blocks per I/O unless the device explicitly advertises a
+        * bigger limit.
+        */
+       if (sdkp->max_ws_blocks == 0)
+               sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
+
+       if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
+               blocks = min_not_zero(sdkp->max_ws_blocks,
+                                     (u32)SD_MAX_WS16_BLOCKS);
+       else
+               blocks = min_not_zero(sdkp->max_ws_blocks,
+                                     (u32)SD_MAX_WS10_BLOCKS);
+
+out:
+       blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
+}
+
+/**
+ * sd_setup_write_same_cmnd - write the same data to multiple blocks
+ * @sdp: scsi device to operate one
+ * @rq: Request to prepare
+ *
+ * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
+ * preference indicated by target device.
+ **/
+static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq)
+{
+       struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+       struct bio *bio = rq->bio;
+       sector_t sector = blk_rq_pos(rq);
+       unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
+       int ret;
+
+       if (sdkp->device->no_write_same)
+               return BLKPREP_KILL;
+
+       BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size);
+
+       sector >>= ilog2(sdp->sector_size) - 9;
+       nr_sectors >>= ilog2(sdp->sector_size) - 9;
+
+       rq->__data_len = sdp->sector_size;
+       rq->timeout = SD_WRITE_SAME_TIMEOUT;
+       memset(rq->cmd, 0, rq->cmd_len);
+
+       if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
+               rq->cmd_len = 16;
+               rq->cmd[0] = WRITE_SAME_16;
+               put_unaligned_be64(sector, &rq->cmd[2]);
+               put_unaligned_be32(nr_sectors, &rq->cmd[10]);
+       } else {
+               rq->cmd_len = 10;
+               rq->cmd[0] = WRITE_SAME;
+               put_unaligned_be32(sector, &rq->cmd[2]);
+               put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+       }
+
+       ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+       rq->__data_len = nr_bytes;
+
+       return ret;
+}
+
 static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 {
        rq->timeout = SD_FLUSH_TIMEOUT;
@@ -712,7 +833,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
         * block PC requests to make life easier.
         */
        if (rq->cmd_flags & REQ_DISCARD) {
-               ret = scsi_setup_discard_cmnd(sdp, rq);
+               ret = sd_setup_discard_cmnd(sdp, rq);
+               goto out;
+       } else if (rq->cmd_flags & REQ_WRITE_SAME) {
+               ret = sd_setup_write_same_cmnd(sdp, rq);
                goto out;
        } else if (rq->cmd_flags & REQ_FLUSH) {
                ret = scsi_setup_flush_cmnd(sdp, rq);
@@ -1482,12 +1606,21 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt);
        struct scsi_sense_hdr sshdr;
        struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
+       struct request *req = SCpnt->request;
        int sense_valid = 0;
        int sense_deferred = 0;
        unsigned char op = SCpnt->cmnd[0];
+       unsigned char unmap = SCpnt->cmnd[1] & 8;
 
-       if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result)
-               scsi_set_resid(SCpnt, 0);
+       if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) {
+               if (!result) {
+                       good_bytes = blk_rq_bytes(req);
+                       scsi_set_resid(SCpnt, 0);
+               } else {
+                       good_bytes = 0;
+                       scsi_set_resid(SCpnt, blk_rq_bytes(req));
+               }
+       }
 
        if (result) {
                sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr);
@@ -1536,9 +1669,25 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                if (sshdr.asc == 0x10)  /* DIX: Host detected corruption */
                        good_bytes = sd_completed_bytes(SCpnt);
                /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
-               if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
-                   (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME))
-                       sd_config_discard(sdkp, SD_LBP_DISABLE);
+               if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+                       switch (op) {
+                       case UNMAP:
+                               sd_config_discard(sdkp, SD_LBP_DISABLE);
+                               break;
+                       case WRITE_SAME_16:
+                       case WRITE_SAME:
+                               if (unmap)
+                                       sd_config_discard(sdkp, SD_LBP_DISABLE);
+                               else {
+                                       sdkp->device->no_write_same = 1;
+                                       sd_config_write_same(sdkp);
+
+                                       good_bytes = 0;
+                                       req->__data_len = blk_rq_bytes(req);
+                                       req->cmd_flags |= REQ_QUIET;
+                               }
+                       }
+               }
                break;
        default:
                break;
@@ -2374,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
        if (buffer[3] == 0x3c) {
                unsigned int lba_count, desc_count;
 
-               sdkp->max_ws_blocks =
-                       (u32) min_not_zero(get_unaligned_be64(&buffer[36]),
-                                          (u64)0xffffffff);
+               sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]);
 
                if (!sdkp->lbpme)
                        goto out;
@@ -2469,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
        kfree(buffer);
 }
 
+static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+       if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
+                              WRITE_SAME_16))
+               sdkp->ws16 = 1;
+}
+
 static int sd_try_extended_inquiry(struct scsi_device *sdp)
 {
        /*
@@ -2528,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
                sd_read_write_protect_flag(sdkp, buffer);
                sd_read_cache_type(sdkp, buffer);
                sd_read_app_tag_own(sdkp, buffer);
+               sd_read_write_same(sdkp, buffer);
        }
 
        sdkp->first_scan = 0;
@@ -2545,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
        blk_queue_flush(sdkp->disk->queue, flush);
 
        set_capacity(disk, sdkp->capacity);
+       sd_config_write_same(sdkp);
        kfree(buffer);
 
  out:
index 47c52a6d733c0f757b4ef42236e89fba172b857c..74a1e4ca5401f9a58e6e705bb2fc8a99fcd04a0f 100644 (file)
@@ -14,6 +14,7 @@
 #define SD_TIMEOUT             (30 * HZ)
 #define SD_MOD_TIMEOUT         (75 * HZ)
 #define SD_FLUSH_TIMEOUT       (60 * HZ)
+#define SD_WRITE_SAME_TIMEOUT  (120 * HZ)
 
 /*
  * Number of allowed retries
@@ -38,6 +39,11 @@ enum {
        SD_MEMPOOL_SIZE = 2,    /* CDB pool size */
 };
 
+enum {
+       SD_MAX_WS10_BLOCKS = 0xffff,
+       SD_MAX_WS16_BLOCKS = 0x7fffff,
+};
+
 enum {
        SD_LBP_FULL = 0,        /* Full logical block provisioning */
        SD_LBP_UNMAP,           /* Use UNMAP command */
@@ -77,6 +83,7 @@ struct scsi_disk {
        unsigned        lbpws : 1;
        unsigned        lbpws10 : 1;
        unsigned        lbpvpd : 1;
+       unsigned        ws16 : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
index f892ae1d212a10a6671b88c60d8ec8a3ad9b822c..114390f967d26e0426a93c3d2e7adf76ba7d3371 100644 (file)
@@ -75,54 +75,61 @@ unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle
 static unsigned long test_8(unsigned long addr, unsigned long h,
                            unsigned long ignore)
 {
-       return intc_get_field_from_handle(__raw_readb(addr), h);
+       void __iomem *ptr = (void __iomem *)addr;
+       return intc_get_field_from_handle(__raw_readb(ptr), h);
 }
 
 static unsigned long test_16(unsigned long addr, unsigned long h,
                             unsigned long ignore)
 {
-       return intc_get_field_from_handle(__raw_readw(addr), h);
+       void __iomem *ptr = (void __iomem *)addr;
+       return intc_get_field_from_handle(__raw_readw(ptr), h);
 }
 
 static unsigned long test_32(unsigned long addr, unsigned long h,
                             unsigned long ignore)
 {
-       return intc_get_field_from_handle(__raw_readl(addr), h);
+       void __iomem *ptr = (void __iomem *)addr;
+       return intc_get_field_from_handle(__raw_readl(ptr), h);
 }
 
 static unsigned long write_8(unsigned long addr, unsigned long h,
                             unsigned long data)
 {
-       __raw_writeb(intc_set_field_from_handle(0, data, h), addr);
-       (void)__raw_readb(addr);        /* Defeat write posting */
+       void __iomem *ptr = (void __iomem *)addr;
+       __raw_writeb(intc_set_field_from_handle(0, data, h), ptr);
+       (void)__raw_readb(ptr); /* Defeat write posting */
        return 0;
 }
 
 static unsigned long write_16(unsigned long addr, unsigned long h,
                              unsigned long data)
 {
-       __raw_writew(intc_set_field_from_handle(0, data, h), addr);
-       (void)__raw_readw(addr);        /* Defeat write posting */
+       void __iomem *ptr = (void __iomem *)addr;
+       __raw_writew(intc_set_field_from_handle(0, data, h), ptr);
+       (void)__raw_readw(ptr); /* Defeat write posting */
        return 0;
 }
 
 static unsigned long write_32(unsigned long addr, unsigned long h,
                              unsigned long data)
 {
-       __raw_writel(intc_set_field_from_handle(0, data, h), addr);
-       (void)__raw_readl(addr);        /* Defeat write posting */
+       void __iomem *ptr = (void __iomem *)addr;
+       __raw_writel(intc_set_field_from_handle(0, data, h), ptr);
+       (void)__raw_readl(ptr); /* Defeat write posting */
        return 0;
 }
 
 static unsigned long modify_8(unsigned long addr, unsigned long h,
                              unsigned long data)
 {
+       void __iomem *ptr = (void __iomem *)addr;
        unsigned long flags;
        unsigned int value;
        local_irq_save(flags);
-       value = intc_set_field_from_handle(__raw_readb(addr), data, h);
-       __raw_writeb(value, addr);
-       (void)__raw_readb(addr);        /* Defeat write posting */
+       value = intc_set_field_from_handle(__raw_readb(ptr), data, h);
+       __raw_writeb(value, ptr);
+       (void)__raw_readb(ptr); /* Defeat write posting */
        local_irq_restore(flags);
        return 0;
 }
@@ -130,12 +137,13 @@ static unsigned long modify_8(unsigned long addr, unsigned long h,
 static unsigned long modify_16(unsigned long addr, unsigned long h,
                               unsigned long data)
 {
+       void __iomem *ptr = (void __iomem *)addr;
        unsigned long flags;
        unsigned int value;
        local_irq_save(flags);
-       value = intc_set_field_from_handle(__raw_readw(addr), data, h);
-       __raw_writew(value, addr);
-       (void)__raw_readw(addr);        /* Defeat write posting */
+       value = intc_set_field_from_handle(__raw_readw(ptr), data, h);
+       __raw_writew(value, ptr);
+       (void)__raw_readw(ptr); /* Defeat write posting */
        local_irq_restore(flags);
        return 0;
 }
@@ -143,12 +151,13 @@ static unsigned long modify_16(unsigned long addr, unsigned long h,
 static unsigned long modify_32(unsigned long addr, unsigned long h,
                               unsigned long data)
 {
+       void __iomem *ptr = (void __iomem *)addr;
        unsigned long flags;
        unsigned int value;
        local_irq_save(flags);
-       value = intc_set_field_from_handle(__raw_readl(addr), data, h);
-       __raw_writel(value, addr);
-       (void)__raw_readl(addr);        /* Defeat write posting */
+       value = intc_set_field_from_handle(__raw_readl(ptr), data, h);
+       __raw_writel(value, ptr);
+       (void)__raw_readl(ptr); /* Defeat write posting */
        local_irq_restore(flags);
        return 0;
 }
index 012df2676a267950b77c713eb23afc56b1a341c8..46427b48e2f1767fcc1fa8732aff3536fb38ec66 100644 (file)
@@ -83,7 +83,7 @@ static void intc_mask_ack(struct irq_data *data)
        unsigned int irq = data->irq;
        struct intc_desc_int *d = get_intc_desc(irq);
        unsigned long handle = intc_get_ack_handle(irq);
-       unsigned long addr;
+       void __iomem *addr;
 
        intc_disable(data);
 
@@ -91,7 +91,7 @@ static void intc_mask_ack(struct irq_data *data)
        if (handle) {
                unsigned int value;
 
-               addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+               addr = (void __iomem *)INTC_REG(d, _INTC_ADDR_D(handle), 0);
                value = intc_set_field_from_handle(0, 1, handle);
 
                switch (_INTC_FN(handle)) {
index edf1360ab09e5be8311b7338a28d75ce8bbb46a3..86dd04d6bc873dfa30f0bab1148bd863aac818fc 100644 (file)
@@ -323,6 +323,7 @@ static int mxs_spi_txrx_dma(struct mxs_spi *spi, int cs,
        if (!ret) {
                dev_err(ssp->dev, "DMA transfer timeout\n");
                ret = -ETIMEDOUT;
+               dmaengine_terminate_all(ssp->dmach);
                goto err_vmalloc;
        }
 
@@ -480,7 +481,7 @@ static int mxs_spi_transfer_one(struct spi_master *master,
                first = last = 0;
        }
 
-       m->status = 0;
+       m->status = status;
        spi_finalize_current_message(master);
 
        return status;
index 919464102d33afb2d493ace07c81c80403d1d51d..a1db91a99b89a670cb7979c5fd758c90796aa2a9 100644 (file)
@@ -2186,8 +2186,6 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
        printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
               adev->res.start, pl022->virtbase);
 
-       pm_runtime_resume(dev);
-
        pl022->clk = devm_clk_get(&adev->dev, NULL);
        if (IS_ERR(pl022->clk)) {
                status = PTR_ERR(pl022->clk);
@@ -2292,7 +2290,6 @@ pl022_remove(struct amba_device *adev)
 
        clk_disable(pl022->clk);
        clk_unprepare(pl022->clk);
-       pm_runtime_disable(&adev->dev);
        amba_release_regions(adev);
        tasklet_disable(&pl022->pump_transfers);
        spi_unregister_master(pl022->master);
index 4894bde4bbffea3f65d7ff30db4277c92ab79587..30faf6d4ab9135c84ecd8f359626ddd75e896b60 100644 (file)
@@ -147,8 +147,6 @@ struct rspi_data {
        unsigned char spsr;
 
        /* for dmaengine */
-       struct sh_dmae_slave dma_tx;
-       struct sh_dmae_slave dma_rx;
        struct dma_chan *chan_tx;
        struct dma_chan *chan_rx;
        int irq;
@@ -663,20 +661,16 @@ static irqreturn_t rspi_irq(int irq, void *_sr)
        return ret;
 }
 
-static bool rspi_filter(struct dma_chan *chan, void *filter_param)
-{
-       chan->private = filter_param;
-       return true;
-}
-
-static void __devinit rspi_request_dma(struct rspi_data *rspi,
-                                      struct platform_device *pdev)
+static int __devinit rspi_request_dma(struct rspi_data *rspi,
+                                     struct platform_device *pdev)
 {
        struct rspi_plat_data *rspi_pd = pdev->dev.platform_data;
        dma_cap_mask_t mask;
+       struct dma_slave_config cfg;
+       int ret;
 
        if (!rspi_pd)
-               return;
+               return 0;       /* The driver assumes no error. */
 
        rspi->dma_width_16bit = rspi_pd->dma_width_16bit;
 
@@ -684,21 +678,35 @@ static void __devinit rspi_request_dma(struct rspi_data *rspi,
        if (rspi_pd->dma_rx_id && rspi_pd->dma_tx_id) {
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               rspi->dma_rx.slave_id = rspi_pd->dma_rx_id;
-               rspi->chan_rx = dma_request_channel(mask, rspi_filter,
-                                                   &rspi->dma_rx);
-               if (rspi->chan_rx)
-                       dev_info(&pdev->dev, "Use DMA when rx.\n");
+               rspi->chan_rx = dma_request_channel(mask, shdma_chan_filter,
+                                                   (void *)rspi_pd->dma_rx_id);
+               if (rspi->chan_rx) {
+                       cfg.slave_id = rspi_pd->dma_rx_id;
+                       cfg.direction = DMA_DEV_TO_MEM;
+                       ret = dmaengine_slave_config(rspi->chan_rx, &cfg);
+                       if (!ret)
+                               dev_info(&pdev->dev, "Use DMA when rx.\n");
+                       else
+                               return ret;
+               }
        }
        if (rspi_pd->dma_tx_id) {
                dma_cap_zero(mask);
                dma_cap_set(DMA_SLAVE, mask);
-               rspi->dma_tx.slave_id = rspi_pd->dma_tx_id;
-               rspi->chan_tx = dma_request_channel(mask, rspi_filter,
-                                                   &rspi->dma_tx);
-               if (rspi->chan_tx)
-                       dev_info(&pdev->dev, "Use DMA when tx\n");
+               rspi->chan_tx = dma_request_channel(mask, shdma_chan_filter,
+                                                   (void *)rspi_pd->dma_tx_id);
+               if (rspi->chan_tx) {
+                       cfg.slave_id = rspi_pd->dma_tx_id;
+                       cfg.direction = DMA_MEM_TO_DEV;
+                       ret = dmaengine_slave_config(rspi->chan_tx, &cfg);
+                       if (!ret)
+                               dev_info(&pdev->dev, "Use DMA when tx\n");
+                       else
+                               return ret;
+               }
        }
+
+       return 0;
 }
 
 static void __devexit rspi_release_dma(struct rspi_data *rspi)
@@ -788,7 +796,11 @@ static int __devinit rspi_probe(struct platform_device *pdev)
        }
 
        rspi->irq = irq;
-       rspi_request_dma(rspi, pdev);
+       ret = rspi_request_dma(rspi, pdev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "rspi_request_dma failed.\n");
+               goto error4;
+       }
 
        ret = spi_register_master(master);
        if (ret < 0) {
index 1a81c90a4a71dc69ce4ec459342a98af3d26b872..6e7a805d324d19d6bec848a8bca2f2a74a4303af 100644 (file)
 
 struct s3c64xx_spi_dma_data {
        unsigned                ch;
-       enum dma_data_direction direction;
+       enum dma_transfer_direction direction;
        enum dma_ch     dmach;
        struct property         *dma_prop;
 };
@@ -1067,11 +1067,11 @@ static int __devinit s3c64xx_spi_get_dmares(
 
        if (tx) {
                dma_data = &sdd->tx_dma;
-               dma_data->direction = DMA_TO_DEVICE;
+               dma_data->direction = DMA_MEM_TO_DEV;
                chan_str = "tx";
        } else {
                dma_data = &sdd->rx_dma;
-               dma_data->direction = DMA_FROM_DEVICE;
+               dma_data->direction = DMA_DEV_TO_MEM;
                chan_str = "rx";
        }
 
index f2ffd963f1c348e3986f761b1d2d2b7b75b361e2..d0cafd6371996c75e3ee094b2be3168ad14d38b7 100644 (file)
@@ -51,12 +51,10 @@ enum android_alarm_return_flags {
 #define ANDROID_ALARM_WAIT                  _IO('a', 1)
 
 #define ALARM_IOW(c, type, size)            _IOW('a', (c) | ((type) << 4), size)
-#define ALARM_IOR(c, type, size)            _IOR('a', (c) | ((type) << 4), size)
-
 /* Set alarm */
 #define ANDROID_ALARM_SET(type)             ALARM_IOW(2, type, struct timespec)
 #define ANDROID_ALARM_SET_AND_WAIT(type)    ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOR(4, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
 #define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)
 #define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
 #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd)    (_IOC_NR(cmd) >> 4)
index 7b0ba92e7e46730d1d5c72137c9f1b2b9ddc3201..5d4610babd8a6a48e4d5ac161a04db7322ad2892 100644 (file)
@@ -567,7 +567,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate,
                page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE];
 
                BUG_ON(*page);
-               *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
                if (*page == NULL) {
                        pr_err("binder: %d: binder_alloc_buf failed "
                               "for page at %p\n", proc->pid, page_addr);
@@ -2419,14 +2419,38 @@ static void binder_release_work(struct list_head *list)
                        struct binder_transaction *t;
 
                        t = container_of(w, struct binder_transaction, work);
-                       if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
+                       if (t->buffer->target_node &&
+                           !(t->flags & TF_ONE_WAY)) {
                                binder_send_failed_reply(t, BR_DEAD_REPLY);
+                       } else {
+                               binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                                       "binder: undelivered transaction %d\n",
+                                       t->debug_id);
+                               t->buffer->transaction = NULL;
+                               kfree(t);
+                               binder_stats_deleted(BINDER_STAT_TRANSACTION);
+                       }
                } break;
                case BINDER_WORK_TRANSACTION_COMPLETE: {
+                       binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                               "binder: undelivered TRANSACTION_COMPLETE\n");
                        kfree(w);
                        binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
                } break;
+               case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
+               case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
+                       struct binder_ref_death *death;
+
+                       death = container_of(w, struct binder_ref_death, work);
+                       binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+                               "binder: undelivered death notification, %p\n",
+                               death->cookie);
+                       kfree(death);
+                       binder_stats_deleted(BINDER_STAT_DEATH);
+               } break;
                default:
+                       pr_err("binder: unexpected work type, %d, not freed\n",
+                              w->type);
                        break;
                }
        }
@@ -2899,6 +2923,7 @@ static void binder_deferred_release(struct binder_proc *proc)
                nodes++;
                rb_erase(&node->rb_node, &proc->nodes);
                list_del_init(&node->work.entry);
+               binder_release_work(&node->async_todo);
                if (hlist_empty(&node->refs)) {
                        kfree(node);
                        binder_stats_deleted(BINDER_STAT_NODE);
@@ -2937,6 +2962,7 @@ static void binder_deferred_release(struct binder_proc *proc)
                binder_delete_ref(ref);
        }
        binder_release_work(&proc->todo);
+       binder_release_work(&proc->delivered_death);
        buffers = 0;
 
        while ((n = rb_first(&proc->allocated_buffers))) {
index 7dff3c01dc29ef3286d5559065a1c2c9e52819d5..d00aff6671df961c475f41bb3bb3141b41d5f83f 100644 (file)
@@ -289,6 +289,8 @@ static void pci_8255_detach(struct comedi_device *dev)
        struct comedi_subdevice *s;
        int i;
 
+       if (!board || !devpriv)
+               return;
        if (dev->subdevices) {
                for (i = 0; i < board->n_8255; i++) {
                        s = &dev->subdevices[i];
index 08f305210a695d57e1ef2c8181ec3d47b2f62c53..29eb52d11d2f7b3ef6b2a7f1372e3b99f95862fc 100644 (file)
@@ -1410,6 +1410,8 @@ static void dio200_detach(struct comedi_device *dev)
        const struct dio200_layout_struct *layout;
        unsigned n;
 
+       if (!thisboard)
+               return;
        if (dev->irq)
                free_irq(dev->irq, dev);
        if (dev->subdevices) {
index eacb5e4735d7df0a3ccf7e794bb0744ab936f71a..4e4f3c15df87e9db99528806b15ba48c54a558c2 100644 (file)
@@ -573,9 +573,10 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,
 static void pc236_detach(struct comedi_device *dev)
 {
        const struct pc236_board *thisboard = comedi_board(dev);
-       struct pc236_private *devpriv = dev->private;
 
-       if (devpriv)
+       if (!thisboard)
+               return;
+       if (dev->iobase)
                pc236_intr_disable(dev);
        if (dev->irq)
                free_irq(dev->irq, dev);
index 60830ccfb903f48fc9720490040d59bc113f0c5c..d0a4c441228b405d4459f70cb264b13717c26161 100644 (file)
@@ -323,6 +323,8 @@ static void pc263_detach(struct comedi_device *dev)
 {
        const struct pc263_board *thisboard = comedi_board(dev);
 
+       if (!thisboard)
+               return;
        if (is_isa_board(thisboard)) {
                if (dev->iobase)
                        release_region(dev->iobase, PC263_IO_SIZE);
index 5fd21fa6c1c76d25f910c41ca26ecec86b8894e8..c304528cfb1341293255f097620c1d1f8877c7fe 100644 (file)
@@ -846,6 +846,8 @@ static void __maybe_unused das08_detach(struct comedi_device *dev)
 {
        const struct das08_board_struct *thisboard = comedi_board(dev);
 
+       if (!thisboard)
+               return;
        das08_common_detach(dev);
        if (is_isa_board(thisboard)) {
                if (dev->iobase)
index 2ba0ade45c6484b940b1ed9559a4bd85f96e5a84..68d7c6a5db7dac901fd2f208f923106930c3553f 100644 (file)
@@ -95,7 +95,7 @@ static int daq700_dio_insn_bits(struct comedi_device *dev,
        }
 
        data[1] = s->state & 0xff;
-       data[1] |= inb(dev->iobase + DIO_R);
+       data[1] |= inb(dev->iobase + DIO_R) << 8;
 
        return insn->n;
 }
index 28b91a6c378908ba2f30b01b88a11d819b3dd9f7..b5a19a0863fbb8ba3e7fe2842f66b0611992b054 100644 (file)
@@ -772,6 +772,8 @@ void labpc_common_detach(struct comedi_device *dev)
 {
        struct comedi_subdevice *s;
 
+       if (!thisboard)
+               return;
        if (dev->subdevices) {
                s = &dev->subdevices[2];
                subdev_8255_cleanup(dev, s);
index 268dcb95204b1501901a7eb0baf20c563bed4cd7..4792d056a36532b179968dda51f73b37ce56cb95 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/sched.h>
 #include <asm/unaligned.h>
 #include <linux/proc_fs.h>
+#include <linux/uaccess.h>
 
 #include "dgrp_common.h"
 
index 28f5c9ab6b4349200f65062e0dc2a5adb275afc3..24327c3bad83427c208a03c231504f5fa42b0510 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/proc_fs.h>
 #include <linux/ctype.h>
 #include <linux/seq_file.h>
+#include <linux/uaccess.h>
 #include <linux/vmalloc.h>
 
 #include "dgrp_common.h"
@@ -228,6 +229,9 @@ static void register_proc_table(struct dgrp_proc_entry *table,
        int len;
        mode_t mode;
 
+       if (table == NULL)
+               return;
+
        for (; table->id; table++) {
                /* Can't do anything without a proc name. */
                if (!table->name)
@@ -296,6 +300,9 @@ static void unregister_proc_table(struct dgrp_proc_entry *table,
        struct proc_dir_entry *de;
        struct nd_struct *tmp;
 
+       if (table == NULL)
+               return;
+
        list_for_each_entry(tmp, &nd_struct_list, list) {
                if ((table == dgrp_net_table) && (tmp->nd_net_de)) {
                        unregister_dgrp_device(tmp->nd_net_de);
index 7d7de873870c68d6b0965a5fbc51784963836388..e125b03598d73e5b40815cad70887793162802c5 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/sched.h>
+#include <linux/uaccess.h>
 
 #include "dgrp_common.h"
 
@@ -3172,6 +3173,9 @@ dgrp_tty_init(struct nd_struct *nd)
         */
 
        nd->nd_serial_ttdriver = alloc_tty_driver(CHAN_MAX);
+       if (!nd->nd_serial_ttdriver)
+               return -ENOMEM;
+
        sprintf(nd->nd_serial_name,  "tty_dgrp_%s_", id);
 
        nd->nd_serial_ttdriver->owner = THIS_MODULE;
@@ -3231,6 +3235,9 @@ dgrp_tty_init(struct nd_struct *nd)
        }
 
        nd->nd_callout_ttdriver = alloc_tty_driver(CHAN_MAX);
+       if (!nd->nd_callout_ttdriver)
+               return -ENOMEM;
+
        sprintf(nd->nd_callout_name, "cu_dgrp_%s_",  id);
 
        nd->nd_callout_ttdriver->owner = THIS_MODULE;
@@ -3268,6 +3275,9 @@ dgrp_tty_init(struct nd_struct *nd)
 
 
        nd->nd_xprint_ttdriver = alloc_tty_driver(CHAN_MAX);
+       if (!nd->nd_xprint_ttdriver)
+               return -ENOMEM;
+
        sprintf(nd->nd_xprint_name,  "pr_dgrp_%s_", id);
 
        nd->nd_xprint_ttdriver->owner = THIS_MODULE;
index 8e37d6e04277663d7b7d135a5dd653f050a16785..b12ca68cd9e4f286191349ba148aabcf3b9d6e56 100644 (file)
@@ -310,30 +310,32 @@ static int adis16201_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.610 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* 0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 462500;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val2 = IIO_G_TO_M_S_2(462400); /* 0.4624 mg */
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_INCLI:
                        *val = 0;
-                       *val2 = 100000;
+                       *val2 = 100000; /* 0.1 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
index 002fa9dfc3756ee5052c9039dd7bb2af48473168..e7b3441115aee59861571a40ebecaaf45a4160e7 100644 (file)
@@ -316,25 +316,27 @@ static int adis16203_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.61 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_INCLI:
                        *val = 0;
-                       *val2 = 25000;
+                       *val2 = 25000; /* 0.025 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 14;
index 05bdb7c2c8e3f100953c8b0fde872ae367f26c45..c6234c2f46aabdac362921e903fcdfa955f4a8a8 100644 (file)
@@ -317,26 +317,28 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 1220;
-                       else
-                               *val2 = 610;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220000; /* 1.22 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610000; /* 0.61 mV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* 0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
                        switch (chan->channel2) {
                        case IIO_MOD_X:
                        case IIO_MOD_ROOT_SUM_SQUARED_X_Y:
-                               *val2 = 17125;
+                               *val2 = IIO_G_TO_M_S_2(17125); /* 17.125 mg */
                                break;
                        case IIO_MOD_Y:
                        case IIO_MOD_Z:
-                               *val2 = 8407;
+                               *val2 = IIO_G_TO_M_S_2(8407); /* 8.407 mg */
                                break;
                        }
                        return IIO_VAL_INT_PLUS_MICRO;
@@ -345,7 +347,7 @@ static int adis16204_read_raw(struct iio_dev *indio_dev,
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
        case IIO_CHAN_INFO_PEAK:
index b7333bfe0b2f1312a51548a731e73f2f41bd36ba..7ee974b45d7d3a3eb354ef073a1094c9183f26c3 100644 (file)
@@ -343,28 +343,29 @@ static int adis16209_read_raw(struct iio_dev *indio_dev,
                case IIO_VOLTAGE:
                        *val = 0;
                        if (chan->channel == 0)
-                               *val2 = 305180;
+                               *val2 = 305180; /* 0.30518 mV */
                        else
-                               *val2 = 610500;
+                               *val2 = 610500; /* 0.6105 mV */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 2394;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       *val2 = IIO_G_TO_M_S_2(244140); /* 0.244140 mg */
+                       return IIO_VAL_INT_PLUS_NANO;
                case IIO_INCLI:
+               case IIO_ROT:
                        *val = 0;
-                       *val2 = 436;
+                       *val2 = 25000; /* 0.025 degree */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / -470 - 0x4FE; /* 25 C = 0x4FE */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
@@ -491,6 +492,7 @@ static const struct iio_chan_spec adis16209_channels[] = {
                .modified = 1,
                .channel2 = IIO_MOD_X,
                .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT,
+               IIO_CHAN_INFO_SCALE_SHARED_BIT,
                .address = rot,
                .scan_index = ADIS16209_SCAN_ROT,
                .scan_type = {
index c755089c711715802ce6e90818a35bae41941acb..eaadd9df3f78360c111b54b05ac3b93a96ba7cb7 100644 (file)
@@ -486,7 +486,7 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                break;
        case IIO_CHAN_INFO_OFFSET:
                if (chan->type == IIO_TEMP) {
-                       *val = 25;
+                       *val = 25000 / -470 - 1278; /* 25 C = 1278 */
                        return IIO_VAL_INT;
                }
                addrind = 1;
@@ -495,19 +495,22 @@ static int adis16220_read_raw(struct iio_dev *indio_dev,
                addrind = 2;
                break;
        case IIO_CHAN_INFO_SCALE:
-               *val = 0;
                switch (chan->type) {
                case IIO_TEMP:
-                       *val2 = -470000;
+                       *val = -470; /* -0.47 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
-                       *val2 = 1887042;
+                       *val2 = IIO_G_TO_M_S_2(19073); /* 19.073 g */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
-                       if (chan->channel == 0)
-                               *val2 = 0012221;
-                       else /* Should really be dependent on VDD */
-                               *val2 = 305;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 220700; /* 1.2207 mV */
+                       } else {
+                               /* Should really be dependent on VDD */
+                               *val2 = 305180; /* 305.18 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
index 0fc26a49d681abbb4ece13156771e429db9aee2f..35e093973d5cb9028992682344f3dc9bba23be96 100644 (file)
@@ -373,30 +373,31 @@ static int adis16240_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 4880;
-                       else
+                       if (chan->channel == 0) {
+                               *val = 4;
+                               *val2 = 880000; /* 4.88 mV */
+                               return IIO_VAL_INT_PLUS_MICRO;
+                       } else {
                                return -EINVAL;
-                       return IIO_VAL_INT_PLUS_MICRO;
+                       }
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 244000;
+                       *val = 244; /* 0.244 C */
+                       *val2 = 0;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
-                       *val2 = 504062;
+                       *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_PEAK_SCALE:
-               *val = 6;
-               *val2 = 629295;
+               *val = 0;
+               *val2 = IIO_G_TO_M_S_2(51400); /* 51.4 mg */
                return IIO_VAL_INT_PLUS_MICRO;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 25000 / 244 - 0x133; /* 25 C = 0x133 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                bits = 10;
index 9571c03aa4cc976346d17bcb27f41d4dc4319060..aa964a2d829016e25b918ede1418d25152a9a425 100644 (file)
@@ -498,28 +498,33 @@ static int adis16260_read_raw(struct iio_dev *indio_dev,
                switch (chan->type) {
                case IIO_ANGL_VEL:
                        *val = 0;
-                       if (spi_get_device_id(st->us)->driver_data)
-                               *val2 = 320;
-                       else
-                               *val2 = 1278;
+                       if (spi_get_device_id(st->us)->driver_data) {
+                               /* 0.01832 degree / sec */
+                               *val2 = IIO_DEGREE_TO_RAD(18320);
+                       } else {
+                               /* 0.07326 degree / sec */
+                               *val2 = IIO_DEGREE_TO_RAD(73260);
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
-                       *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 18315;
-                       else
-                               *val2 = 610500;
+                       if (chan->channel == 0) {
+                               *val = 1;
+                               *val2 = 831500; /* 1.8315 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 610500; /* 610.5 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 145300;
+                       *val = 145;
+                       *val2 = 300000; /* 0.1453 C */
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
                }
                break;
        case IIO_CHAN_INFO_OFFSET:
-               *val = 25;
+               *val = 250000 / 1453; /* 25 C = 0x00 */
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_CALIBBIAS:
                switch (chan->type) {
index d59d7ac856a9db8bb3c0bff7ccf1811d97917539..77c601da184603c6391cecc1b10d887cb38ffb70 100644 (file)
@@ -139,6 +139,8 @@ struct adis16400_chip_info {
        const long flags;
        unsigned int gyro_scale_micro;
        unsigned int accel_scale_micro;
+       int temp_scale_nano;
+       int temp_offset;
        unsigned long default_scan_mask;
 };
 
index b302c9ba271260e2f31476e51420af68fbbd28db..3144a7b1e1c4f6cd03f0b55780aa473603afa51e 100644 (file)
@@ -553,10 +553,13 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_VOLTAGE:
                        *val = 0;
-                       if (chan->channel == 0)
-                               *val2 = 2418;
-                       else
-                               *val2 = 806;
+                       if (chan->channel == 0) {
+                               *val = 2;
+                               *val2 = 418000; /* 2.418 mV */
+                       } else {
+                               *val = 0;
+                               *val2 = 805800; /* 805.8 uV */
+                       }
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_ACCEL:
                        *val = 0;
@@ -564,11 +567,11 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_MAGN:
                        *val = 0;
-                       *val2 = 500;
+                       *val2 = 500; /* 0.5 mgauss */
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       *val2 = 140000;
+                       *val = st->variant->temp_scale_nano / 1000000;
+                       *val2 = (st->variant->temp_scale_nano % 1000000);
                        return IIO_VAL_INT_PLUS_MICRO;
                default:
                        return -EINVAL;
@@ -586,9 +589,8 @@ static int adis16400_read_raw(struct iio_dev *indio_dev,
                return IIO_VAL_INT;
        case IIO_CHAN_INFO_OFFSET:
                /* currently only temperature */
-               *val = 198;
-               *val2 = 160000;
-               return IIO_VAL_INT_PLUS_MICRO;
+               *val = st->variant->temp_offset;
+               return IIO_VAL_INT;
        case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
                mutex_lock(&indio_dev->mlock);
                /* Need both the number of taps and the sampling frequency */
@@ -1035,7 +1037,7 @@ static const struct iio_chan_spec adis16334_channels[] = {
                .indexed = 1,
                .channel = 0,
                .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |
-               IIO_CHAN_INFO_CALIBBIAS_SEPARATE_BIT |
+               IIO_CHAN_INFO_OFFSET_SEPARATE_BIT |
                IIO_CHAN_INFO_SCALE_SHARED_BIT,
                .address = temp0,
                .scan_index = ADIS16400_SCAN_TEMP,
@@ -1058,8 +1060,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16300] = {
                .channels = adis16300_channels,
                .num_channels = ARRAY_SIZE(adis16300_channels),
-               .gyro_scale_micro = 873,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
                .accel_scale_micro = 5884,
+               .temp_scale_nano = 140000000, /* 0.14 C */
+               .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
                .default_scan_mask = (1 << ADIS16400_SCAN_SUPPLY) |
                (1 << ADIS16400_SCAN_GYRO_X) | (1 << ADIS16400_SCAN_ACC_X) |
                (1 << ADIS16400_SCAN_ACC_Y) | (1 << ADIS16400_SCAN_ACC_Z) |
@@ -1070,8 +1074,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16334] = {
                .channels = adis16334_channels,
                .num_channels = ARRAY_SIZE(adis16334_channels),
-               .gyro_scale_micro = 873,
-               .accel_scale_micro = 981,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 67850000, /* 0.06785 C */
+               .temp_offset = 25000000 / 67850, /* 25 C = 0x00 */
                .default_scan_mask = (1 << ADIS16400_SCAN_GYRO_X) |
                (1 << ADIS16400_SCAN_GYRO_Y) | (1 << ADIS16400_SCAN_GYRO_Z) |
                (1 << ADIS16400_SCAN_ACC_X) | (1 << ADIS16400_SCAN_ACC_Y) |
@@ -1080,8 +1086,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
        [ADIS16350] = {
                .channels = adis16350_channels,
                .num_channels = ARRAY_SIZE(adis16350_channels),
-               .gyro_scale_micro = 872664,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(73260), /* 0.07326 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(2522), /* 0.002522 g */
+               .temp_scale_nano = 145300000, /* 0.1453 C */
+               .temp_offset = 25000000 / 145300, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
                .flags = ADIS16400_NO_BURST,
        },
@@ -1090,8 +1098,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FE8,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16362] = {
@@ -1099,8 +1109,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FEA,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(333), /* 0.333 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16364] = {
@@ -1108,8 +1120,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FEC,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16365] = {
@@ -1117,8 +1131,10 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16350_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x3FED,
-               .gyro_scale_micro = 1279,
-               .accel_scale_micro = 24732,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(1000), /* 1 mg */
+               .temp_scale_nano = 136000000, /* 0.136 C */
+               .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
                .default_scan_mask = 0x7FF,
        },
        [ADIS16400] = {
@@ -1126,9 +1142,11 @@ static struct adis16400_chip_info adis16400_chips[] = {
                .num_channels = ARRAY_SIZE(adis16400_channels),
                .flags = ADIS16400_HAS_PROD_ID,
                .product_id = 0x4015,
-               .gyro_scale_micro = 873,
-               .accel_scale_micro = 32656,
+               .gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
+               .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
                .default_scan_mask = 0xFFF,
+               .temp_scale_nano = 140000000, /* 0.14 C */
+               .temp_offset = 25000000 / 140000, /* 25 C = 0x00 */
        }
 };
 
index bb8aa70281cd9da9aa55edf89850b08f1b848a2c..46d6657280b8490799f818123166827771d22615 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/module.h>
+#include <linux/slab.h>
 #include "tpci200.h"
 
 static u16 tpci200_status_timeout[] = {
index 3434e6ec01426677ff576de960ffbf65440af8d6..66e2c2f8a239964c22f3fe18dbd8d6a644b95013 100644 (file)
@@ -246,7 +246,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
         * DSS, GPU, etc. are not cache coherent:
         */
        if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
-               addrs = kmalloc(npages * sizeof(addrs), GFP_KERNEL);
+               addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL);
                if (!addrs) {
                        ret = -ENOMEM;
                        goto free_pages;
@@ -257,7 +257,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
                                        0, PAGE_SIZE, DMA_BIDIRECTIONAL);
                }
        } else {
-               addrs = kzalloc(npages * sizeof(addrs), GFP_KERNEL);
+               addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL);
                if (!addrs) {
                        ret = -ENOMEM;
                        goto free_pages;
index 843c54101438fa1aa30aafe564016d45aa3ba10d..3abf6619dace58319beee2be2fba640d02f059d2 100644 (file)
@@ -18,6 +18,7 @@ config ZCACHE2
 config RAMSTER
        bool "Cross-machine RAM capacity sharing, aka peer-to-peer tmem"
        depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE2=y
+       depends on NET
        # must ensure struct page is 8-byte aligned
        select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT
        default n
index 066a3ceec65e92fccb725401e41e410e52d7ee1a..f619fb3c56d298334a615eb1b34203ccd1e5f5d3 100644 (file)
@@ -126,7 +126,8 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,
                                  u32 ul_num_bytes,
                                  struct hw_mmu_map_attrs_t *hw_attrs);
 
-bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr);
+bool wait_for_start(struct bridge_dev_context *dev_context,
+                       void __iomem *sync_addr);
 
 /*  ----------------------------------- Globals */
 
@@ -363,10 +364,11 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
 {
        int status = 0;
        struct bridge_dev_context *dev_context = dev_ctxt;
-       u32 dw_sync_addr = 0;
+       void __iomem *sync_addr;
        u32 ul_shm_base;        /* Gpp Phys SM base addr(byte) */
        u32 ul_shm_base_virt;   /* Dsp Virt SM base addr */
        u32 ul_tlb_base_virt;   /* Base of MMU TLB entry */
+       u32 shm_sync_pa;
        /* Offset of shm_base_virt from tlb_base_virt */
        u32 ul_shm_offset_virt;
        s32 entry_ndx;
@@ -397,15 +399,22 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
        /* Kernel logical address */
        ul_shm_base = dev_context->atlb_entry[0].gpp_va + ul_shm_offset_virt;
 
+       /* SHM physical sync address */
+       shm_sync_pa = dev_context->atlb_entry[0].gpp_pa + ul_shm_offset_virt +
+                       SHMSYNCOFFSET;
+
        /* 2nd wd is used as sync field */
-       dw_sync_addr = ul_shm_base + SHMSYNCOFFSET;
+       sync_addr = ioremap(shm_sync_pa, SZ_32);
+       if (!sync_addr)
+               return -ENOMEM;
+
        /* Write a signature into the shm base + offset; this will
         * get cleared when the DSP program starts. */
        if ((ul_shm_base_virt == 0) || (ul_shm_base == 0)) {
                pr_err("%s: Illegal SM base\n", __func__);
                status = -EPERM;
        } else
-               __raw_writel(0xffffffff, dw_sync_addr);
+               __raw_writel(0xffffffff, sync_addr);
 
        if (!status) {
                resources = dev_context->resources;
@@ -419,8 +428,10 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                         * function is made available.
                         */
                        void __iomem *ctrl = ioremap(0x48002000, SZ_4K);
-                       if (!ctrl)
+                       if (!ctrl) {
+                               iounmap(sync_addr);
                                return -ENOMEM;
+                       }
 
                        (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK,
                                        OMAP3430_RST1_IVA2_MASK, OMAP3430_IVA2_MOD,
@@ -588,15 +599,15 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                (*pdata->dsp_prm_rmw_bits)(OMAP3430_RST1_IVA2_MASK, 0,
                                        OMAP3430_IVA2_MOD, OMAP2_RM_RSTCTRL);
 
-               dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", dw_sync_addr);
+               dev_dbg(bridge, "Waiting for Sync @ 0x%x\n", *(u32 *)sync_addr);
                dev_dbg(bridge, "DSP c_int00 Address =  0x%x\n", dsp_addr);
                if (dsp_debug)
-                       while (__raw_readw(dw_sync_addr))
+                       while (__raw_readw(sync_addr))
                                ;
 
                /* Wait for DSP to clear word in shared memory */
                /* Read the Location */
-               if (!wait_for_start(dev_context, dw_sync_addr))
+               if (!wait_for_start(dev_context, sync_addr))
                        status = -ETIMEDOUT;
 
                dev_get_symbol(dev_context->dev_obj, "_WDT_enable", &wdt_en);
@@ -612,7 +623,7 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                        /* Write the synchronization bit to indicate the
                         * completion of OPP table update to DSP
                         */
-                       __raw_writel(0XCAFECAFE, dw_sync_addr);
+                       __raw_writel(0XCAFECAFE, sync_addr);
 
                        /* update board state */
                        dev_context->brd_state = BRD_RUNNING;
@@ -621,6 +632,9 @@ static int bridge_brd_start(struct bridge_dev_context *dev_ctxt,
                        dev_context->brd_state = BRD_UNKNOWN;
                }
        }
+
+       iounmap(sync_addr);
+
        return status;
 }
 
@@ -1796,12 +1810,13 @@ static int mem_map_vmalloc(struct bridge_dev_context *dev_context,
  *  ======== wait_for_start ========
  *      Wait for the singal from DSP that it has started, or time out.
  */
-bool wait_for_start(struct bridge_dev_context *dev_context, u32 dw_sync_addr)
+bool wait_for_start(struct bridge_dev_context *dev_context,
+                       void __iomem *sync_addr)
 {
        u16 timeout = TIHELEN_ACKTIMEOUT;
 
        /*  Wait for response from board */
-       while (__raw_readw(dw_sync_addr) && --timeout)
+       while (__raw_readw(sync_addr) && --timeout)
                udelay(10);
 
        /*  If timed out: return false */
index 71cb822936499fb23b82f19053337a5159307c87..50244a474178610b6f0271b88dbb6479e21e03ac 100644 (file)
@@ -47,38 +47,13 @@ enum hw_mmu_page_size_t {
        HW_MMU_SUPERSECTION
 };
 
-/*
- * FUNCTION          : mmu_flush_entry
- *
- * INPUTS:
- *
- *       Identifier      : base_address
- *       Type          : const u32
- *       Description     : Base Address of instance of MMU module
- *
- * RETURNS:
- *
- *       Type          : hw_status
- *       Description     : 0            -- No errors occurred
- *                      RET_BAD_NULL_PARAM     -- A Pointer
- *                                             Parameter was set to NULL
- *
- * PURPOSE:          : Flush the TLB entry pointed by the
- *                     lock counter register
- *                     even if this entry is set protected
- *
- * METHOD:            : Check the Input parameter and Flush a
- *                      single entry in the TLB.
- */
-static hw_status mmu_flush_entry(const void __iomem *base_address);
-
 /*
  * FUNCTION          : mmu_set_cam_entry
  *
  * INPUTS:
  *
  *       Identifier      : base_address
- *       TypE          : const u32
+ *       Type           : void __iomem *
  *       Description     : Base Address of instance of MMU module
  *
  *       Identifier      : page_sz
@@ -112,7 +87,7 @@ static hw_status mmu_flush_entry(const void __iomem *base_address);
  *
  * METHOD:             : Check the Input parameters and set the CAM entry.
  */
-static hw_status mmu_set_cam_entry(const void __iomem *base_address,
+static hw_status mmu_set_cam_entry(void __iomem *base_address,
                                   const u32 page_sz,
                                   const u32 preserved_bit,
                                   const u32 valid_bit,
@@ -124,7 +99,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
  * INPUTS:
  *
  *       Identifier      : base_address
- *       Type          : const u32
+ *       Type           : void __iomem *
  *       Description     : Base Address of instance of MMU module
  *
  *       Identifier      : physical_addr
@@ -157,7 +132,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
  *
  * METHOD:            : Check the Input parameters and set the RAM entry.
  */
-static hw_status mmu_set_ram_entry(const void __iomem *base_address,
+static hw_status mmu_set_ram_entry(void __iomem *base_address,
                                   const u32 physical_addr,
                                   enum hw_endianism_t endianism,
                                   enum hw_element_size_t element_size,
@@ -165,7 +140,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
 
 /* HW FUNCTIONS */
 
-hw_status hw_mmu_enable(const void __iomem *base_address)
+hw_status hw_mmu_enable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -174,7 +149,7 @@ hw_status hw_mmu_enable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_disable(const void __iomem *base_address)
+hw_status hw_mmu_disable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -183,7 +158,7 @@ hw_status hw_mmu_disable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
+hw_status hw_mmu_num_locked_set(void __iomem *base_address,
                                u32 num_locked_entries)
 {
        hw_status status = 0;
@@ -193,7 +168,7 @@ hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
        return status;
 }
 
-hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
+hw_status hw_mmu_victim_num_set(void __iomem *base_address,
                                u32 victim_entry_num)
 {
        hw_status status = 0;
@@ -203,7 +178,7 @@ hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
        return status;
 }
 
-hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_ack(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
 
@@ -212,7 +187,7 @@ hw_status hw_mmu_event_ack(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_disable(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
        u32 irq_reg;
@@ -224,7 +199,7 @@ hw_status hw_mmu_event_disable(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
+hw_status hw_mmu_event_enable(void __iomem *base_address, u32 irq_mask)
 {
        hw_status status = 0;
        u32 irq_reg;
@@ -236,7 +211,7 @@ hw_status hw_mmu_event_enable(const void __iomem *base_address, u32 irq_mask)
        return status;
 }
 
-hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
+hw_status hw_mmu_event_status(void __iomem *base_address, u32 *irq_mask)
 {
        hw_status status = 0;
 
@@ -245,7 +220,7 @@ hw_status hw_mmu_event_status(const void __iomem *base_address, u32 *irq_mask)
        return status;
 }
 
-hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
+hw_status hw_mmu_fault_addr_read(void __iomem *base_address, u32 *addr)
 {
        hw_status status = 0;
 
@@ -255,7 +230,7 @@ hw_status hw_mmu_fault_addr_read(const void __iomem *base_address, u32 *addr)
        return status;
 }
 
-hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
+hw_status hw_mmu_ttb_set(void __iomem *base_address, u32 ttb_phys_addr)
 {
        hw_status status = 0;
        u32 load_ttb;
@@ -267,7 +242,7 @@ hw_status hw_mmu_ttb_set(const void __iomem *base_address, u32 ttb_phys_addr)
        return status;
 }
 
-hw_status hw_mmu_twl_enable(const void __iomem *base_address)
+hw_status hw_mmu_twl_enable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -276,7 +251,7 @@ hw_status hw_mmu_twl_enable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_twl_disable(const void __iomem *base_address)
+hw_status hw_mmu_twl_disable(void __iomem *base_address)
 {
        hw_status status = 0;
 
@@ -285,45 +260,7 @@ hw_status hw_mmu_twl_disable(const void __iomem *base_address)
        return status;
 }
 
-hw_status hw_mmu_tlb_flush(const void __iomem *base_address, u32 virtual_addr,
-                          u32 page_sz)
-{
-       hw_status status = 0;
-       u32 virtual_addr_tag;
-       enum hw_mmu_page_size_t pg_size_bits;
-
-       switch (page_sz) {
-       case HW_PAGE_SIZE4KB:
-               pg_size_bits = HW_MMU_SMALL_PAGE;
-               break;
-
-       case HW_PAGE_SIZE64KB:
-               pg_size_bits = HW_MMU_LARGE_PAGE;
-               break;
-
-       case HW_PAGE_SIZE1MB:
-               pg_size_bits = HW_MMU_SECTION;
-               break;
-
-       case HW_PAGE_SIZE16MB:
-               pg_size_bits = HW_MMU_SUPERSECTION;
-               break;
-
-       default:
-               return -EINVAL;
-       }
-
-       /* Generate the 20-bit tag from virtual address */
-       virtual_addr_tag = ((virtual_addr & MMU_ADDR_MASK) >> 12);
-
-       mmu_set_cam_entry(base_address, pg_size_bits, 0, 0, virtual_addr_tag);
-
-       mmu_flush_entry(base_address);
-
-       return status;
-}
-
-hw_status hw_mmu_tlb_add(const void __iomem *base_address,
+hw_status hw_mmu_tlb_add(void __iomem *base_address,
                         u32 physical_addr,
                         u32 virtual_addr,
                         u32 page_sz,
@@ -503,20 +440,8 @@ hw_status hw_mmu_pte_clear(const u32 pg_tbl_va, u32 virtual_addr, u32 page_size)
        return status;
 }
 
-/* mmu_flush_entry */
-static hw_status mmu_flush_entry(const void __iomem *base_address)
-{
-       hw_status status = 0;
-       u32 flush_entry_data = 0x1;
-
-       /* write values to register */
-       MMUMMU_FLUSH_ENTRY_WRITE_REGISTER32(base_address, flush_entry_data);
-
-       return status;
-}
-
 /* mmu_set_cam_entry */
-static hw_status mmu_set_cam_entry(const void __iomem *base_address,
+static hw_status mmu_set_cam_entry(void __iomem *base_address,
                                   const u32 page_sz,
                                   const u32 preserved_bit,
                                   const u32 valid_bit,
@@ -536,7 +461,7 @@ static hw_status mmu_set_cam_entry(const void __iomem *base_address,
 }
 
 /* mmu_set_ram_entry */
-static hw_status mmu_set_ram_entry(const void __iomem *base_address,
+static hw_status mmu_set_ram_entry(void __iomem *base_address,
                                   const u32 physical_addr,
                                   enum hw_endianism_t endianism,
                                   enum hw_element_size_t element_size,
@@ -556,7 +481,7 @@ static hw_status mmu_set_ram_entry(const void __iomem *base_address,
 
 }
 
-void hw_mmu_tlb_flush_all(const void __iomem *base)
+void hw_mmu_tlb_flush_all(void __iomem *base)
 {
        __raw_writel(1, base + MMU_GFLUSH);
 }
index 1458a2c6027b7e1fc3cac1c160b837e10b29c6b3..1c50bb36edfee4e4ba918b6d86ee5f18cee78624 100644 (file)
@@ -42,44 +42,41 @@ struct hw_mmu_map_attrs_t {
        bool donotlockmpupage;
 };
 
-extern hw_status hw_mmu_enable(const void __iomem *base_address);
+extern hw_status hw_mmu_enable(void __iomem *base_address);
 
-extern hw_status hw_mmu_disable(const void __iomem *base_address);
+extern hw_status hw_mmu_disable(void __iomem *base_address);
 
-extern hw_status hw_mmu_num_locked_set(const void __iomem *base_address,
+extern hw_status hw_mmu_num_locked_set(void __iomem *base_address,
                                       u32 num_locked_entries);
 
-extern hw_status hw_mmu_victim_num_set(const void __iomem *base_address,
+extern hw_status hw_mmu_victim_num_set(void __iomem *base_address,
                                       u32 victim_entry_num);
 
 /* For MMU faults */
-extern hw_status hw_mmu_event_ack(const void __iomem *base_address,
+extern hw_status hw_mmu_event_ack(void __iomem *base_address,
                                  u32 irq_mask);
 
-extern hw_status hw_mmu_event_disable(const void __iomem *base_address,
+extern hw_status hw_mmu_event_disable(void __iomem *base_address,
                                      u32 irq_mask);
 
-extern hw_status hw_mmu_event_enable(const void __iomem *base_address,
+extern hw_status hw_mmu_event_enable(void __iomem *base_address,
                                     u32 irq_mask);
 
-extern hw_status hw_mmu_event_status(const void __iomem *base_address,
+extern hw_status hw_mmu_event_status(void __iomem *base_address,
                                     u32 *irq_mask);
 
-extern hw_status hw_mmu_fault_addr_read(const void __iomem *base_address,
+extern hw_status hw_mmu_fault_addr_read(void __iomem *base_address,
                                        u32 *addr);
 
 /* Set the TT base address */
-extern hw_status hw_mmu_ttb_set(const void __iomem *base_address,
+extern hw_status hw_mmu_ttb_set(void __iomem *base_address,
                                u32 ttb_phys_addr);
 
-extern hw_status hw_mmu_twl_enable(const void __iomem *base_address);
+extern hw_status hw_mmu_twl_enable(void __iomem *base_address);
 
-extern hw_status hw_mmu_twl_disable(const void __iomem *base_address);
+extern hw_status hw_mmu_twl_disable(void __iomem *base_address);
 
-extern hw_status hw_mmu_tlb_flush(const void __iomem *base_address,
-                                 u32 virtual_addr, u32 page_sz);
-
-extern hw_status hw_mmu_tlb_add(const void __iomem *base_address,
+extern hw_status hw_mmu_tlb_add(void __iomem *base_address,
                                u32 physical_addr,
                                u32 virtual_addr,
                                u32 page_sz,
@@ -97,7 +94,7 @@ extern hw_status hw_mmu_pte_set(const u32 pg_tbl_va,
 extern hw_status hw_mmu_pte_clear(const u32 pg_tbl_va,
                                  u32 virtual_addr, u32 page_size);
 
-void hw_mmu_tlb_flush_all(const void __iomem *base);
+void hw_mmu_tlb_flush_all(void __iomem *base);
 
 static inline u32 hw_mmu_pte_addr_l1(u32 l1_base, u32 va)
 {
index 60a278136bdf58f14718fb43913d292a51b01397..b32c75673ab441c5795b456d25d272ffdaf79866 100644 (file)
@@ -53,8 +53,8 @@ struct cfg_hostres {
        u32 chnl_buf_size;
        u32 num_chnls;
        void __iomem *per_base;
-       u32 per_pm_base;
-       u32 core_pm_base;
+       void __iomem *per_pm_base;
+       void __iomem *core_pm_base;
        void __iomem *dmmu_base;
 };
 
index ed00d3da3205a0074333fb0a4dfd778ca6417280..5e2f4d82d925fbf76b628299347c4f83a86321a3 100644 (file)
@@ -47,8 +47,8 @@
 #include <asm/cacheflush.h>
 #include <linux/dma-mapping.h>
 
-/* TODO -- Remove, once BP defines them */
-#define INT_DSP_MMU_IRQ        28
+/* TODO -- Remove, once omap-iommu is used */
+#define INT_DSP_MMU_IRQ        (28 + NR_IRQS)
 
 #define PRCM_VDD1 1
 
index 6795205b01553e07b671c63a1c49519b092c6e7f..db1da28cecba84d4800363df964647e85b8177c9 100644 (file)
@@ -667,10 +667,10 @@ int drv_request_bridge_res_dsp(void **phost_resources)
                                                         OMAP_DSP_MEM3_SIZE);
                host_res->per_base = ioremap(OMAP_PER_CM_BASE,
                                                OMAP_PER_CM_SIZE);
-               host_res->per_pm_base = (u32) ioremap(OMAP_PER_PRM_BASE,
-                                                        OMAP_PER_PRM_SIZE);
-               host_res->core_pm_base = (u32) ioremap(OMAP_CORE_PRM_BASE,
-                                                         OMAP_CORE_PRM_SIZE);
+               host_res->per_pm_base = ioremap(OMAP_PER_PRM_BASE,
+                                               OMAP_PER_PRM_SIZE);
+               host_res->core_pm_base = ioremap(OMAP_CORE_PRM_BASE,
+                                                       OMAP_CORE_PRM_SIZE);
                host_res->dmmu_base = ioremap(OMAP_DMMU_BASE,
                                                 OMAP_DMMU_SIZE);
 
index c2fc6137c7708372ff4cde1d8f9f6375fe3086a8..294e9b40f51666396c2a56c3d92036951e04382d 100644 (file)
@@ -304,8 +304,7 @@ int node_allocate(struct proc_object *hprocessor,
        u32 pul_value;
        u32 dynext_base;
        u32 off_set = 0;
-       u32 ul_stack_seg_addr, ul_stack_seg_val;
-       u32 ul_gpp_mem_base;
+       u32 ul_stack_seg_val;
        struct cfg_hostres *host_res;
        struct bridge_dev_context *pbridge_context;
        u32 mapped_addr = 0;
@@ -581,6 +580,9 @@ func_cont:
                if (strcmp((char *)
                           pnode->dcd_props.obj_data.node_obj.ndb_props.
                           stack_seg_name, STACKSEGLABEL) == 0) {
+                       void __iomem *stack_seg;
+                       u32 stack_seg_pa;
+
                        status =
                            hnode_mgr->nldr_fxns.
                            get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
@@ -608,14 +610,21 @@ func_cont:
                                goto func_end;
                        }
 
-                       ul_gpp_mem_base = (u32) host_res->mem_base[1];
                        off_set = pul_value - dynext_base;
-                       ul_stack_seg_addr = ul_gpp_mem_base + off_set;
-                       ul_stack_seg_val = readl(ul_stack_seg_addr);
+                       stack_seg_pa = host_res->mem_phys[1] + off_set;
+                       stack_seg = ioremap(stack_seg_pa, SZ_32);
+                       if (!stack_seg) {
+                               status = -ENOMEM;
+                               goto func_end;
+                       }
+
+                       ul_stack_seg_val = readl(stack_seg);
+
+                       iounmap(stack_seg);
 
                        dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="
                                " 0x%x\n", __func__, ul_stack_seg_val,
-                               ul_stack_seg_addr);
+                               host_res->mem_base[1] + off_set);
 
                        pnode->create_args.asa.task_arg_obj.stack_seg =
                            ul_stack_seg_val;
index 653b074035f7b165d04d1587d428097ecfac780a..6edefde23722b436641166f5b678291d6648c6b2 100644 (file)
@@ -223,8 +223,13 @@ static int zram_bvec_read(struct zram *zram, struct bio_vec *bvec,
        cmem = zs_map_object(zram->mem_pool, zram->table[index].handle,
                                ZS_MM_RO);
 
-       ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
+       if (zram->table[index].size == PAGE_SIZE) {
+               memcpy(uncmem, cmem, PAGE_SIZE);
+               ret = LZO_E_OK;
+       } else {
+               ret = lzo1x_decompress_safe(cmem, zram->table[index].size,
                                    uncmem, &clen);
+       }
 
        if (is_partial_io(bvec)) {
                memcpy(user_mem + bvec->bv_offset, uncmem + offset,
@@ -342,8 +347,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
                goto out;
        }
 
-       if (unlikely(clen > max_zpage_size))
+       if (unlikely(clen > max_zpage_size)) {
                zram_stat_inc(&zram->stats.bad_compress);
+               src = uncmem;
+               clen = PAGE_SIZE;
+       }
 
        handle = zs_malloc(zram->mem_pool, clen);
        if (!handle) {
index d6ce2182e67207d41932fec75914b9d2c7f44479..035c2c762537c63e9bf62210b5476f7aef5c687a 100644 (file)
@@ -3719,7 +3719,9 @@ restart:
                 */
                iscsit_thread_check_cpumask(conn, current, 1);
 
-               schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT);
+               wait_event_interruptible(conn->queues_wq,
+                                        !iscsit_conn_all_queues_empty(conn) ||
+                                        ts->status == ISCSI_THREAD_SET_RESET);
 
                if ((ts->status == ISCSI_THREAD_SET_RESET) ||
                     signal_pending(current))
index 2ba9f9b9435c8684e59d0c65b6a18a6586ec5490..21048dbf7d13cc7ac116be38bb13a9ac6300c2a0 100644 (file)
@@ -486,6 +486,7 @@ struct iscsi_tmr_req {
 };
 
 struct iscsi_conn {
+       wait_queue_head_t       queues_wq;
        /* Authentication Successful for this connection */
        u8                      auth_complete;
        /* State connection is currently in */
index cdc8a10939c3d8d00912a6d9b5d735930d4e60ab..f8dbec05d5e56736fdc9238f997fcc8b18209021 100644 (file)
@@ -41,6 +41,7 @@
 
 static int iscsi_login_init_conn(struct iscsi_conn *conn)
 {
+       init_waitqueue_head(&conn->queues_wq);
        INIT_LIST_HEAD(&conn->conn_list);
        INIT_LIST_HEAD(&conn->conn_cmd_list);
        INIT_LIST_HEAD(&conn->immed_queue_list);
index afd98ccd40ae564f8013155bf6a4d99f857f339a..1a91195ab619a9ebbfa503cf7851c3cb8ca02b49 100644 (file)
@@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(
        atomic_set(&conn->check_immediate_queue, 1);
        spin_unlock_bh(&conn->immed_queue_lock);
 
-       wake_up_process(conn->thread_set->tx_thread);
+       wake_up(&conn->queues_wq);
 }
 
 struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn)
@@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(
        atomic_inc(&cmd->response_queue_count);
        spin_unlock_bh(&conn->response_queue_lock);
 
-       wake_up_process(conn->thread_set->tx_thread);
+       wake_up(&conn->queues_wq);
 }
 
 struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn)
@@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(
        }
 }
 
+bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn)
+{
+       bool empty;
+
+       spin_lock_bh(&conn->immed_queue_lock);
+       empty = list_empty(&conn->immed_queue_list);
+       spin_unlock_bh(&conn->immed_queue_lock);
+
+       if (!empty)
+               return empty;
+
+       spin_lock_bh(&conn->response_queue_lock);
+       empty = list_empty(&conn->response_queue_list);
+       spin_unlock_bh(&conn->response_queue_lock);
+
+       return empty;
+}
+
 void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
 {
        struct iscsi_queue_req *qr, *qr_tmp;
index 44054bd35437af3b21fbdc5422171d7d8032f76c..894d0f8379246f63166666b36259fbe0315d8dd4 100644 (file)
@@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_
 extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);
 extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);
 extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *);
+extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);
 extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);
 extern void iscsit_release_cmd(struct iscsi_cmd *);
 extern void iscsit_free_cmd(struct iscsi_cmd *);
index 015f5be27bf6f00dab299b20b295ef71df4af3e2..c123327499a3572f5e950f6483ea20d99096ebab 100644 (file)
@@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)
        if (ret < 0)
                goto out;
 
-       if (core_dev_setup_virtual_lun0() < 0)
+       ret = core_dev_setup_virtual_lun0();
+       if (ret < 0)
                goto out;
 
        return 0;
index 8d774da16320707cb81f525f511188ff202c57ae..9abef9f8eb760a88e7073802ceec77197421bf97 100644 (file)
@@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)
 
 static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
 {
-       u32 tmp, aligned_max_sectors;
+       u32 aligned_max_sectors;
+       u32 alignment;
        /*
         * Limit max_sectors to a PAGE_SIZE aligned value for modern
         * transport_allocate_data_tasks() operation.
         */
-       tmp = rounddown((max_sectors * block_size), PAGE_SIZE);
-       aligned_max_sectors = (tmp / block_size);
-       if (max_sectors != aligned_max_sectors) {
-               printk(KERN_INFO "Rounding down aligned max_sectors from %u"
-                               " to %u\n", max_sectors, aligned_max_sectors);
-               return aligned_max_sectors;
-       }
+       alignment = max(1ul, PAGE_SIZE / block_size);
+       aligned_max_sectors = rounddown(max_sectors, alignment);
+
+       if (max_sectors != aligned_max_sectors)
+               pr_info("Rounding down aligned max_sectors from %u to %u\n",
+                       max_sectors, aligned_max_sectors);
 
-       return max_sectors;
+       return aligned_max_sectors;
 }
 
 void se_dev_set_default_attribs(
index 868f8aa04f13d318b1c752d08887703f7a72de21..a6e27d967c7b7b4abc53dd194927252ed2cde897 100644 (file)
@@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)
        return 0;
 }
 
+static int sbc_emulate_noop(struct se_cmd *cmd)
+{
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
 static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
 {
        return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
@@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
                size = 0;
                cmd->execute_cmd = sbc_emulate_verify;
                break;
+       case REZERO_UNIT:
+       case SEEK_6:
+       case SEEK_10:
+               /*
+                * There are still clients out there which use these old SCSI-2
+                * commands. This mainly happens when running VMs with legacy
+                * guest systems, connected via SCSI command pass-through to
+                * iSCSI targets. Make them happy and return status GOOD.
+                */
+               size = 0;
+               cmd->execute_cmd = sbc_emulate_noop;
+               break;
        default:
                ret = spc_parse_cdb(cmd, &size);
                if (ret)
index 9229bd9ad61b3db7cd4d182ab3d5315f24785a5f..6fd434d3d7e477ab7d49660d20e02b0d638b8e3a 100644 (file)
@@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)
        unsigned char buf[SE_INQUIRY_BUF];
        int p, ret;
 
+       memset(buf, 0, SE_INQUIRY_BUF);
+
        if (dev == tpg->tpg_virt_lun0.lun_se_dev)
                buf[0] = 0x3f; /* Not connected */
        else
index 1c59a3c23b2c1b37ee8a3c54d62b8c66ea6f9e87..be75c4331a9222a5ca4d0b015ebdbe5a983c20ae 100644 (file)
@@ -140,15 +140,15 @@ void core_tmr_abort_task(
                printk("ABORT_TASK: Found referenced %s task_tag: %u\n",
                        se_cmd->se_tfo->get_fabric_name(), ref_tag);
 
-               spin_lock_irq(&se_cmd->t_state_lock);
+               spin_lock(&se_cmd->t_state_lock);
                if (se_cmd->transport_state & CMD_T_COMPLETE) {
                        printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag);
-                       spin_unlock_irq(&se_cmd->t_state_lock);
+                       spin_unlock(&se_cmd->t_state_lock);
                        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
                        goto out;
                }
                se_cmd->transport_state |= CMD_T_ABORTED;
-               spin_unlock_irq(&se_cmd->t_state_lock);
+               spin_unlock(&se_cmd->t_state_lock);
 
                list_del_init(&se_cmd->se_cmd_list);
                kref_get(&se_cmd->cmd_kref);
index c33baff86aa699deacd04bd873e3c31fa5569cf5..9097155e9ebe7100c0bc1a4ac13b7c508a84ac8a 100644 (file)
@@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)
 
        se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
        se_cmd->se_tfo->queue_tm_rsp(se_cmd);
-       transport_generic_free_cmd(se_cmd, 0);
 }
 
 /**
index edfd67d2501349c99a9abe1540c23252488008b1..e1cb6bd75f60335517dc26d50d7b5726205da41a 100644 (file)
@@ -22,6 +22,7 @@ config THERMAL_HWMON
 config CPU_THERMAL
        bool "generic cpu cooling support"
        depends on THERMAL && CPU_FREQ
+       select CPU_FREQ_TABLE
        help
          This implements the generic cpu cooling mechanism through frequency
          reduction, cpu hotplug and any other ways of reducing temperature. An
@@ -50,6 +51,7 @@ config RCAR_THERMAL
 config EXYNOS_THERMAL
        tristate "Temperature sensor on Samsung EXYNOS"
        depends on (ARCH_EXYNOS4 || ARCH_EXYNOS5) && THERMAL
+       select CPU_FREQ_TABLE
        help
          If you say yes here you get support for TMU (Thermal Managment
          Unit) on SAMSUNG EXYNOS series of SoC.
index fd03e8581afc2a8e86ed354c03c06e84a1b604cc..6dd29e4ce36b1cd4841b94b6f1c1bd6251040972 100644 (file)
@@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {
        },
        { },
 };
-MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids);
+MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);
 
 static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(
                        struct platform_device *pdev)
index d4452716aaab1a7dbec7e3df53ec0abbed43aabd..f7a1b574a304e8808cb0cfda0d7e91ef6272bd50 100644 (file)
@@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                goto error_free_priv;
        }
 
-       zone = thermal_zone_device_register("rcar_thermal", 0, priv,
+       zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,
                                            &rcar_thermal_zone_ops, 0, 0);
        if (IS_ERR(zone)) {
                dev_err(&pdev->dev, "thermal zone device is NULL\n");
index a5dec1ca1b826bad18d9a1bf5c69eae17bfba423..13ee53bd0bf66869c201e901d3bf16ff35039e17 100644 (file)
@@ -424,7 +424,6 @@ static void hvc_hangup(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
        unsigned long flags;
-       int temp_open_count;
 
        if (!hp)
                return;
@@ -444,7 +443,6 @@ static void hvc_hangup(struct tty_struct *tty)
                return;
        }
 
-       temp_open_count = hp->port.count;
        hp->port.count = 0;
        spin_unlock_irqrestore(&hp->port.lock, flags);
        tty_port_tty_set(&hp->port, NULL);
@@ -453,11 +451,6 @@ static void hvc_hangup(struct tty_struct *tty)
 
        if (hp->ops->notifier_hangup)
                hp->ops->notifier_hangup(hp, hp->data);
-
-       while(temp_open_count) {
-               --temp_open_count;
-               tty_port_put(&hp->port);
-       }
 }
 
 /*
index 8f1dd2cc00a8de79ac9538248271d2be376336aa..f3d0edf46644da2505db40ee0422b3bca2ee8234 100644 (file)
@@ -162,7 +162,7 @@ int __init hp300_setup_serial_console(void)
 static int __devinit hpdca_init_one(struct dio_dev *d,
                                const struct dio_device_id *ent)
 {
-       struct uart_port port;
+       struct uart_8250_port uart;
        int line;
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
@@ -174,19 +174,19 @@ static int __devinit hpdca_init_one(struct dio_dev *d,
        memset(&uart, 0, sizeof(uart));
 
        /* Memory mapped I/O */
-       port.iotype = UPIO_MEM;
-       port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
-       port.irq = d->ipl;
-       port.uartclk = HPDCA_BAUD_BASE * 16;
-       port.mapbase = (d->resource.start + UART_OFFSET);
-       port.membase = (char *)(port.mapbase + DIO_VIRADDRBASE);
-       port.regshift = 1;
-       port.dev = &d->dev;
+       uart.port.iotype = UPIO_MEM;
+       uart.port.flags = UPF_SKIP_TEST | UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF;
+       uart.port.irq = d->ipl;
+       uart.port.uartclk = HPDCA_BAUD_BASE * 16;
+       uart.port.mapbase = (d->resource.start + UART_OFFSET);
+       uart.port.membase = (char *)(uart.port.mapbase + DIO_VIRADDRBASE);
+       uart.port.regshift = 1;
+       uart.port.dev = &d->dev;
        line = serial8250_register_8250_port(&uart);
 
        if (line < 0) {
                printk(KERN_NOTICE "8250_hp300: register_serial() DCA scode %d"
-                      " irq %d failed\n", d->scode, port.irq);
+                      " irq %d failed\n", d->scode, uart.port.irq);
                return -ENOMEM;
        }
 
index 233fbaaf25596ae4515f0d3e1890d4b62da617d6..2a53be5f010d9af3ee0ed1950f5951524e9a7cb3 100644 (file)
@@ -1150,7 +1150,7 @@ config SERIAL_SC26XX_CONSOLE
          Support for Console on SC2681/SC2692 serial ports.
 
 config SERIAL_SCCNXP
-       bool "SCCNXP serial port support"
+       tristate "SCCNXP serial port support"
        depends on !SERIAL_SC26XX
        select SERIAL_CORE
        default n
@@ -1162,7 +1162,7 @@ config SERIAL_SCCNXP
 
 config SERIAL_SCCNXP_CONSOLE
        bool "Console on SCCNXP serial port"
-       depends on SERIAL_SCCNXP
+       depends on SERIAL_SCCNXP=y
        select SERIAL_CORE_CONSOLE
        help
          Support for console on SCCNXP serial ports.
index 2bc28a59d38514f762718d19a8ebe50851311b49..1ab1d2c66de43ad749772c240f4f4c6944783e22 100644 (file)
@@ -1239,6 +1239,7 @@ static int __devexit max310x_remove(struct spi_device *spi)
 static const struct spi_device_id max310x_id_table[] = {
        { "max3107",    MAX310X_TYPE_MAX3107 },
        { "max3108",    MAX310X_TYPE_MAX3108 },
+       { }
 };
 MODULE_DEVICE_TABLE(spi, max310x_id_table);
 
index 6ede6fd92b4cd00e939dca479e0f3e3a0a0d923e..6d3d26a607b9fd26bc03cff7d50f62ccbf8a589b 100644 (file)
@@ -671,19 +671,19 @@ serial_omap_configure_xonxoff
 
        /*
         * IXON Flag:
-        * Flow control for OMAP.TX
-        * OMAP.RX should listen for XON/XOFF
+        * Enable XON/XOFF flow control on output.
+        * Transmit XON1, XOFF1
         */
        if (termios->c_iflag & IXON)
-               up->efr |= OMAP_UART_SW_RX;
+               up->efr |= OMAP_UART_SW_TX;
 
        /*
         * IXOFF Flag:
-        * Flow control for OMAP.RX
-        * OMAP.TX should send XON/XOFF
+        * Enable XON/XOFF flow control on input.
+        * Receiver compares XON1, XOFF1.
         */
        if (termios->c_iflag & IXOFF)
-               up->efr |= OMAP_UART_SW_TX;
+               up->efr |= OMAP_UART_SW_RX;
 
        serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
        serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
index b7086d004f5f36cb47422d5225edf5540ad7d8b2..e821068cd95b0f798dc7a9bb39d6507c6733812c 100644 (file)
@@ -971,6 +971,7 @@ static const struct platform_device_id sccnxp_id_table[] = {
        { "sc28202",    SCCNXP_TYPE_SC28202 },
        { "sc68681",    SCCNXP_TYPE_SC68681 },
        { "sc68692",    SCCNXP_TYPE_SC68692 },
+       { },
 };
 MODULE_DEVICE_TABLE(platform, sccnxp_id_table);
 
index 9be296cf729518d1cc48f7f6918229860f49bda0..6ee59001d61d742d1c0bd0f73355c10421fb3f4d 100644 (file)
@@ -530,7 +530,8 @@ static inline int sci_rxd_in(struct uart_port *port)
        if (s->cfg->port_reg <= 0)
                return 1;
 
-       return !!__raw_readb(s->cfg->port_reg);
+       /* Cast for ARM damage */
+       return !!__raw_readb((void __iomem *)s->cfg->port_reg);
 }
 
 /* ********************************************************************** *
index 05728894a88c23330e7b57eb8994f50477fc1b73..16ee6cee07da6b3ba904dea07127f41d98c65133 100644 (file)
@@ -452,6 +452,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
        NULL,                           /* v */
        &sysrq_showstate_blocked_op,    /* w */
        /* x: May be registered on ppc/powerpc for xmon */
+       /* x: May be registered on sparc64 for global PMU dump */
        NULL,                           /* x */
        /* y: May be registered on sparc64 for global register dump */
        NULL,                           /* y */
index f87d7e8964bf0849c1ab3e3da327e3a14c9b35a2..4e0d0c3734b326f80c635b1839fb4397eadcc59f 100644 (file)
@@ -539,25 +539,25 @@ static void insert_char(struct vc_data *vc, unsigned int nr)
 {
        unsigned short *p = (unsigned short *) vc->vc_pos;
 
-       scr_memmovew(p + nr, p, vc->vc_cols - vc->vc_x);
+       scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x) * 2);
        scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
        vc->vc_need_wrap = 0;
        if (DO_UPDATE(vc))
                do_update_region(vc, (unsigned long) p,
-                       (vc->vc_cols - vc->vc_x) / 2 + 1);
+                       vc->vc_cols - vc->vc_x);
 }
 
 static void delete_char(struct vc_data *vc, unsigned int nr)
 {
        unsigned short *p = (unsigned short *) vc->vc_pos;
 
-       scr_memcpyw(p, p + nr, vc->vc_cols - vc->vc_x - nr);
+       scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2);
        scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
                        nr * 2);
        vc->vc_need_wrap = 0;
        if (DO_UPDATE(vc))
                do_update_region(vc, (unsigned long) p,
-                       (vc->vc_cols - vc->vc_x) / 2);
+                       vc->vc_cols - vc->vc_x);
 }
 
 static int softcursor_original;
index 981f2132d1283c44234f4fa79466c4d11241c94e..6e49ec6f3adcaeae67898e53cc1c5eb6cd62b756 100644 (file)
@@ -817,10 +817,6 @@ static const __u32 acm_tty_speed[] = {
        2500000, 3000000, 3500000, 4000000
 };
 
-static const __u8 acm_tty_size[] = {
-       5, 6, 7, 8
-};
-
 static void acm_tty_set_termios(struct tty_struct *tty,
                                                struct ktermios *termios_old)
 {
@@ -834,7 +830,21 @@ static void acm_tty_set_termios(struct tty_struct *tty,
        newline.bParityType = termios->c_cflag & PARENB ?
                                (termios->c_cflag & PARODD ? 1 : 2) +
                                (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
-       newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+               newline.bDataBits = 5;
+               break;
+       case CS6:
+               newline.bDataBits = 6;
+               break;
+       case CS7:
+               newline.bDataBits = 7;
+               break;
+       case CS8:
+       default:
+               newline.bDataBits = 8;
+               break;
+       }
        /* FIXME: Needs to clear unsupported bits in the termios */
        acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
 
@@ -1233,7 +1243,7 @@ made_compressed_probe:
 
                if (usb_endpoint_xfer_int(epwrite))
                        usb_fill_int_urb(snd->urb, usb_dev,
-                               usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
+                               usb_sndintpipe(usb_dev, epwrite->bEndpointAddress),
                                NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval);
                else
                        usb_fill_bulk_urb(snd->urb, usb_dev,
index e0356cb859b5910eaaf5aa6e0b324808c56f4c0a..b78fbe222b72c2e3bc662973e9f9f08941ce2628 100644 (file)
@@ -1348,6 +1348,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
                                        ret = -EFAULT;
                                        goto error;
                                }
+                               uurb->buffer += u;
                        }
                        totlen -= u;
                }
index ddd820d25288b57da71336bf4eed397a4cc16410..6056db7af410fac833ed00d8c5f793773f628931 100644 (file)
@@ -367,6 +367,10 @@ static int usb_probe_interface(struct device *dev)
        intf->condition = USB_INTERFACE_UNBOUND;
        usb_cancel_queued_reset(intf);
 
+       /* If the LPM disable succeeded, balance the ref counts. */
+       if (!lpm_disable_error)
+               usb_unlocked_enable_lpm(udev);
+
        /* Unbound interfaces are always runtime-PM-disabled and -suspended */
        if (driver->supports_autosuspend)
                pm_runtime_disable(dev);
index 1e741bca02652e8f4ed2b027654abc3ac9d16a4f..f034716190ff425c89b007e2e10e4cd98ca6cb61 100644 (file)
@@ -2151,8 +2151,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
 irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
        struct usb_hcd          *hcd = __hcd;
+       unsigned long           flags;
        irqreturn_t             rc;
 
+       /* IRQF_DISABLED doesn't work correctly with shared IRQs
+        * when the first handler doesn't use it.  So let's just
+        * assume it's never used.
+        */
+       local_irq_save(flags);
+
        if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
                rc = IRQ_NONE;
        else if (hcd->driver->irq(hcd) == IRQ_NONE)
@@ -2160,6 +2167,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
        else
                rc = IRQ_HANDLED;
 
+       local_irq_restore(flags);
        return rc;
 }
 EXPORT_SYMBOL_GPL(usb_hcd_irq);
@@ -2347,6 +2355,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
        int retval;
 
        if (hcd->driver->irq) {
+
+               /* IRQF_DISABLED doesn't work as advertised when used together
+                * with IRQF_SHARED. As usb_hcd_irq() will always disable
+                * interrupts we can remove it here.
+                */
+               if (irqflags & IRQF_SHARED)
+                       irqflags &= ~IRQF_DISABLED;
+
                snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
                                hcd->driver->description, hcd->self.busnum);
                retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
index 673ee46962621e8013b102f2876c918bfa1d56f0..1af04bdeaf0c1884487ed830bcee7dd32ee720b6 100644 (file)
@@ -739,13 +739,16 @@ static void hub_tt_work(struct work_struct *work)
        int                     limit = 100;
 
        spin_lock_irqsave (&hub->tt.lock, flags);
-       while (--limit && !list_empty (&hub->tt.clear_list)) {
+       while (!list_empty(&hub->tt.clear_list)) {
                struct list_head        *next;
                struct usb_tt_clear     *clear;
                struct usb_device       *hdev = hub->hdev;
                const struct hc_driver  *drv;
                int                     status;
 
+               if (!hub->quiescing && --limit < 0)
+                       break;
+
                next = hub->tt.clear_list.next;
                clear = list_entry (next, struct usb_tt_clear, clear_list);
                list_del (&clear->clear_list);
@@ -1210,7 +1213,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type)
        if (hub->has_indicators)
                cancel_delayed_work_sync(&hub->leds);
        if (hub->tt.hub)
-               cancel_work_sync(&hub->tt.clear_work);
+               flush_work(&hub->tt.clear_work);
 }
 
 /* caller has locked the hub device */
@@ -3241,8 +3244,7 @@ static int usb_req_set_sel(struct usb_device *udev, enum usb3_link_state state)
                        (state == USB3_LPM_U2 &&
                         (u2_sel > USB3_LPM_MAX_U2_SEL_PEL ||
                          u2_pel > USB3_LPM_MAX_U2_SEL_PEL))) {
-               dev_dbg(&udev->dev, "Device-initiated %s disabled due "
-                               "to long SEL %llu ms or PEL %llu ms\n",
+               dev_dbg(&udev->dev, "Device-initiated %s disabled due to long SEL %llu us or PEL %llu us\n",
                                usb3_lpm_names[state], u1_sel, u1_pel);
                return -EINVAL;
        }
@@ -3319,16 +3321,6 @@ static int usb_set_device_initiated_lpm(struct usb_device *udev,
        }
 
        if (enable) {
-               /*
-                * First, let the device know about the exit latencies
-                * associated with the link state we're about to enable.
-                */
-               ret = usb_req_set_sel(udev, state);
-               if (ret < 0) {
-                       dev_warn(&udev->dev, "Set SEL for device-initiated "
-                                       "%s failed.\n", usb3_lpm_names[state]);
-                       return -EBUSY;
-               }
                /*
                 * Now send the control transfer to enable device-initiated LPM
                 * for either U1 or U2.
@@ -3414,7 +3406,28 @@ static int usb_set_lpm_timeout(struct usb_device *udev,
 static void usb_enable_link_state(struct usb_hcd *hcd, struct usb_device *udev,
                enum usb3_link_state state)
 {
-       int timeout;
+       int timeout, ret;
+       __u8 u1_mel = udev->bos->ss_cap->bU1devExitLat;
+       __le16 u2_mel = udev->bos->ss_cap->bU2DevExitLat;
+
+       /* If the device says it doesn't have *any* exit latency to come out of
+        * U1 or U2, it's probably lying.  Assume it doesn't implement that link
+        * state.
+        */
+       if ((state == USB3_LPM_U1 && u1_mel == 0) ||
+                       (state == USB3_LPM_U2 && u2_mel == 0))
+               return;
+
+       /*
+        * First, let the device know about the exit latencies
+        * associated with the link state we're about to enable.
+        */
+       ret = usb_req_set_sel(udev, state);
+       if (ret < 0) {
+               dev_warn(&udev->dev, "Set SEL for device-initiated %s failed.\n",
+                               usb3_lpm_names[state]);
+               return;
+       }
 
        /* We allow the host controller to set the U1/U2 timeout internally
         * first, so that it can change its schedule to account for the
index b415c0c859d3d2b3e990fc571b57d4e6e88f81fd..c14ebc975ba422028b663b4b90ac6e605c1c6115 100644 (file)
@@ -409,6 +409,10 @@ static void dwc3_core_exit(struct dwc3 *dwc)
 {
        dwc3_event_buffers_cleanup(dwc);
        dwc3_free_event_buffers(dwc);
+
+       usb_phy_shutdown(dwc->usb2_phy);
+       usb_phy_shutdown(dwc->usb3_phy);
+
 }
 
 #define DWC3_ALIGN_MASK                (16 - 1)
index c9e729a4bf6562876ba58b1776ce235ecc5ca5ed..7b7deddf6a52a264f02b7d47fa84d1916c461e6f 100644 (file)
@@ -1904,7 +1904,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
        ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
-
+       dep->flags &= ~DWC3_EP_BUSY;
        udelay(100);
 }
 
index e426ad626d7498bf5e6537ac100c7a508979066a..4bfa78af379cff63e1e74fa57453d7f55c96fb5e 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/ehci_def.h>
 #include <linux/delay.h>
 #include <linux/serial_core.h>
+#include <linux/kconfig.h>
 #include <linux/kgdb.h>
 #include <linux/kthread.h>
 #include <asm/io.h>
@@ -614,12 +615,6 @@ err:
        return -ENODEV;
 }
 
-int dbgp_external_startup(struct usb_hcd *hcd)
-{
-       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
-}
-EXPORT_SYMBOL_GPL(dbgp_external_startup);
-
 static int ehci_reset_port(int port)
 {
        u32 portsc;
@@ -979,6 +974,7 @@ struct console early_dbgp_console = {
        .index =        -1,
 };
 
+#if IS_ENABLED(CONFIG_USB_EHCI_HCD)
 int dbgp_reset_prep(struct usb_hcd *hcd)
 {
        int ret = xen_dbgp_reset_prep(hcd);
@@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(dbgp_reset_prep);
 
+int dbgp_external_startup(struct usb_hcd *hcd)
+{
+       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
+}
+EXPORT_SYMBOL_GPL(dbgp_external_startup);
+#endif /* USB_EHCI_HCD */
+
 #ifdef CONFIG_KGDB
 
 static char kgdbdbgp_buf[DBGP_MAX_PACKET];
index dfb51a45496c10cbaa2d930ae6a6f45ffb9860a4..e0ff51b895296ab66988e509bd6b73d94a663701 100644 (file)
@@ -952,6 +952,7 @@ endif
 config USB_G_WEBCAM
        tristate "USB Webcam Gadget"
        depends on VIDEO_DEV
+       select USB_LIBCOMPOSITE
        help
          The Webcam Gadget acts as a composite USB Audio and Video Class
          device. It provides a userspace API to process UVC control requests
index f696fb9b136ded4b8c32ba8b360ef2550551f73d..21a9861dabf0a9660a3c1cf74f04d055fbb0b649 100644 (file)
@@ -2930,10 +2930,10 @@ static void vbus_work(struct work_struct *work)
 
                /* Get the VBUS status from the transceiver */
                value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client,
-                                                ISP1301_I2C_OTG_CONTROL_2);
+                                                ISP1301_I2C_INTERRUPT_SOURCE);
 
                /* VBUS on or off? */
-               if (value & OTG_B_SESS_VLD)
+               if (value & INT_SESS_VLD)
                        udc->vbus = 1;
                else
                        udc->vbus = 0;
index 43ac7482fa9184dbd4748d42d6a6008e21f330ef..c009263a47e3250951fc1b16cab143ba0934eb86 100644 (file)
@@ -2069,8 +2069,10 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
 #if defined(PLX_PCI_RDK2)
        /* see if PCI int for us by checking irqstat */
        intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-       if (!intcsr & (1 << NET2272_PCI_IRQ))
+       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+               spin_unlock(&dev->lock);
                return IRQ_NONE;
+       }
        /* check dma interrupts */
 #endif
        /* Platform/devcice interrupt handler */
index 6458764994efe5d2523ca0cfded7af6a0fd91432..4ec3c0d7a18b84bb895262de69bf080886391025 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/ctype.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
+#include <linux/if_vlan.h>
 
 #include "u_ether.h"
 
@@ -295,7 +296,7 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req)
                while (skb2) {
                        if (status < 0
                                        || ETH_HLEN > skb2->len
-                                       || skb2->len > ETH_FRAME_LEN) {
+                                       || skb2->len > VLAN_ETH_FRAME_LEN) {
                                dev->net->stats.rx_errors++;
                                dev->net->stats.rx_length_errors++;
                                DBG(dev, "rx length %d\n", skb2->len);
index 9bfde82078ecabde8236fc504aaf2a1794d25fb3..0d2f35ca93f1d5e7091cc77122e70b162f22679d 100644 (file)
@@ -222,7 +222,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd,
 
        if (pdata->controller_ver < 0) {
                dev_warn(hcd->self.controller, "Could not get controller version\n");
-               return;
+               return -ENODEV;
        }
 
        portsc = ehci_readl(ehci, &ehci->regs->port_status[port_offset]);
index ca759652626bcf5f823a32bf9e6640acda23a02b..aa0f328922dfad88495b919a84d82abd3a494ac9 100644 (file)
@@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
                goto err_put_hcd;
        }
 
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (ret)
                goto err_put_hcd;
 
index 8e7eca62f169fc204c6e1ef2034f26acdf2729dc..9c2717d66730ad74d9f99ef2aa0795b25c716a1b 100644 (file)
@@ -160,7 +160,7 @@ static const struct hc_driver ehci_orion_hc_driver = {
        .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
 };
 
-static void __init
+static void __devinit
 ehci_orion_conf_mbus_windows(struct usb_hcd *hcd,
                             const struct mbus_dram_target_info *dram)
 {
index 96722bfebc84ba0bed49f6cd4c0aa3313f7f55dd..d3c9a3e397b99ed4f423ee41575038890ff4e4eb 100644 (file)
@@ -85,6 +85,8 @@ static const struct hc_driver vt8500_ehci_hc_driver = {
        .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
 };
 
+static u64 vt8500_ehci_dma_mask = DMA_BIT_MASK(32);
+
 static int vt8500_ehci_drv_probe(struct platform_device *pdev)
 {
        struct usb_hcd *hcd;
@@ -95,6 +97,14 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev)
        if (usb_disabled())
                return -ENODEV;
 
+       /*
+        * Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we have dma capability bindings this can go away.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &vt8500_ehci_dma_mask;
+
        if (pdev->resource[1].flags != IORESOURCE_IRQ) {
                pr_debug("resource[1] is not IORESOURCE_IRQ");
                return -ENOMEM;
index 84201cd1a472cd5b00bd959b28bcf35af24137e6..41e378f17c66ac453f2aabfd25640c8e77120224 100644 (file)
@@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver,
                goto err3;
        }
 
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (retval != 0)
                goto err4;
        return retval;
index 966d1484ee79a2db8c5e78e135c5e0760814d183..39f9e4a9a2d3f086470c6cac459ca0ab4a4fec78 100644 (file)
@@ -545,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = {
                /*  Pegatron Lucid (Ordissimo AIRIS) */
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "M11JB"),
-                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
+               },
+       },
+       {
+               /*  Pegatron Lucid (Ordissimo) */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"),
+                       DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"),
                },
        },
        { }
index e4780491df4a8255de5f5196ca0813be6f44c681..68ebf20e15192f954eaf1a1e69735fadc878bd68 100644 (file)
@@ -60,6 +60,7 @@ static const struct hc_driver uhci_platform_hc_driver = {
        .hub_control =          uhci_hub_control,
 };
 
+static u64 platform_uhci_dma_mask = DMA_BIT_MASK(32);
 
 static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev)
 {
@@ -71,6 +72,14 @@ static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev)
        if (usb_disabled())
                return -ENODEV;
 
+       /*
+        * Right now device-tree probed devices don't get dma_mask set.
+        * Since shared usb code relies on it, set it here for now.
+        * Once we have dma capability bindings this can go away.
+        */
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &platform_uhci_dma_mask;
+
        hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev,
                        pdev->name);
        if (!hcd)
index 4b436f5a41711bc1a7747f3c7b187ff547c7acbd..5f3a7c74aa8d39404212d342f6236fe1ea48d514 100644 (file)
@@ -544,7 +544,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
        int i;
        /* Fields are 32 bits wide, DMA addresses are in bytes */
        int field_size = 32 / 8;
-       struct xhci_slot_ctx *slot_ctx;
        dma_addr_t dma = ctx->dma;
        int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
 
@@ -570,7 +569,6 @@ void xhci_dbg_ctx(struct xhci_hcd *xhci,
                        dbg_rsvd64(xhci, (u64 *)ctrl_ctx, dma);
        }
 
-       slot_ctx = xhci_get_slot_ctx(xhci, ctx);
        xhci_dbg_slot_ctx(xhci, ctx);
        xhci_dbg_ep_ctx(xhci, ctx, last_ep);
 }
index aa90ad4d4fd53b2f70288641dcd13942355ca875..a686cf4905bb80ae3e4c7b206c05d7cd2b960920 100644 (file)
@@ -151,9 +151,8 @@ static void xhci_usb3_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
                if (portsc & PORT_DEV_REMOVE)
                        port_removable |= 1 << (i + 1);
        }
-       memset(&desc->u.ss.DeviceRemovable,
-                       (__force __u16) cpu_to_le16(port_removable),
-                       sizeof(__u16));
+
+       desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);
 }
 
 static void xhci_hub_descriptor(struct usb_hcd *hcd, struct xhci_hcd *xhci,
@@ -809,11 +808,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        temp = xhci_readl(xhci, port_array[wIndex]);
                        xhci_dbg(xhci, "set port power, actual port %d status  = 0x%x\n", wIndex, temp);
 
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        temp = usb_acpi_power_manageable(hcd->self.root_hub,
                                        wIndex);
                        if (temp)
                                usb_acpi_set_power_state(hcd->self.root_hub,
                                                wIndex, true);
+                       spin_lock_irqsave(&xhci->lock, flags);
                        break;
                case USB_PORT_FEAT_RESET:
                        temp = (temp | PORT_RESET);
@@ -917,11 +918,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                        xhci_writel(xhci, temp & ~PORT_POWER,
                                port_array[wIndex]);
 
+                       spin_unlock_irqrestore(&xhci->lock, flags);
                        temp = usb_acpi_power_manageable(hcd->self.root_hub,
                                        wIndex);
                        if (temp)
                                usb_acpi_set_power_state(hcd->self.root_hub,
                                                wIndex, false);
+                       spin_lock_irqsave(&xhci->lock, flags);
                        break;
                default:
                        goto error;
index c6ebb176dc4fb33d1307b9068ea7d27728356637..4e1a8946b8d167c1f36be62b3bc63265f7271815 100644 (file)
@@ -1228,6 +1228,17 @@ static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd)
        cur_seg = find_trb_seg(xhci->cmd_ring->first_seg,
                        xhci->cmd_ring->dequeue, &cycle_state);
 
+       if (!cur_seg) {
+               xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n",
+                               xhci->cmd_ring->dequeue,
+                               (unsigned long long)
+                               xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+                                       xhci->cmd_ring->dequeue));
+               xhci_debug_ring(xhci, xhci->cmd_ring);
+               xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring);
+               return;
+       }
+
        /* find the command trb matched by cd from command ring */
        for (cmd_trb = xhci->cmd_ring->dequeue;
                        cmd_trb != xhci->cmd_ring->enqueue;
index 8d7fcbbe6ade92df9dab163402be686544ae7f84..c9e419f29b7454225516cb8629ddff80af5187d9 100644 (file)
@@ -479,7 +479,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void)
 
        if (strstr(dmi_product_name, "Z420") ||
                        strstr(dmi_product_name, "Z620") ||
-                       strstr(dmi_product_name, "Z820"))
+                       strstr(dmi_product_name, "Z820") ||
+                       strstr(dmi_product_name, "Z1"))
                return true;
 
        return false;
@@ -1626,7 +1627,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        struct xhci_hcd *xhci;
        struct xhci_container_ctx *in_ctx, *out_ctx;
        unsigned int ep_index;
-       struct xhci_ep_ctx *ep_ctx;
        struct xhci_slot_ctx *slot_ctx;
        struct xhci_input_control_ctx *ctrl_ctx;
        u32 added_ctxs;
@@ -1662,7 +1662,6 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
        out_ctx = virt_dev->out_ctx;
        ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
        ep_index = xhci_get_endpoint_index(&ep->desc);
-       ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
 
        /* If this endpoint is already in use, and the upper layers are trying
         * to add it again without dropping it, reject the addition.
@@ -1816,6 +1815,8 @@ static int xhci_evaluate_context_result(struct xhci_hcd *xhci,
        case COMP_EBADSLT:
                dev_warn(&udev->dev, "WARN: slot not enabled for"
                                "evaluate context command.\n");
+               ret = -EINVAL;
+               break;
        case COMP_CTX_STATE:
                dev_warn(&udev->dev, "WARN: invalid context state for "
                                "evaluate context command.\n");
@@ -4020,7 +4021,7 @@ int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
 static unsigned long long xhci_service_interval_to_ns(
                struct usb_endpoint_descriptor *desc)
 {
-       return (1 << (desc->bInterval - 1)) * 125 * 1000;
+       return (1ULL << (desc->bInterval - 1)) * 125 * 1000;
 }
 
 static u16 xhci_get_timeout_no_hub_lpm(struct usb_device *udev,
@@ -4141,7 +4142,7 @@ static u16 xhci_calculate_intel_u2_timeout(struct usb_device *udev,
                        (xhci_service_interval_to_ns(desc) > timeout_ns))
                timeout_ns = xhci_service_interval_to_ns(desc);
 
-       u2_del_ns = udev->bos->ss_cap->bU2DevExitLat * 1000;
+       u2_del_ns = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat) * 1000ULL;
        if (u2_del_ns > timeout_ns)
                timeout_ns = u2_del_ns;
 
index 4223d761223d3440a243a87150d4283537e89a4b..6589268a651517da44f99cd7391e2ca35f84f12a 100644 (file)
@@ -158,3 +158,4 @@ int ezusb_fx2_ihex_firmware_download(struct usb_device *dev,
 }
 EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download);
 
+MODULE_LICENSE("GPL");
index 457f25e62c519a33be80e39dcbb8b222cee8de12..c964d6af178bd0196e20a80bd482529c38369900 100644 (file)
@@ -305,6 +305,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
                ret = IRQ_HANDLED;
        }
 
+       /* Drop spurious RX and TX if device is disconnected */
+       if (musb->int_usb & MUSB_INTR_DISCONNECT) {
+               musb->int_tx = 0;
+               musb->int_rx = 0;
+       }
+
        if (musb->int_tx || musb->int_rx || musb->int_usb)
                ret |= musb_interrupt(musb);
 
index 444346e1e10d768086b1e10487f6b6428c892897..ff5f112053d28f114e4d90844b7aa2172f3856d4 100644 (file)
@@ -458,11 +458,11 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        struct platform_device  *musb;
        struct resource *res;
        struct resource resources[2];
-       char res_name[10];
+       char res_name[11];
        int ret, musbid;
 
        /* get memory resource */
-       sprintf(res_name, "musb%d", id);
+       snprintf(res_name, sizeof(res_name), "musb%d", id);
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name);
        if (!res) {
                dev_err(dev, "%s get mem resource failed\n", res_name);
@@ -473,7 +473,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
        resources[0] = *res;
 
        /* get irq resource */
-       sprintf(res_name, "musb%d-irq", id);
+       snprintf(res_name, sizeof(res_name), "musb%d-irq", id);
        res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name);
        if (!res) {
                dev_err(dev, "%s get irq resource failed\n", res_name);
@@ -530,7 +530,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id)
 
                of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
                of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
-               sprintf(res_name, "port%d-mode", id);
+               snprintf(res_name, sizeof(res_name), "port%d-mode", id);
                of_property_read_u32(np, res_name, (u32 *)&pdata->mode);
                of_property_read_u32(np, "power", (u32 *)&pdata->power);
                config->multipoint = of_property_read_bool(np, "multipoint");
index d0b87e7b4abfd98b232c135df7661d6dbe0bfe90..b6b84dacc7917070fb20503243ac51098c927631 100644 (file)
@@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                fifo_count = musb_readw(epio, MUSB_RXCOUNT);
 
                /*
-                *  use mode 1 only if we expect data of at least ep packet_sz
-                *  and have not yet received a short packet
+                * Enable Mode 1 on RX transfers only when short_not_ok flag
+                * is set. Currently short_not_ok flag is set only from
+                * file_storage and f_mass_storage drivers
                 */
-               if ((request->length - request->actual >= musb_ep->packet_sz) &&
-                       (fifo_count >= musb_ep->packet_sz))
+
+               if (request->short_not_ok && fifo_count == musb_ep->packet_sz)
                        use_mode_1 = 1;
                else
                        use_mode_1 = 0;
@@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                c = musb->dma_controller;
                                channel = musb_ep->dma;
 
+       /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
+        * mode 0 only. So we do not get endpoint interrupts due to DMA
+        * completion. We only get interrupts from DMA controller.
+        *
+        * We could operate in DMA mode 1 if we knew the size of the tranfer
+        * in advance. For mass storage class, request->length = what the host
+        * sends, so that'd work.  But for pretty much everything else,
+        * request->length is routinely more than what the host sends. For
+        * most these gadgets, end of is signified either by a short packet,
+        * or filling the last byte of the buffer.  (Sending extra data in
+        * that last pckate should trigger an overflow fault.)  But in mode 1,
+        * we don't get DMA completion interrupt for short packets.
+        *
+        * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
+        * to get endpoint interrupt on every DMA req, but that didn't seem
+        * to work reliably.
+        *
+        * REVISIT an updated g_file_storage can set req->short_not_ok, which
+        * then becomes usable as a runtime "use mode 1" hint...
+        */
+
                                /* Experimental: Mode1 works with mass storage use cases */
                                if (use_mode_1) {
                                        csr |= MUSB_RXCSR_AUTOCLEAR;
index d62a91fedc221c02774de2c8b9c9e66c3a880ade..0e62f504410eaaf1120edb49ef40381eb7d41d59 100644 (file)
@@ -65,7 +65,7 @@ static int __devinit ux500_probe(struct platform_device *pdev)
        struct platform_device          *musb;
        struct ux500_glue               *glue;
        struct clk                      *clk;
-
+       int                             musbid;
        int                             ret = -ENOMEM;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
index d8c8a42bff3eb0bb9187849e8136a6ba358a92cf..6223062d5d1b5487534dc29724508d2e5df68793 100644 (file)
@@ -58,7 +58,7 @@ config USB_ULPI_VIEWPORT
 
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
-       depends on TWL4030_CORE && REGULATOR_TWL4030
+       depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
        select USB_OTG_UTILS
        help
          Enable this to support the USB OTG transceiver on TWL4030
@@ -68,7 +68,7 @@ config TWL4030_USB
 
 config TWL6030_USB
        tristate "TWL6030 USB Transceiver Driver"
-       depends on TWL4030_CORE && OMAP_USB2
+       depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
        select USB_OTG_UTILS
        help
          Enable this to support the USB OTG transceiver on TWL6030
index 143c4e9e1be45cc24c0a612d38e590a5ad136be9..c021b202c0f3fe05894d3a94075c55bea8dd1a66 100644 (file)
@@ -795,6 +795,7 @@ static void xfer_work(struct work_struct *work)
        dev_dbg(dev, "  %s %d (%d/ %d)\n",
                fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
 
+       usbhs_pipe_enable(pipe);
        usbhsf_dma_start(pipe, fifo);
        dma_async_issue_pending(chan);
 }
index 35c5208f32494d7c55f4fd98fa79cf517425ca46..61933a90e5bfdbe41fed1679979977e6ff849b4b 100644 (file)
@@ -273,9 +273,9 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
        usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
        usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
 
-       usbhs_write(priv, BRDYSTS, 0);
-       usbhs_write(priv, NRDYSTS, 0);
-       usbhs_write(priv, BEMPSTS, 0);
+       usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
+       usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
+       usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
 
        /*
         * call irq callback functions
index 9b69a132329474052486e0483649b6c64a746a4f..069cd765400cbf51f649564d5ed8490d90cd8259 100644 (file)
@@ -334,6 +334,11 @@ static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
        struct device *dev = usbhs_priv_to_dev(priv);
        unsigned long flags;
 
+       if (unlikely(!uep)) {
+               dev_err(dev, "no uep\n");
+               return;
+       }
+
        /********************  spin lock ********************/
        usbhs_lock(priv, flags);
 
index 08786c06dcf1d21f0784ea6d02553c381a11dfd0..3d80c7b1fd1b4ba15133e2ffcd3c5db7be2e9933 100644 (file)
@@ -54,7 +54,7 @@ struct usbhs_pipe_info {
  * pipe list
  */
 #define __usbhs_for_each_pipe(start, pos, info, i)     \
-       for (i = start, pos = (info)->pipe;             \
+       for (i = start, pos = (info)->pipe + i;         \
             i < (info)->size;                          \
             i++, pos = (info)->pipe + i)
 
index cf2522c397d3957c0477a591d20f59d108496aa2..bd50a8a41a0f583a589c06586d09765ae2c13a27 100644 (file)
@@ -125,9 +125,6 @@ static inline int calc_divisor(int bps)
 
 static int ark3116_attach(struct usb_serial *serial)
 {
-       struct usb_serial_port *port = serial->port[0];
-       struct ark3116_private *priv;
-
        /* make sure we have our end-points */
        if ((serial->num_bulk_in == 0) ||
            (serial->num_bulk_out == 0) ||
@@ -142,8 +139,15 @@ static int ark3116_attach(struct usb_serial *serial)
                return -EINVAL;
        }
 
-       priv = kzalloc(sizeof(struct ark3116_private),
-                      GFP_KERNEL);
+       return 0;
+}
+
+static int ark3116_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct ark3116_private *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
@@ -198,18 +202,15 @@ static int ark3116_attach(struct usb_serial *serial)
        return 0;
 }
 
-static void ark3116_release(struct usb_serial *serial)
+static int ark3116_port_remove(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct ark3116_private *priv = usb_get_serial_port_data(port);
 
        /* device is closed, so URBs and DMA should be down */
-
-       usb_set_serial_port_data(port, NULL);
-
        mutex_destroy(&priv->hw_lock);
-
        kfree(priv);
+
+       return 0;
 }
 
 static void ark3116_init_termios(struct tty_struct *tty)
@@ -723,7 +724,8 @@ static struct usb_serial_driver ark3116_device = {
        .id_table =             id_table,
        .num_ports =            1,
        .attach =               ark3116_attach,
-       .release =              ark3116_release,
+       .port_probe =           ark3116_port_probe,
+       .port_remove =          ark3116_port_remove,
        .set_termios =          ark3116_set_termios,
        .init_termios =         ark3116_init_termios,
        .ioctl =                ark3116_ioctl,
index 99449424193f7295f5e3e5160e7993542080bda1..ea29556f0d7222a87475afa34e6fe683f6b4e513 100644 (file)
@@ -45,8 +45,8 @@
 #define DRIVER_DESC "USB Belkin Serial converter driver"
 
 /* function prototypes for a Belkin USB Serial Adapter F5U103 */
-static int  belkin_sa_startup(struct usb_serial *serial);
-static void belkin_sa_release(struct usb_serial *serial);
+static int belkin_sa_port_probe(struct usb_serial_port *port);
+static int belkin_sa_port_remove(struct usb_serial_port *port);
 static int  belkin_sa_open(struct tty_struct *tty,
                        struct usb_serial_port *port);
 static void belkin_sa_close(struct usb_serial_port *port);
@@ -88,8 +88,8 @@ static struct usb_serial_driver belkin_device = {
        .break_ctl =            belkin_sa_break_ctl,
        .tiocmget =             belkin_sa_tiocmget,
        .tiocmset =             belkin_sa_tiocmset,
-       .attach =               belkin_sa_startup,
-       .release =              belkin_sa_release,
+       .port_probe =           belkin_sa_port_probe,
+       .port_remove =          belkin_sa_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -118,17 +118,15 @@ struct belkin_sa_private {
                                            (c), BELKIN_SA_SET_REQUEST_TYPE, \
                                            (v), 0, NULL, 0, WDR_TIMEOUT)
 
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int belkin_sa_startup(struct usb_serial *serial)
+static int belkin_sa_port_probe(struct usb_serial_port *port)
 {
-       struct usb_device *dev = serial->dev;
+       struct usb_device *dev = port->serial->dev;
        struct belkin_sa_private *priv;
 
-       /* allocate the private data structure */
        priv = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL);
        if (!priv)
-               return -1; /* error */
-       /* set initial values for control structures */
+               return -ENOMEM;
+
        spin_lock_init(&priv->lock);
        priv->control_state = 0;
        priv->last_lsr = 0;
@@ -140,18 +138,19 @@ static int belkin_sa_startup(struct usb_serial *serial)
                                        le16_to_cpu(dev->descriptor.bcdDevice),
                                        priv->bad_flow_control);
 
-       init_waitqueue_head(&serial->port[0]->write_wait);
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
 
        return 0;
 }
 
-static void belkin_sa_release(struct usb_serial *serial)
+static int belkin_sa_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct belkin_sa_private *priv;
 
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static int belkin_sa_open(struct tty_struct *tty,
index e9c7046ae355a9da6746c83b669b8605c38fec96..d255f66e708e80ee78d72bc052bef4e71ba578e2 100644 (file)
@@ -242,13 +242,11 @@ out:      kfree(buffer);
        return r;
 }
 
-/* allocate private data */
-static int ch341_attach(struct usb_serial *serial)
+static int ch341_port_probe(struct usb_serial_port *port)
 {
        struct ch341_private *priv;
        int r;
 
-       /* private data */
        priv = kzalloc(sizeof(struct ch341_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
@@ -258,17 +256,27 @@ static int ch341_attach(struct usb_serial *serial)
        priv->baud_rate = DEFAULT_BAUD_RATE;
        priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
-       r = ch341_configure(serial->dev, priv);
+       r = ch341_configure(port->serial->dev, priv);
        if (r < 0)
                goto error;
 
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
        return 0;
 
 error: kfree(priv);
        return r;
 }
 
+static int ch341_port_remove(struct usb_serial_port *port)
+{
+       struct ch341_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
+
 static int ch341_carrier_raised(struct usb_serial_port *port)
 {
        struct ch341_private *priv = usb_get_serial_port_data(port);
@@ -304,7 +312,7 @@ static void ch341_close(struct usb_serial_port *port)
 static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
-       struct ch341_private *priv = usb_get_serial_port_data(serial->port[0]);
+       struct ch341_private *priv = usb_get_serial_port_data(port);
        int r;
 
        priv->baud_rate = DEFAULT_BAUD_RATE;
@@ -608,7 +616,8 @@ static struct usb_serial_driver ch341_device = {
        .tiocmget          = ch341_tiocmget,
        .tiocmset          = ch341_tiocmset,
        .read_int_callback = ch341_read_int_callback,
-       .attach            = ch341_attach,
+       .port_probe        = ch341_port_probe,
+       .port_remove       = ch341_port_remove,
        .reset_resume      = ch341_reset_resume,
 };
 
index 28af5acc3360c57beaad356f1b4aa016fc221810..eb033fc92a156bf3c8f43e94a248ead38f695642 100644 (file)
@@ -162,7 +162,7 @@ static const struct usb_device_id id_table[] = {
 
 MODULE_DEVICE_TABLE(usb, id_table);
 
-struct cp210x_port_private {
+struct cp210x_serial_private {
        __u8                    bInterfaceNumber;
 };
 
@@ -276,7 +276,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
                unsigned int *data, int size)
 {
        struct usb_serial *serial = port->serial;
-       struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+       struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
        __le32 *buf;
        int result, i, length;
 
@@ -292,7 +292,7 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request,
        /* Issue the request, attempting to read 'size' bytes */
        result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
                                request, REQTYPE_INTERFACE_TO_HOST, 0x0000,
-                               port_priv->bInterfaceNumber, buf, size,
+                               spriv->bInterfaceNumber, buf, size,
                                USB_CTRL_GET_TIMEOUT);
 
        /* Convert data into an array of integers */
@@ -323,7 +323,7 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
                unsigned int *data, int size)
 {
        struct usb_serial *serial = port->serial;
-       struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
+       struct cp210x_serial_private *spriv = usb_get_serial_data(serial);
        __le32 *buf;
        int result, i, length;
 
@@ -345,13 +345,13 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request,
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0),
                                request, REQTYPE_HOST_TO_INTERFACE, 0x0000,
-                               port_priv->bInterfaceNumber, buf, size,
+                               spriv->bInterfaceNumber, buf, size,
                                USB_CTRL_SET_TIMEOUT);
        } else {
                result = usb_control_msg(serial->dev,
                                usb_sndctrlpipe(serial->dev, 0),
                                request, REQTYPE_HOST_TO_INTERFACE, data[0],
-                               port_priv->bInterfaceNumber, NULL, 0,
+                               spriv->bInterfaceNumber, NULL, 0,
                                USB_CTRL_SET_TIMEOUT);
        }
 
@@ -845,36 +845,30 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
 
 static int cp210x_startup(struct usb_serial *serial)
 {
-       struct cp210x_port_private *port_priv;
-       int i;
+       struct usb_host_interface *cur_altsetting;
+       struct cp210x_serial_private *spriv;
 
        /* cp210x buffers behave strangely unless device is reset */
        usb_reset_device(serial->dev);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-               if (!port_priv)
-                       return -ENOMEM;
+       spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+       if (!spriv)
+               return -ENOMEM;
 
-               port_priv->bInterfaceNumber =
-                   serial->interface->cur_altsetting->desc.bInterfaceNumber;
+       cur_altsetting = serial->interface->cur_altsetting;
+       spriv->bInterfaceNumber = cur_altsetting->desc.bInterfaceNumber;
 
-               usb_set_serial_port_data(serial->port[i], port_priv);
-       }
+       usb_set_serial_data(serial, spriv);
 
        return 0;
 }
 
 static void cp210x_release(struct usb_serial *serial)
 {
-       struct cp210x_port_private *port_priv;
-       int i;
+       struct cp210x_serial_private *spriv;
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(port_priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
+       spriv = usb_get_serial_data(serial);
+       kfree(spriv);
 }
 
 module_usb_serial_driver(serial_drivers, id_table);
index 2a7aecc72237ccaac68b2c922093182c878acbda..4ee77dcbe690dc73e95f79ebf2d3d75e2784326b 100644 (file)
@@ -55,9 +55,9 @@
 #define CYBERJACK_PRODUCT_ID   0x0100
 
 /* Function prototypes */
-static int cyberjack_startup(struct usb_serial *serial);
 static void cyberjack_disconnect(struct usb_serial *serial);
-static void cyberjack_release(struct usb_serial *serial);
+static int cyberjack_port_probe(struct usb_serial_port *port);
+static int cyberjack_port_remove(struct usb_serial_port *port);
 static int  cyberjack_open(struct tty_struct *tty,
        struct usb_serial_port *port);
 static void cyberjack_close(struct usb_serial_port *port);
@@ -83,9 +83,9 @@ static struct usb_serial_driver cyberjack_device = {
        .description =          "Reiner SCT Cyberjack USB card reader",
        .id_table =             id_table,
        .num_ports =            1,
-       .attach =               cyberjack_startup,
        .disconnect =           cyberjack_disconnect,
-       .release =              cyberjack_release,
+       .port_probe =           cyberjack_port_probe,
+       .port_remove =          cyberjack_port_remove,
        .open =                 cyberjack_open,
        .close =                cyberjack_close,
        .write =                cyberjack_write,
@@ -107,56 +107,45 @@ struct cyberjack_private {
        short           wrsent;         /* Data already sent */
 };
 
-/* do some startup allocations not currently performed by usb_serial_probe() */
-static int cyberjack_startup(struct usb_serial *serial)
+static int cyberjack_port_probe(struct usb_serial_port *port)
 {
        struct cyberjack_private *priv;
-       int i;
+       int result;
 
-       /* allocate the private data structure */
        priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
-       /* set initial values */
        spin_lock_init(&priv->lock);
        priv->rdtodo = 0;
        priv->wrfilled = 0;
        priv->wrsent = 0;
-       usb_set_serial_port_data(serial->port[0], priv);
 
-       init_waitqueue_head(&serial->port[0]->write_wait);
+       usb_set_serial_port_data(port, priv);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               int result;
-               result = usb_submit_urb(serial->port[i]->interrupt_in_urb,
-                                       GFP_KERNEL);
-               if (result)
-                       dev_err(&serial->dev->dev,
-                               "usb_submit_urb(read int) failed\n");
-               dev_dbg(&serial->dev->dev, "%s - usb_submit_urb(int urb)\n",
-                       __func__);
-       }
+       result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
+       if (result)
+               dev_err(&port->dev, "usb_submit_urb(read int) failed\n");
 
        return 0;
 }
 
-static void cyberjack_disconnect(struct usb_serial *serial)
+static int cyberjack_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct cyberjack_private *priv;
 
-       for (i = 0; i < serial->num_ports; ++i)
-               usb_kill_urb(serial->port[i]->interrupt_in_urb);
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
-static void cyberjack_release(struct usb_serial *serial)
+static void cyberjack_disconnect(struct usb_serial *serial)
 {
        int i;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* My special items, the standard routines free my urbs */
-               kfree(usb_get_serial_port_data(serial->port[i]));
-       }
+       for (i = 0; i < serial->num_ports; ++i)
+               usb_kill_urb(serial->port[i]->interrupt_in_urb);
 }
 
 static int  cyberjack_open(struct tty_struct *tty,
index 1befce21e1734df489e940e49023a9b8a3c37d95..f0da1279c11410ece644a5fd4f4cf9e4532588c8 100644 (file)
@@ -123,10 +123,10 @@ struct cypress_private {
 };
 
 /* function prototypes for the Cypress USB to serial device */
-static int  cypress_earthmate_startup(struct usb_serial *serial);
-static int  cypress_hidcom_startup(struct usb_serial *serial);
-static int  cypress_ca42v2_startup(struct usb_serial *serial);
-static void cypress_release(struct usb_serial *serial);
+static int  cypress_earthmate_port_probe(struct usb_serial_port *port);
+static int  cypress_hidcom_port_probe(struct usb_serial_port *port);
+static int  cypress_ca42v2_port_probe(struct usb_serial_port *port);
+static int  cypress_port_remove(struct usb_serial_port *port);
 static int  cypress_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void cypress_close(struct usb_serial_port *port);
 static void cypress_dtr_rts(struct usb_serial_port *port, int on);
@@ -156,8 +156,8 @@ static struct usb_serial_driver cypress_earthmate_device = {
        .description =                  "DeLorme Earthmate USB",
        .id_table =                     id_table_earthmate,
        .num_ports =                    1,
-       .attach =                       cypress_earthmate_startup,
-       .release =                      cypress_release,
+       .port_probe =                   cypress_earthmate_port_probe,
+       .port_remove =                  cypress_port_remove,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .dtr_rts =                      cypress_dtr_rts,
@@ -182,8 +182,8 @@ static struct usb_serial_driver cypress_hidcom_device = {
        .description =                  "HID->COM RS232 Adapter",
        .id_table =                     id_table_cyphidcomrs232,
        .num_ports =                    1,
-       .attach =                       cypress_hidcom_startup,
-       .release =                      cypress_release,
+       .port_probe =                   cypress_hidcom_port_probe,
+       .port_remove =                  cypress_port_remove,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .dtr_rts =                      cypress_dtr_rts,
@@ -208,8 +208,8 @@ static struct usb_serial_driver cypress_ca42v2_device = {
        .description =                  "Nokia CA-42 V2 Adapter",
        .id_table =                     id_table_nokiaca42v2,
        .num_ports =                    1,
-       .attach =                       cypress_ca42v2_startup,
-       .release =                      cypress_release,
+       .port_probe =                   cypress_ca42v2_port_probe,
+       .port_remove =                  cypress_port_remove,
        .open =                         cypress_open,
        .close =                        cypress_close,
        .dtr_rts =                      cypress_dtr_rts,
@@ -438,10 +438,10 @@ static void cypress_set_dead(struct usb_serial_port *port)
  *****************************************************************************/
 
 
-static int generic_startup(struct usb_serial *serial)
+static int cypress_generic_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct cypress_private *priv;
-       struct usb_serial_port *port = serial->port[0];
 
        priv = kzalloc(sizeof(struct cypress_private), GFP_KERNEL);
        if (!priv)
@@ -490,14 +490,16 @@ static int generic_startup(struct usb_serial *serial)
 }
 
 
-static int cypress_earthmate_startup(struct usb_serial *serial)
+static int cypress_earthmate_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct cypress_private *priv;
-       struct usb_serial_port *port = serial->port[0];
+       int ret;
 
-       if (generic_startup(serial)) {
+       ret = cypress_generic_port_probe(port);
+       if (ret) {
                dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
-               return 1;
+               return ret;
        }
 
        priv = usb_get_serial_port_data(port);
@@ -518,56 +520,53 @@ static int cypress_earthmate_startup(struct usb_serial *serial)
        }
 
        return 0;
-} /* cypress_earthmate_startup */
-
+}
 
-static int cypress_hidcom_startup(struct usb_serial *serial)
+static int cypress_hidcom_port_probe(struct usb_serial_port *port)
 {
        struct cypress_private *priv;
-       struct usb_serial_port *port = serial->port[0];
+       int ret;
 
-       if (generic_startup(serial)) {
+       ret = cypress_generic_port_probe(port);
+       if (ret) {
                dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
-               return 1;
+               return ret;
        }
 
        priv = usb_get_serial_port_data(port);
        priv->chiptype = CT_CYPHIDCOM;
 
        return 0;
-} /* cypress_hidcom_startup */
-
+}
 
-static int cypress_ca42v2_startup(struct usb_serial *serial)
+static int cypress_ca42v2_port_probe(struct usb_serial_port *port)
 {
        struct cypress_private *priv;
-       struct usb_serial_port *port = serial->port[0];
+       int ret;
 
-       if (generic_startup(serial)) {
+       ret = cypress_generic_port_probe(port);
+       if (ret) {
                dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__);
-               return 1;
+               return ret;
        }
 
        priv = usb_get_serial_port_data(port);
        priv->chiptype = CT_CA42V2;
 
        return 0;
-} /* cypress_ca42v2_startup */
-
+}
 
-static void cypress_release(struct usb_serial *serial)
+static int cypress_port_remove(struct usb_serial_port *port)
 {
        struct cypress_private *priv;
 
-       /* all open ports are closed at this point */
-       priv = usb_get_serial_port_data(serial->port[0]);
+       priv = usb_get_serial_port_data(port);
 
-       if (priv) {
-               kfifo_free(&priv->write_fifo);
-               kfree(priv);
-       }
-}
+       kfifo_free(&priv->write_fifo);
+       kfree(priv);
 
+       return 0;
+}
 
 static int cypress_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
index c86f68c6b0785942e16315ebf34443a0f94b2161..b50fa1c6d885be8df8d5675edbedc6637fb9c33f 100644 (file)
@@ -244,6 +244,8 @@ static int digi_startup_device(struct usb_serial *serial);
 static int digi_startup(struct usb_serial *serial);
 static void digi_disconnect(struct usb_serial *serial);
 static void digi_release(struct usb_serial *serial);
+static int digi_port_probe(struct usb_serial_port *port);
+static int digi_port_remove(struct usb_serial_port *port);
 static void digi_read_bulk_callback(struct urb *urb);
 static int digi_read_inb_callback(struct urb *urb);
 static int digi_read_oob_callback(struct urb *urb);
@@ -294,6 +296,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
        .attach =                       digi_startup,
        .disconnect =                   digi_disconnect,
        .release =                      digi_release,
+       .port_probe =                   digi_port_probe,
+       .port_remove =                  digi_port_remove,
 };
 
 static struct usb_serial_driver digi_acceleport_4_device = {
@@ -320,6 +324,8 @@ static struct usb_serial_driver digi_acceleport_4_device = {
        .attach =                       digi_startup,
        .disconnect =                   digi_disconnect,
        .release =                      digi_release,
+       .port_probe =                   digi_port_probe,
+       .port_remove =                  digi_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -1240,59 +1246,50 @@ static int digi_startup_device(struct usb_serial *serial)
        return ret;
 }
 
-
-static int digi_startup(struct usb_serial *serial)
+static int digi_port_init(struct usb_serial_port *port, unsigned port_num)
 {
-
-       int i;
        struct digi_port *priv;
-       struct digi_serial *serial_priv;
 
-       /* allocate the private data structures for all ports */
-       /* number of regular ports + 1 for the out-of-band port */
-       for (i = 0; i < serial->type->num_ports + 1; i++) {
-               /* allocate port private structure */
-               priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
-               if (priv == NULL) {
-                       while (--i >= 0)
-                               kfree(usb_get_serial_port_data(serial->port[i]));
-                       return 1;                       /* error */
-               }
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               /* initialize port private structure */
-               spin_lock_init(&priv->dp_port_lock);
-               priv->dp_port_num = i;
-               priv->dp_out_buf_len = 0;
-               priv->dp_write_urb_in_use = 0;
-               priv->dp_modem_signals = 0;
-               init_waitqueue_head(&priv->dp_modem_change_wait);
-               priv->dp_transmit_idle = 0;
-               init_waitqueue_head(&priv->dp_transmit_idle_wait);
-               priv->dp_throttled = 0;
-               priv->dp_throttle_restart = 0;
-               init_waitqueue_head(&priv->dp_flush_wait);
-               init_waitqueue_head(&priv->dp_close_wait);
-               INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
-               priv->dp_port = serial->port[i];
-               /* initialize write wait queue for this port */
-               init_waitqueue_head(&serial->port[i]->write_wait);
-
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
+       spin_lock_init(&priv->dp_port_lock);
+       priv->dp_port_num = port_num;
+       init_waitqueue_head(&priv->dp_modem_change_wait);
+       init_waitqueue_head(&priv->dp_transmit_idle_wait);
+       init_waitqueue_head(&priv->dp_flush_wait);
+       init_waitqueue_head(&priv->dp_close_wait);
+       INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
+       priv->dp_port = port;
 
-       /* allocate serial private structure */
-       serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
-       if (serial_priv == NULL) {
-               for (i = 0; i < serial->type->num_ports + 1; i++)
-                       kfree(usb_get_serial_port_data(serial->port[i]));
-               return 1;                       /* error */
-       }
+       init_waitqueue_head(&port->write_wait);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
+}
+
+static int digi_startup(struct usb_serial *serial)
+{
+       struct digi_serial *serial_priv;
+       int ret;
+
+       serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
+       if (!serial_priv)
+               return -ENOMEM;
 
-       /* initialize serial private structure */
        spin_lock_init(&serial_priv->ds_serial_lock);
        serial_priv->ds_oob_port_num = serial->type->num_ports;
        serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
-       serial_priv->ds_device_started = 0;
+
+       ret = digi_port_init(serial_priv->ds_oob_port,
+                                               serial_priv->ds_oob_port_num);
+       if (ret) {
+               kfree(serial_priv);
+               return ret;
+       }
+
        usb_set_serial_data(serial, serial_priv);
 
        return 0;
@@ -1313,15 +1310,35 @@ static void digi_disconnect(struct usb_serial *serial)
 
 static void digi_release(struct usb_serial *serial)
 {
-       int i;
+       struct digi_serial *serial_priv;
+       struct digi_port *priv;
+
+       serial_priv = usb_get_serial_data(serial);
+
+       priv = usb_get_serial_port_data(serial_priv->ds_oob_port);
+       kfree(priv);
 
-       /* free the private data structures for all ports */
-       /* number of regular ports + 1 for the out-of-band port */
-       for (i = 0; i < serial->type->num_ports + 1; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
-       kfree(usb_get_serial_data(serial));
+       kfree(serial_priv);
 }
 
+static int digi_port_probe(struct usb_serial_port *port)
+{
+       unsigned port_num;
+
+       port_num = port->number - port->serial->minor;
+
+       return digi_port_init(port, port_num);
+}
+
+static int digi_port_remove(struct usb_serial_port *port)
+{
+       struct digi_port *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
 
 static void digi_read_bulk_callback(struct urb *urb)
 {
index 244477107e2f1f1b9a13e0d26349eac502563c0a..6e4eb57d0177406c5eb8f9d30c83f0551dd159f7 100644 (file)
@@ -318,39 +318,30 @@ static int f81232_ioctl(struct tty_struct *tty,
        return -ENOIOCTLCMD;
 }
 
-static int f81232_startup(struct usb_serial *serial)
+static int f81232_port_probe(struct usb_serial_port *port)
 {
        struct f81232_private *priv;
-       int i;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = kzalloc(sizeof(struct f81232_private), GFP_KERNEL);
-               if (!priv)
-                       goto cleanup;
-               spin_lock_init(&priv->lock);
-               init_waitqueue_head(&priv->delta_msr_wait);
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
-       return 0;
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-cleanup:
-       for (--i; i >= 0; --i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       return -ENOMEM;
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->delta_msr_wait);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
 }
 
-static void f81232_release(struct usb_serial *serial)
+static int f81232_port_remove(struct usb_serial_port *port)
 {
-       int i;
        struct f81232_private *priv;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-       }
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static struct usb_serial_driver f81232_device = {
@@ -373,8 +364,8 @@ static struct usb_serial_driver f81232_device = {
        .tiocmset =             f81232_tiocmset,
        .process_read_urb =     f81232_process_read_urb,
        .read_int_callback =    f81232_read_int_callback,
-       .attach =               f81232_startup,
-       .release =              f81232_release,
+       .port_probe =           f81232_port_probe,
+       .port_remove =          f81232_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 3ee92648c02dd589a75dc7d29125f26d3aa1f9ff..203358d7e7bc6ed23d78bf0a35cbf797e3e4f4bb 100644 (file)
@@ -1405,11 +1405,10 @@ static void timeout_handler(unsigned long data)
 
 
 
-static int garmin_attach(struct usb_serial *serial)
+static int garmin_port_probe(struct usb_serial_port *port)
 {
-       int status = 0;
-       struct usb_serial_port *port = serial->port[0];
-       struct garmin_data *garmin_data_p = NULL;
+       int status;
+       struct garmin_data *garmin_data_p;
 
        garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
        if (garmin_data_p == NULL) {
@@ -1434,22 +1433,14 @@ static int garmin_attach(struct usb_serial *serial)
 }
 
 
-static void garmin_disconnect(struct usb_serial *serial)
+static int garmin_port_remove(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
 
        usb_kill_urb(port->interrupt_in_urb);
        del_timer_sync(&garmin_data_p->timer);
-}
-
-
-static void garmin_release(struct usb_serial *serial)
-{
-       struct usb_serial_port *port = serial->port[0];
-       struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
-
        kfree(garmin_data_p);
+       return 0;
 }
 
 
@@ -1466,9 +1457,8 @@ static struct usb_serial_driver garmin_device = {
        .close               = garmin_close,
        .throttle            = garmin_throttle,
        .unthrottle          = garmin_unthrottle,
-       .attach              = garmin_attach,
-       .disconnect          = garmin_disconnect,
-       .release             = garmin_release,
+       .port_probe             = garmin_port_probe,
+       .port_remove            = garmin_port_remove,
        .write               = garmin_write,
        .write_room          = garmin_write_room,
        .write_bulk_callback = garmin_write_bulk_callback,
index 8e6faaf3580cb102abaea73be8d3636446dba7b6..5acc0d13864a400344a012400f20bc989fa23574 100644 (file)
@@ -225,6 +225,8 @@ static int  edge_get_icount(struct tty_struct *tty,
 static int  edge_startup(struct usb_serial *serial);
 static void edge_disconnect(struct usb_serial *serial);
 static void edge_release(struct usb_serial *serial);
+static int edge_port_probe(struct usb_serial_port *port);
+static int edge_port_remove(struct usb_serial_port *port);
 
 #include "io_tables.h" /* all of the devices that this driver supports */
 
@@ -2875,10 +2877,9 @@ static void load_application_firmware(struct edgeport_serial *edge_serial)
 static int edge_startup(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial;
-       struct edgeport_port *edge_port;
        struct usb_device *dev;
        struct device *ddev = &serial->dev->dev;
-       int i, j;
+       int i;
        int response;
        bool interrupt_in_found;
        bool bulk_in_found;
@@ -2961,25 +2962,6 @@ static int edge_startup(struct usb_serial *serial)
        /* we set up the pointers to the endpoints in the edge_open function,
         * as the structures aren't created yet. */
 
-       /* set up our port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
-               if (edge_port == NULL) {
-                       dev_err(ddev, "%s - Out of memory\n", __func__);
-                       for (j = 0; j < i; ++j) {
-                               kfree(usb_get_serial_port_data(serial->port[j]));
-                               usb_set_serial_port_data(serial->port[j],
-                                                                       NULL);
-                       }
-                       usb_set_serial_data(serial, NULL);
-                       kfree(edge_serial);
-                       return -ENOMEM;
-               }
-               spin_lock_init(&edge_port->ep_lock);
-               edge_port->port = serial->port[i];
-               usb_set_serial_port_data(serial->port[i], edge_port);
-       }
-
        response = 0;
 
        if (edge_serial->is_epic) {
@@ -3120,14 +3102,36 @@ static void edge_disconnect(struct usb_serial *serial)
 static void edge_release(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
-       int i;
-
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
 
        kfree(edge_serial);
 }
 
+static int edge_port_probe(struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port;
+
+       edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+       if (!edge_port)
+               return -ENOMEM;
+
+       spin_lock_init(&edge_port->ep_lock);
+       edge_port->port = port;
+
+       usb_set_serial_port_data(port, edge_port);
+
+       return 0;
+}
+
+static int edge_port_remove(struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port;
+
+       edge_port = usb_get_serial_port_data(port);
+       kfree(edge_port);
+
+       return 0;
+}
+
 module_usb_serial_driver(serial_drivers, id_table_combined);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 350afddb55ba8c1fd276068518de05c78ac280ee..1511dd0ad3242650e6da605d316b2d7165b1fb2d 100644 (file)
@@ -110,6 +110,8 @@ static struct usb_serial_driver edgeport_2port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -139,6 +141,8 @@ static struct usb_serial_driver edgeport_4port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -168,6 +172,8 @@ static struct usb_serial_driver edgeport_8port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -197,6 +203,8 @@ static struct usb_serial_driver epic_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
index a2209cd4509396d3827d4a0627c59f42b5d713be..60023c2d2a317008d7aab0c78bd5120f77b1597c 100644 (file)
@@ -2532,12 +2532,7 @@ static void edge_break(struct tty_struct *tty, int break_state)
 static int edge_startup(struct usb_serial *serial)
 {
        struct edgeport_serial *edge_serial;
-       struct edgeport_port *edge_port;
-       struct usb_device *dev;
        int status;
-       int i;
-
-       dev = serial->dev;
 
        /* create our private serial structure */
        edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
@@ -2555,40 +2550,7 @@ static int edge_startup(struct usb_serial *serial)
                return status;
        }
 
-       /* set up our port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL);
-               if (edge_port == NULL) {
-                       dev_err(&serial->dev->dev, "%s - Out of memory\n",
-                                                               __func__);
-                       goto cleanup;
-               }
-               spin_lock_init(&edge_port->ep_lock);
-               if (kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
-                                                               GFP_KERNEL)) {
-                       dev_err(&serial->dev->dev, "%s - Out of memory\n",
-                                                               __func__);
-                       kfree(edge_port);
-                       goto cleanup;
-               }
-               edge_port->port = serial->port[i];
-               edge_port->edge_serial = edge_serial;
-               usb_set_serial_port_data(serial->port[i], edge_port);
-               edge_port->bUartMode = default_uart_mode;
-       }
-
        return 0;
-
-cleanup:
-       for (--i; i >= 0; --i) {
-               edge_port = usb_get_serial_port_data(serial->port[i]);
-               kfifo_free(&edge_port->write_fifo);
-               kfree(edge_port);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       kfree(edge_serial);
-       usb_set_serial_data(serial, NULL);
-       return -ENOMEM;
 }
 
 static void edge_disconnect(struct usb_serial *serial)
@@ -2597,17 +2559,54 @@ static void edge_disconnect(struct usb_serial *serial)
 
 static void edge_release(struct usb_serial *serial)
 {
-       int i;
+       kfree(usb_get_serial_data(serial));
+}
+
+static int edge_port_probe(struct usb_serial_port *port)
+{
        struct edgeport_port *edge_port;
+       int ret;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               edge_port = usb_get_serial_port_data(serial->port[i]);
+       edge_port = kzalloc(sizeof(*edge_port), GFP_KERNEL);
+       if (!edge_port)
+               return -ENOMEM;
+
+       ret = kfifo_alloc(&edge_port->write_fifo, EDGE_OUT_BUF_SIZE,
+                                                               GFP_KERNEL);
+       if (ret) {
+               kfree(edge_port);
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&edge_port->ep_lock);
+       edge_port->port = port;
+       edge_port->edge_serial = usb_get_serial_data(port->serial);
+       edge_port->bUartMode = default_uart_mode;
+
+       usb_set_serial_port_data(port, edge_port);
+
+       ret = edge_create_sysfs_attrs(port);
+       if (ret) {
                kfifo_free(&edge_port->write_fifo);
                kfree(edge_port);
+               return ret;
        }
-       kfree(usb_get_serial_data(serial));
+
+       return 0;
 }
 
+static int edge_port_remove(struct usb_serial_port *port)
+{
+       struct edgeport_port *edge_port;
+
+       edge_port = usb_get_serial_port_data(port);
+
+       edge_remove_sysfs_attrs(port);
+       kfifo_free(&edge_port->write_fifo);
+       kfree(edge_port);
+
+       return 0;
+}
 
 /* Sysfs Attributes */
 
@@ -2667,8 +2666,8 @@ static struct usb_serial_driver edgeport_1port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
-       .port_probe             = edge_create_sysfs_attrs,
-       .port_remove            = edge_remove_sysfs_attrs,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
@@ -2698,8 +2697,8 @@ static struct usb_serial_driver edgeport_2port_device = {
        .attach                 = edge_startup,
        .disconnect             = edge_disconnect,
        .release                = edge_release,
-       .port_probe             = edge_create_sysfs_attrs,
-       .port_remove            = edge_remove_sysfs_attrs,
+       .port_probe             = edge_port_probe,
+       .port_remove            = edge_port_remove,
        .ioctl                  = edge_ioctl,
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
index 20a132ec39e201c4190027a4f2d6750654d553cd..4264821a3b34fb653d28dafe2171e6b9239ca8e5 100644 (file)
@@ -203,8 +203,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port)
        return 0;
 }
 
-/* fake probe - only to allocate data structures */
-static int ipw_probe(struct usb_serial *serial, const struct usb_device_id *id)
+static int ipw_attach(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *data;
 
@@ -303,9 +302,9 @@ static struct usb_serial_driver ipw_device = {
        .num_ports =            1,
        .open =                 ipw_open,
        .close =                ipw_close,
-       .probe =                ipw_probe,
-       .attach =               usb_wwan_startup,
+       .attach =               ipw_attach,
        .release =              ipw_release,
+       .port_probe =           usb_wwan_port_probe,
        .port_remove =          usb_wwan_port_remove,
        .dtr_rts =              ipw_dtr_rts,
        .write =                usb_wwan_write,
index 01da3ea36e89d5363a8890339eac6165dec0e14c..cd5533e81de7e113d77898795996346ce036378a 100644 (file)
@@ -53,6 +53,8 @@ static int iuu_cardout;
 static bool xmas;
 static int vcc_default = 5;
 
+static int iuu_create_sysfs_attrs(struct usb_serial_port *port);
+static int iuu_remove_sysfs_attrs(struct usb_serial_port *port);
 static void read_rxcmd_callback(struct urb *urb);
 
 struct iuu_private {
@@ -72,63 +74,55 @@ struct iuu_private {
        u32 clk;
 };
 
-
-static void iuu_free_buf(struct iuu_private *priv)
-{
-       kfree(priv->buf);
-       kfree(priv->writebuf);
-}
-
-static int iuu_alloc_buf(struct usb_serial *serial, struct iuu_private *priv)
-{
-       priv->buf = kzalloc(256, GFP_KERNEL);
-       priv->writebuf = kzalloc(256, GFP_KERNEL);
-       if (!priv->buf || !priv->writebuf) {
-               iuu_free_buf(priv);
-               dev_dbg(&serial->dev->dev, "%s problem allocation buffer\n", __func__);
-               return -ENOMEM;
-       }
-       dev_dbg(&serial->dev->dev, "%s - Privates buffers allocation success\n", __func__);
-       return 0;
-}
-
-static int iuu_startup(struct usb_serial *serial)
+static int iuu_port_probe(struct usb_serial_port *port)
 {
        struct iuu_private *priv;
+       int ret;
 
        priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL);
-       dev_dbg(&serial->dev->dev, "%s- priv allocation success\n", __func__);
        if (!priv)
                return -ENOMEM;
-       if (iuu_alloc_buf(serial, priv)) {
+
+       priv->buf = kzalloc(256, GFP_KERNEL);
+       if (!priv->buf) {
+               kfree(priv);
+               return -ENOMEM;
+       }
+
+       priv->writebuf = kzalloc(256, GFP_KERNEL);
+       if (!priv->writebuf) {
+               kfree(priv->buf);
                kfree(priv);
                return -ENOMEM;
        }
+
        priv->vcc = vcc_default;
        spin_lock_init(&priv->lock);
        init_waitqueue_head(&priv->delta_msr_wait);
-       usb_set_serial_port_data(serial->port[0], priv);
+
+       usb_set_serial_port_data(port, priv);
+
+       ret = iuu_create_sysfs_attrs(port);
+       if (ret) {
+               kfree(priv->writebuf);
+               kfree(priv->buf);
+               kfree(priv);
+               return ret;
+       }
+
        return 0;
 }
 
-/* Release function */
-static void iuu_release(struct usb_serial *serial)
+static int iuu_port_remove(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct iuu_private *priv = usb_get_serial_port_data(port);
-       if (!port)
-               return;
 
-       if (priv) {
-               iuu_free_buf(priv);
-               dev_dbg(&port->dev, "%s - I will free all\n", __func__);
-               usb_set_serial_port_data(port, NULL);
-
-               dev_dbg(&port->dev, "%s - priv is not anymore in port structure\n", __func__);
-               kfree(priv);
+       iuu_remove_sysfs_attrs(port);
+       kfree(priv->writebuf);
+       kfree(priv->buf);
+       kfree(priv);
 
-               dev_dbg(&port->dev, "%s priv is now kfree\n", __func__);
-       }
+       return 0;
 }
 
 static int iuu_tiocmset(struct tty_struct *tty,
@@ -1215,8 +1209,6 @@ static struct usb_serial_driver iuu_device = {
        .num_ports = 1,
        .bulk_in_size = 512,
        .bulk_out_size = 512,
-       .port_probe = iuu_create_sysfs_attrs,
-       .port_remove = iuu_remove_sysfs_attrs,
        .open = iuu_open,
        .close = iuu_close,
        .write = iuu_uart_write,
@@ -1225,8 +1217,8 @@ static struct usb_serial_driver iuu_device = {
        .tiocmset = iuu_tiocmset,
        .set_termios = iuu_set_termios,
        .init_termios = iuu_init_termios,
-       .attach = iuu_startup,
-       .release = iuu_release,
+       .port_probe = iuu_port_probe,
+       .port_remove = iuu_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 29c943d737d0db508b70cda61ce6770d3a335f43..cff8dd5b462d0c35a264ef850c0b7877f9702afa 100644 (file)
@@ -1374,13 +1374,9 @@ static struct callbacks {
           data in device_details */
 static void keyspan_setup_urbs(struct usb_serial *serial)
 {
-       int                             i, j;
        struct keyspan_serial_private   *s_priv;
        const struct keyspan_device_details     *d_details;
-       struct usb_serial_port          *port;
-       struct keyspan_port_private     *p_priv;
        struct callbacks                *cback;
-       int                             endp;
 
        s_priv = usb_get_serial_data(serial);
        d_details = s_priv->device_details;
@@ -1404,45 +1400,6 @@ static void keyspan_setup_urbs(struct usb_serial *serial)
                (serial, d_details->glocont_endpoint, USB_DIR_OUT,
                 serial, s_priv->glocont_buf, GLOCONT_BUFLEN,
                 cback->glocont_callback);
-
-       /* Setup endpoints for each port specific thing */
-       for (i = 0; i < d_details->num_ports; i++) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-
-               /* Do indat endpoints first, once for each flip */
-               endp = d_details->indat_endpoints[i];
-               for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) {
-                       p_priv->in_urbs[j] = keyspan_setup_urb
-                               (serial, endp, USB_DIR_IN, port,
-                                p_priv->in_buffer[j], 64,
-                                cback->indat_callback);
-               }
-               for (; j < 2; ++j)
-                       p_priv->in_urbs[j] = NULL;
-
-               /* outdat endpoints also have flip */
-               endp = d_details->outdat_endpoints[i];
-               for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) {
-                       p_priv->out_urbs[j] = keyspan_setup_urb
-                               (serial, endp, USB_DIR_OUT, port,
-                                p_priv->out_buffer[j], 64,
-                                cback->outdat_callback);
-               }
-               for (; j < 2; ++j)
-                       p_priv->out_urbs[j] = NULL;
-
-               /* inack endpoint */
-               p_priv->inack_urb = keyspan_setup_urb
-                       (serial, d_details->inack_endpoints[i], USB_DIR_IN,
-                        port, p_priv->inack_buffer, 1, cback->inack_callback);
-
-               /* outcont endpoint */
-               p_priv->outcont_urb = keyspan_setup_urb
-                       (serial, d_details->outcont_endpoints[i], USB_DIR_OUT,
-                        port, p_priv->outcont_buffer, 64,
-                        cback->outcont_callback);
-       }
 }
 
 /* usa19 function doesn't require prescaler */
@@ -2407,9 +2364,7 @@ static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
 static int keyspan_startup(struct usb_serial *serial)
 {
        int                             i, err;
-       struct usb_serial_port          *port;
        struct keyspan_serial_private   *s_priv;
-       struct keyspan_port_private     *p_priv;
        const struct keyspan_device_details     *d_details;
 
        for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i)
@@ -2432,19 +2387,6 @@ static int keyspan_startup(struct usb_serial *serial)
        s_priv->device_details = d_details;
        usb_set_serial_data(serial, s_priv);
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               p_priv = kzalloc(sizeof(struct keyspan_port_private),
-                                                               GFP_KERNEL);
-               if (!p_priv) {
-                       dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i);
-                       return 1;
-               }
-               p_priv->device_details = d_details;
-               usb_set_serial_port_data(port, p_priv);
-       }
-
        keyspan_setup_urbs(serial);
 
        if (s_priv->instat_urb != NULL) {
@@ -2463,59 +2405,111 @@ static int keyspan_startup(struct usb_serial *serial)
 
 static void keyspan_disconnect(struct usb_serial *serial)
 {
-       int                             i, j;
-       struct usb_serial_port          *port;
-       struct keyspan_serial_private   *s_priv;
-       struct keyspan_port_private     *p_priv;
+       struct keyspan_serial_private *s_priv;
 
        s_priv = usb_get_serial_data(serial);
 
-       /* Stop reading/writing urbs */
        stop_urb(s_priv->instat_urb);
        stop_urb(s_priv->glocont_urb);
        stop_urb(s_priv->indat_urb);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-               stop_urb(p_priv->inack_urb);
-               stop_urb(p_priv->outcont_urb);
-               for (j = 0; j < 2; j++) {
-                       stop_urb(p_priv->in_urbs[j]);
-                       stop_urb(p_priv->out_urbs[j]);
-               }
-       }
+}
+
+static void keyspan_release(struct usb_serial *serial)
+{
+       struct keyspan_serial_private *s_priv;
+
+       s_priv = usb_get_serial_data(serial);
 
-       /* Now free them */
        usb_free_urb(s_priv->instat_urb);
        usb_free_urb(s_priv->indat_urb);
        usb_free_urb(s_priv->glocont_urb);
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               p_priv = usb_get_serial_port_data(port);
-               usb_free_urb(p_priv->inack_urb);
-               usb_free_urb(p_priv->outcont_urb);
-               for (j = 0; j < 2; j++) {
-                       usb_free_urb(p_priv->in_urbs[j]);
-                       usb_free_urb(p_priv->out_urbs[j]);
-               }
-       }
+
+       kfree(s_priv);
 }
 
-static void keyspan_release(struct usb_serial *serial)
+static int keyspan_port_probe(struct usb_serial_port *port)
 {
-       int                             i;
-       struct usb_serial_port          *port;
-       struct keyspan_serial_private   *s_priv;
+       struct usb_serial *serial = port->serial;
+       struct keyspan_serial_private *s_priv;
+       struct keyspan_port_private *p_priv;
+       const struct keyspan_device_details *d_details;
+       struct callbacks *cback;
+       int endp;
+       int port_num;
+       int i;
 
        s_priv = usb_get_serial_data(serial);
+       d_details = s_priv->device_details;
 
-       kfree(s_priv);
+       p_priv = kzalloc(sizeof(*p_priv), GFP_KERNEL);
+       if (!p_priv)
+               return -ENOMEM;
 
-       /* Now free per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               kfree(usb_get_serial_port_data(port));
+       p_priv->device_details = d_details;
+
+       /* Setup values for the various callback routines */
+       cback = &keyspan_callbacks[d_details->msg_format];
+
+       port_num = port->number - port->serial->minor;
+
+       /* Do indat endpoints first, once for each flip */
+       endp = d_details->indat_endpoints[port_num];
+       for (i = 0; i <= d_details->indat_endp_flip; ++i, ++endp) {
+               p_priv->in_urbs[i] = keyspan_setup_urb(serial, endp,
+                                               USB_DIR_IN, port,
+                                               p_priv->in_buffer[i], 64,
+                                               cback->indat_callback);
+       }
+       /* outdat endpoints also have flip */
+       endp = d_details->outdat_endpoints[port_num];
+       for (i = 0; i <= d_details->outdat_endp_flip; ++i, ++endp) {
+               p_priv->out_urbs[i] = keyspan_setup_urb(serial, endp,
+                                               USB_DIR_OUT, port,
+                                               p_priv->out_buffer[i], 64,
+                                               cback->outdat_callback);
+       }
+       /* inack endpoint */
+       p_priv->inack_urb = keyspan_setup_urb(serial,
+                                       d_details->inack_endpoints[port_num],
+                                       USB_DIR_IN, port,
+                                       p_priv->inack_buffer, 1,
+                                       cback->inack_callback);
+       /* outcont endpoint */
+       p_priv->outcont_urb = keyspan_setup_urb(serial,
+                                       d_details->outcont_endpoints[port_num],
+                                       USB_DIR_OUT, port,
+                                       p_priv->outcont_buffer, 64,
+                                        cback->outcont_callback);
+
+       usb_set_serial_port_data(port, p_priv);
+
+       return 0;
+}
+
+static int keyspan_port_remove(struct usb_serial_port *port)
+{
+       struct keyspan_port_private *p_priv;
+       int i;
+
+       p_priv = usb_get_serial_port_data(port);
+
+       stop_urb(p_priv->inack_urb);
+       stop_urb(p_priv->outcont_urb);
+       for (i = 0; i < 2; i++) {
+               stop_urb(p_priv->in_urbs[i]);
+               stop_urb(p_priv->out_urbs[i]);
+       }
+
+       usb_free_urb(p_priv->inack_urb);
+       usb_free_urb(p_priv->outcont_urb);
+       for (i = 0; i < 2; i++) {
+               usb_free_urb(p_priv->in_urbs[i]);
+               usb_free_urb(p_priv->out_urbs[i]);
        }
+
+       kfree(p_priv);
+
+       return 0;
 }
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 0a8a40b5711e8d288a222aef5c86573c1a674cc1..0273dda303a4672f348175b6787b03c356a62b72 100644 (file)
@@ -42,6 +42,8 @@ static void keyspan_dtr_rts           (struct usb_serial_port *port, int on);
 static int  keyspan_startup            (struct usb_serial *serial);
 static void keyspan_disconnect         (struct usb_serial *serial);
 static void keyspan_release            (struct usb_serial *serial);
+static int keyspan_port_probe(struct usb_serial_port *port);
+static int keyspan_port_remove(struct usb_serial_port *port);
 static int  keyspan_write_room         (struct tty_struct *tty);
 
 static int  keyspan_write              (struct tty_struct *tty,
@@ -567,6 +569,8 @@ static struct usb_serial_driver keyspan_1port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_2port_device = {
@@ -589,6 +593,8 @@ static struct usb_serial_driver keyspan_2port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver keyspan_4port_device = {
@@ -611,6 +617,8 @@ static struct usb_serial_driver keyspan_4port_device = {
        .attach                 = keyspan_startup,
        .disconnect             = keyspan_disconnect,
        .release                = keyspan_release,
+       .port_probe             = keyspan_port_probe,
+       .port_remove            = keyspan_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index ca43ecb4a2bdd494e997a36ecd591b3a410132d2..bb87e29c4ac29645804b05a9e52455f8125ff05c 100644 (file)
@@ -713,29 +713,33 @@ MODULE_FIRMWARE("keyspan_pda/keyspan_pda.fw");
 MODULE_FIRMWARE("keyspan_pda/xircom_pgs.fw");
 #endif
 
-static int keyspan_pda_startup(struct usb_serial *serial)
+static int keyspan_pda_port_probe(struct usb_serial_port *port)
 {
 
        struct keyspan_pda_private *priv;
 
-       /* allocate the private data structures for all ports. Well, for all
-          one ports. */
-
        priv = kmalloc(sizeof(struct keyspan_pda_private), GFP_KERNEL);
        if (!priv)
-               return 1; /* error */
-       usb_set_serial_port_data(serial->port[0], priv);
-       init_waitqueue_head(&serial->port[0]->write_wait);
+               return -ENOMEM;
+
        INIT_WORK(&priv->wakeup_work, keyspan_pda_wakeup_write);
        INIT_WORK(&priv->unthrottle_work, keyspan_pda_request_unthrottle);
-       priv->serial = serial;
-       priv->port = serial->port[0];
+       priv->serial = port->serial;
+       priv->port = port;
+
+       usb_set_serial_port_data(port, priv);
+
        return 0;
 }
 
-static void keyspan_pda_release(struct usb_serial *serial)
+static int keyspan_pda_port_remove(struct usb_serial_port *port)
 {
-       kfree(usb_get_serial_port_data(serial->port[0]));
+       struct keyspan_pda_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 #ifdef KEYSPAN
@@ -786,8 +790,8 @@ static struct usb_serial_driver keyspan_pda_device = {
        .break_ctl =            keyspan_pda_break_ctl,
        .tiocmget =             keyspan_pda_tiocmget,
        .tiocmset =             keyspan_pda_tiocmset,
-       .attach =               keyspan_pda_startup,
-       .release =              keyspan_pda_release,
+       .port_probe =           keyspan_pda_port_probe,
+       .port_remove =          keyspan_pda_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index 3f6d7376c02d48e5a145449d79fe5ed4a3f01b3d..1f4517864cd25cd6bdf665bce9d154f0c708f99d 100644 (file)
@@ -60,8 +60,8 @@
 /*
  * Function prototypes
  */
-static int  klsi_105_startup(struct usb_serial *serial);
-static void klsi_105_release(struct usb_serial *serial);
+static int klsi_105_port_probe(struct usb_serial_port *port);
+static int klsi_105_port_remove(struct usb_serial_port *port);
 static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void klsi_105_close(struct usb_serial_port *port);
 static void klsi_105_set_termios(struct tty_struct *tty,
@@ -99,8 +99,8 @@ static struct usb_serial_driver kl5kusb105d_device = {
        /*.break_ctl =          klsi_105_break_ctl,*/
        .tiocmget =             klsi_105_tiocmget,
        .tiocmset =             klsi_105_tiocmset,
-       .attach =               klsi_105_startup,
-       .release =              klsi_105_release,
+       .port_probe =           klsi_105_port_probe,
+       .port_remove =          klsi_105_port_remove,
        .throttle =             usb_serial_generic_throttle,
        .unthrottle =           usb_serial_generic_unthrottle,
        .process_read_urb =     klsi_105_process_read_urb,
@@ -223,60 +223,40 @@ static int klsi_105_get_line_state(struct usb_serial_port *port,
  * Driver's tty interface functions
  */
 
-static int klsi_105_startup(struct usb_serial *serial)
+static int klsi_105_port_probe(struct usb_serial_port *port)
 {
        struct klsi_105_private *priv;
-       int i;
 
-       /* check if we support the product id (see keyspan.c)
-        * FIXME
-        */
+       priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-       /* allocate the private data structure */
-       for (i = 0; i < serial->num_ports; i++) {
-               priv = kmalloc(sizeof(struct klsi_105_private),
-                                                  GFP_KERNEL);
-               if (!priv) {
-                       dev_dbg(&serial->interface->dev,
-                               "%s - kmalloc for klsi_105_private failed.\n",
-                               __func__);
-                       i--;
-                       goto err_cleanup;
-               }
-               /* set initial values for control structures */
-               priv->cfg.pktlen    = 5;
-               priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
-               priv->cfg.databits  = kl5kusb105a_dtb_8;
-               priv->cfg.unknown1  = 0;
-               priv->cfg.unknown2  = 1;
+       /* set initial values for control structures */
+       priv->cfg.pktlen    = 5;
+       priv->cfg.baudrate  = kl5kusb105a_sio_b9600;
+       priv->cfg.databits  = kl5kusb105a_dtb_8;
+       priv->cfg.unknown1  = 0;
+       priv->cfg.unknown2  = 1;
 
-               priv->line_state    = 0;
+       priv->line_state    = 0;
 
-               usb_set_serial_port_data(serial->port[i], priv);
+       spin_lock_init(&priv->lock);
 
-               spin_lock_init(&priv->lock);
+       /* priv->termios is left uninitialized until port opening */
 
-               /* priv->termios is left uninitialized until port opening */
-               init_waitqueue_head(&serial->port[i]->write_wait);
-       }
+       usb_set_serial_port_data(port, priv);
 
        return 0;
-
-err_cleanup:
-       for (; i >= 0; i--) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       return -ENOMEM;
 }
 
-static void klsi_105_release(struct usb_serial *serial)
+static int klsi_105_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct klsi_105_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
 
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       return 0;
 }
 
 static int  klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port)
index 5c4d2fbd4e11892e7c40479b322c3f56e74e7294..c9ca7a5b12e09c883f08562ca93a8fbede32e82b 100644 (file)
@@ -54,8 +54,8 @@
 
 
 /* Function prototypes */
-static int  kobil_startup(struct usb_serial *serial);
-static void kobil_release(struct usb_serial *serial);
+static int kobil_port_probe(struct usb_serial_port *probe);
+static int kobil_port_remove(struct usb_serial_port *probe);
 static int  kobil_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void kobil_close(struct usb_serial_port *port);
 static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -89,8 +89,8 @@ static struct usb_serial_driver kobil_device = {
        .description =          "KOBIL USB smart card terminal",
        .id_table =             id_table,
        .num_ports =            1,
-       .attach =               kobil_startup,
-       .release =              kobil_release,
+       .port_probe =           kobil_port_probe,
+       .port_remove =          kobil_port_remove,
        .ioctl =                kobil_ioctl,
        .set_termios =          kobil_set_termios,
        .init_termios =         kobil_init_termios,
@@ -117,9 +117,10 @@ struct kobil_private {
 };
 
 
-static int kobil_startup(struct usb_serial *serial)
+static int kobil_port_probe(struct usb_serial_port *port)
 {
        int i;
+       struct usb_serial *serial = port->serial;
        struct kobil_private *priv;
        struct usb_device *pdev;
        struct usb_host_config *actconfig;
@@ -149,7 +150,7 @@ static int kobil_startup(struct usb_serial *serial)
                dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n");
                break;
        }
-       usb_set_serial_port_data(serial->port[0], priv);
+       usb_set_serial_port_data(port, priv);
 
        /* search for the necessary endpoints */
        pdev = serial->dev;
@@ -179,12 +180,14 @@ static int kobil_startup(struct usb_serial *serial)
 }
 
 
-static void kobil_release(struct usb_serial *serial)
+static int kobil_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct kobil_private *priv;
 
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static void kobil_init_termios(struct tty_struct *tty)
index f3947712e1375db3ee407a5efa20a1acad3d3c9d..8a2081004107977dc929d586ffda41fdf34abf06 100644 (file)
@@ -49,7 +49,8 @@
  * Function prototypes
  */
 static int  mct_u232_startup(struct usb_serial *serial);
-static void mct_u232_release(struct usb_serial *serial);
+static int  mct_u232_port_probe(struct usb_serial_port *port);
+static int  mct_u232_port_remove(struct usb_serial_port *remove);
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void mct_u232_close(struct usb_serial_port *port);
 static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
@@ -99,7 +100,8 @@ static struct usb_serial_driver mct_u232_device = {
        .tiocmget =          mct_u232_tiocmget,
        .tiocmset =          mct_u232_tiocmset,
        .attach =            mct_u232_startup,
-       .release =           mct_u232_release,
+       .port_probe =        mct_u232_port_probe,
+       .port_remove =       mct_u232_port_remove,
        .ioctl =             mct_u232_ioctl,
        .get_icount =        mct_u232_get_icount,
 };
@@ -388,18 +390,8 @@ static void mct_u232_msr_to_state(struct usb_serial_port *port,
 
 static int mct_u232_startup(struct usb_serial *serial)
 {
-       struct mct_u232_private *priv;
        struct usb_serial_port *port, *rport;
 
-       priv = kzalloc(sizeof(struct mct_u232_private), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-       spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->msr_wait);
-       usb_set_serial_port_data(serial->port[0], priv);
-
-       init_waitqueue_head(&serial->port[0]->write_wait);
-
        /* Puh, that's dirty */
        port = serial->port[0];
        rport = serial->port[1];
@@ -412,18 +404,31 @@ static int mct_u232_startup(struct usb_serial *serial)
        return 0;
 } /* mct_u232_startup */
 
+static int mct_u232_port_probe(struct usb_serial_port *port)
+{
+       struct mct_u232_private *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->msr_wait);
+
+       usb_set_serial_port_data(port, priv);
 
-static void mct_u232_release(struct usb_serial *serial)
+       return 0;
+}
+
+static int mct_u232_port_remove(struct usb_serial_port *port)
 {
        struct mct_u232_private *priv;
-       int i;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* My special items, the standard routines free my urbs */
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-       }
-} /* mct_u232_release */
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
+}
 
 static int  mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
@@ -515,12 +520,14 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
 
 static void mct_u232_close(struct usb_serial_port *port)
 {
-       if (port->serial->dev) {
-               /* shutdown our urbs */
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->read_urb);
-               usb_kill_urb(port->interrupt_in_urb);
-       }
+       /*
+        * Must kill the read urb as it is actually an interrupt urb, which
+        * generic close thus fails to kill.
+        */
+       usb_kill_urb(port->read_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       usb_serial_generic_close(port);
 } /* mct_u232_close */
 
 
index 0b257ddffbdbd903da48db51746bee3da9ebe4d6..6f29c74eb76925098a9cab841142c955c6d3a725 100644 (file)
@@ -179,16 +179,13 @@ static void metrousb_cleanup(struct usb_serial_port *port)
 {
        dev_dbg(&port->dev, "%s\n", __func__);
 
-       if (port->serial->dev) {
-               /* Shutdown any interrupt in urbs. */
-               if (port->interrupt_in_urb) {
-                       usb_unlink_urb(port->interrupt_in_urb);
-                       usb_kill_urb(port->interrupt_in_urb);
-               }
-
-               /* Send deactivate cmd to device */
+       usb_unlink_urb(port->interrupt_in_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       mutex_lock(&port->serial->disc_mutex);
+       if (!port->serial->disconnected)
                metrousb_send_unidirectional_cmd(UNI_CMD_CLOSE, port);
-       }
+       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port)
@@ -271,51 +268,27 @@ static int metrousb_set_modem_ctrl(struct usb_serial *serial, unsigned int contr
        return retval;
 }
 
-static void metrousb_shutdown(struct usb_serial *serial)
+static int metrousb_port_probe(struct usb_serial_port *port)
 {
-       int i = 0;
+       struct metrousb_private *metro_priv;
 
-       dev_dbg(&serial->dev->dev, "%s\n", __func__);
+       metro_priv = kzalloc(sizeof(*metro_priv), GFP_KERNEL);
+       if (!metro_priv)
+               return -ENOMEM;
 
-       /* Stop reading and writing on all ports. */
-       for (i = 0; i < serial->num_ports; ++i) {
-               /* Close any open urbs. */
-               metrousb_cleanup(serial->port[i]);
+       spin_lock_init(&metro_priv->lock);
 
-               /* Free memory. */
-               kfree(usb_get_serial_port_data(serial->port[i]));
-               usb_set_serial_port_data(serial->port[i], NULL);
+       usb_set_serial_port_data(port, metro_priv);
 
-               dev_dbg(&serial->dev->dev, "%s - freed port number=%d\n",
-                       __func__, serial->port[i]->number);
-       }
+       return 0;
 }
 
-static int metrousb_startup(struct usb_serial *serial)
+static int metrousb_port_remove(struct usb_serial_port *port)
 {
        struct metrousb_private *metro_priv;
-       struct usb_serial_port *port;
-       int i = 0;
 
-       dev_dbg(&serial->dev->dev, "%s\n", __func__);
-
-       /* Loop through the serial ports setting up the private structures.
-        * Currently we only use one port. */
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-
-               /* Declare memory. */
-               metro_priv = kzalloc(sizeof(struct metrousb_private), GFP_KERNEL);
-               if (!metro_priv)
-                       return -ENOMEM;
-
-               /* Initialize memory. */
-               spin_lock_init(&metro_priv->lock);
-               usb_set_serial_port_data(port, metro_priv);
-
-               dev_dbg(&serial->dev->dev, "%s - port number=%d\n ",
-                       __func__, port->number);
-       }
+       metro_priv = usb_get_serial_port_data(port);
+       kfree(metro_priv);
 
        return 0;
 }
@@ -414,8 +387,8 @@ static struct usb_serial_driver metrousb_device = {
        .close                  = metrousb_cleanup,
        .read_int_callback      = metrousb_read_int_callback,
        .write_int_callback     = metrousb_write_int_callback,
-       .attach                 = metrousb_startup,
-       .release                = metrousb_shutdown,
+       .port_probe             = metrousb_port_probe,
+       .port_remove            = metrousb_port_remove,
        .throttle               = metrousb_throttle,
        .unthrottle             = metrousb_unthrottle,
        .tiocmget               = metrousb_tiocmget,
index 1bf1ad0666667a9c31284c658814b651d91d2c66..75267421aad85636d480b732a507a176e874814f 100644 (file)
@@ -1966,9 +1966,7 @@ static int mos7720_ioctl(struct tty_struct *tty,
 
 static int mos7720_startup(struct usb_serial *serial)
 {
-       struct moschip_port *mos7720_port;
        struct usb_device *dev;
-       int i;
        char data;
        u16 product;
        int ret_val;
@@ -1999,29 +1997,6 @@ static int mos7720_startup(struct usb_serial *serial)
                serial->port[1]->interrupt_in_buffer = NULL;
        }
 
-
-       /* set up serial port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-               if (mos7720_port == NULL) {
-                       dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-                       return -ENOMEM;
-               }
-
-               /* Initialize all port interrupt end point to port 0 int
-                * endpoint.  Our device has only one interrupt endpoint
-                * common to all ports */
-               serial->port[i]->interrupt_in_endpointAddress =
-                               serial->port[0]->interrupt_in_endpointAddress;
-
-               mos7720_port->port = serial->port[i];
-               usb_set_serial_port_data(serial->port[i], mos7720_port);
-
-               dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number);
-               dev_dbg(&dev->dev, "serial number is %d\n", serial->minor);
-       }
-
-
        /* setting configuration feature to one */
        usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                        (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ);
@@ -2049,8 +2024,6 @@ static int mos7720_startup(struct usb_serial *serial)
 
 static void mos7720_release(struct usb_serial *serial)
 {
-       int i;
-
 #ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT
        /* close the parallel port */
 
@@ -2089,9 +2062,36 @@ static void mos7720_release(struct usb_serial *serial)
                kref_put(&mos_parport->ref_count, destroy_mos_parport);
        }
 #endif
-       /* free private structure allocated for serial port */
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+}
+
+static int mos7720_port_probe(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7720_port;
+
+       mos7720_port = kzalloc(sizeof(*mos7720_port), GFP_KERNEL);
+       if (!mos7720_port)
+               return -ENOMEM;
+
+       /* Initialize all port interrupt end point to port 0 int endpoint.
+        * Our device has only one interrupt endpoint common to all ports.
+        */
+       port->interrupt_in_endpointAddress =
+               port->serial->port[0]->interrupt_in_endpointAddress;
+       mos7720_port->port = port;
+
+       usb_set_serial_port_data(port, mos7720_port);
+
+       return 0;
+}
+
+static int mos7720_port_remove(struct usb_serial_port *port)
+{
+       struct moschip_port *mos7720_port;
+
+       mos7720_port = usb_get_serial_port_data(port);
+       kfree(mos7720_port);
+
+       return 0;
 }
 
 static struct usb_serial_driver moschip7720_2port_driver = {
@@ -2109,6 +2109,8 @@ static struct usb_serial_driver moschip7720_2port_driver = {
        .probe                  = mos77xx_probe,
        .attach                 = mos7720_startup,
        .release                = mos7720_release,
+       .port_probe             = mos7720_port_probe,
+       .port_remove            = mos7720_port_remove,
        .ioctl                  = mos7720_ioctl,
        .tiocmget               = mos7720_tiocmget,
        .tiocmset               = mos7720_tiocmset,
index d6d4eeca8c68390ef4555e455cbfea66c68038b9..1cf3375ec1afb12fbea2314a63539ced2c36b221 100644 (file)
@@ -218,12 +218,10 @@ struct moschip_port {
        int port_num;           /*Actual port number in the device(1,2,etc) */
        struct urb *write_urb;  /* write URB for this port */
        struct urb *read_urb;   /* read URB for this port */
-       struct urb *int_urb;
        __u8 shadowLCR;         /* last LCR value received */
        __u8 shadowMCR;         /* last MCR value received */
        char open;
        char open_ports;
-       char zombie;
        wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
        wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
        int delta_msr_cond;
@@ -478,7 +476,6 @@ static void mos7840_control_callback(struct urb *urb)
        struct moschip_port *mos7840_port;
        struct device *dev = &urb->dev->dev;
        __u8 regval = 0x0;
-       int result = 0;
        int status = urb->status;
 
        mos7840_port = urb->context;
@@ -495,7 +492,7 @@ static void mos7840_control_callback(struct urb *urb)
                return;
        default:
                dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status);
-               goto exit;
+               return;
        }
 
        dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length);
@@ -508,16 +505,6 @@ static void mos7840_control_callback(struct urb *urb)
                mos7840_handle_new_msr(mos7840_port, regval);
        else if (mos7840_port->MsrLsr == 1)
                mos7840_handle_new_lsr(mos7840_port, regval);
-
-exit:
-       spin_lock(&mos7840_port->pool_lock);
-       if (!mos7840_port->zombie)
-               result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC);
-       spin_unlock(&mos7840_port->pool_lock);
-       if (result) {
-               dev_err(dev, "%s - Error %d submitting interrupt urb\n",
-                       __func__, result);
-       }
 }
 
 static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg,
@@ -686,14 +673,7 @@ static void mos7840_interrupt_callback(struct urb *urb)
                                        wreg = MODEM_STATUS_REGISTER;
                                        break;
                                }
-                               spin_lock(&mos7840_port->pool_lock);
-                               if (!mos7840_port->zombie) {
-                                       rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
-                               } else {
-                                       spin_unlock(&mos7840_port->pool_lock);
-                                       return;
-                               }
-                               spin_unlock(&mos7840_port->pool_lock);
+                               rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data);
                        }
                }
        }
@@ -2347,309 +2327,249 @@ static int mos7840_calc_num_ports(struct usb_serial *serial)
        return mos7840_num_ports;
 }
 
-/****************************************************************************
- * mos7840_startup
- ****************************************************************************/
-
-static int mos7840_startup(struct usb_serial *serial)
+static int mos7840_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct moschip_port *mos7840_port;
-       struct usb_device *dev;
-       int i, status;
+       int status;
+       int pnum;
        __u16 Data;
 
-       dev = serial->dev;
-
        /* we set up the pointers to the endpoints in the mos7840_open *
         * function, as the structures aren't created yet.             */
 
-       /* set up port private structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i);
-               mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
-               if (mos7840_port == NULL) {
-                       dev_err(&dev->dev, "%s - Out of memory\n", __func__);
-                       status = -ENOMEM;
-                       i--; /* don't follow NULL pointer cleaning up */
-                       goto error;
-               }
-
-               /* Initialize all port interrupt end point to port 0 int
-                * endpoint. Our device has only one interrupt end point
-                * common to all port */
-
-               mos7840_port->port = serial->port[i];
-               mos7840_set_port_private(serial->port[i], mos7840_port);
-               spin_lock_init(&mos7840_port->pool_lock);
-
-               /* minor is not initialised until later by
-                * usb-serial.c:get_free_serial() and cannot therefore be used
-                * to index device instances */
-               mos7840_port->port_num = i + 1;
-               dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number);
-               dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor);
-               dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
-               dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor);
-
-               if (mos7840_port->port_num == 1) {
-                       mos7840_port->SpRegOffset = 0x0;
-                       mos7840_port->ControlRegOffset = 0x1;
-                       mos7840_port->DcrRegOffset = 0x4;
-               } else if ((mos7840_port->port_num == 2)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0x8;
-                       mos7840_port->ControlRegOffset = 0x9;
-                       mos7840_port->DcrRegOffset = 0x16;
-               } else if ((mos7840_port->port_num == 2)
-                          && (serial->num_ports == 2)) {
-                       mos7840_port->SpRegOffset = 0xa;
-                       mos7840_port->ControlRegOffset = 0xb;
-                       mos7840_port->DcrRegOffset = 0x19;
-               } else if ((mos7840_port->port_num == 3)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0xa;
-                       mos7840_port->ControlRegOffset = 0xb;
-                       mos7840_port->DcrRegOffset = 0x19;
-               } else if ((mos7840_port->port_num == 4)
-                          && (serial->num_ports == 4)) {
-                       mos7840_port->SpRegOffset = 0xc;
-                       mos7840_port->ControlRegOffset = 0xd;
-                       mos7840_port->DcrRegOffset = 0x1c;
-               }
-               mos7840_dump_serial_port(serial->port[i], mos7840_port);
-               mos7840_set_port_private(serial->port[i], mos7840_port);
+       pnum = port->number - serial->minor;
 
-               /* enable rx_disable bit in control register */
-               status = mos7840_get_reg_sync(serial->port[i],
-                                mos7840_port->ControlRegOffset, &Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
-               Data |= 0x08;   /* setting driver done bit */
-               Data |= 0x04;   /* sp1_bit to have cts change reflect in
-                                  modem status reg */
-
-               /* Data |= 0x20; //rx_disable bit */
-               status = mos7840_set_reg_sync(serial->port[i],
-                                        mos7840_port->ControlRegOffset, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
+       dev_dbg(&port->dev, "mos7840_startup: configuring port %d\n", pnum);
+       mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
+       if (mos7840_port == NULL) {
+               dev_err(&port->dev, "%s - Out of memory\n", __func__);
+               return -ENOMEM;
+       }
 
-               /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
-                  and 0x24 in DCR3 */
-               Data = 0x01;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 0), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status);
+       /* Initialize all port interrupt end point to port 0 int
+        * endpoint. Our device has only one interrupt end point
+        * common to all port */
+
+       mos7840_port->port = port;
+       mos7840_set_port_private(port, mos7840_port);
+       spin_lock_init(&mos7840_port->pool_lock);
+
+       /* minor is not initialised until later by
+        * usb-serial.c:get_free_serial() and cannot therefore be used
+        * to index device instances */
+       mos7840_port->port_num = pnum + 1;
+       dev_dbg(&port->dev, "port->number = %d\n", port->number);
+       dev_dbg(&port->dev, "port->serial->minor = %d\n", port->serial->minor);
+       dev_dbg(&port->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num);
+       dev_dbg(&port->dev, "serial->minor = %d\n", serial->minor);
+
+       if (mos7840_port->port_num == 1) {
+               mos7840_port->SpRegOffset = 0x0;
+               mos7840_port->ControlRegOffset = 0x1;
+               mos7840_port->DcrRegOffset = 0x4;
+       } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0x8;
+               mos7840_port->ControlRegOffset = 0x9;
+               mos7840_port->DcrRegOffset = 0x16;
+       } else if ((mos7840_port->port_num == 2) && (serial->num_ports == 2)) {
+               mos7840_port->SpRegOffset = 0xa;
+               mos7840_port->ControlRegOffset = 0xb;
+               mos7840_port->DcrRegOffset = 0x19;
+       } else if ((mos7840_port->port_num == 3) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0xa;
+               mos7840_port->ControlRegOffset = 0xb;
+               mos7840_port->DcrRegOffset = 0x19;
+       } else if ((mos7840_port->port_num == 4) && (serial->num_ports == 4)) {
+               mos7840_port->SpRegOffset = 0xc;
+               mos7840_port->ControlRegOffset = 0xd;
+               mos7840_port->DcrRegOffset = 0x1c;
+       }
+       mos7840_dump_serial_port(port, mos7840_port);
+       mos7840_set_port_private(port, mos7840_port);
+
+       /* enable rx_disable bit in control register */
+       status = mos7840_get_reg_sync(port,
+                       mos7840_port->ControlRegOffset, &Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Reading ControlReg failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "ControlReg Reading success val is %x, status%d\n", Data, status);
+       Data |= 0x08;   /* setting driver done bit */
+       Data |= 0x04;   /* sp1_bit to have cts change reflect in
+                          modem status reg */
 
-               Data = 0x05;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 1), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status);
+       /* Data |= 0x20; //rx_disable bit */
+       status = mos7840_set_reg_sync(port,
+                       mos7840_port->ControlRegOffset, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "ControlReg Writing success(rx_disable) status%d\n", status);
 
-               Data = 0x24;
-               status = mos7840_set_reg_sync(serial->port[i],
-                        (__u16) (mos7840_port->DcrRegOffset + 2), Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status);
+       /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2
+          and 0x24 in DCR3 */
+       Data = 0x01;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 0), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR0 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR0 Writing success status%d\n", status);
 
-               /* write values in clkstart0x0 and clkmulti 0x20 */
-               Data = 0x0;
-               status = mos7840_set_reg_sync(serial->port[i],
-                                        CLK_START_VALUE_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
+       Data = 0x05;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 1), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR1 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR1 Writing success status%d\n", status);
 
-               Data = 0x20;
-               status = mos7840_set_reg_sync(serial->port[i],
-                                       CLK_MULTI_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
-                       goto error;
-               } else
-                       dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
+       Data = 0x24;
+       status = mos7840_set_reg_sync(port,
+                       (__u16) (mos7840_port->DcrRegOffset + 2), Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing DCR2 failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "DCR2 Writing success status%d\n", status);
 
-               /* write value 0x0 to scratchpad register */
-               Data = 0x00;
-               status = mos7840_set_uart_reg(serial->port[i],
-                                               SCRATCH_PAD_REGISTER, Data);
-               if (status < 0) {
-                       dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
-                       break;
-               } else
-                       dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+       /* write values in clkstart0x0 and clkmulti 0x20 */
+       Data = 0x0;
+       status = mos7840_set_reg_sync(port, CLK_START_VALUE_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status);
 
-               /* Zero Length flag register */
-               if ((mos7840_port->port_num != 1)
-                   && (serial->num_ports == 2)) {
+       Data = 0x20;
+       status = mos7840_set_reg_sync(port, CLK_MULTI_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status);
+               goto error;
+       } else
+               dev_dbg(&port->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status);
 
-                       Data = 0xff;
-                       status = mos7840_set_reg_sync(serial->port[i],
-                                     (__u16) (ZLP_REG1 +
-                                     ((__u16)mos7840_port->port_num)), Data);
-                       dev_dbg(&dev->dev, "ZLIP offset %x\n",
+       /* write value 0x0 to scratchpad register */
+       Data = 0x00;
+       status = mos7840_set_uart_reg(port, SCRATCH_PAD_REGISTER, Data);
+       if (status < 0) {
+               dev_dbg(&port->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status);
+               goto out;
+       } else
+               dev_dbg(&port->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status);
+
+       /* Zero Length flag register */
+       if ((mos7840_port->port_num != 1) && (serial->num_ports == 2)) {
+               Data = 0xff;
+               status = mos7840_set_reg_sync(port,
+                               (__u16) (ZLP_REG1 +
+                                       ((__u16)mos7840_port->port_num)), Data);
+               dev_dbg(&port->dev, "ZLIP offset %x\n",
                                (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num)));
-                       if (status < 0) {
-                               dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status);
-                               break;
-                       } else
-                               dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status);
-               } else {
-                       Data = 0xff;
-                       status = mos7840_set_reg_sync(serial->port[i],
-                             (__u16) (ZLP_REG1 +
-                             ((__u16)mos7840_port->port_num) - 0x1), Data);
-                       dev_dbg(&dev->dev, "ZLIP offset %x\n",
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 2, status);
+                       goto out;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 2, status);
+       } else {
+               Data = 0xff;
+               status = mos7840_set_reg_sync(port,
+                               (__u16) (ZLP_REG1 +
+                                       ((__u16)mos7840_port->port_num) - 0x1), Data);
+               dev_dbg(&port->dev, "ZLIP offset %x\n",
                                (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1));
-                       if (status < 0) {
-                               dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status);
-                               break;
-                       } else
-                               dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status);
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG%d failed status-0x%x\n", pnum + 1, status);
+                       goto out;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG%d Writing success status%d\n", pnum + 1, status);
 
-               }
-               mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
-               mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
-               mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
-                                                               GFP_KERNEL);
-               if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
-                                                       !mos7840_port->dr) {
-                       status = -ENOMEM;
-                       goto error;
-               }
+       }
+       mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL);
+       mos7840_port->ctrl_buf = kmalloc(16, GFP_KERNEL);
+       mos7840_port->dr = kmalloc(sizeof(struct usb_ctrlrequest),
+                       GFP_KERNEL);
+       if (!mos7840_port->control_urb || !mos7840_port->ctrl_buf ||
+                       !mos7840_port->dr) {
+               status = -ENOMEM;
+               goto error;
+       }
 
-               mos7840_port->has_led = false;
+       mos7840_port->has_led = false;
 
-               /* Initialize LED timers */
-               if (device_type == MOSCHIP_DEVICE_ID_7810) {
-                       mos7840_port->has_led = true;
+       /* Initialize LED timers */
+       if (device_type == MOSCHIP_DEVICE_ID_7810) {
+               mos7840_port->has_led = true;
 
-                       init_timer(&mos7840_port->led_timer1);
-                       mos7840_port->led_timer1.function = mos7840_led_off;
-                       mos7840_port->led_timer1.expires =
-                                       jiffies + msecs_to_jiffies(LED_ON_MS);
-                       mos7840_port->led_timer1.data =
-                                               (unsigned long)mos7840_port;
+               init_timer(&mos7840_port->led_timer1);
+               mos7840_port->led_timer1.function = mos7840_led_off;
+               mos7840_port->led_timer1.expires =
+                       jiffies + msecs_to_jiffies(LED_ON_MS);
+               mos7840_port->led_timer1.data = (unsigned long)mos7840_port;
 
-                       init_timer(&mos7840_port->led_timer2);
-                       mos7840_port->led_timer2.function =
-                                               mos7840_led_flag_off;
-                       mos7840_port->led_timer2.expires =
-                                       jiffies + msecs_to_jiffies(LED_OFF_MS);
-                       mos7840_port->led_timer2.data =
-                                               (unsigned long)mos7840_port;
+               init_timer(&mos7840_port->led_timer2);
+               mos7840_port->led_timer2.function = mos7840_led_flag_off;
+               mos7840_port->led_timer2.expires =
+                       jiffies + msecs_to_jiffies(LED_OFF_MS);
+               mos7840_port->led_timer2.data = (unsigned long)mos7840_port;
 
-                       mos7840_port->led_flag = false;
+               mos7840_port->led_flag = false;
 
-                       /* Turn off LED */
-                       mos7840_set_led_sync(serial->port[i],
-                                               MODEM_CONTROL_REGISTER, 0x0300);
-               }
+               /* Turn off LED */
+               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
        }
+out:
+       if (pnum == serial->num_ports - 1) {
+               /* Zero Length flag enable */
+               Data = 0x0f;
+               status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
+               if (status < 0) {
+                       dev_dbg(&port->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
+                       goto error;
+               } else
+                       dev_dbg(&port->dev, "ZLP_REG5 Writing success status%d\n", status);
 
-       /* Zero Length flag enable */
-       Data = 0x0f;
-       status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data);
-       if (status < 0) {
-               dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status);
-               goto error;
-       } else
-               dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status);
-
-       /* setting configuration feature to one */
-       usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                       (__u8) 0x03, 0x00, 0x01, 0x00, NULL, 0x00, MOS_WDR_TIMEOUT);
+               /* setting configuration feature to one */
+               usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
+                               0x03, 0x00, 0x01, 0x00, NULL, 0x00,
+                               MOS_WDR_TIMEOUT);
+       }
        return 0;
 error:
-       for (/* nothing */; i >= 0; i--) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
+       kfree(mos7840_port->dr);
+       kfree(mos7840_port->ctrl_buf);
+       usb_free_urb(mos7840_port->control_urb);
+       kfree(mos7840_port);
 
-               kfree(mos7840_port->dr);
-               kfree(mos7840_port->ctrl_buf);
-               usb_free_urb(mos7840_port->control_urb);
-               kfree(mos7840_port);
-               serial->port[i] = NULL;
-       }
        return status;
 }
 
-/****************************************************************************
- * mos7840_disconnect
- *     This function is called whenever the device is removed from the usb bus.
- ****************************************************************************/
-
-static void mos7840_disconnect(struct usb_serial *serial)
+static int mos7840_port_remove(struct usb_serial_port *port)
 {
-       int i;
-       unsigned long flags;
        struct moschip_port *mos7840_port;
 
-       /* check for the ports to be closed,close the ports and disconnect */
+       mos7840_port = mos7840_get_port_private(port);
 
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
+       if (mos7840_port->has_led) {
+               /* Turn off LED */
+               mos7840_set_led_sync(port, MODEM_CONTROL_REGISTER, 0x0300);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
-               if (mos7840_port) {
-                       spin_lock_irqsave(&mos7840_port->pool_lock, flags);
-                       mos7840_port->zombie = 1;
-                       spin_unlock_irqrestore(&mos7840_port->pool_lock, flags);
-                       usb_kill_urb(mos7840_port->control_urb);
-               }
+               del_timer_sync(&mos7840_port->led_timer1);
+               del_timer_sync(&mos7840_port->led_timer2);
        }
-}
-
-/****************************************************************************
- * mos7840_release
- *     This function is called when the usb_serial structure is freed.
- ****************************************************************************/
-
-static void mos7840_release(struct usb_serial *serial)
-{
-       int i;
-       struct moschip_port *mos7840_port;
-
-       /* check for the ports to be closed,close the ports and disconnect */
+       usb_kill_urb(mos7840_port->control_urb);
+       usb_free_urb(mos7840_port->control_urb);
+       kfree(mos7840_port->ctrl_buf);
+       kfree(mos7840_port->dr);
+       kfree(mos7840_port);
 
-       /* free private structure allocated for serial port  *
-        * stop reads and writes on all ports                */
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               mos7840_port = mos7840_get_port_private(serial->port[i]);
-               if (mos7840_port) {
-                       if (mos7840_port->has_led) {
-                               /* Turn off LED */
-                               mos7840_set_led_sync(mos7840_port->port,
-                                               MODEM_CONTROL_REGISTER, 0x0300);
-
-                               del_timer_sync(&mos7840_port->led_timer1);
-                               del_timer_sync(&mos7840_port->led_timer2);
-                       }
-                       kfree(mos7840_port->ctrl_buf);
-                       kfree(mos7840_port->dr);
-                       kfree(mos7840_port);
-               }
-       }
+       return 0;
 }
 
 static struct usb_serial_driver moschip7840_4port_device = {
@@ -2677,9 +2597,8 @@ static struct usb_serial_driver moschip7840_4port_device = {
        .tiocmget = mos7840_tiocmget,
        .tiocmset = mos7840_tiocmset,
        .get_icount = mos7840_get_icount,
-       .attach = mos7840_startup,
-       .disconnect = mos7840_disconnect,
-       .release = mos7840_release,
+       .port_probe = mos7840_port_probe,
+       .port_remove = mos7840_port_remove,
        .read_bulk_callback = mos7840_bulk_in_callback,
        .read_int_callback = mos7840_interrupt_callback,
 };
index 6def58b79382f97511929b2c3fc8e386c71ffa51..9ab73d2957746d49292357382f7a081faa25cd55 100644 (file)
@@ -44,8 +44,8 @@ static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
                                const unsigned char *buf, int count);
 static int  omninet_write_room(struct tty_struct *tty);
 static void omninet_disconnect(struct usb_serial *serial);
-static void omninet_release(struct usb_serial *serial);
-static int omninet_attach(struct usb_serial *serial);
+static int omninet_port_probe(struct usb_serial_port *port);
+static int omninet_port_remove(struct usb_serial_port *port);
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
@@ -62,7 +62,8 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .description =          "ZyXEL - omni.net lcd plus usb",
        .id_table =             id_table,
        .num_ports =            1,
-       .attach =               omninet_attach,
+       .port_probe =           omninet_port_probe,
+       .port_remove =          omninet_port_remove,
        .open =                 omninet_open,
        .close =                omninet_close,
        .write =                omninet_write,
@@ -70,7 +71,6 @@ static struct usb_serial_driver zyxel_omninet_device = {
        .read_bulk_callback =   omninet_read_bulk_callback,
        .write_bulk_callback =  omninet_write_bulk_callback,
        .disconnect =           omninet_disconnect,
-       .release =              omninet_release,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -112,18 +112,26 @@ struct omninet_data {
        __u8    od_outseq;      /* Sequence number for bulk_out URBs */
 };
 
-static int omninet_attach(struct usb_serial *serial)
+static int omninet_port_probe(struct usb_serial_port *port)
 {
        struct omninet_data *od;
-       struct usb_serial_port *port = serial->port[0];
 
        od = kmalloc(sizeof(struct omninet_data), GFP_KERNEL);
-       if (!od) {
-               dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n",
-                       __func__, sizeof(struct omninet_data));
+       if (!od)
                return -ENOMEM;
-       }
+
        usb_set_serial_port_data(port, od);
+
+       return 0;
+}
+
+static int omninet_port_remove(struct usb_serial_port *port)
+{
+       struct omninet_data *od;
+
+       od = usb_get_serial_port_data(port);
+       kfree(od);
+
        return 0;
 }
 
@@ -279,14 +287,6 @@ static void omninet_disconnect(struct usb_serial *serial)
        usb_kill_urb(wport->write_urb);
 }
 
-
-static void omninet_release(struct usb_serial *serial)
-{
-       struct usb_serial_port *port = serial->port[0];
-
-       kfree(usb_get_serial_port_data(port));
-}
-
 module_usb_serial_driver(serial_drivers, id_table);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
index 41b1647306eb0970f55993f0099307af50739349..6aba731d4864457acba4e644b463a5c2f725dfc7 100644 (file)
@@ -155,7 +155,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
 {
        struct usb_serial *serial = port->serial;
        int retval;
-       u8 buffer[2];
+       u8 *buffer;
+
+       buffer = kzalloc(1, GFP_KERNEL);
+       if (!buffer)
+               return -ENOMEM;
 
        buffer[0] = val;
        /* Send the message to the vendor control endpoint
@@ -164,6 +168,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
                                requesttype,
                                USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
                                0, 0, buffer, 1, 0);
+       kfree(buffer);
 
        return retval;
 }
@@ -281,7 +286,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
        if (!dr) {
                dev_err(&port->dev, "out of memory\n");
                count = -ENOMEM;
-               goto error;
+               goto error_no_dr;
        }
 
        dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT;
@@ -311,6 +316,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port,
 
        return count;
 error:
+       kfree(dr);
+error_no_dr:
        usb_free_urb(urb);
 error_no_urb:
        kfree(buffer);
index 30cff03e9f012ffee6ecc2548477f8b1020c66f6..edc64bb6f457e45408f2c360dfc6de4500108499 100644 (file)
@@ -47,6 +47,7 @@
 /* Function prototypes */
 static int  option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id);
+static int option_attach(struct usb_serial *serial);
 static void option_release(struct usb_serial *serial);
 static int option_send_setup(struct usb_serial_port *port);
 static void option_instat_callback(struct urb *urb);
@@ -157,6 +158,7 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED        0x8001
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED        0x9000
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0x9001
+#define NOVATELWIRELESS_PRODUCT_E362           0x9010
 #define NOVATELWIRELESS_PRODUCT_G1             0xA001
 #define NOVATELWIRELESS_PRODUCT_G1_M           0xA002
 #define NOVATELWIRELESS_PRODUCT_G2             0xA010
@@ -192,6 +194,9 @@ static void option_instat_callback(struct urb *urb);
 #define DELL_PRODUCT_5730_MINICARD_TELUS       0x8181
 #define DELL_PRODUCT_5730_MINICARD_VZW         0x8182
 
+#define DELL_PRODUCT_5800_MINICARD_VZW         0x8195  /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW      0x8196  /* Novatel E362 */
+
 #define KYOCERA_VENDOR_ID                      0x0c88
 #define KYOCERA_PRODUCT_KPC650                 0x17da
 #define KYOCERA_PRODUCT_KPC680                 0x180a
@@ -282,6 +287,7 @@ static void option_instat_callback(struct urb *urb);
 /* ALCATEL PRODUCTS */
 #define ALCATEL_VENDOR_ID                      0x1bbb
 #define ALCATEL_PRODUCT_X060S_X200             0x0000
+#define ALCATEL_PRODUCT_X220_X500D             0x0017
 
 #define PIRELLI_VENDOR_ID                      0x1266
 #define PIRELLI_PRODUCT_C100_1                 0x1002
@@ -503,11 +509,19 @@ static const struct option_blacklist_info net_intf5_blacklist = {
        .reserved = BIT(5),
 };
 
+static const struct option_blacklist_info net_intf6_blacklist = {
+       .reserved = BIT(6),
+};
+
 static const struct option_blacklist_info zte_mf626_blacklist = {
        .sendsetup = BIT(0) | BIT(1),
        .reserved = BIT(4),
 };
 
+static const struct option_blacklist_info zte_1255_blacklist = {
+       .reserved = BIT(3) | BIT(4),
+};
+
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -697,6 +711,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
        /* Novatel Ovation MC551 a.k.a. Verizon USB551L */
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -719,6 +734,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) },      /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) },       /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) },         /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
+       { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },   /* ADU-E100, ADU-310 */
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
@@ -853,13 +870,19 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf6_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) },
@@ -872,7 +895,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) },
@@ -880,13 +904,22 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */
+         .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
+         .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -1002,18 +1035,24 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&zte_1255_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff),
+         .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) },
@@ -1058,8 +1097,16 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff),  /* ZTE MF91 */
+               .driver_info = (kernel_ulong_t)&net_intf2_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
          0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
@@ -1071,15 +1118,21 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf5_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
+               .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
 
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
@@ -1112,6 +1165,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
          .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
        },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
        { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
        { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
@@ -1244,8 +1298,9 @@ static struct usb_serial_driver option_1port_device = {
        .tiocmget          = usb_wwan_tiocmget,
        .tiocmset          = usb_wwan_tiocmset,
        .ioctl             = usb_wwan_ioctl,
-       .attach            = usb_wwan_startup,
+       .attach            = option_attach,
        .release           = option_release,
+       .port_probe        = usb_wwan_port_probe,
        .port_remove       = usb_wwan_port_remove,
        .read_int_callback = option_instat_callback,
 #ifdef CONFIG_PM
@@ -1291,8 +1346,6 @@ static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason,
 static int option_probe(struct usb_serial *serial,
                        const struct usb_device_id *id)
 {
-       struct usb_wwan_intf_private *data;
-       struct option_private *priv;
        struct usb_interface_descriptor *iface_desc =
                                &serial->interface->cur_altsetting->desc;
        struct usb_device_descriptor *dev_desc = &serial->dev->descriptor;
@@ -1330,6 +1383,19 @@ static int option_probe(struct usb_serial *serial,
                iface_desc->bInterfaceClass != USB_CLASS_CDC_DATA)
                return -ENODEV;
 
+       /* Store device id so we can use it during attach. */
+       usb_set_serial_data(serial, (void *)id);
+
+       return 0;
+}
+
+static int option_attach(struct usb_serial *serial)
+{
+       struct usb_interface_descriptor *iface_desc;
+       const struct usb_device_id *id;
+       struct usb_wwan_intf_private *data;
+       struct option_private *priv;
+
        data = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -1340,6 +1406,10 @@ static int option_probe(struct usb_serial *serial,
                return -ENOMEM;
        }
 
+       /* Retrieve device id stored at probe. */
+       id = usb_get_serial_data(serial);
+       iface_desc = &serial->interface->cur_altsetting->desc;
+
        priv->bInterfaceNumber = iface_desc->bInterfaceNumber;
        data->private = priv;
 
index 933241f03fd8382f9e1dcd6f9fee38c8d1b89298..cee9a52ca891cd0857b324fba5f99933b03771f0 100644 (file)
@@ -137,8 +137,8 @@ static int oti6858_chars_in_buffer(struct tty_struct *tty);
 static int oti6858_tiocmget(struct tty_struct *tty);
 static int oti6858_tiocmset(struct tty_struct *tty,
                                unsigned int set, unsigned int clear);
-static int oti6858_startup(struct usb_serial *serial);
-static void oti6858_release(struct usb_serial *serial);
+static int oti6858_port_probe(struct usb_serial_port *port);
+static int oti6858_port_remove(struct usb_serial_port *port);
 
 /* device info */
 static struct usb_serial_driver oti6858_device = {
@@ -161,8 +161,8 @@ static struct usb_serial_driver oti6858_device = {
        .write_bulk_callback =  oti6858_write_bulk_callback,
        .write_room =           oti6858_write_room,
        .chars_in_buffer =      oti6858_chars_in_buffer,
-       .attach =               oti6858_startup,
-       .release =              oti6858_release,
+       .port_probe =           oti6858_port_probe,
+       .port_remove =          oti6858_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
@@ -331,36 +331,33 @@ static void send_data(struct work_struct *work)
        usb_serial_port_softint(port);
 }
 
-static int oti6858_startup(struct usb_serial *serial)
+static int oti6858_port_probe(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = serial->port[0];
        struct oti6858_private *priv;
-       int i;
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = kzalloc(sizeof(struct oti6858_private), GFP_KERNEL);
-               if (!priv)
-                       break;
-
-               spin_lock_init(&priv->lock);
-               init_waitqueue_head(&priv->intr_wait);
-/*             INIT_WORK(&priv->setup_work, setup_line, serial->port[i]); */
-/*             INIT_WORK(&priv->write_work, send_data, serial->port[i]); */
-               priv->port = port;
-               INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
-               INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
-
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
-       if (i == serial->num_ports)
-               return 0;
 
-       for (--i; i >= 0; --i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       return -ENOMEM;
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->intr_wait);
+       priv->port = port;
+       INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
+       INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
+}
+
+static int oti6858_port_remove(struct usb_serial_port *port)
+{
+       struct oti6858_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static int oti6858_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -709,15 +706,6 @@ static int oti6858_ioctl(struct tty_struct *tty,
        return -ENOIOCTLCMD;
 }
 
-
-static void oti6858_release(struct usb_serial *serial)
-{
-       int i;
-
-       for (i = 0; i < serial->num_ports; ++i)
-               kfree(usb_get_serial_port_data(serial->port[i]));
-}
-
 static void oti6858_read_int_callback(struct urb *urb)
 {
        struct usb_serial_port *port =  urb->context;
index 892ebdc7a364b29572a908453c37443374965513..600241901361e62458d0d002e22261e1e5c0bc5f 100644 (file)
@@ -133,12 +133,15 @@ enum pl2303_type {
        HX,             /* HX version of the pl2303 chip */
 };
 
+struct pl2303_serial_private {
+       enum pl2303_type type;
+};
+
 struct pl2303_private {
        spinlock_t lock;
        wait_queue_head_t delta_msr_wait;
        u8 line_control;
        u8 line_status;
-       enum pl2303_type type;
 };
 
 static int pl2303_vendor_read(__u16 value, __u16 index,
@@ -167,14 +170,19 @@ static int pl2303_vendor_write(__u16 value, __u16 index,
 
 static int pl2303_startup(struct usb_serial *serial)
 {
-       struct pl2303_private *priv;
+       struct pl2303_serial_private *spriv;
        enum pl2303_type type = type_0;
        unsigned char *buf;
-       int i;
+
+       spriv = kzalloc(sizeof(*spriv), GFP_KERNEL);
+       if (!spriv)
+               return -ENOMEM;
 
        buf = kmalloc(10, GFP_KERNEL);
-       if (buf == NULL)
+       if (!buf) {
+               kfree(spriv);
                return -ENOMEM;
+       }
 
        if (serial->dev->descriptor.bDeviceClass == 0x02)
                type = type_0;
@@ -186,15 +194,8 @@ static int pl2303_startup(struct usb_serial *serial)
                type = type_1;
        dev_dbg(&serial->interface->dev, "device type: %d\n", type);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = kzalloc(sizeof(struct pl2303_private), GFP_KERNEL);
-               if (!priv)
-                       goto cleanup;
-               spin_lock_init(&priv->lock);
-               init_waitqueue_head(&priv->delta_msr_wait);
-               priv->type = type;
-               usb_set_serial_port_data(serial->port[i], priv);
-       }
+       spriv->type = type;
+       usb_set_serial_data(serial, spriv);
 
        pl2303_vendor_read(0x8484, 0, serial, buf);
        pl2303_vendor_write(0x0404, 0, serial);
@@ -213,15 +214,40 @@ static int pl2303_startup(struct usb_serial *serial)
 
        kfree(buf);
        return 0;
+}
 
-cleanup:
-       kfree(buf);
-       for (--i; i >= 0; --i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
-       return -ENOMEM;
+static void pl2303_release(struct usb_serial *serial)
+{
+       struct pl2303_serial_private *spriv;
+
+       spriv = usb_get_serial_data(serial);
+       kfree(spriv);
+}
+
+static int pl2303_port_probe(struct usb_serial_port *port)
+{
+       struct pl2303_private *priv;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->delta_msr_wait);
+
+       usb_set_serial_port_data(port, priv);
+
+       return 0;
+}
+
+static int pl2303_port_remove(struct usb_serial_port *port)
+{
+       struct pl2303_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static int set_control_lines(struct usb_device *dev, u8 value)
@@ -240,6 +266,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
                struct usb_serial_port *port, struct ktermios *old_termios)
 {
        struct usb_serial *serial = port->serial;
+       struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
        unsigned int cflag;
@@ -323,7 +350,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
                }
                if (baud > 1228800) {
                        /* type_0, type_1 only support up to 1228800 baud */
-                       if (priv->type != HX)
+                       if (spriv->type != HX)
                                baud = 1228800;
                        else if (baud > 6000000)
                                baud = 6000000;
@@ -426,7 +453,7 @@ static void pl2303_set_termios(struct tty_struct *tty,
             buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
 
        if (cflag & CRTSCTS) {
-               if (priv->type == HX)
+               if (spriv->type == HX)
                        pl2303_vendor_write(0x0, 0x61, serial);
                else
                        pl2303_vendor_write(0x0, 0x41, serial);
@@ -468,10 +495,10 @@ static int pl2303_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
        struct ktermios tmp_termios;
        struct usb_serial *serial = port->serial;
-       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
        int result;
 
-       if (priv->type != HX) {
+       if (spriv->type != HX) {
                usb_clear_halt(serial->dev, port->write_urb->pipe);
                usb_clear_halt(serial->dev, port->read_urb->pipe);
        } else {
@@ -655,17 +682,6 @@ static void pl2303_break_ctl(struct tty_struct *tty, int break_state)
                dev_err(&port->dev, "error sending break = %d\n", result);
 }
 
-static void pl2303_release(struct usb_serial *serial)
-{
-       int i;
-       struct pl2303_private *priv;
-
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-       }
-}
-
 static void pl2303_update_line_status(struct usb_serial_port *port,
                                      unsigned char *data,
                                      unsigned int actual_length)
@@ -827,6 +843,8 @@ static struct usb_serial_driver pl2303_device = {
        .read_int_callback =    pl2303_read_int_callback,
        .attach =               pl2303_startup,
        .release =              pl2303_release,
+       .port_probe =           pl2303_port_probe,
+       .port_remove =          pl2303_port_remove,
 };
 
 static struct usb_serial_driver * const serial_drivers[] = {
index c3ddb65c05f295158ee6ac4022cbca367bf11f21..aa148c21ea40e82a6f49b58b855ed2278f53cf3a 100644 (file)
@@ -138,7 +138,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 {
-       struct usb_wwan_intf_private *data;
        struct usb_host_interface *intf = serial->interface->cur_altsetting;
        struct device *dev = &serial->dev->dev;
        int retval = -ENODEV;
@@ -154,13 +153,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        ifnum = intf->desc.bInterfaceNumber;
        dev_dbg(dev, "This Interface = %d\n", ifnum);
 
-       data = kzalloc(sizeof(struct usb_wwan_intf_private),
-                                        GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       spin_lock_init(&data->susp_lock);
-
        if (nintf == 1) {
                /* QDL mode */
                /* Gobi 2000 has a single altsetting, older ones have two */
@@ -253,20 +245,28 @@ done:
                }
        }
 
-       /* Set serial->private if not returning error */
-       if (retval == 0)
-               usb_set_serial_data(serial, data);
-       else
-               kfree(data);
-
        return retval;
 }
 
+static int qc_attach(struct usb_serial *serial)
+{
+       struct usb_wwan_intf_private *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       spin_lock_init(&data->susp_lock);
+
+       usb_set_serial_data(serial, data);
+
+       return 0;
+}
+
 static void qc_release(struct usb_serial *serial)
 {
        struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
 
-       /* Free the private data allocated in qcprobe */
        usb_set_serial_data(serial, NULL);
        kfree(priv);
 }
@@ -285,8 +285,9 @@ static struct usb_serial_driver qcdevice = {
        .write               = usb_wwan_write,
        .write_room          = usb_wwan_write_room,
        .chars_in_buffer     = usb_wwan_chars_in_buffer,
-       .attach              = usb_wwan_startup,
+       .attach              = qc_attach,
        .release             = qc_release,
+       .port_probe          = usb_wwan_port_probe,
        .port_remove         = usb_wwan_port_remove,
 #ifdef CONFIG_PM
        .suspend             = usb_wwan_suspend,
index 2cdfdcc90b378b68402fc016cb0f1b4344b10ef3..ffcfc962ab10b5a4043cd900f8ca6e90094ff417 100644 (file)
@@ -143,12 +143,12 @@ static void qt2_read_bulk_callback(struct urb *urb);
 
 static void qt2_release(struct usb_serial *serial)
 {
-       int i;
+       struct qt2_serial_private *serial_priv;
 
-       kfree(usb_get_serial_data(serial));
+       serial_priv = usb_get_serial_data(serial);
 
-       for (i = 0; i < serial->num_ports; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       usb_free_urb(serial_priv->read_urb);
+       kfree(serial_priv);
 }
 
 static inline int calc_baud_divisor(int baudrate)
@@ -423,11 +423,16 @@ static void qt2_close(struct usb_serial_port *port)
        port_priv->is_open = false;
 
        spin_lock_irqsave(&port_priv->urb_lock, flags);
-       if (port_priv->write_urb->status == -EINPROGRESS)
-               usb_kill_urb(port_priv->write_urb);
+       usb_kill_urb(port_priv->write_urb);
        port_priv->urb_in_use = false;
        spin_unlock_irqrestore(&port_priv->urb_lock, flags);
 
+       mutex_lock(&port->serial->disc_mutex);
+       if (port->serial->disconnected) {
+               mutex_unlock(&port->serial->disc_mutex);
+               return;
+       }
+
        /* flush the port transmit buffer */
        i = usb_control_msg(serial->dev,
                            usb_rcvctrlpipe(serial->dev, 0),
@@ -459,26 +464,14 @@ static void qt2_close(struct usb_serial_port *port)
                dev_err(&port->dev, "%s - close port failed %i\n",
                        __func__, i);
 
+       mutex_unlock(&port->serial->disc_mutex);
 }
 
 static void qt2_disconnect(struct usb_serial *serial)
 {
        struct qt2_serial_private *serial_priv = usb_get_serial_data(serial);
-       struct qt2_port_private *port_priv;
-       int i;
-
-       if (serial_priv->read_urb->status == -EINPROGRESS)
-               usb_kill_urb(serial_priv->read_urb);
-
-       usb_free_urb(serial_priv->read_urb);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port_priv = usb_get_serial_port_data(serial->port[i]);
-
-               if (port_priv->write_urb->status == -EINPROGRESS)
-                       usb_kill_urb(port_priv->write_urb);
-               usb_free_urb(port_priv->write_urb);
-       }
+       usb_kill_urb(serial_priv->read_urb);
 }
 
 static int get_serial_info(struct usb_serial_port *port,
@@ -773,11 +766,9 @@ static void qt2_read_bulk_callback(struct urb *urb)
 
 static int qt2_setup_urbs(struct usb_serial *serial)
 {
-       struct usb_serial_port *port;
        struct usb_serial_port *port0;
        struct qt2_serial_private *serial_priv;
-       struct qt2_port_private *port_priv;
-       int pcount, status;
+       int status;
 
        port0 = serial->port[0];
 
@@ -795,46 +786,21 @@ static int qt2_setup_urbs(struct usb_serial *serial)
                          sizeof(serial_priv->read_buffer),
                          qt2_read_bulk_callback, serial);
 
-       /* setup write_urb for each port */
-       for (pcount = 0; pcount < serial->num_ports; pcount++) {
-
-               port = serial->port[pcount];
-               port_priv = usb_get_serial_port_data(port);
-
-               port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
-               if (!port_priv->write_urb) {
-                       dev_err(&serial->dev->dev,
-                               "failed to alloc write_urb for port %i\n",
-                               pcount);
-                       return -ENOMEM;
-               }
-
-               usb_fill_bulk_urb(port_priv->write_urb,
-                                 serial->dev,
-                                 usb_sndbulkpipe(serial->dev,
-                                                 port0->
-                                                 bulk_out_endpointAddress),
-                                 port_priv->write_buffer,
-                                 sizeof(port_priv->write_buffer),
-                                 qt2_write_bulk_callback, port);
-       }
-
        status = usb_submit_urb(serial_priv->read_urb, GFP_KERNEL);
        if (status != 0) {
                dev_err(&serial->dev->dev,
                        "%s - submit read urb failed %i\n", __func__, status);
+               usb_free_urb(serial_priv->read_urb);
                return status;
        }
 
        return 0;
-
 }
 
 static int qt2_attach(struct usb_serial *serial)
 {
        struct qt2_serial_private *serial_priv;
-       struct qt2_port_private *port_priv;
-       int status, pcount;
+       int status;
 
        /* power on unit */
        status = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
@@ -854,26 +820,6 @@ static int qt2_attach(struct usb_serial *serial)
 
        usb_set_serial_data(serial, serial_priv);
 
-       for (pcount = 0; pcount < serial->num_ports; pcount++) {
-               port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
-               if (!port_priv) {
-                       dev_err(&serial->dev->dev,
-                               "%s- kmalloc(%Zd) failed.\n", __func__,
-                               sizeof(*port_priv));
-                       pcount--;
-                       status = -ENOMEM;
-                       goto attach_failed;
-               }
-
-               spin_lock_init(&port_priv->lock);
-               spin_lock_init(&port_priv->urb_lock);
-               init_waitqueue_head(&port_priv->delta_msr_wait);
-
-               port_priv->port = serial->port[pcount];
-
-               usb_set_serial_port_data(serial->port[pcount], port_priv);
-       }
-
        status = qt2_setup_urbs(serial);
        if (status != 0)
                goto attach_failed;
@@ -881,14 +827,53 @@ static int qt2_attach(struct usb_serial *serial)
        return 0;
 
 attach_failed:
-       for (/* empty */; pcount >= 0; pcount--) {
-               port_priv = usb_get_serial_port_data(serial->port[pcount]);
-               kfree(port_priv);
-       }
        kfree(serial_priv);
        return status;
 }
 
+static int qt2_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       struct qt2_port_private *port_priv;
+       u8 bEndpointAddress;
+
+       port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
+       if (!port_priv)
+               return -ENOMEM;
+
+       spin_lock_init(&port_priv->lock);
+       spin_lock_init(&port_priv->urb_lock);
+       init_waitqueue_head(&port_priv->delta_msr_wait);
+       port_priv->port = port;
+
+       port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!port_priv->write_urb) {
+               kfree(port_priv);
+               return -ENOMEM;
+       }
+       bEndpointAddress = serial->port[0]->bulk_out_endpointAddress;
+       usb_fill_bulk_urb(port_priv->write_urb, serial->dev,
+                               usb_sndbulkpipe(serial->dev, bEndpointAddress),
+                               port_priv->write_buffer,
+                               sizeof(port_priv->write_buffer),
+                               qt2_write_bulk_callback, port);
+
+       usb_set_serial_port_data(port, port_priv);
+
+       return 0;
+}
+
+static int qt2_port_remove(struct usb_serial_port *port)
+{
+       struct qt2_port_private *port_priv;
+
+       port_priv = usb_get_serial_port_data(port);
+       usb_free_urb(port_priv->write_urb);
+       kfree(port_priv);
+
+       return 0;
+}
+
 static int qt2_tiocmget(struct tty_struct *tty)
 {
        struct usb_serial_port *port = tty->driver_data;
@@ -1127,6 +1112,8 @@ static struct usb_serial_driver qt2_device = {
        .attach              = qt2_attach,
        .release             = qt2_release,
        .disconnect          = qt2_disconnect,
+       .port_probe          = qt2_port_probe,
+       .port_remove         = qt2_port_remove,
        .dtr_rts             = qt2_dtr_rts,
        .break_ctl           = qt2_break_ctl,
        .tiocmget            = qt2_tiocmget,
index 01d882cf3775a2523662e4ab40f917a91eac5099..270860f6bb2aee0a97f2091c7c33041332cccc1e 100644 (file)
@@ -161,7 +161,6 @@ static int sierra_probe(struct usb_serial *serial,
 {
        int result = 0;
        struct usb_device *udev;
-       struct sierra_intf_private *data;
        u8 ifnum;
 
        udev = serial->dev;
@@ -188,11 +187,6 @@ static int sierra_probe(struct usb_serial *serial,
                return -ENODEV;
        }
 
-       data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       spin_lock_init(&data->susp_lock);
-
        return result;
 }
 
@@ -884,11 +878,15 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on)
 
 static int sierra_startup(struct usb_serial *serial)
 {
-       struct usb_serial_port *port;
-       struct sierra_port_private *portdata;
-       struct sierra_iface_info *himemoryp = NULL;
-       int i;
-       u8 ifnum;
+       struct sierra_intf_private *intfdata;
+
+       intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL);
+       if (!intfdata)
+               return -ENOMEM;
+
+       spin_lock_init(&intfdata->susp_lock);
+
+       usb_set_serial_data(serial, intfdata);
 
        /* Set Device mode to D0 */
        sierra_set_power_state(serial->dev, 0x0000);
@@ -897,68 +895,71 @@ static int sierra_startup(struct usb_serial *serial)
        if (nmea)
                sierra_vsc_set_nmea(serial->dev, 1);
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-               if (!portdata) {
-                       dev_dbg(&port->dev, "%s: kmalloc for "
-                               "sierra_port_private (%d) failed!\n",
-                               __func__, i);
-                       return -ENOMEM;
-               }
-               spin_lock_init(&portdata->lock);
-               init_usb_anchor(&portdata->active);
-               init_usb_anchor(&portdata->delayed);
-               ifnum = i;
-               /* Assume low memory requirements */
-               portdata->num_out_urbs = N_OUT_URB;
-               portdata->num_in_urbs  = N_IN_URB;
-
-               /* Determine actual memory requirements */
-               if (serial->num_ports == 1) {
-                       /* Get interface number for composite device */
-                       ifnum = sierra_calc_interface(serial);
-                       himemoryp =
-                           (struct sierra_iface_info *)&typeB_interface_list;
-                       if (is_himemory(ifnum, himemoryp)) {
-                               portdata->num_out_urbs = N_OUT_URB_HM;
-                               portdata->num_in_urbs  = N_IN_URB_HM;
-                       }
-               }
-               else {
-                       himemoryp =
-                           (struct sierra_iface_info *)&typeA_interface_list;
-                       if (is_himemory(i, himemoryp)) {
-                               portdata->num_out_urbs = N_OUT_URB_HM;
-                               portdata->num_in_urbs  = N_IN_URB_HM;
-                       }
-               }
-               dev_dbg(&serial->dev->dev,
-                       "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
-                       ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
-               /* Set the port private data pointer */
-               usb_set_serial_port_data(port, portdata);
-       }
-
        return 0;
 }
 
 static void sierra_release(struct usb_serial *serial)
 {
-       int i;
-       struct usb_serial_port *port;
+       struct sierra_intf_private *intfdata;
+
+       intfdata = usb_get_serial_data(serial);
+       kfree(intfdata);
+}
+
+static int sierra_port_probe(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
+       const struct sierra_iface_info *himemoryp;
+       u8 ifnum;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               port = serial->port[i];
-               if (!port)
-                       continue;
-               portdata = usb_get_serial_port_data(port);
-               if (!portdata)
-                       continue;
-               kfree(portdata);
+       portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+       if (!portdata)
+               return -ENOMEM;
+
+       spin_lock_init(&portdata->lock);
+       init_usb_anchor(&portdata->active);
+       init_usb_anchor(&portdata->delayed);
+
+       /* Assume low memory requirements */
+       portdata->num_out_urbs = N_OUT_URB;
+       portdata->num_in_urbs  = N_IN_URB;
+
+       /* Determine actual memory requirements */
+       if (serial->num_ports == 1) {
+               /* Get interface number for composite device */
+               ifnum = sierra_calc_interface(serial);
+               himemoryp = &typeB_interface_list;
+       } else {
+               /* This is really the usb-serial port number of the interface
+                * rather than the interface number.
+                */
+               ifnum = port->number - serial->minor;
+               himemoryp = &typeA_interface_list;
        }
+
+       if (is_himemory(ifnum, himemoryp)) {
+               portdata->num_out_urbs = N_OUT_URB_HM;
+               portdata->num_in_urbs  = N_IN_URB_HM;
+       }
+
+       dev_dbg(&port->dev,
+                       "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
+                       ifnum, portdata->num_in_urbs, portdata->num_out_urbs);
+
+       usb_set_serial_port_data(port, portdata);
+
+       return 0;
+}
+
+static int sierra_port_remove(struct usb_serial_port *port)
+{
+       struct sierra_port_private *portdata;
+
+       portdata = usb_get_serial_port_data(port);
+       kfree(portdata);
+
+       return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1062,6 +1063,8 @@ static struct usb_serial_driver sierra_device = {
        .tiocmset          = sierra_tiocmset,
        .attach            = sierra_startup,
        .release           = sierra_release,
+       .port_probe        = sierra_port_probe,
+       .port_remove       = sierra_port_remove,
        .suspend           = sierra_suspend,
        .resume            = sierra_resume,
        .read_int_callback = sierra_instat_callback,
index 9716efe92955bdd26d2aa7d5d5a3ea3ebdf9f540..769c137f8975689fd9a798e12fda23bf27036728 100644 (file)
@@ -157,13 +157,10 @@ struct spcp8x5_private {
        u8                      line_status;
 };
 
-/* desc : when device plug in,this function would be called.
- * thanks to usb_serial subsystem,then do almost every things for us. And what
- * we should do just alloc the buffer */
-static int spcp8x5_startup(struct usb_serial *serial)
+static int spcp8x5_port_probe(struct usb_serial_port *port)
 {
+       struct usb_serial *serial = port->serial;
        struct spcp8x5_private *priv;
-       int i;
        enum spcp8x5_type type = SPCP825_007_TYPE;
        u16 product = le16_to_cpu(serial->dev->descriptor.idProduct);
 
@@ -180,34 +177,27 @@ static int spcp8x5_startup(struct usb_serial *serial)
                type = SPCP825_PHILIP_TYPE;
        dev_dbg(&serial->dev->dev, "device type = %d\n", (int)type);
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               priv = kzalloc(sizeof(struct spcp8x5_private), GFP_KERNEL);
-               if (!priv)
-                       goto cleanup;
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
 
-               spin_lock_init(&priv->lock);
-               init_waitqueue_head(&priv->delta_msr_wait);
-               priv->type = type;
-               usb_set_serial_port_data(serial->port[i] , priv);
-       }
+       spin_lock_init(&priv->lock);
+       init_waitqueue_head(&priv->delta_msr_wait);
+       priv->type = type;
+
+       usb_set_serial_port_data(port , priv);
 
        return 0;
-cleanup:
-       for (--i; i >= 0; --i) {
-               priv = usb_get_serial_port_data(serial->port[i]);
-               kfree(priv);
-               usb_set_serial_port_data(serial->port[i] , NULL);
-       }
-       return -ENOMEM;
 }
 
-/* call when the device plug out. free all the memory alloced by probe */
-static void spcp8x5_release(struct usb_serial *serial)
+static int spcp8x5_port_remove(struct usb_serial_port *port)
 {
-       int i;
+       struct spcp8x5_private *priv;
 
-       for (i = 0; i < serial->num_ports; i++)
-               kfree(usb_get_serial_port_data(serial->port[i]));
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 /* set the modem control line of the device.
@@ -649,8 +639,8 @@ static struct usb_serial_driver spcp8x5_device = {
        .ioctl                  = spcp8x5_ioctl,
        .tiocmget               = spcp8x5_tiocmget,
        .tiocmset               = spcp8x5_tiocmset,
-       .attach                 = spcp8x5_startup,
-       .release                = spcp8x5_release,
+       .port_probe             = spcp8x5_port_probe,
+       .port_remove            = spcp8x5_port_remove,
        .process_read_urb       = spcp8x5_process_read_urb,
 };
 
index 015810b3785bb72938d60691b81433a918583750..868d1e6852e2ab6086a354cd62a352a241cb51c7 100644 (file)
@@ -67,13 +67,6 @@ struct ssu100_port_private {
        struct async_icount icount;
 };
 
-static void ssu100_release(struct usb_serial *serial)
-{
-       struct ssu100_port_private *priv = usb_get_serial_port_data(*serial->port);
-
-       kfree(priv);
-}
-
 static inline int ssu100_control_msg(struct usb_device *dev,
                                     u8 request, u16 data, u16 index)
 {
@@ -441,22 +434,34 @@ static int ssu100_ioctl(struct tty_struct *tty,
 }
 
 static int ssu100_attach(struct usb_serial *serial)
+{
+       return ssu100_initdevice(serial->dev);
+}
+
+static int ssu100_port_probe(struct usb_serial_port *port)
 {
        struct ssu100_port_private *priv;
-       struct usb_serial_port *port = *serial->port;
 
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv) {
-               dev_err(&port->dev, "%s- kmalloc(%Zd) failed.\n", __func__,
-                       sizeof(*priv));
+       if (!priv)
                return -ENOMEM;
-       }
 
        spin_lock_init(&priv->status_lock);
        init_waitqueue_head(&priv->delta_msr_wait);
+
        usb_set_serial_port_data(port, priv);
 
-       return ssu100_initdevice(serial->dev);
+       return 0;
+}
+
+static int ssu100_port_remove(struct usb_serial_port *port)
+{
+       struct ssu100_port_private *priv;
+
+       priv = usb_get_serial_port_data(port);
+       kfree(priv);
+
+       return 0;
 }
 
 static int ssu100_tiocmget(struct tty_struct *tty)
@@ -647,7 +652,8 @@ static struct usb_serial_driver ssu100_device = {
        .open                = ssu100_open,
        .close               = ssu100_close,
        .attach              = ssu100_attach,
-       .release             = ssu100_release,
+       .port_probe          = ssu100_port_probe,
+       .port_remove         = ssu100_port_remove,
        .dtr_rts             = ssu100_dtr_rts,
        .process_read_urb    = ssu100_process_read_urb,
        .tiocmget            = ssu100_tiocmget,
index 6f49392cda5bdb889192a118c94a0573b48348a8..f2530d2ef3c42af788e75c1db2554a95642c6207 100644 (file)
@@ -97,6 +97,8 @@ struct ti_device {
 
 static int ti_startup(struct usb_serial *serial);
 static void ti_release(struct usb_serial *serial);
+static int ti_port_probe(struct usb_serial_port *port);
+static int ti_port_remove(struct usb_serial_port *port);
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port);
 static void ti_close(struct usb_serial_port *port);
 static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -221,6 +223,8 @@ static struct usb_serial_driver ti_1port_device = {
        .num_ports              = 1,
        .attach                 = ti_startup,
        .release                = ti_release,
+       .port_probe             = ti_port_probe,
+       .port_remove            = ti_port_remove,
        .open                   = ti_open,
        .close                  = ti_close,
        .write                  = ti_write,
@@ -249,6 +253,8 @@ static struct usb_serial_driver ti_2port_device = {
        .num_ports              = 2,
        .attach                 = ti_startup,
        .release                = ti_release,
+       .port_probe             = ti_port_probe,
+       .port_remove            = ti_port_remove,
        .open                   = ti_open,
        .close                  = ti_close,
        .write                  = ti_write,
@@ -347,11 +353,8 @@ module_exit(ti_exit);
 static int ti_startup(struct usb_serial *serial)
 {
        struct ti_device *tdev;
-       struct ti_port *tport;
        struct usb_device *dev = serial->dev;
        int status;
-       int i;
-
 
        dev_dbg(&dev->dev,
                "%s - product 0x%4X, num configurations %d, configuration value %d",
@@ -399,42 +402,8 @@ static int ti_startup(struct usb_serial *serial)
                goto free_tdev;
        }
 
-       /* set up port structures */
-       for (i = 0; i < serial->num_ports; ++i) {
-               tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
-               if (tport == NULL) {
-                       dev_err(&dev->dev, "%s - out of memory\n", __func__);
-                       status = -ENOMEM;
-                       goto free_tports;
-               }
-               spin_lock_init(&tport->tp_lock);
-               tport->tp_uart_base_addr = (i == 0 ?
-                               TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
-               tport->tp_closing_wait = closing_wait;
-               init_waitqueue_head(&tport->tp_msr_wait);
-               init_waitqueue_head(&tport->tp_write_wait);
-               if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE,
-                                                               GFP_KERNEL)) {
-                       dev_err(&dev->dev, "%s - out of memory\n", __func__);
-                       kfree(tport);
-                       status = -ENOMEM;
-                       goto free_tports;
-               }
-               tport->tp_port = serial->port[i];
-               tport->tp_tdev = tdev;
-               usb_set_serial_port_data(serial->port[i], tport);
-               tport->tp_uart_mode = 0;        /* default is RS232 */
-       }
-
        return 0;
 
-free_tports:
-       for (--i; i >= 0; --i) {
-               tport = usb_get_serial_port_data(serial->port[i]);
-               kfifo_free(&tport->write_fifo);
-               kfree(tport);
-               usb_set_serial_port_data(serial->port[i], NULL);
-       }
 free_tdev:
        kfree(tdev);
        usb_set_serial_data(serial, NULL);
@@ -444,21 +413,50 @@ free_tdev:
 
 static void ti_release(struct usb_serial *serial)
 {
-       int i;
        struct ti_device *tdev = usb_get_serial_data(serial);
+
+       kfree(tdev);
+}
+
+static int ti_port_probe(struct usb_serial_port *port)
+{
        struct ti_port *tport;
 
-       for (i = 0; i < serial->num_ports; ++i) {
-               tport = usb_get_serial_port_data(serial->port[i]);
-               if (tport) {
-                       kfifo_free(&tport->write_fifo);
-                       kfree(tport);
-               }
+       tport = kzalloc(sizeof(*tport), GFP_KERNEL);
+       if (!tport)
+               return -ENOMEM;
+
+       spin_lock_init(&tport->tp_lock);
+       if (port == port->serial->port[0])
+               tport->tp_uart_base_addr = TI_UART1_BASE_ADDR;
+       else
+               tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
+       tport->tp_closing_wait = closing_wait;
+       init_waitqueue_head(&tport->tp_msr_wait);
+       init_waitqueue_head(&tport->tp_write_wait);
+       if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
+               kfree(tport);
+               return -ENOMEM;
        }
+       tport->tp_port = port;
+       tport->tp_tdev = usb_get_serial_data(port->serial);
+       tport->tp_uart_mode = 0;        /* default is RS232 */
 
-       kfree(tdev);
+       usb_set_serial_port_data(port, tport);
+
+       return 0;
 }
 
+static int ti_port_remove(struct usb_serial_port *port)
+{
+       struct ti_port *tport;
+
+       tport = usb_get_serial_port_data(port);
+       kfifo_free(&tport->write_fifo);
+       kfree(tport);
+
+       return 0;
+}
 
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port)
 {
index 1f034d2397c6c6ea3888e79aa6cd2ddb6d73202b..684739b8efd05b15a5646585d94417f3aa20a53d 100644 (file)
@@ -8,7 +8,7 @@
 extern void usb_wwan_dtr_rts(struct usb_serial_port *port, int on);
 extern int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port);
 extern void usb_wwan_close(struct usb_serial_port *port);
-extern int usb_wwan_startup(struct usb_serial *serial);
+extern int usb_wwan_port_probe(struct usb_serial_port *port);
 extern int usb_wwan_port_remove(struct usb_serial_port *port);
 extern int usb_wwan_write_room(struct tty_struct *tty);
 extern void usb_wwan_set_termios(struct tty_struct *tty,
index e42aa398ed37a3e8f774c2cbbdbaed8ae72e6eb3..a3e9c095f0d83a39738ef74b9e3a9ef7b41a2d6e 100644 (file)
@@ -447,15 +447,14 @@ void usb_wwan_close(struct usb_serial_port *port)
 EXPORT_SYMBOL(usb_wwan_close);
 
 /* Helper functions used by usb_wwan_setup_urbs */
-static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
+static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
+                                     int endpoint,
                                      int dir, void *ctx, char *buf, int len,
                                      void (*callback) (struct urb *))
 {
+       struct usb_serial *serial = port->serial;
        struct urb *urb;
 
-       if (endpoint == -1)
-               return NULL;    /* endpoint not needed */
-
        urb = usb_alloc_urb(0, GFP_KERNEL);     /* No ISO */
        if (urb == NULL) {
                dev_dbg(&serial->interface->dev,
@@ -472,101 +471,78 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint,
        return urb;
 }
 
-/* Setup urbs */
-static void usb_wwan_setup_urbs(struct usb_serial *serial)
+int usb_wwan_port_probe(struct usb_serial_port *port)
 {
-       int i, j;
-       struct usb_serial_port *port;
        struct usb_wwan_port_private *portdata;
+       struct urb *urb;
+       u8 *buffer;
+       int err;
+       int i;
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = usb_get_serial_port_data(port);
+       portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
+       if (!portdata)
+               return -ENOMEM;
 
-               /* Do indat endpoints first */
-               for (j = 0; j < N_IN_URB; ++j) {
-                       portdata->in_urbs[j] = usb_wwan_setup_urb(serial,
-                                                                 port->
-                                                                 bulk_in_endpointAddress,
-                                                                 USB_DIR_IN,
-                                                                 port,
-                                                                 portdata->
-                                                                 in_buffer[j],
-                                                                 IN_BUFLEN,
-                                                                 usb_wwan_indat_callback);
-               }
+       init_usb_anchor(&portdata->delayed);
 
-               /* outdat endpoints */
-               for (j = 0; j < N_OUT_URB; ++j) {
-                       portdata->out_urbs[j] = usb_wwan_setup_urb(serial,
-                                                                  port->
-                                                                  bulk_out_endpointAddress,
-                                                                  USB_DIR_OUT,
-                                                                  port,
-                                                                  portdata->
-                                                                  out_buffer
-                                                                  [j],
-                                                                  OUT_BUFLEN,
-                                                                  usb_wwan_outdat_callback);
-               }
-       }
-}
+       for (i = 0; i < N_IN_URB; i++) {
+               if (!port->bulk_in_size)
+                       break;
 
-int usb_wwan_startup(struct usb_serial *serial)
-{
-       int i, j, err;
-       struct usb_serial_port *port;
-       struct usb_wwan_port_private *portdata;
-       u8 *buffer;
+               buffer = (u8 *)__get_free_page(GFP_KERNEL);
+               if (!buffer)
+                       goto bail_out_error;
+               portdata->in_buffer[i] = buffer;
 
-       /* Now setup per port private data */
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-               portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
-               if (!portdata) {
-                       dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n",
-                               __func__, i);
-                       return 1;
-               }
-               init_usb_anchor(&portdata->delayed);
+               urb = usb_wwan_setup_urb(port, port->bulk_in_endpointAddress,
+                                               USB_DIR_IN, port,
+                                               buffer, IN_BUFLEN,
+                                               usb_wwan_indat_callback);
+               portdata->in_urbs[i] = urb;
+       }
 
-               for (j = 0; j < N_IN_URB; j++) {
-                       buffer = (u8 *) __get_free_page(GFP_KERNEL);
-                       if (!buffer)
-                               goto bail_out_error;
-                       portdata->in_buffer[j] = buffer;
-               }
+       for (i = 0; i < N_OUT_URB; i++) {
+               if (!port->bulk_out_size)
+                       break;
 
-               for (j = 0; j < N_OUT_URB; j++) {
-                       buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
-                       if (!buffer)
-                               goto bail_out_error2;
-                       portdata->out_buffer[j] = buffer;
-               }
+               buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
+               if (!buffer)
+                       goto bail_out_error2;
+               portdata->out_buffer[i] = buffer;
 
-               usb_set_serial_port_data(port, portdata);
+               urb = usb_wwan_setup_urb(port, port->bulk_out_endpointAddress,
+                                               USB_DIR_OUT, port,
+                                               buffer, OUT_BUFLEN,
+                                               usb_wwan_outdat_callback);
+               portdata->out_urbs[i] = urb;
+       }
 
-               if (!port->interrupt_in_urb)
-                       continue;
+       usb_set_serial_port_data(port, portdata);
+
+       if (port->interrupt_in_urb) {
                err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
                if (err)
                        dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n",
                                __func__, err);
        }
-       usb_wwan_setup_urbs(serial);
+
        return 0;
 
 bail_out_error2:
-       for (j = 0; j < N_OUT_URB; j++)
-               kfree(portdata->out_buffer[j]);
+       for (i = 0; i < N_OUT_URB; i++) {
+               usb_free_urb(portdata->out_urbs[i]);
+               kfree(portdata->out_buffer[i]);
+       }
 bail_out_error:
-       for (j = 0; j < N_IN_URB; j++)
-               if (portdata->in_buffer[j])
-                       free_page((unsigned long)portdata->in_buffer[j]);
+       for (i = 0; i < N_IN_URB; i++) {
+               usb_free_urb(portdata->in_urbs[i]);
+               free_page((unsigned long)portdata->in_buffer[i]);
+       }
        kfree(portdata);
-       return 1;
+
+       return -ENOMEM;
 }
-EXPORT_SYMBOL(usb_wwan_startup);
+EXPORT_SYMBOL_GPL(usb_wwan_port_probe);
 
 int usb_wwan_port_remove(struct usb_serial_port *port)
 {
index 346c7efc20b06d42899616cb8bb0766007cde82e..b9fca3586d741003a50ffb435be7de74020c48e8 100644 (file)
@@ -83,6 +83,8 @@ static int  whiteheat_firmware_attach(struct usb_serial *serial);
 /* function prototypes for the Connect Tech WhiteHEAT serial converter */
 static int  whiteheat_attach(struct usb_serial *serial);
 static void whiteheat_release(struct usb_serial *serial);
+static int  whiteheat_port_probe(struct usb_serial_port *port);
+static int  whiteheat_port_remove(struct usb_serial_port *port);
 static int  whiteheat_open(struct tty_struct *tty,
                        struct usb_serial_port *port);
 static void whiteheat_close(struct usb_serial_port *port);
@@ -117,6 +119,8 @@ static struct usb_serial_driver whiteheat_device = {
        .num_ports =            4,
        .attach =               whiteheat_attach,
        .release =              whiteheat_release,
+       .port_probe =           whiteheat_port_probe,
+       .port_remove =          whiteheat_port_remove,
        .open =                 whiteheat_open,
        .close =                whiteheat_close,
        .ioctl =                whiteheat_ioctl,
@@ -218,15 +222,12 @@ static int whiteheat_attach(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
        struct whiteheat_command_private *command_info;
-       struct usb_serial_port *port;
-       struct whiteheat_private *info;
        struct whiteheat_hw_info *hw_info;
        int pipe;
        int ret;
        int alen;
        __u8 *command;
        __u8 *result;
-       int i;
 
        command_port = serial->port[COMMAND_PORT];
 
@@ -285,22 +286,6 @@ static int whiteheat_attach(struct usb_serial *serial)
                 serial->type->description,
                 hw_info->sw_major_rev, hw_info->sw_minor_rev);
 
-       for (i = 0; i < serial->num_ports; i++) {
-               port = serial->port[i];
-
-               info = kmalloc(sizeof(struct whiteheat_private), GFP_KERNEL);
-               if (info == NULL) {
-                       dev_err(&port->dev,
-                               "%s: Out of memory for port structures\n",
-                               serial->type->description);
-                       goto no_private;
-               }
-
-               info->mcr = 0;
-
-               usb_set_serial_port_data(port, info);
-       }
-
        command_info = kmalloc(sizeof(struct whiteheat_command_private),
                                                                GFP_KERNEL);
        if (command_info == NULL) {
@@ -333,16 +318,10 @@ no_firmware:
                "%s: please contact support@connecttech.com\n",
                serial->type->description);
        kfree(result);
+       kfree(command);
        return -ENODEV;
 
 no_command_private:
-       for (i = serial->num_ports - 1; i >= 0; i--) {
-               port = serial->port[i];
-               info = usb_get_serial_port_data(port);
-               kfree(info);
-no_private:
-               ;
-       }
        kfree(result);
 no_result_buffer:
        kfree(command);
@@ -350,21 +329,36 @@ no_command_buffer:
        return -ENOMEM;
 }
 
-
 static void whiteheat_release(struct usb_serial *serial)
 {
        struct usb_serial_port *command_port;
-       struct whiteheat_private *info;
-       int i;
 
        /* free up our private data for our command port */
        command_port = serial->port[COMMAND_PORT];
        kfree(usb_get_serial_port_data(command_port));
+}
 
-       for (i = 0; i < serial->num_ports; i++) {
-               info = usb_get_serial_port_data(serial->port[i]);
-               kfree(info);
-       }
+static int whiteheat_port_probe(struct usb_serial_port *port)
+{
+       struct whiteheat_private *info;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       usb_set_serial_port_data(port, info);
+
+       return 0;
+}
+
+static int whiteheat_port_remove(struct usb_serial_port *port)
+{
+       struct whiteheat_private *info;
+
+       info = usb_get_serial_port_data(port);
+       kfree(info);
+
+       return 0;
 }
 
 static int whiteheat_open(struct tty_struct *tty, struct usb_serial_port *port)
index a3d54366afccde598a4ba5f3240909044f975266..92f35abee92d281990e17ccdb4f388d33ed67f0e 100644 (file)
@@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev)
                /* Some devices don't handle VPD pages correctly */
                sdev->skip_vpd_pages = 1;
 
+               /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
+               sdev->no_report_opcodes = 1;
+
+               /* Do not attempt to use WRITE SAME */
+               sdev->no_write_same = 1;
+
                /* Some disks return the total number of blocks in response
                 * to READ CAPACITY rather than the highest block number.
                 * If this device makes that mistake, tell the sd driver. */
index 779cd954abcbd26d1fc935650d102dc524b8ca5a..d305a5aa3a5d7683a5bcd1c2e60c4a0262f35f65 100644 (file)
@@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999,
                USB_SC_8070, USB_PR_CB, NULL,
                US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ),
 
+/* Submitted by Oleksandr Chumachenko <ledest@gmail.com> */
+UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100,
+               "Casio",
+               "EX-N1 DigitalCamera",
+               USB_SC_8070, USB_PR_DEVICE, NULL, 0),
+
 /* Submitted by Hartmut Wahl <hwahl@hwahl.de>*/
 UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001,
                "Samsung",
index 072cbbadbc3683ef75fd6ff2420e40463b8f722e..ebd08b21b23432696047487367d44f76d4fa4f02 100644 (file)
 
 #include "vhost.h"
 
-static int experimental_zcopytx;
+static int experimental_zcopytx = 1;
 module_param(experimental_zcopytx, int, 0444);
-MODULE_PARM_DESC(experimental_zcopytx, "Enable Experimental Zero Copy TX");
+MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"
+                                      " 1 -Enable; 0 - Disable");
 
 /* Max number of bytes transferred before requeueing the job.
  * Using this limit prevents one virtqueue from starving others. */
@@ -42,6 +43,21 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Experimental Zero Copy TX");
 #define VHOST_MAX_PEND 128
 #define VHOST_GOODCOPY_LEN 256
 
+/*
+ * For transmit, used buffer len is unused; we override it to track buffer
+ * status internally; used for zerocopy tx only.
+ */
+/* Lower device DMA failed */
+#define VHOST_DMA_FAILED_LEN   3
+/* Lower device DMA done */
+#define VHOST_DMA_DONE_LEN     2
+/* Lower device DMA in progress */
+#define VHOST_DMA_IN_PROGRESS  1
+/* Buffer unused */
+#define VHOST_DMA_CLEAR_LEN    0
+
+#define VHOST_DMA_IS_DONE(len) ((len) >= VHOST_DMA_DONE_LEN)
+
 enum {
        VHOST_NET_VQ_RX = 0,
        VHOST_NET_VQ_TX = 1,
@@ -62,8 +78,39 @@ struct vhost_net {
         * We only do this when socket buffer fills up.
         * Protected by tx vq lock. */
        enum vhost_net_poll_state tx_poll_state;
+       /* Number of TX recently submitted.
+        * Protected by tx vq lock. */
+       unsigned tx_packets;
+       /* Number of times zerocopy TX recently failed.
+        * Protected by tx vq lock. */
+       unsigned tx_zcopy_err;
+       /* Flush in progress. Protected by tx vq lock. */
+       bool tx_flush;
 };
 
+static void vhost_net_tx_packet(struct vhost_net *net)
+{
+       ++net->tx_packets;
+       if (net->tx_packets < 1024)
+               return;
+       net->tx_packets = 0;
+       net->tx_zcopy_err = 0;
+}
+
+static void vhost_net_tx_err(struct vhost_net *net)
+{
+       ++net->tx_zcopy_err;
+}
+
+static bool vhost_net_tx_select_zcopy(struct vhost_net *net)
+{
+       /* TX flush waits for outstanding DMAs to be done.
+        * Don't start new DMAs.
+        */
+       return !net->tx_flush &&
+               net->tx_packets / 64 >= net->tx_zcopy_err;
+}
+
 static bool vhost_sock_zcopy(struct socket *sock)
 {
        return unlikely(experimental_zcopytx) &&
@@ -126,6 +173,55 @@ static void tx_poll_start(struct vhost_net *net, struct socket *sock)
        net->tx_poll_state = VHOST_NET_POLL_STARTED;
 }
 
+/* In case of DMA done not in order in lower device driver for some reason.
+ * upend_idx is used to track end of used idx, done_idx is used to track head
+ * of used idx. Once lower device DMA done contiguously, we will signal KVM
+ * guest used idx.
+ */
+static int vhost_zerocopy_signal_used(struct vhost_net *net,
+                                     struct vhost_virtqueue *vq)
+{
+       int i;
+       int j = 0;
+
+       for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
+               if (vq->heads[i].len == VHOST_DMA_FAILED_LEN)
+                       vhost_net_tx_err(net);
+               if (VHOST_DMA_IS_DONE(vq->heads[i].len)) {
+                       vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
+                       vhost_add_used_and_signal(vq->dev, vq,
+                                                 vq->heads[i].id, 0);
+                       ++j;
+               } else
+                       break;
+       }
+       if (j)
+               vq->done_idx = i;
+       return j;
+}
+
+static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)
+{
+       struct vhost_ubuf_ref *ubufs = ubuf->ctx;
+       struct vhost_virtqueue *vq = ubufs->vq;
+       int cnt = atomic_read(&ubufs->kref.refcount);
+
+       /*
+        * Trigger polling thread if guest stopped submitting new buffers:
+        * in this case, the refcount after decrement will eventually reach 1
+        * so here it is 2.
+        * We also trigger polling periodically after each 16 packets
+        * (the value 16 here is more or less arbitrary, it's tuned to trigger
+        * less than 10% of times).
+        */
+       if (cnt <= 2 || !(cnt % 16))
+               vhost_poll_queue(&vq->poll);
+       /* set len to mark this desc buffers done DMA */
+       vq->heads[ubuf->desc].len = success ?
+               VHOST_DMA_DONE_LEN : VHOST_DMA_FAILED_LEN;
+       vhost_ubuf_put(ubufs);
+}
+
 /* Expects to be always run from workqueue - which acts as
  * read-size critical section for our kind of RCU. */
 static void handle_tx(struct vhost_net *net)
@@ -146,7 +242,7 @@ static void handle_tx(struct vhost_net *net)
        size_t hdr_size;
        struct socket *sock;
        struct vhost_ubuf_ref *uninitialized_var(ubufs);
-       bool zcopy;
+       bool zcopy, zcopy_used;
 
        /* TODO: check that we are running from vhost_worker? */
        sock = rcu_dereference_check(vq->private_data, 1);
@@ -172,7 +268,7 @@ static void handle_tx(struct vhost_net *net)
        for (;;) {
                /* Release DMAs done buffers first */
                if (zcopy)
-                       vhost_zerocopy_signal_used(vq);
+                       vhost_zerocopy_signal_used(net, vq);
 
                head = vhost_get_vq_desc(&net->dev, vq, vq->iov,
                                         ARRAY_SIZE(vq->iov),
@@ -224,10 +320,14 @@ static void handle_tx(struct vhost_net *net)
                               iov_length(vq->hdr, s), hdr_size);
                        break;
                }
+               zcopy_used = zcopy && (len >= VHOST_GOODCOPY_LEN ||
+                                      vq->upend_idx != vq->done_idx);
+
                /* use msg_control to pass vhost zerocopy ubuf info to skb */
-               if (zcopy) {
+               if (zcopy_used) {
                        vq->heads[vq->upend_idx].id = head;
-                       if (len < VHOST_GOODCOPY_LEN) {
+                       if (!vhost_net_tx_select_zcopy(net) ||
+                           len < VHOST_GOODCOPY_LEN) {
                                /* copy don't need to wait for DMA done */
                                vq->heads[vq->upend_idx].len =
                                                        VHOST_DMA_DONE_LEN;
@@ -237,7 +337,8 @@ static void handle_tx(struct vhost_net *net)
                        } else {
                                struct ubuf_info *ubuf = &vq->ubuf_info[head];
 
-                               vq->heads[vq->upend_idx].len = len;
+                               vq->heads[vq->upend_idx].len =
+                                       VHOST_DMA_IN_PROGRESS;
                                ubuf->callback = vhost_zerocopy_callback;
                                ubuf->ctx = vq->ubufs;
                                ubuf->desc = vq->upend_idx;
@@ -251,7 +352,7 @@ static void handle_tx(struct vhost_net *net)
                /* TODO: Check specific error and bomb out unless ENOBUFS? */
                err = sock->ops->sendmsg(NULL, sock, &msg, len);
                if (unlikely(err < 0)) {
-                       if (zcopy) {
+                       if (zcopy_used) {
                                if (ubufs)
                                        vhost_ubuf_put(ubufs);
                                vq->upend_idx = ((unsigned)vq->upend_idx - 1) %
@@ -265,11 +366,12 @@ static void handle_tx(struct vhost_net *net)
                if (err != len)
                        pr_debug("Truncated TX packet: "
                                 " len %d != %zd\n", err, len);
-               if (!zcopy)
+               if (!zcopy_used)
                        vhost_add_used_and_signal(&net->dev, vq, head, 0);
                else
-                       vhost_zerocopy_signal_used(vq);
+                       vhost_zerocopy_signal_used(net, vq);
                total_len += len;
+               vhost_net_tx_packet(net);
                if (unlikely(total_len >= VHOST_NET_WEIGHT)) {
                        vhost_poll_queue(&vq->poll);
                        break;
@@ -379,7 +481,8 @@ static void handle_rx(struct vhost_net *net)
                .hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE
        };
        size_t total_len = 0;
-       int err, headcount, mergeable;
+       int err, mergeable;
+       s16 headcount;
        size_t vhost_hlen, sock_hlen;
        size_t vhost_len, sock_len;
        /* TODO: check that we are running from vhost_worker? */
@@ -586,6 +689,17 @@ static void vhost_net_flush(struct vhost_net *n)
 {
        vhost_net_flush_vq(n, VHOST_NET_VQ_TX);
        vhost_net_flush_vq(n, VHOST_NET_VQ_RX);
+       if (n->dev.vqs[VHOST_NET_VQ_TX].ubufs) {
+               mutex_lock(&n->dev.vqs[VHOST_NET_VQ_TX].mutex);
+               n->tx_flush = true;
+               mutex_unlock(&n->dev.vqs[VHOST_NET_VQ_TX].mutex);
+               /* Wait for all lower device DMAs done. */
+               vhost_ubuf_put_and_wait(n->dev.vqs[VHOST_NET_VQ_TX].ubufs);
+               mutex_lock(&n->dev.vqs[VHOST_NET_VQ_TX].mutex);
+               n->tx_flush = false;
+               kref_init(&n->dev.vqs[VHOST_NET_VQ_TX].ubufs->kref);
+               mutex_unlock(&n->dev.vqs[VHOST_NET_VQ_TX].mutex);
+       }
 }
 
 static int vhost_net_release(struct inode *inode, struct file *f)
@@ -596,6 +710,7 @@ static int vhost_net_release(struct inode *inode, struct file *f)
 
        vhost_net_stop(n, &tx_sock, &rx_sock);
        vhost_net_flush(n);
+       vhost_dev_stop(&n->dev);
        vhost_dev_cleanup(&n->dev, false);
        if (tx_sock)
                fput(tx_sock->file);
@@ -721,6 +836,10 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
                r = vhost_init_used(vq);
                if (r)
                        goto err_vq;
+
+               n->tx_packets = 0;
+               n->tx_zcopy_err = 0;
+               n->tx_flush = false;
        }
 
        mutex_unlock(&vq->mutex);
@@ -728,7 +847,7 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd)
        if (oldubufs) {
                vhost_ubuf_put_and_wait(oldubufs);
                mutex_lock(&vq->mutex);
-               vhost_zerocopy_signal_used(vq);
+               vhost_zerocopy_signal_used(n, vq);
                mutex_unlock(&vq->mutex);
        }
 
@@ -837,8 +956,11 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
                return vhost_net_reset_owner(n);
        default:
                mutex_lock(&n->dev.mutex);
-               r = vhost_dev_ioctl(&n->dev, ioctl, arg);
-               vhost_net_flush(n);
+               r = vhost_dev_ioctl(&n->dev, ioctl, argp);
+               if (r == -ENOIOCTLCMD)
+                       r = vhost_vring_ioctl(&n->dev, ioctl, argp);
+               else
+                       vhost_net_flush(n);
                mutex_unlock(&n->dev.mutex);
                return r;
        }
index aa31692064ddd08b6aa91718ed1ece369da74631..79e7e4d45eb242b42aeb20ab14dfe73aaabfa565 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/ctype.h>
 #include <linux/compat.h>
 #include <linux/eventfd.h>
-#include <linux/vhost.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <asm/unaligned.h>
@@ -415,14 +414,12 @@ static struct tcm_vhost_cmd *vhost_scsi_allocate_cmd(
 {
        struct tcm_vhost_cmd *tv_cmd;
        struct tcm_vhost_nexus *tv_nexus;
-       struct se_session *se_sess;
 
        tv_nexus = tv_tpg->tpg_nexus;
        if (!tv_nexus) {
                pr_err("Unable to locate active struct tcm_vhost_nexus\n");
                return ERR_PTR(-EIO);
        }
-       se_sess = tv_nexus->tvn_se_sess;
 
        tv_cmd = kzalloc(sizeof(struct tcm_vhost_cmd), GFP_ATOMIC);
        if (!tv_cmd) {
@@ -895,6 +892,7 @@ static int vhost_scsi_release(struct inode *inode, struct file *f)
                vhost_scsi_clear_endpoint(s, &backend);
        }
 
+       vhost_dev_stop(&s->dev);
        vhost_dev_cleanup(&s->dev, false);
        kfree(s);
        return 0;
@@ -970,7 +968,10 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
                return vhost_scsi_set_features(vs, features);
        default:
                mutex_lock(&vs->dev.mutex);
-               r = vhost_dev_ioctl(&vs->dev, ioctl, arg);
+               r = vhost_dev_ioctl(&vs->dev, ioctl, argp);
+               /* TODO: flush backend after dev ioctl. */
+               if (r == -ENOIOCTLCMD)
+                       r = vhost_vring_ioctl(&vs->dev, ioctl, argp);
                mutex_unlock(&vs->dev.mutex);
                return r;
        }
index 99ac2cb08b43bcb3b570969d752bff25126f298d..34389f75fe65693a4ad5baa36715159fd5759bbb 100644 (file)
 #include <linux/kthread.h>
 #include <linux/cgroup.h>
 
-#include <linux/net.h>
-#include <linux/if_packet.h>
-#include <linux/if_arp.h>
-
 #include "vhost.h"
 
 enum {
@@ -414,28 +410,16 @@ long vhost_dev_reset_owner(struct vhost_dev *dev)
        return 0;
 }
 
-/* In case of DMA done not in order in lower device driver for some reason.
- * upend_idx is used to track end of used idx, done_idx is used to track head
- * of used idx. Once lower device DMA done contiguously, we will signal KVM
- * guest used idx.
- */
-int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq)
+void vhost_dev_stop(struct vhost_dev *dev)
 {
        int i;
-       int j = 0;
-
-       for (i = vq->done_idx; i != vq->upend_idx; i = (i + 1) % UIO_MAXIOV) {
-               if ((vq->heads[i].len == VHOST_DMA_DONE_LEN)) {
-                       vq->heads[i].len = VHOST_DMA_CLEAR_LEN;
-                       vhost_add_used_and_signal(vq->dev, vq,
-                                                 vq->heads[i].id, 0);
-                       ++j;
-               } else
-                       break;
+
+       for (i = 0; i < dev->nvqs; ++i) {
+               if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
+                       vhost_poll_stop(&dev->vqs[i].poll);
+                       vhost_poll_flush(&dev->vqs[i].poll);
+               }
        }
-       if (j)
-               vq->done_idx = i;
-       return j;
 }
 
 /* Caller should have device mutex if and only if locked is set */
@@ -444,17 +428,6 @@ void vhost_dev_cleanup(struct vhost_dev *dev, bool locked)
        int i;
 
        for (i = 0; i < dev->nvqs; ++i) {
-               if (dev->vqs[i].kick && dev->vqs[i].handle_kick) {
-                       vhost_poll_stop(&dev->vqs[i].poll);
-                       vhost_poll_flush(&dev->vqs[i].poll);
-               }
-               /* Wait for all lower device DMAs done. */
-               if (dev->vqs[i].ubufs)
-                       vhost_ubuf_put_and_wait(dev->vqs[i].ubufs);
-
-               /* Signal guest as appropriate. */
-               vhost_zerocopy_signal_used(&dev->vqs[i]);
-
                if (dev->vqs[i].error_ctx)
                        eventfd_ctx_put(dev->vqs[i].error_ctx);
                if (dev->vqs[i].error)
@@ -634,7 +607,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
        return 0;
 }
 
-static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
+long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp)
 {
        struct file *eventfp, *filep = NULL;
        bool pollstart = false, pollstop = false;
@@ -829,9 +802,8 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp)
 }
 
 /* Caller must have device mutex */
-long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
+long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
 {
-       void __user *argp = (void __user *)arg;
        struct file *eventfp, *filep = NULL;
        struct eventfd_ctx *ctx = NULL;
        u64 p;
@@ -902,7 +874,7 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg)
                        fput(filep);
                break;
        default:
-               r = vhost_set_vring(d, ioctl, argp);
+               r = -ENOIOCTLCMD;
                break;
        }
 done:
@@ -1076,7 +1048,7 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len,
                }
                _iov = iov + ret;
                size = reg->memory_size - addr + reg->guest_phys_addr;
-               _iov->iov_len = min((u64)len, size);
+               _iov->iov_len = min((u64)len - s, size);
                _iov->iov_base = (void __user *)(unsigned long)
                        (reg->userspace_addr + addr - reg->guest_phys_addr);
                s += size;
@@ -1599,14 +1571,3 @@ void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *ubufs)
        wait_event(ubufs->wait, !atomic_read(&ubufs->kref.refcount));
        kfree(ubufs);
 }
-
-void vhost_zerocopy_callback(struct ubuf_info *ubuf)
-{
-       struct vhost_ubuf_ref *ubufs = ubuf->ctx;
-       struct vhost_virtqueue *vq = ubufs->vq;
-
-       vhost_poll_queue(&vq->poll);
-       /* set len = 1 to mark this desc buffers done DMA */
-       vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN;
-       kref_put(&ubufs->kref, vhost_zerocopy_done_signal);
-}
index 1125af3d27d12b3f724a79a259aa774e6d214b67..2639c58b23ab497ace850895f3322df661a965df 100644 (file)
@@ -7,17 +7,11 @@
 #include <linux/mutex.h>
 #include <linux/poll.h>
 #include <linux/file.h>
-#include <linux/skbuff.h>
 #include <linux/uio.h>
 #include <linux/virtio_config.h>
 #include <linux/virtio_ring.h>
 #include <linux/atomic.h>
 
-/* This is for zerocopy, used buffer len is set to 1 when lower device DMA
- * done */
-#define VHOST_DMA_DONE_LEN     1
-#define VHOST_DMA_CLEAR_LEN    0
-
 struct vhost_device;
 
 struct vhost_work;
@@ -70,6 +64,8 @@ struct vhost_ubuf_ref *vhost_ubuf_alloc(struct vhost_virtqueue *, bool zcopy);
 void vhost_ubuf_put(struct vhost_ubuf_ref *);
 void vhost_ubuf_put_and_wait(struct vhost_ubuf_ref *);
 
+struct ubuf_info;
+
 /* The virtqueue structure describes a queue attached to a device. */
 struct vhost_virtqueue {
        struct vhost_dev *dev;
@@ -167,7 +163,9 @@ long vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue *vqs, int nvqs);
 long vhost_dev_check_owner(struct vhost_dev *);
 long vhost_dev_reset_owner(struct vhost_dev *);
 void vhost_dev_cleanup(struct vhost_dev *, bool locked);
-long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, unsigned long arg);
+void vhost_dev_stop(struct vhost_dev *);
+long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp);
+long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp);
 int vhost_vq_access_ok(struct vhost_virtqueue *vq);
 int vhost_log_access_ok(struct vhost_dev *);
 
@@ -191,8 +189,6 @@ bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
                    unsigned int log_num, u64 len);
-void vhost_zerocopy_callback(struct ubuf_info *);
-int vhost_zerocopy_signal_used(struct vhost_virtqueue *vq);
 
 #define vq_err(vq, fmt, ...) do {                                  \
                pr_debug(pr_fmt(fmt), ##__VA_ARGS__);       \
index c101697a4ba708e06b2ea102ba6000d97eaa0ed8..765a945f8ea12ef2e1a9fc80c428a885f9806320 100644 (file)
@@ -60,7 +60,8 @@ config LCD_LTV350QV
          The LTV350QV panel is present on all ATSTK1000 boards.
 
 config LCD_ILI9320
-       tristate
+       tristate "ILI Technology ILI9320 controller support"
+       depends on SPI
        help
          If you have a panel based on the ILI9320 controller chip
          then say y to include a power driver for it.
index c6915c6c3cd1e5fc3941a8a3e6fe242fa9db0310..585949b570550fd5e681b23a2564f8f65eb8f83a 100644 (file)
@@ -206,11 +206,11 @@ static ssize_t lm3639_bled_mode_store(struct device *dev,
 
 out:
        dev_err(pchip->dev, "%s:i2c access fail to register\n", __func__);
-       return size;
+       return ret;
 
 out_input:
        dev_err(pchip->dev, "%s:input conversion fail\n", __func__);
-       return size;
+       return ret;
 
 }
 
index d64ac3842884f4e9eac994dd03fdc311646d27b9..bee92846cfab930f6304a9ebb4316b25b8780bc7 100644 (file)
@@ -365,11 +365,20 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
        struct omap_dss_output *out;
        enum omap_dss_output_id id;
 
-       id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+       switch (module) {
+       case 0:
+               id = OMAP_DSS_OUTPUT_DSI1;
+               break;
+       case 1:
+               id = OMAP_DSS_OUTPUT_DSI2;
+               break;
+       default:
+               return NULL;
+       }
 
        out = omap_dss_get_output(id);
 
-       return out->pdev;
+       return out ? out->pdev : NULL;
 }
 
 static inline void dsi_write_reg(struct platform_device *dsidev,
index 2ab1c3e96553d81297ad5f942eed2cfb76a5064b..5f6eea801b064a37949b3cc66bf9ca5f2dde3431 100644 (file)
@@ -697,11 +697,15 @@ static int dss_get_clocks(void)
 
        dss.dss_clk = clk;
 
-       clk = clk_get(NULL, dss.feat->clk_name);
-       if (IS_ERR(clk)) {
-               DSSERR("Failed to get %s\n", dss.feat->clk_name);
-               r = PTR_ERR(clk);
-               goto err;
+       if (dss.feat->clk_name) {
+               clk = clk_get(NULL, dss.feat->clk_name);
+               if (IS_ERR(clk)) {
+                       DSSERR("Failed to get %s\n", dss.feat->clk_name);
+                       r = PTR_ERR(clk);
+                       goto err;
+               }
+       } else {
+               clk = NULL;
        }
 
        dss.dpll4_m4_ck = clk;
@@ -805,10 +809,10 @@ static int __init dss_init_features(struct device *dev)
 
        if (cpu_is_omap24xx())
                src = &omap24xx_dss_feats;
-       else if (cpu_is_omap34xx())
-               src = &omap34xx_dss_feats;
        else if (cpu_is_omap3630())
                src = &omap3630_dss_feats;
+       else if (cpu_is_omap34xx())
+               src = &omap34xx_dss_feats;
        else if (cpu_is_omap44xx())
                src = &omap44xx_dss_feats;
        else if (soc_is_omap54xx())
index a48a7dd75b3303a3bba28e10b01e4c1f133c00d3..8c9b8b3b7f773cd41c00f78b923070f87c325f70 100644 (file)
@@ -644,8 +644,10 @@ static void hdmi_dump_regs(struct seq_file *s)
 {
        mutex_lock(&hdmi.lock);
 
-       if (hdmi_runtime_get())
+       if (hdmi_runtime_get()) {
+               mutex_unlock(&hdmi.lock);
                return;
+       }
 
        hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
        hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
index 606b89f12351d4e1cc2cb234fd4e5c481bf82cda..d630b26a005c7ae2e0bea55b1c0a644fc64ad1e9 100644 (file)
@@ -787,7 +787,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        case OMAPFB_WAITFORVSYNC:
                DBG("ioctl WAITFORVSYNC\n");
-               if (!display && !display->output && !display->output->manager) {
+               if (!display || !display->output || !display->output->manager) {
                        r = -EINVAL;
                        break;
                }
index b7f5173ff9e94214ed40c3c40f4444324e128888..917bb5681684d31490e1b228b60db57cc0d53a7b 100644 (file)
@@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev,
        case XenbusStateReconfiguring:
        case XenbusStateReconfigured:
        case XenbusStateUnknown:
-       case XenbusStateClosed:
                break;
 
        case XenbusStateInitWait:
@@ -670,6 +669,10 @@ InitWait:
                info->feature_resize = val;
                break;
 
+       case XenbusStateClosed:
+               if (dev->state == XenbusStateClosed)
+                       break;
+               /* Missed the backend's CLOSING state -- fallthrough */
        case XenbusStateClosing:
                xenbus_frontend_closed(dev);
                break;
index 1e8659ca27ef4228d55e97ec5cbafc99d861b22a..809b0de59c0982cc30bca6d0b06b6229a5403c65 100644 (file)
@@ -225,8 +225,10 @@ EXPORT_SYMBOL_GPL(register_virtio_device);
 
 void unregister_virtio_device(struct virtio_device *dev)
 {
+       int index = dev->index; /* save for after device release */
+
        device_unregister(&dev->dev);
-       ida_simple_remove(&virtio_index_ida, dev->index);
+       ida_simple_remove(&virtio_index_ida, index);
 }
 EXPORT_SYMBOL_GPL(unregister_virtio_device);
 
index d4dffcd528730330a0d4cff238dcf0b56e3f318b..126d8ce591ce5fc7e69348f746e91e60b04bc4ee 100644 (file)
@@ -3,6 +3,7 @@ menu "Xen driver support"
 
 config XEN_BALLOON
        bool "Xen memory balloon driver"
+       depends on !ARM
        default y
        help
          The balloon driver allows the Xen domain to request more memory from
@@ -145,6 +146,7 @@ config SWIOTLB_XEN
 
 config XEN_TMEM
        bool
+       depends on !ARM
        default y if (CLEANCACHE || FRONTSWAP)
        help
          Shim to interface in-kernel Transcendent Memory hooks
index 0e86370354572ac7d4116eb70cf6e41d1a52cf35..74354708c6c4e7dd9040ead14affbfa88924ca74 100644 (file)
@@ -2,6 +2,7 @@ ifneq ($(CONFIG_ARM),y)
 obj-y  += manage.o balloon.o
 obj-$(CONFIG_HOTPLUG_CPU)              += cpu_hotplug.o
 endif
+obj-$(CONFIG_X86)                      += fallback.o
 obj-y  += grant-table.o features.o events.o
 obj-y  += xenbus/
 
index 31ab82fda38a264cd045c4b52c117eb375f8e80e..d6886d90ccfd53eed62773a755ee282e9553a55f 100644 (file)
@@ -55,7 +55,6 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/tlb.h>
-#include <asm/e820.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -88,7 +87,7 @@ struct balloon_stats balloon_stats;
 EXPORT_SYMBOL_GPL(balloon_stats);
 
 /* We increase/decrease in batches which fit in a page */
-static unsigned long frame_list[PAGE_SIZE / sizeof(unsigned long)];
+static xen_pfn_t frame_list[PAGE_SIZE / sizeof(unsigned long)];
 
 #ifdef CONFIG_HIGHMEM
 #define inc_totalhigh_pages() (totalhigh_pages++)
index 42569c77ccc8886d38b924a457489819d0dd53c4..f3ccc80a455f54c0abd15c1018f2fc79c7a0332a 100644 (file)
@@ -8,7 +8,9 @@
 
 static int xen_dbgp_op(struct usb_hcd *hcd, int op)
 {
+#ifdef CONFIG_PCI
        const struct device *ctrlr = hcd_to_bus(hcd)->controller;
+#endif
        struct physdev_dbgp_op dbgp;
 
        if (!xen_initial_domain())
index 59e10a1286d53ff73aa3e0a6c91a5aed9033de9e..0be4df39e953a5b870948e6ed8a1553a15cc2c2a 100644 (file)
@@ -115,7 +115,9 @@ struct irq_info {
 #define PIRQ_SHAREABLE (1 << 1)
 
 static int *evtchn_to_irq;
+#ifdef CONFIG_X86
 static unsigned long *pirq_eoi_map;
+#endif
 static bool (*pirq_needs_eoi)(unsigned irq);
 
 static DEFINE_PER_CPU(unsigned long [NR_EVENT_CHANNELS/BITS_PER_LONG],
@@ -277,10 +279,12 @@ static unsigned int cpu_from_evtchn(unsigned int evtchn)
        return ret;
 }
 
+#ifdef CONFIG_X86
 static bool pirq_check_eoi_map(unsigned irq)
 {
        return test_bit(pirq_from_irq(irq), pirq_eoi_map);
 }
+#endif
 
 static bool pirq_needs_eoi_flag(unsigned irq)
 {
@@ -1391,10 +1395,10 @@ void xen_evtchn_do_upcall(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 
+       irq_enter();
 #ifdef CONFIG_X86
        exit_idle();
 #endif
-       irq_enter();
 
        __xen_evtchn_do_upcall();
 
diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c
new file mode 100644 (file)
index 0000000..0ef7c4d
--- /dev/null
@@ -0,0 +1,80 @@
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <asm/hypervisor.h>
+#include <asm/xen/hypercall.h>
+
+int xen_event_channel_op_compat(int cmd, void *arg)
+{
+       struct evtchn_op op;
+       int rc;
+
+       op.cmd = cmd;
+       memcpy(&op.u, arg, sizeof(op.u));
+       rc = _hypercall1(int, event_channel_op_compat, &op);
+
+       switch (cmd) {
+       case EVTCHNOP_close:
+       case EVTCHNOP_send:
+       case EVTCHNOP_bind_vcpu:
+       case EVTCHNOP_unmask:
+               /* no output */
+               break;
+
+#define COPY_BACK(eop) \
+       case EVTCHNOP_##eop: \
+               memcpy(arg, &op.u.eop, sizeof(op.u.eop)); \
+               break
+
+       COPY_BACK(bind_interdomain);
+       COPY_BACK(bind_virq);
+       COPY_BACK(bind_pirq);
+       COPY_BACK(status);
+       COPY_BACK(alloc_unbound);
+       COPY_BACK(bind_ipi);
+#undef COPY_BACK
+
+       default:
+               WARN_ON(rc != -ENOSYS);
+               break;
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
+
+int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
+{
+       struct physdev_op op;
+       int rc;
+
+       op.cmd = cmd;
+       memcpy(&op.u, arg, sizeof(op.u));
+       rc = _hypercall1(int, physdev_op_compat, &op);
+
+       switch (cmd) {
+       case PHYSDEVOP_IRQ_UNMASK_NOTIFY:
+       case PHYSDEVOP_set_iopl:
+       case PHYSDEVOP_set_iobitmap:
+       case PHYSDEVOP_apic_write:
+               /* no output */
+               break;
+
+#define COPY_BACK(pop, fld) \
+       case PHYSDEVOP_##pop: \
+               memcpy(arg, &op.u.fld, sizeof(op.u.fld)); \
+               break
+
+       COPY_BACK(irq_status_query, irq_status_query);
+       COPY_BACK(apic_read, apic_op);
+       COPY_BACK(ASSIGN_VECTOR, irq_op);
+#undef COPY_BACK
+
+       default:
+               WARN_ON(rc != -ENOSYS);
+               break;
+       }
+
+       return rc;
+}
index 610bfc6be17708594783d231d608c14651625376..2e22df2f7a3f8b57fe44ce8842b825602a012658 100644 (file)
@@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv,
 #endif
 }
 
+static void gntdev_free_map(struct grant_map *map)
+{
+       if (map == NULL)
+               return;
+
+       if (map->pages)
+               free_xenballooned_pages(map->count, map->pages);
+       kfree(map->pages);
+       kfree(map->grants);
+       kfree(map->map_ops);
+       kfree(map->unmap_ops);
+       kfree(map->kmap_ops);
+       kfree(map);
+}
+
 static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
 {
        struct grant_map *add;
@@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
        return add;
 
 err:
-       kfree(add->pages);
-       kfree(add->grants);
-       kfree(add->map_ops);
-       kfree(add->unmap_ops);
-       kfree(add->kmap_ops);
-       kfree(add);
+       gntdev_free_map(add);
        return NULL;
 }
 
@@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map)
                evtchn_put(map->notify.event);
        }
 
-       if (map->pages) {
-               if (!use_ptemod)
-                       unmap_grant_pages(map, 0, map->count);
-
-               free_xenballooned_pages(map->count, map->pages);
-       }
-       kfree(map->pages);
-       kfree(map->grants);
-       kfree(map->map_ops);
-       kfree(map->unmap_ops);
-       kfree(map);
+       if (map->pages && !use_ptemod)
+               unmap_grant_pages(map, 0, map->count);
+       gntdev_free_map(map);
 }
 
 /* ------------------------------------------------------------------ */
index b2b0a375b3484b162b0c2ebc6cd09d5584f8ec60..b91f14e831648e68093a02f804f82e4113325360 100644 (file)
@@ -84,7 +84,7 @@ struct gnttab_ops {
         * nr_gframes is the number of frames to map grant table. Returning
         * GNTST_okay means success and negative value means failure.
         */
-       int (*map_frames)(unsigned long *frames, unsigned int nr_gframes);
+       int (*map_frames)(xen_pfn_t *frames, unsigned int nr_gframes);
        /*
         * Release a list of frames which are mapped in map_frames for grant
         * entry status.
@@ -960,7 +960,7 @@ static unsigned nr_status_frames(unsigned nr_grant_frames)
        return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
 }
 
-static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        int rc;
 
@@ -977,7 +977,7 @@ static void gnttab_unmap_frames_v1(void)
        arch_gnttab_unmap(gnttab_shared.addr, nr_grant_frames);
 }
 
-static int gnttab_map_frames_v2(unsigned long *frames, unsigned int nr_gframes)
+static int gnttab_map_frames_v2(xen_pfn_t *frames, unsigned int nr_gframes)
 {
        uint64_t *sframes;
        unsigned int nr_sframes;
@@ -1029,7 +1029,7 @@ static void gnttab_unmap_frames_v2(void)
 static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
 {
        struct gnttab_setup_table setup;
-       unsigned long *frames;
+       xen_pfn_t *frames;
        unsigned int nr_gframes = end_idx + 1;
        int rc;
 
index 8adb9cc267f96e201ade041441ef8a317ce336d8..71f5c459b088aa5e21066b77adbcb5f34f7b9843 100644 (file)
@@ -361,13 +361,13 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
        down_write(&mm->mmap_sem);
 
        vma = find_vma(mm, m.addr);
-       ret = -EINVAL;
        if (!vma ||
            vma->vm_ops != &privcmd_vm_ops ||
            (m.addr != vma->vm_start) ||
            ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
            !privcmd_enforce_singleshot_mapping(vma)) {
                up_write(&mm->mmap_sem);
+               ret = -EINVAL;
                goto out;
        }
 
@@ -383,12 +383,16 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
 
        up_write(&mm->mmap_sem);
 
-       if (state.global_error && (version == 1)) {
-               /* Write back errors in second pass. */
-               state.user_mfn = (xen_pfn_t *)m.arr;
-               state.err      = err_array;
-               ret = traverse_pages(m.num, sizeof(xen_pfn_t),
-                                    &pagelist, mmap_return_errors_v1, &state);
+       if (version == 1) {
+               if (state.global_error) {
+                       /* Write back errors in second pass. */
+                       state.user_mfn = (xen_pfn_t *)m.arr;
+                       state.err      = err_array;
+                       ret = traverse_pages(m.num, sizeof(xen_pfn_t),
+                                            &pagelist, mmap_return_errors_v1, &state);
+               } else
+                       ret = 0;
+
        } else if (version == 2) {
                ret = __copy_to_user(m.err, err_array, m.num * sizeof(int));
                if (ret)
index 5e5ad7e2885832f64f2131aa43aead50548cae0a..96453f8a85c5543f506ecc128f22e91b3d2dbdbb 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/kobject.h>
+#include <linux/err.h>
 
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
@@ -284,7 +285,8 @@ static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
                ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
                                             parms);
                if (!ret)
-                       ret = sprintf(buffer, "%lx\n", parms->virt_start);
+                       ret = sprintf(buffer, "%"PRI_xen_ulong"\n",
+                                     parms->virt_start);
                kfree(parms);
        }
 
index 46d140baebd8770463b9d37399f5149220920532..0f478ac483cd418e1a8a0b84fdb1b35651ce6404 100644 (file)
@@ -89,9 +89,15 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
 
        mutex_lock(&vpci_dev->lock);
 
-       /* Keep multi-function devices together on the virtual PCI bus */
-       for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
-               if (!list_empty(&vpci_dev->dev_list[slot])) {
+       /*
+        * Keep multi-function devices together on the virtual PCI bus, except
+        * virtual functions.
+        */
+       if (!dev->is_virtfn) {
+               for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
+                       if (list_empty(&vpci_dev->dev_list[slot]))
+                               continue;
+
                        t = list_entry(list_first(&vpci_dev->dev_list[slot]),
                                       struct pci_dev_entry, list);
 
@@ -116,7 +122,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
                               pci_name(dev), slot);
                        list_add_tail(&dev_entry->list,
                                      &vpci_dev->dev_list[slot]);
-                       func = PCI_FUNC(dev->devfn);
+                       func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn);
                        goto unlock;
                }
        }
index 89f76252a16f20e2638ee578faf4e3cbb4a316c6..ac727028e658f75778fa916ca94e91c5d80e0737 100644 (file)
@@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp,
                goto out;
 
        /* Can't write a xenbus message larger we can buffer */
-       if ((len + u->len) > sizeof(u->u.buffer)) {
+       if (len > sizeof(u->u.buffer) - u->len) {
                /* On error, dump existing buffer */
                u->len = 0;
                rc = -EINVAL;
index 48220e129f854435292065c5e928f95d982a4ad3..acedeabe589c94eaecd5ab5d478f7e7b3bfbe4af 100644 (file)
@@ -625,8 +625,9 @@ static struct xenbus_watch *find_watch(const char *token)
  * so if we are running on anything older than 4 do not attempt to read
  * control/platform-feature-xs_reset_watches.
  */
-static bool xen_strict_xenbus_quirk()
+static bool xen_strict_xenbus_quirk(void)
 {
+#ifdef CONFIG_X86
        uint32_t eax, ebx, ecx, edx, base;
 
        base = xen_cpuid_base();
@@ -634,6 +635,7 @@ static bool xen_strict_xenbus_quirk()
 
        if ((eax >> 16) < 4)
                return true;
+#endif
        return false;
 
 }
index 9298c65ad9c74bb1c4adde9ef9ffa07b397ca63f..b96fc6ce485595f0179bc909c807ae197258e671 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -75,6 +75,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
        unsigned int sz = sizeof(struct bio) + extra_size;
        struct kmem_cache *slab = NULL;
        struct bio_slab *bslab, *new_bio_slabs;
+       unsigned int new_bio_slab_max;
        unsigned int i, entry = -1;
 
        mutex_lock(&bio_slab_lock);
@@ -97,12 +98,13 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
                goto out_unlock;
 
        if (bio_slab_nr == bio_slab_max && entry == -1) {
-               bio_slab_max <<= 1;
+               new_bio_slab_max = bio_slab_max << 1;
                new_bio_slabs = krealloc(bio_slabs,
-                                        bio_slab_max * sizeof(struct bio_slab),
+                                        new_bio_slab_max * sizeof(struct bio_slab),
                                         GFP_KERNEL);
                if (!new_bio_slabs)
                        goto out_unlock;
+               bio_slab_max = new_bio_slab_max;
                bio_slabs = new_bio_slabs;
        }
        if (entry == -1)
index b3c1d3dae77d06fcde3fa3ecf36b2af9e2b25d85..1a1e5e3b1eafc7f00454cb2d544b8761161d015e 100644 (file)
@@ -1661,6 +1661,39 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
        return ret;
 }
 
+static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos,
+                                 struct pipe_inode_info *pipe, size_t len,
+                                 unsigned int flags)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_splice_read(file, ppos, pipe, len, flags);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
+static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe,
+                                  struct file *file, loff_t *ppos, size_t len,
+                                  unsigned int flags)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_splice_write(pipe, file, ppos, len, flags);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
+
 /*
  * Try to release a page associated with block device when the system
  * is under memory pressure.
@@ -1699,8 +1732,8 @@ const struct file_operations def_blk_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
-       .splice_read    = generic_file_splice_read,
-       .splice_write   = generic_file_splice_write,
+       .splice_read    = blkdev_splice_read,
+       .splice_write   = blkdev_splice_write,
 };
 
 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
index f3187938e081c7dcbf842d424f5de6ed06d3f93f..208d8aa5b07e488f1f39cb0877ff46bb5d08d5a6 100644 (file)
@@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
                goto out;
        }
 
-       rcu_read_lock();
-       root_level = btrfs_header_level(root->node);
-       rcu_read_unlock();
+       root_level = btrfs_old_root_level(root, time_seq);
 
        if (root_level + 1 == level)
                goto out;
@@ -1177,16 +1175,15 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid,
        return ret;
 }
 
-static char *ref_to_path(struct btrfs_root *fs_root,
-                        struct btrfs_path *path,
-                        u32 name_len, unsigned long name_off,
-                        struct extent_buffer *eb_in, u64 parent,
-                        char *dest, u32 size)
+char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                       u32 name_len, unsigned long name_off,
+                       struct extent_buffer *eb_in, u64 parent,
+                       char *dest, u32 size)
 {
        int slot;
        u64 next_inum;
        int ret;
-       s64 bytes_left = size - 1;
+       s64 bytes_left = ((s64)size) - 1;
        struct extent_buffer *eb = eb_in;
        struct btrfs_key found_key;
        int leave_spinning = path->leave_spinning;
@@ -1266,10 +1263,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root,
                         struct extent_buffer *eb_in, u64 parent,
                         char *dest, u32 size)
 {
-       return ref_to_path(fs_root, path,
-                          btrfs_inode_ref_name_len(eb_in, iref),
-                          (unsigned long)(iref + 1),
-                          eb_in, parent, dest, size);
+       return btrfs_ref_to_path(fs_root, path,
+                                btrfs_inode_ref_name_len(eb_in, iref),
+                                (unsigned long)(iref + 1),
+                                eb_in, parent, dest, size);
 }
 
 /*
@@ -1715,9 +1712,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off,
                                        ipath->fspath->bytes_left - s_ptr : 0;
 
        fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr;
-       fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
-                            name_off, eb, inum, fspath_min,
-                            bytes_left);
+       fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len,
+                                  name_off, eb, inum, fspath_min, bytes_left);
        if (IS_ERR(fspath))
                return PTR_ERR(fspath);
 
index e75533043a5ffbab21ff133877c352b743ef6592..d61feca79455bda94308c9ab3608b23409a84c73 100644 (file)
@@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans,
 char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
                         struct btrfs_inode_ref *iref, struct extent_buffer *eb,
                         u64 parent, char *dest, u32 size);
+char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
+                       u32 name_len, unsigned long name_off,
+                       struct extent_buffer *eb_in, u64 parent,
+                       char *dest, u32 size);
 
 struct btrfs_data_container *init_data_container(u32 total_bytes);
 struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root,
index b334362110003165a72b63433b192f2b481c3b01..cdfb4c49a806ad4ba0ebe83b5569a4121a10a220 100644 (file)
@@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, eb))
                return 0;
 
+       /*
+        * When we override something during the move, we log these removals.
+        * This can only happen when we move towards the beginning of the
+        * buffer, i.e. dst_slot < src_slot.
+        */
        for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) {
                ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot,
                                              MOD_LOG_KEY_REMOVE_WHILE_MOVING);
@@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, NULL))
                return 0;
 
-       __tree_mod_log_free_eb(fs_info, old_root);
-
        ret = tree_mod_alloc(fs_info, flags, &tm);
        if (ret < 0)
                goto out;
@@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                        ret = btrfs_dec_ref(trans, root, buf, 1, 1);
                        BUG_ON(ret); /* -ENOMEM */
                }
-               /*
-                * don't log freeing in case we're freeing the root node, this
-                * is done by tree_mod_log_set_root_pointer later
-                */
-               if (buf != root->node && btrfs_header_level(buf) != 0)
-                       tree_mod_log_free_eb(root->fs_info, buf);
+               tree_mod_log_free_eb(root->fs_info, buf);
                clean_tree_block(trans, root, buf);
                *last_ref = 1;
        }
@@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb,
        free_extent_buffer(eb);
 
        __tree_mod_log_rewind(eb_rewin, time_seq, tm);
+       WARN_ON(btrfs_header_nritems(eb_rewin) >
+               BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root));
 
        return eb_rewin;
 }
@@ -1241,9 +1241,11 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
 {
        struct tree_mod_elem *tm;
        struct extent_buffer *eb;
+       struct extent_buffer *old;
        struct tree_mod_root *old_root = NULL;
        u64 old_generation = 0;
        u64 logical;
+       u32 blocksize;
 
        eb = btrfs_read_lock_root_node(root);
        tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
@@ -1259,14 +1261,32 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
        }
 
        tm = tree_mod_log_search(root->fs_info, logical, time_seq);
-       if (old_root)
+       if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) {
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
+               blocksize = btrfs_level_size(root, old_root->level);
+               old = read_tree_block(root, logical, blocksize, 0);
+               if (!old) {
+                       pr_warn("btrfs: failed to read tree block %llu from get_old_root\n",
+                               logical);
+                       WARN_ON(1);
+               } else {
+                       eb = btrfs_clone_extent_buffer(old);
+                       free_extent_buffer(old);
+               }
+       } else if (old_root) {
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
                eb = alloc_dummy_extent_buffer(logical, root->nodesize);
-       else
+       } else {
                eb = btrfs_clone_extent_buffer(root->node);
-       btrfs_tree_read_unlock(root->node);
-       free_extent_buffer(root->node);
+               btrfs_tree_read_unlock(root->node);
+               free_extent_buffer(root->node);
+       }
+
        if (!eb)
                return NULL;
+       extent_buffer_get(eb);
        btrfs_tree_read_lock(eb);
        if (old_root) {
                btrfs_set_header_bytenr(eb, eb->start);
@@ -1279,11 +1299,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq)
                __tree_mod_log_rewind(eb, time_seq, tm);
        else
                WARN_ON(btrfs_header_level(eb) != 0);
-       extent_buffer_get(eb);
+       WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root));
 
        return eb;
 }
 
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq)
+{
+       struct tree_mod_elem *tm;
+       int level;
+
+       tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq);
+       if (tm && tm->op == MOD_LOG_ROOT_REPLACE) {
+               level = tm->old_root.level;
+       } else {
+               rcu_read_lock();
+               level = btrfs_header_level(root->node);
+               rcu_read_unlock();
+       }
+
+       return level;
+}
+
 static inline int should_cow_block(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
                                   struct extent_buffer *buf)
@@ -1725,6 +1762,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                        goto enospc;
                }
 
+               tree_mod_log_free_eb(root->fs_info, root->node);
                tree_mod_log_set_root_pointer(root, child);
                rcu_assign_pointer(root->node, child);
 
@@ -2970,8 +3008,10 @@ static int push_node_left(struct btrfs_trans_handle *trans,
                           push_items * sizeof(struct btrfs_key_ptr));
 
        if (push_items < src_nritems) {
-               tree_mod_log_eb_move(root->fs_info, src, 0, push_items,
-                                    src_nritems - push_items);
+               /*
+                * don't call tree_mod_log_eb_move here, key removal was already
+                * fully logged by tree_mod_log_eb_copy above.
+                */
                memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0),
                                      btrfs_node_key_ptr_offset(push_items),
                                      (src_nritems - push_items) *
index 926c9ffc66d93324d155481c4ecba13d27fa3fec..c72ead869507412ac9939c0748a482035baaf2aa 100644 (file)
@@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info)
 {
        return atomic_inc_return(&fs_info->tree_mod_seq);
 }
+int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq);
 
 /* root-item.c */
 int btrfs_find_root_ref(struct btrfs_root *tree_root,
@@ -3338,6 +3339,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page,
 int btrfs_update_inode(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root,
                              struct inode *inode);
+int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode);
 int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode);
 int btrfs_orphan_cleanup(struct btrfs_root *root);
index 8036d3a848530daed167453ebfb68eb8a83950f3..472873a94d969a86967e832eac2d452f274f11f9 100644 (file)
@@ -4110,8 +4110,8 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len)
 
        return eb;
 err:
-       for (i--; i >= 0; i--)
-               __free_page(eb->pages[i]);
+       for (; i > 0; i--)
+               __free_page(eb->pages[i - 1]);
        __free_extent_buffer(eb);
        return NULL;
 }
index 85a1e5053fe63a9d8df6682da38198883e00bb22..95542a1b3dfc99632219310f0108788789247fc9 100644 (file)
@@ -94,8 +94,6 @@ static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
                                   u64 start, u64 end, int *page_started,
                                   unsigned long *nr_written, int unlock);
-static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct inode *inode);
 
 static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
                                     struct inode *inode,  struct inode *dir,
@@ -2746,8 +2744,9 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
        return btrfs_update_inode_item(trans, root, inode);
 }
 
-static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct inode *inode)
+noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                                        struct btrfs_root *root,
+                                        struct inode *inode)
 {
        int ret;
 
index 61168805f175b3c50ffef99b87e97fdeb2643ebd..8fcf9a59c28d08c5c8a6c65e34844e321ca2b66c 100644 (file)
@@ -343,7 +343,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg)
                return -EOPNOTSUPP;
        if (copy_from_user(&range, arg, sizeof(range)))
                return -EFAULT;
-       if (range.start > total_bytes)
+       if (range.start > total_bytes ||
+           range.len < fs_info->sb->s_blocksize)
                return -EINVAL;
 
        range.len = min(range.len, total_bytes - range.start);
@@ -570,7 +571,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
                ret = btrfs_commit_transaction(trans,
                                               root->fs_info->extent_root);
        }
-       BUG_ON(ret);
+       if (ret)
+               goto fail;
 
        ret = pending_snapshot->error;
        if (ret)
index 5039686df6ae8e801ed8985eb5e821a226e18855..fe9d02c45f8e521f87b44d6deff3e5f8d99aa3a9 100644 (file)
@@ -790,8 +790,10 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        }
 
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               ret = -ENOMEM;
+               goto out_free_root;
+       }
 
        key.objectid = 0;
        key.type = BTRFS_QGROUP_STATUS_KEY;
@@ -800,7 +802,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        ret = btrfs_insert_empty_item(trans, quota_root, path, &key,
                                      sizeof(*ptr));
        if (ret)
-               goto out;
+               goto out_free_path;
 
        leaf = path->nodes[0];
        ptr = btrfs_item_ptr(leaf, path->slots[0],
@@ -818,8 +820,15 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans,
        fs_info->quota_root = quota_root;
        fs_info->pending_quota_state = 1;
        spin_unlock(&fs_info->qgroup_lock);
-out:
+out_free_path:
        btrfs_free_path(path);
+out_free_root:
+       if (ret) {
+               free_extent_buffer(quota_root->node);
+               free_extent_buffer(quota_root->commit_root);
+               kfree(quota_root);
+       }
+out:
        return ret;
 }
 
index c7beb543a4a89300f1e586492b767ea8f9bef683..e78b297b0b00cc990e8eb7a3f1f34619638e5ef4 100644 (file)
@@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index,
                                   void *ctx);
 
 /*
- * Helper function to iterate the entries in ONE btrfs_inode_ref.
+ * Helper function to iterate the entries in ONE btrfs_inode_ref or
+ * btrfs_inode_extref.
  * The iterate callback may return a non zero value to stop iteration. This can
  * be a negative value for error codes or 1 to simply stop it.
  *
- * path must point to the INODE_REF when called.
+ * path must point to the INODE_REF or INODE_EXTREF when called.
  */
 static int iterate_inode_ref(struct send_ctx *sctx,
                             struct btrfs_root *root, struct btrfs_path *path,
                             struct btrfs_key *found_key, int resolve,
                             iterate_inode_ref_t iterate, void *ctx)
 {
-       struct extent_buffer *eb;
+       struct extent_buffer *eb = path->nodes[0];
        struct btrfs_item *item;
        struct btrfs_inode_ref *iref;
+       struct btrfs_inode_extref *extref;
        struct btrfs_path *tmp_path;
        struct fs_path *p;
-       u32 cur;
-       u32 len;
+       u32 cur = 0;
        u32 total;
-       int slot;
+       int slot = path->slots[0];
        u32 name_len;
        char *start;
        int ret = 0;
-       int num;
+       int num = 0;
        int index;
+       u64 dir;
+       unsigned long name_off;
+       unsigned long elem_size;
+       unsigned long ptr;
 
        p = fs_path_alloc_reversed(sctx);
        if (!p)
@@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                return -ENOMEM;
        }
 
-       eb = path->nodes[0];
-       slot = path->slots[0];
-       item = btrfs_item_nr(eb, slot);
-       iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
-       cur = 0;
-       len = 0;
-       total = btrfs_item_size(eb, item);
 
-       num = 0;
+       if (found_key->type == BTRFS_INODE_REF_KEY) {
+               ptr = (unsigned long)btrfs_item_ptr(eb, slot,
+                                                   struct btrfs_inode_ref);
+               item = btrfs_item_nr(eb, slot);
+               total = btrfs_item_size(eb, item);
+               elem_size = sizeof(*iref);
+       } else {
+               ptr = btrfs_item_ptr_offset(eb, slot);
+               total = btrfs_item_size_nr(eb, slot);
+               elem_size = sizeof(*extref);
+       }
+
        while (cur < total) {
                fs_path_reset(p);
 
-               name_len = btrfs_inode_ref_name_len(eb, iref);
-               index = btrfs_inode_ref_index(eb, iref);
+               if (found_key->type == BTRFS_INODE_REF_KEY) {
+                       iref = (struct btrfs_inode_ref *)(ptr + cur);
+                       name_len = btrfs_inode_ref_name_len(eb, iref);
+                       name_off = (unsigned long)(iref + 1);
+                       index = btrfs_inode_ref_index(eb, iref);
+                       dir = found_key->offset;
+               } else {
+                       extref = (struct btrfs_inode_extref *)(ptr + cur);
+                       name_len = btrfs_inode_extref_name_len(eb, extref);
+                       name_off = (unsigned long)&extref->name;
+                       index = btrfs_inode_extref_index(eb, extref);
+                       dir = btrfs_inode_extref_parent(eb, extref);
+               }
+
                if (resolve) {
-                       start = btrfs_iref_to_path(root, tmp_path, iref, eb,
-                                               found_key->offset, p->buf,
-                                               p->buf_len);
+                       start = btrfs_ref_to_path(root, tmp_path, name_len,
+                                                 name_off, eb, dir,
+                                                 p->buf, p->buf_len);
                        if (IS_ERR(start)) {
                                ret = PTR_ERR(start);
                                goto out;
@@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                                                p->buf_len + p->buf - start);
                                if (ret < 0)
                                        goto out;
-                               start = btrfs_iref_to_path(root, tmp_path, iref,
-                                               eb, found_key->offset, p->buf,
-                                               p->buf_len);
+                               start = btrfs_ref_to_path(root, tmp_path,
+                                                         name_len, name_off,
+                                                         eb, dir,
+                                                         p->buf, p->buf_len);
                                if (IS_ERR(start)) {
                                        ret = PTR_ERR(start);
                                        goto out;
@@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx,
                        }
                        p->start = start;
                } else {
-                       ret = fs_path_add_from_extent_buffer(p, eb,
-                                       (unsigned long)(iref + 1), name_len);
+                       ret = fs_path_add_from_extent_buffer(p, eb, name_off,
+                                                            name_len);
                        if (ret < 0)
                                goto out;
                }
 
-
-               len = sizeof(*iref) + name_len;
-               iref = (struct btrfs_inode_ref *)((char *)iref + len);
-               cur += len;
-
-               ret = iterate(num, found_key->offset, index, p, ctx);
+               cur += elem_size + name_len;
+               ret = iterate(num, dir, index, p, ctx);
                if (ret)
                        goto out;
-
                num++;
        }
 
@@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root,
        }
        btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]);
        if (found_key.objectid != ino ||
-               found_key.type != BTRFS_INODE_REF_KEY) {
+           (found_key.type != BTRFS_INODE_REF_KEY &&
+            found_key.type != BTRFS_INODE_EXTREF_KEY)) {
                ret = -ENOENT;
                goto out;
        }
@@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx,
        struct btrfs_key key;
        struct btrfs_key found_key;
        struct btrfs_path *path;
-       struct btrfs_inode_ref *iref;
        int len;
+       u64 parent_dir;
 
        path = alloc_path_for_send();
        if (!path)
@@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx,
        if (!ret)
                btrfs_item_key_to_cpu(path->nodes[0], &found_key,
                                path->slots[0]);
-       if (ret || found_key.objectid != key.objectid ||
-           found_key.type != key.type) {
+       if (ret || found_key.objectid != ino ||
+           (found_key.type != BTRFS_INODE_REF_KEY &&
+            found_key.type != BTRFS_INODE_EXTREF_KEY)) {
                ret = -ENOENT;
                goto out;
        }
 
-       iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
-                       struct btrfs_inode_ref);
-       len = btrfs_inode_ref_name_len(path->nodes[0], iref);
-       ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
-                       (unsigned long)(iref + 1), len);
+       if (key.type == BTRFS_INODE_REF_KEY) {
+               struct btrfs_inode_ref *iref;
+               iref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                     struct btrfs_inode_ref);
+               len = btrfs_inode_ref_name_len(path->nodes[0], iref);
+               ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
+                                                    (unsigned long)(iref + 1),
+                                                    len);
+               parent_dir = found_key.offset;
+       } else {
+               struct btrfs_inode_extref *extref;
+               extref = btrfs_item_ptr(path->nodes[0], path->slots[0],
+                                       struct btrfs_inode_extref);
+               len = btrfs_inode_extref_name_len(path->nodes[0], extref);
+               ret = fs_path_add_from_extent_buffer(name, path->nodes[0],
+                                       (unsigned long)&extref->name, len);
+               parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref);
+       }
        if (ret < 0)
                goto out;
        btrfs_release_path(path);
 
-       ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL,
+       ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL,
                        NULL, NULL);
        if (ret < 0)
                goto out;
 
-       *dir = found_key.offset;
+       *dir = parent_dir;
 
 out:
        btrfs_free_path(path);
@@ -2430,7 +2462,8 @@ verbose_printk("btrfs: send_create_inode %llu\n", ino);
                TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p);
        } else if (S_ISCHR(mode) || S_ISBLK(mode) ||
                   S_ISFIFO(mode) || S_ISSOCK(mode)) {
-               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev);
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev));
+               TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode);
        }
 
        ret = send_cmd(sctx);
@@ -3226,7 +3259,8 @@ static int process_all_refs(struct send_ctx *sctx,
                btrfs_item_key_to_cpu(eb, &found_key, slot);
 
                if (found_key.objectid != key.objectid ||
-                   found_key.type != key.type)
+                   (found_key.type != BTRFS_INODE_REF_KEY &&
+                    found_key.type != BTRFS_INODE_EXTREF_KEY))
                        break;
 
                ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb,
@@ -3987,7 +4021,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end)
        if (sctx->cur_ino == 0)
                goto out;
        if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid &&
-           sctx->cmp_key->type <= BTRFS_INODE_REF_KEY)
+           sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY)
                goto out;
        if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs))
                goto out;
@@ -4033,22 +4067,21 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end)
        if (ret < 0)
                goto out;
 
-       if (!S_ISLNK(sctx->cur_inode_mode)) {
-               if (!sctx->parent_root || sctx->cur_inode_new) {
+       if (!sctx->parent_root || sctx->cur_inode_new) {
+               need_chown = 1;
+               if (!S_ISLNK(sctx->cur_inode_mode))
                        need_chmod = 1;
-                       need_chown = 1;
-               } else {
-                       ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
-                                       NULL, NULL, &right_mode, &right_uid,
-                                       &right_gid, NULL);
-                       if (ret < 0)
-                               goto out;
+       } else {
+               ret = get_inode_info(sctx->parent_root, sctx->cur_ino,
+                               NULL, NULL, &right_mode, &right_uid,
+                               &right_gid, NULL);
+               if (ret < 0)
+                       goto out;
 
-                       if (left_uid != right_uid || left_gid != right_gid)
-                               need_chown = 1;
-                       if (left_mode != right_mode)
-                               need_chmod = 1;
-               }
+               if (left_uid != right_uid || left_gid != right_gid)
+                       need_chown = 1;
+               if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode)
+                       need_chmod = 1;
        }
 
        if (S_ISREG(sctx->cur_inode_mode)) {
@@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root,
 
        if (key->type == BTRFS_INODE_ITEM_KEY)
                ret = changed_inode(sctx, result);
-       else if (key->type == BTRFS_INODE_REF_KEY)
+       else if (key->type == BTRFS_INODE_REF_KEY ||
+                key->type == BTRFS_INODE_EXTREF_KEY)
                ret = changed_ref(sctx, result);
        else if (key->type == BTRFS_XATTR_ITEM_KEY)
                ret = changed_xattr(sctx, result);
index 77db875b511638b7ff94854c6b1482942da2b3fb..04bbfb1052ebfee9db25427d5542e795cac351cd 100644 (file)
@@ -1200,7 +1200,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_i_size_write(parent_inode, parent_inode->i_size +
                                         dentry->d_name.len * 2);
        parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
-       ret = btrfs_update_inode(trans, parent_root, parent_inode);
+       ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode);
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
 fail:
index 029b903a4ae3797322e05090790b86c9e8596c43..0f5ebb72a5ea01693b339d66e3f928de9b783f78 100644 (file)
@@ -1819,6 +1819,13 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
                                    "Failed to relocate sys chunks after "
                                    "device initialization. This can be fixed "
                                    "using the \"btrfs balance\" command.");
+               trans = btrfs_attach_transaction(root);
+               if (IS_ERR(trans)) {
+                       if (PTR_ERR(trans) == -ENOENT)
+                               return 0;
+                       return PTR_ERR(trans);
+               }
+               ret = btrfs_commit_transaction(trans, root);
        }
 
        return ret;
index 02ce90972d81ca6e8b60ed580931c676c441fc2c..9349bb37a2fe68df93651e6afeb384468157edd2 100644 (file)
@@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
                *max_len = handle_length;
                type = 255;
        }
+       if (dentry)
+               dput(dentry);
        return type;
 }
 
index 3f152b92a94ad2824876fd99c9fbfdd05098d0cf..afc2bb6917806e85ee916d8b2c25cb2183890055 100644 (file)
@@ -471,9 +471,19 @@ static int exact_lock(dev_t dev, void *data)
  */
 int cdev_add(struct cdev *p, dev_t dev, unsigned count)
 {
+       int error;
+
        p->dev = dev;
        p->count = count;
-       return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
+
+       error = kobj_map(cdev_map, dev, count, NULL,
+                        exact_match, exact_lock, p);
+       if (error)
+               return error;
+
+       kobject_get(p->kobj.parent);
+
+       return 0;
 }
 
 static void cdev_unmap(dev_t dev, unsigned count)
@@ -498,14 +508,20 @@ void cdev_del(struct cdev *p)
 static void cdev_default_release(struct kobject *kobj)
 {
        struct cdev *p = container_of(kobj, struct cdev, kobj);
+       struct kobject *parent = kobj->parent;
+
        cdev_purge(p);
+       kobject_put(parent);
 }
 
 static void cdev_dynamic_release(struct kobject *kobj)
 {
        struct cdev *p = container_of(kobj, struct cdev, kobj);
+       struct kobject *parent = kobj->parent;
+
        cdev_purge(p);
        kfree(p);
+       kobject_put(parent);
 }
 
 static struct kobj_type ktype_cdev_default = {
index fc783e264420a890751aa81e819fc8b53aaa1a81..0fb15bbbe43cd955150336dec51b415ee1901c5a 100644 (file)
@@ -224,6 +224,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr)
        }
 }
 
+static void
+cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
+{
+       memcpy(dst, src, sizeof(*dst));
+       dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS);
+}
+
 static void
 id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
                struct cifs_sid_id **psidid, char *typestr)
@@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr,
                }
        }
 
-       memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid));
+       cifs_copy_sid(&(*psidid)->sid, sidptr);
        (*psidid)->time = jiffies - (SID_MAP_RETRY + 1);
        (*psidid)->refcount = 0;
 
@@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
         * any fields of the node after a reference is put .
         */
        if (test_bit(SID_ID_MAPPED, &psidid->state)) {
-               memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+               cifs_copy_sid(ssid, &psidid->sid);
                psidid->time = jiffies; /* update ts for accessing */
                goto id_sid_out;
        }
@@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                if (IS_ERR(sidkey)) {
                        rc = -EINVAL;
                        cFYI(1, "%s: Can't map and id to a SID", __func__);
+               } else if (sidkey->datalen < sizeof(struct cifs_sid)) {
+                       rc = -EIO;
+                       cFYI(1, "%s: Downcall contained malformed key "
+                               "(datalen=%hu)", __func__, sidkey->datalen);
                } else {
                        lsid = (struct cifs_sid *)sidkey->payload.data;
-                       memcpy(&psidid->sid, lsid,
-                               sidkey->datalen < sizeof(struct cifs_sid) ?
-                               sidkey->datalen : sizeof(struct cifs_sid));
-                       memcpy(ssid, &psidid->sid,
-                               sidkey->datalen < sizeof(struct cifs_sid) ?
-                               sidkey->datalen : sizeof(struct cifs_sid));
+                       cifs_copy_sid(&psidid->sid, lsid);
+                       cifs_copy_sid(ssid, &psidid->sid);
                        set_bit(SID_ID_MAPPED, &psidid->state);
                        key_put(sidkey);
                        kfree(psidid->sidstr);
@@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid)
                        return rc;
                }
                if (test_bit(SID_ID_MAPPED, &psidid->state))
-                       memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid));
+                       cifs_copy_sid(ssid, &psidid->sid);
                else
                        rc = -EINVAL;
        }
@@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
 static void copy_sec_desc(const struct cifs_ntsd *pntsd,
                                struct cifs_ntsd *pnntsd, __u32 sidsoffset)
 {
-       int i;
-
        struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
        struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 
@@ -692,26 +697,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd,
        owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->osidoffset));
        nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
-
-       nowner_sid_ptr->revision = owner_sid_ptr->revision;
-       nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
-       for (i = 0; i < 6; i++)
-               nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
-       for (i = 0; i < 5; i++)
-               nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
+       cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
 
        /* copy group sid */
        group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
                                le32_to_cpu(pntsd->gsidoffset));
        ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
                                        sizeof(struct cifs_sid));
-
-       ngroup_sid_ptr->revision = group_sid_ptr->revision;
-       ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
-       for (i = 0; i < 6; i++)
-               ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
-       for (i = 0; i < 5; i++)
-               ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
+       cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
 
        return;
 }
@@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                                kfree(nowner_sid_ptr);
                                return rc;
                        }
-                       memcpy(owner_sid_ptr, nowner_sid_ptr,
-                                       sizeof(struct cifs_sid));
+                       cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
                        kfree(nowner_sid_ptr);
                        *aclflag = CIFS_ACL_OWNER;
                }
@@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
                                kfree(ngroup_sid_ptr);
                                return rc;
                        }
-                       memcpy(group_sid_ptr, ngroup_sid_ptr,
-                                       sizeof(struct cifs_sid));
+                       cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
                        kfree(ngroup_sid_ptr);
                        *aclflag = CIFS_ACL_GROUP;
                }
index 7c0a8128364546111322b4a89caef9009a276980..d3671f2acb29bd313779cf8022efe4c41e9987ef 100644 (file)
@@ -398,7 +398,16 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
         * in network traffic in the other paths.
         */
        if (!(oflags & O_CREAT)) {
-               struct dentry *res = cifs_lookup(inode, direntry, 0);
+               struct dentry *res;
+
+               /*
+                * Check for hashed negative dentry. We have already revalidated
+                * the dentry and it is fine. No need to perform another lookup.
+                */
+               if (!d_unhashed(direntry))
+                       return -ENOENT;
+
+               res = cifs_lookup(inode, direntry, 0);
                if (IS_ERR(res))
                        return PTR_ERR(res);
 
index f5054025f9da7c154b067db092cc44f8b953f835..4c6285fff598e1faf9bb471f8b3b5593db74b355 100644 (file)
@@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd,
 
        err  = get_user(palp, &up->palette);
        err |= get_user(length, &up->length);
+       if (err)
+               return -EFAULT;
 
        up_native = compat_alloc_user_space(sizeof(struct video_spu_palette));
        err  = put_user(compat_ptr(palp), &up_native->palette);
index fd37facac8dc55f40281008ceb6799c667105588..ce47379bfa61cfecb7bc747d3fbc7031a65f3080 100644 (file)
@@ -450,11 +450,12 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
 
        cp->file = files[1];
 
-       replace_fd(0, files[0], 0);
+       err = replace_fd(0, files[0], 0);
+       fput(files[0]);
        /* and disallow core files too */
        current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1};
 
-       return 0;
+       return err;
 }
 
 void do_coredump(siginfo_t *siginfo, struct pt_regs *regs)
index da72250ddc1cf2331336a23cbe8239bf880a10cf..cd96649bfe62da9e408dbd629f56f6452c139bc9 100644 (file)
@@ -346,7 +346,7 @@ static inline struct epitem *ep_item_from_epqueue(poll_table *p)
 /* Tells if the epoll_ctl(2) operation needs an event copy from userspace */
 static inline int ep_op_has_event(int op)
 {
-       return op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD;
+       return op != EPOLL_CTL_DEL;
 }
 
 /* Initialize the poll safe wake up structure */
@@ -676,34 +676,6 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
        return 0;
 }
 
-/*
- * Disables a "struct epitem" in the eventpoll set. Returns -EBUSY if the item
- * had no event flags set, indicating that another thread may be currently
- * handling that item's events (in the case that EPOLLONESHOT was being
- * used). Otherwise a zero result indicates that the item has been disabled
- * from receiving events. A disabled item may be re-enabled via
- * EPOLL_CTL_MOD. Must be called with "mtx" held.
- */
-static int ep_disable(struct eventpoll *ep, struct epitem *epi)
-{
-       int result = 0;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ep->lock, flags);
-       if (epi->event.events & ~EP_PRIVATE_BITS) {
-               if (ep_is_linked(&epi->rdllink))
-                       list_del_init(&epi->rdllink);
-               /* Ensure ep_poll_callback will not add epi back onto ready
-                  list: */
-               epi->event.events &= EP_PRIVATE_BITS;
-               }
-       else
-               result = -EBUSY;
-       spin_unlock_irqrestore(&ep->lock, flags);
-
-       return result;
-}
-
 static void ep_free(struct eventpoll *ep)
 {
        struct rb_node *rbp;
@@ -1048,6 +1020,8 @@ static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
        rb_insert_color(&epi->rbn, &ep->rbr);
 }
 
+
+
 #define PATH_ARR_SIZE 5
 /*
  * These are the number paths of length 1 to 5, that we are allowing to emanate
@@ -1813,12 +1787,6 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
                } else
                        error = -ENOENT;
                break;
-       case EPOLL_CTL_DISABLE:
-               if (epi)
-                       error = ep_disable(ep, epi);
-               else
-                       error = -ENOENT;
-               break;
        }
        mutex_unlock(&ep->mtx);
 
index 8b9011b67041ddcd57dbcc42e77fa7d0d8b05f7e..0039055b1fc6533c636ca98dd2b9ad73b52d5de6 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1083,7 +1083,8 @@ int flush_old_exec(struct linux_binprm * bprm)
        bprm->mm = NULL;                /* We're using it now */
 
        set_fs(USER_DS);
-       current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD);
+       current->flags &=
+               ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE);
        flush_thread();
        current->personality &= ~bprm->per_clear;
 
index 6c205d0c565b2595fe837eab5cf789d995df2d18..fa04d023177e71dcd8376adfbc097d2ddb4ee3ae 100644 (file)
@@ -469,7 +469,7 @@ static int parse_options(char *options, struct super_block *sb)
                        uid = make_kuid(current_user_ns(), option);
                        if (!uid_valid(uid)) {
                                ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option);
-                               return -1;
+                               return 0;
 
                        }
                        sbi->s_resuid = uid;
@@ -480,7 +480,7 @@ static int parse_options(char *options, struct super_block *sb)
                        gid = make_kgid(current_user_ns(), option);
                        if (!gid_valid(gid)) {
                                ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option);
-                               return -1;
+                               return 0;
                        }
                        sbi->s_resgid = gid;
                        break;
index 7320a66e958f8d45e796c796ee150b786c3f7f8e..22548f56197b52cf06b343285b7e7beb7d74cb10 100644 (file)
@@ -2101,8 +2101,9 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
        end = start + (range->len >> sb->s_blocksize_bits) - 1;
        minlen = range->minlen >> sb->s_blocksize_bits;
 
-       if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) ||
-           unlikely(start >= max_blks))
+       if (minlen > EXT3_BLOCKS_PER_GROUP(sb) ||
+           start >= max_blks ||
+           range->len < sb->s_blocksize)
                return -EINVAL;
        if (end >= max_blks)
                end = max_blks - 1;
index 8f4fddac01a679456c8ef867d0a2e33f6592cbee..890b8947c5468b863327e87985ef42334f53fa74 100644 (file)
@@ -46,8 +46,7 @@ static struct buffer_head *ext3_append(handle_t *handle,
 
        *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
 
-       bh = ext3_bread(handle, inode, *block, 1, err);
-       if (bh) {
+       if ((bh = ext3_dir_bread(handle, inode, *block, 1, err))) {
                inode->i_size += inode->i_sb->s_blocksize;
                EXT3_I(inode)->i_disksize = inode->i_size;
                *err = ext3_journal_get_write_access(handle, bh);
@@ -339,8 +338,10 @@ dx_probe(struct qstr *entry, struct inode *dir,
        u32 hash;
 
        frame->bh = NULL;
-       if (!(bh = ext3_bread (NULL,dir, 0, 0, err)))
+       if (!(bh = ext3_dir_bread(NULL, dir, 0, 0, err))) {
+               *err = ERR_BAD_DX_DIR;
                goto fail;
+       }
        root = (struct dx_root *) bh->b_data;
        if (root->info.hash_version != DX_HASH_TEA &&
            root->info.hash_version != DX_HASH_HALF_MD4 &&
@@ -436,8 +437,10 @@ dx_probe(struct qstr *entry, struct inode *dir,
                frame->entries = entries;
                frame->at = at;
                if (!indirect--) return frame;
-               if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err)))
+               if (!(bh = ext3_dir_bread(NULL, dir, dx_get_block(at), 0, err))) {
+                       *err = ERR_BAD_DX_DIR;
                        goto fail2;
+               }
                at = entries = ((struct dx_node *) bh->b_data)->entries;
                if (dx_get_limit(entries) != dx_node_limit (dir)) {
                        ext3_warning(dir->i_sb, __func__,
@@ -535,8 +538,8 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash,
         * block so no check is necessary
         */
        while (num_frames--) {
-               if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at),
-                                     0, &err)))
+               if (!(bh = ext3_dir_bread(NULL, dir, dx_get_block(p->at),
+                                         0, &err)))
                        return err; /* Failure */
                p++;
                brelse (p->bh);
@@ -559,10 +562,11 @@ static int htree_dirblock_to_tree(struct file *dir_file,
 {
        struct buffer_head *bh;
        struct ext3_dir_entry_2 *de, *top;
-       int err, count = 0;
+       int err = 0, count = 0;
 
        dxtrace(printk("In htree dirblock_to_tree: block %d\n", block));
-       if (!(bh = ext3_bread (NULL, dir, block, 0, &err)))
+
+       if (!(bh = ext3_dir_bread(NULL, dir, block, 0, &err)))
                return err;
 
        de = (struct ext3_dir_entry_2 *) bh->b_data;
@@ -976,7 +980,7 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir,
                return NULL;
        do {
                block = dx_get_block(frame->at);
-               if (!(bh = ext3_bread (NULL,dir, block, 0, err)))
+               if (!(bh = ext3_dir_bread (NULL, dir, block, 0, err)))
                        goto errout;
 
                retval = search_dirblock(bh, dir, entry,
@@ -1458,9 +1462,9 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
        }
        blocks = dir->i_size >> sb->s_blocksize_bits;
        for (block = 0; block < blocks; block++) {
-               bh = ext3_bread(handle, dir, block, 0, &retval);
-               if(!bh)
+               if (!(bh = ext3_dir_bread(handle, dir, block, 0, &retval)))
                        return retval;
+
                retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
                if (retval != -ENOSPC)
                        return retval;
@@ -1500,7 +1504,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry,
        entries = frame->entries;
        at = frame->at;
 
-       if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err)))
+       if (!(bh = ext3_dir_bread(handle, dir, dx_get_block(frame->at), 0, &err)))
                goto cleanup;
 
        BUFFER_TRACE(bh, "get_write_access");
@@ -1790,8 +1794,7 @@ retry:
        inode->i_op = &ext3_dir_inode_operations;
        inode->i_fop = &ext3_dir_operations;
        inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize;
-       dir_block = ext3_bread (handle, inode, 0, 1, &err);
-       if (!dir_block)
+       if (!(dir_block = ext3_dir_bread(handle, inode, 0, 1, &err)))
                goto out_clear_inode;
 
        BUFFER_TRACE(dir_block, "get_write_access");
@@ -1859,7 +1862,7 @@ static int empty_dir (struct inode * inode)
 
        sb = inode->i_sb;
        if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) ||
-           !(bh = ext3_bread (NULL, inode, 0, 0, &err))) {
+           !(bh = ext3_dir_bread(NULL, inode, 0, 0, &err))) {
                if (err)
                        ext3_error(inode->i_sb, __func__,
                                   "error %d reading directory #%lu offset 0",
@@ -1890,9 +1893,8 @@ static int empty_dir (struct inode * inode)
                        (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
                        err = 0;
                        brelse (bh);
-                       bh = ext3_bread (NULL, inode,
-                               offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err);
-                       if (!bh) {
+                       if (!(bh = ext3_dir_bread (NULL, inode,
+                               offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err))) {
                                if (err)
                                        ext3_error(sb, __func__,
                                                   "error %d reading directory"
@@ -2388,7 +2390,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry,
                                goto end_rename;
                }
                retval = -EIO;
-               dir_bh = ext3_bread (handle, old_inode, 0, 0, &retval);
+               dir_bh = ext3_dir_bread(handle, old_inode, 0, 0, &retval);
                if (!dir_bh)
                        goto end_rename;
                if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino)
index f2ce2b0065c944640cac8f30361db7b9cbb29c04..46304d8c9f0a05d60dd7c31b65dc42ce311c4cb9 100644 (file)
@@ -6,3 +6,22 @@
 */
 
 extern struct dentry *ext3_get_parent(struct dentry *child);
+
+static inline struct buffer_head *ext3_dir_bread(handle_t *handle,
+                                                struct inode *inode,
+                                                int block, int create,
+                                                int *err)
+{
+       struct buffer_head *bh;
+
+       bh = ext3_bread(handle, inode, block, create, err);
+
+       if (!bh && !(*err)) {
+               *err = -EIO;
+               ext3_error(inode->i_sb, __func__,
+                          "Directory hole detected on inode %lu\n",
+                          inode->i_ino);
+               return NULL;
+       }
+       return bh;
+}
index 29e79713c7eb6ccd37eac31c20c02fb5fd826744..5366393528dfbd622120549729cf22a891026f44 100644 (file)
@@ -1001,7 +1001,7 @@ static int parse_options (char *options, struct super_block *sb,
                        uid = make_kuid(current_user_ns(), option);
                        if (!uid_valid(uid)) {
                                ext3_msg(sb, KERN_ERR, "Invalid uid value %d", option);
-                               return -1;
+                               return 0;
 
                        }
                        sbi->s_resuid = uid;
@@ -1012,7 +1012,7 @@ static int parse_options (char *options, struct super_block *sb,
                        gid = make_kgid(current_user_ns(), option);
                        if (!gid_valid(gid)) {
                                ext3_msg(sb, KERN_ERR, "Invalid gid value %d", option);
-                               return -1;
+                               return 0;
                        }
                        sbi->s_resgid = gid;
                        break;
index 1b5089067d018d581c68242f39fcf522a8fee55d..cf1821784a16bff41349319400940c7e4218fa5a 100644 (file)
@@ -174,8 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
                ext4_free_inodes_set(sb, gdp, 0);
                ext4_itable_unused_set(sb, gdp, 0);
                memset(bh->b_data, 0xff, sb->s_blocksize);
-               ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-                                          EXT4_BLOCKS_PER_GROUP(sb) / 8);
+               ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
                return;
        }
        memset(bh->b_data, 0, sb->s_blocksize);
@@ -212,8 +211,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh,
         */
        ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group),
                             sb->s_blocksize * 8, bh->b_data);
-       ext4_block_bitmap_csum_set(sb, block_group, gdp, bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
 }
 
@@ -350,7 +348,7 @@ void ext4_validate_block_bitmap(struct super_block *sb,
                return;
        }
        if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group,
-                       desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) {
+                       desc, bh))) {
                ext4_unlock_group(sb, block_group);
                ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
                return;
index 5c2d1813ebe919188d53dac74de8b512a7f02965..3285aa5a706af3f97c6a182a12304c7478177d9d 100644 (file)
@@ -58,11 +58,12 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
 
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct ext4_group_desc *gdp,
-                                 struct buffer_head *bh, int sz)
+                                 struct buffer_head *bh)
 {
        __u32 hi;
        __u32 provided, calculated;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
+       int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
 
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
                                        EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
@@ -84,8 +85,9 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
 
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
                                struct ext4_group_desc *gdp,
-                               struct buffer_head *bh, int sz)
+                               struct buffer_head *bh)
 {
+       int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8;
        __u32 csum;
        struct ext4_sb_info *sbi = EXT4_SB(sb);
 
index 3ab2539b7b2eb477222a3dbb7dd8b51cea3cca84..3c20de1d59d0d44586199ade586864758e2ce204 100644 (file)
@@ -1882,10 +1882,10 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct buffer_head *bh, int sz);
 void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group,
                                struct ext4_group_desc *gdp,
-                               struct buffer_head *bh, int sz);
+                               struct buffer_head *bh);
 int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
                                  struct ext4_group_desc *gdp,
-                                 struct buffer_head *bh, int sz);
+                                 struct buffer_head *bh);
 
 /* balloc.c */
 extern void ext4_validate_block_bitmap(struct super_block *sb,
@@ -2063,8 +2063,7 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
 extern int ext4_calculate_overhead(struct super_block *sb);
 extern int ext4_superblock_csum_verify(struct super_block *sb,
                                       struct ext4_super_block *es);
-extern void ext4_superblock_csum_set(struct super_block *sb,
-                                    struct ext4_super_block *es);
+extern void ext4_superblock_csum_set(struct super_block *sb);
 extern void *ext4_kvmalloc(size_t size, gfp_t flags);
 extern void *ext4_kvzalloc(size_t size, gfp_t flags);
 extern void ext4_kvfree(void *ptr);
index bfa65b49d4243d75a5c73456fc2ee4e3698537f4..b4323ba846b52ad09fe0740699ea2d82ff92ba65 100644 (file)
@@ -143,17 +143,13 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line,
        struct buffer_head *bh = EXT4_SB(sb)->s_sbh;
        int err = 0;
 
+       ext4_superblock_csum_set(sb);
        if (ext4_handle_valid(handle)) {
-               ext4_superblock_csum_set(sb,
-                               (struct ext4_super_block *)bh->b_data);
                err = jbd2_journal_dirty_metadata(handle, bh);
                if (err)
                        ext4_journal_abort_handle(where, line, __func__,
                                                  bh, handle, err);
-       } else {
-               ext4_superblock_csum_set(sb,
-                               (struct ext4_super_block *)bh->b_data);
+       } else
                mark_buffer_dirty(bh);
-       }
        return err;
 }
index 1c94cca35ed1a12ce42ce39bddea7c9dd23111cf..7011ac967208e941272f09a07e3292d72ef576f9 100644 (file)
@@ -52,6 +52,9 @@
 #define EXT4_EXT_MARK_UNINIT1  0x2  /* mark first half uninitialized */
 #define EXT4_EXT_MARK_UNINIT2  0x4  /* mark second half uninitialized */
 
+#define EXT4_EXT_DATA_VALID1   0x8  /* first half contains valid data */
+#define EXT4_EXT_DATA_VALID2   0x10 /* second half contains valid data */
+
 static __le32 ext4_extent_block_csum(struct inode *inode,
                                     struct ext4_extent_header *eh)
 {
@@ -2914,6 +2917,9 @@ static int ext4_split_extent_at(handle_t *handle,
        unsigned int ee_len, depth;
        int err = 0;
 
+       BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) ==
+              (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2));
+
        ext_debug("ext4_split_extents_at: inode %lu, logical"
                "block %llu\n", inode->i_ino, (unsigned long long)split);
 
@@ -2972,7 +2978,14 @@ static int ext4_split_extent_at(handle_t *handle,
 
        err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
        if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
-               err = ext4_ext_zeroout(inode, &orig_ex);
+               if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
+                       if (split_flag & EXT4_EXT_DATA_VALID1)
+                               err = ext4_ext_zeroout(inode, ex2);
+                       else
+                               err = ext4_ext_zeroout(inode, ex);
+               } else
+                       err = ext4_ext_zeroout(inode, &orig_ex);
+
                if (err)
                        goto fix_extent_len;
                /* update the extent length and mark as initialized */
@@ -3025,12 +3038,13 @@ static int ext4_split_extent(handle_t *handle,
        uninitialized = ext4_ext_is_uninitialized(ex);
 
        if (map->m_lblk + map->m_len < ee_block + ee_len) {
-               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-                             EXT4_EXT_MAY_ZEROOUT : 0;
+               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT;
                flags1 = flags | EXT4_GET_BLOCKS_PRE_IO;
                if (uninitialized)
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1 |
                                       EXT4_EXT_MARK_UNINIT2;
+               if (split_flag & EXT4_EXT_DATA_VALID2)
+                       split_flag1 |= EXT4_EXT_DATA_VALID1;
                err = ext4_split_extent_at(handle, inode, path,
                                map->m_lblk + map->m_len, split_flag1, flags1);
                if (err)
@@ -3043,8 +3057,8 @@ static int ext4_split_extent(handle_t *handle,
                return PTR_ERR(path);
 
        if (map->m_lblk >= ee_block) {
-               split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ?
-                             EXT4_EXT_MAY_ZEROOUT : 0;
+               split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT |
+                                           EXT4_EXT_DATA_VALID2);
                if (uninitialized)
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1;
                if (split_flag & EXT4_EXT_MARK_UNINIT2)
@@ -3323,26 +3337,47 @@ static int ext4_split_unwritten_extents(handle_t *handle,
 
        split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0;
        split_flag |= EXT4_EXT_MARK_UNINIT2;
-
+       if (flags & EXT4_GET_BLOCKS_CONVERT)
+               split_flag |= EXT4_EXT_DATA_VALID2;
        flags |= EXT4_GET_BLOCKS_PRE_IO;
        return ext4_split_extent(handle, inode, path, map, split_flag, flags);
 }
 
 static int ext4_convert_unwritten_extents_endio(handle_t *handle,
-                                             struct inode *inode,
-                                             struct ext4_ext_path *path)
+                                               struct inode *inode,
+                                               struct ext4_map_blocks *map,
+                                               struct ext4_ext_path *path)
 {
        struct ext4_extent *ex;
+       ext4_lblk_t ee_block;
+       unsigned int ee_len;
        int depth;
        int err = 0;
 
        depth = ext_depth(inode);
        ex = path[depth].p_ext;
+       ee_block = le32_to_cpu(ex->ee_block);
+       ee_len = ext4_ext_get_actual_len(ex);
 
        ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical"
                "block %llu, max_blocks %u\n", inode->i_ino,
-               (unsigned long long)le32_to_cpu(ex->ee_block),
-               ext4_ext_get_actual_len(ex));
+                 (unsigned long long)ee_block, ee_len);
+
+       /* If extent is larger than requested then split is required */
+       if (ee_block != map->m_lblk || ee_len > map->m_len) {
+               err = ext4_split_unwritten_extents(handle, inode, map, path,
+                                                  EXT4_GET_BLOCKS_CONVERT);
+               if (err < 0)
+                       goto out;
+               ext4_ext_drop_refs(path);
+               path = ext4_ext_find_extent(inode, map->m_lblk, path);
+               if (IS_ERR(path)) {
+                       err = PTR_ERR(path);
+                       goto out;
+               }
+               depth = ext_depth(inode);
+               ex = path[depth].p_ext;
+       }
 
        err = ext4_ext_get_access(handle, inode, path + depth);
        if (err)
@@ -3652,7 +3687,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
        }
        /* IO end_io complete, convert the filled extent to written */
        if ((flags & EXT4_GET_BLOCKS_CONVERT)) {
-               ret = ext4_convert_unwritten_extents_endio(handle, inode,
+               ret = ext4_convert_unwritten_extents_endio(handle, inode, map,
                                                        path);
                if (ret >= 0) {
                        ext4_update_inode_fsync_trans(handle, inode, 1);
@@ -4428,6 +4463,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
         */
        if (len <= EXT_UNINIT_MAX_LEN << blkbits)
                flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
+
+       /* Prevent race condition between unwritten */
+       ext4_flush_unwritten_io(inode);
 retry:
        while (ret >= 0 && ret < max_blocks) {
                map.m_lblk = map.m_lblk + ret;
index fa36372f3fdf827ed2557a3ecf5ccceab9e2cfe1..3a100e7a62a8343d31912a423330e11ea40e2e2a 100644 (file)
@@ -725,6 +725,10 @@ repeat_in_this_group:
                                   "inode=%lu", ino + 1);
                        continue;
                }
+               BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
+               err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
+               if (err)
+                       goto fail;
                ext4_lock_group(sb, group);
                ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);
                ext4_unlock_group(sb, group);
@@ -738,6 +742,11 @@ repeat_in_this_group:
        goto out;
 
 got:
+       BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
+       err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
+       if (err)
+               goto fail;
+
        /* We may have to initialize the block bitmap if it isn't already */
        if (ext4_has_group_desc_csum(sb) &&
            gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
@@ -762,9 +771,7 @@ got:
                        ext4_free_group_clusters_set(sb, gdp,
                                ext4_free_clusters_after_init(sb, group, gdp));
                        ext4_block_bitmap_csum_set(sb, group, gdp,
-                                                  block_bitmap_bh,
-                                                  EXT4_BLOCKS_PER_GROUP(sb) /
-                                                  8);
+                                                  block_bitmap_bh);
                        ext4_group_desc_csum_set(sb, group, gdp);
                }
                ext4_unlock_group(sb, group);
@@ -773,11 +780,6 @@ got:
                        goto fail;
        }
 
-       BUFFER_TRACE(inode_bitmap_bh, "get_write_access");
-       err = ext4_journal_get_write_access(handle, inode_bitmap_bh);
-       if (err)
-               goto fail;
-
        BUFFER_TRACE(group_desc_bh, "get_write_access");
        err = ext4_journal_get_write_access(handle, group_desc_bh);
        if (err)
@@ -825,11 +827,6 @@ got:
        }
        ext4_unlock_group(sb, group);
 
-       BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata");
-       err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh);
-       if (err)
-               goto fail;
-
        BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");
        err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);
        if (err)
index f8b27bf80acaf45a3b9ce9aa872d2bed48b2f27d..526e55358606c83a548657449907cd94eed3c155 100644 (file)
@@ -2805,8 +2805,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        }
        len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len;
        ext4_free_group_clusters_set(sb, gdp, len);
-       ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh);
        ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp);
 
        ext4_unlock_group(sb, ac->ac_b_ex.fe_group);
@@ -4666,8 +4665,7 @@ do_more:
 
        ret = ext4_free_group_clusters(sb, gdp) + count_clusters;
        ext4_free_group_clusters_set(sb, gdp, ret);
-       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh);
        ext4_group_desc_csum_set(sb, block_group, gdp);
        ext4_unlock_group(sb, block_group);
        percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters);
@@ -4811,8 +4809,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
        mb_free_blocks(NULL, &e4b, bit, count);
        blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc);
        ext4_free_group_clusters_set(sb, desc, blk_free_count);
-       ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh);
        ext4_group_desc_csum_set(sb, block_group, desc);
        ext4_unlock_group(sb, block_group);
        percpu_counter_add(&sbi->s_freeclusters_counter,
@@ -4993,8 +4990,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
        minlen = EXT4_NUM_B2C(EXT4_SB(sb),
                              range->minlen >> sb->s_blocksize_bits);
 
-       if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) ||
-           unlikely(start >= max_blks))
+       if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) ||
+           start >= max_blks ||
+           range->len < sb->s_blocksize)
                return -EINVAL;
        if (end >= max_blks)
                end = max_blks - 1;
index 7a75e1086961eedb674b8c2bf1bb84e657f4dfa2..47bf06a2765ddcbbd37eb84e693680278ea96fb9 100644 (file)
@@ -1212,8 +1212,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb,
        bh = ext4_get_bitmap(sb, group_data->block_bitmap);
        if (!bh)
                return -EIO;
-       ext4_block_bitmap_csum_set(sb, group, gdp, bh,
-                                  EXT4_BLOCKS_PER_GROUP(sb) / 8);
+       ext4_block_bitmap_csum_set(sb, group, gdp, bh);
        brelse(bh);
 
        return 0;
index 7265a0367476a87f0355b17c22b2488f65ec9a5f..80928f716850924cb34e7a591367cadf115fb95a 100644 (file)
@@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb,
        return es->s_checksum == ext4_superblock_csum(sb, es);
 }
 
-void ext4_superblock_csum_set(struct super_block *sb,
-                             struct ext4_super_block *es)
+void ext4_superblock_csum_set(struct super_block *sb)
 {
+       struct ext4_super_block *es = EXT4_SB(sb)->s_es;
+
        if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
                EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
                return;
@@ -1963,7 +1964,7 @@ static int ext4_fill_flex_info(struct super_block *sb)
                sbi->s_log_groups_per_flex = 0;
                return 1;
        }
-       groups_per_flex = 1 << sbi->s_log_groups_per_flex;
+       groups_per_flex = 1U << sbi->s_log_groups_per_flex;
 
        err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count);
        if (err)
@@ -4381,7 +4382,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
                cpu_to_le32(percpu_counter_sum_positive(
                                &EXT4_SB(sb)->s_freeinodes_counter));
        BUFFER_TRACE(sbh, "marking dirty");
-       ext4_superblock_csum_set(sb, es);
+       ext4_superblock_csum_set(sb);
        mark_buffer_dirty(sbh);
        if (sync) {
                error = sync_dirty_buffer(sbh);
index d3b5fa80b71b76a973919a6b9cfa2ebb34096adf..7cb71b99260340fe7302d2a8c5dc4f84f8029aff 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -685,7 +685,6 @@ void do_close_on_exec(struct files_struct *files)
        struct fdtable *fdt;
 
        /* exec unshares first */
-       BUG_ON(atomic_read(&files->count) != 1);
        spin_lock(&files->file_lock);
        for (i = 0; ; i++) {
                unsigned long set;
@@ -900,7 +899,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags)
                return __close_fd(files, fd);
 
        if (fd >= rlimit(RLIMIT_NOFILE))
-               return -EMFILE;
+               return -EBADF;
 
        spin_lock(&files->file_lock);
        err = expand_files(files, fd);
@@ -926,7 +925,7 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)
                return -EINVAL;
 
        if (newfd >= rlimit(RLIMIT_NOFILE))
-               return -EMFILE;
+               return -EBADF;
 
        spin_lock(&files->file_lock);
        err = expand_files(files, newfd);
index 51ea267d444c4d7aef1259521aa1f06154f26d13..3e3422f7f0a4b4c46080cf798c4185af0642e05d 100644 (file)
@@ -228,6 +228,8 @@ static void requeue_io(struct inode *inode, struct bdi_writeback *wb)
 static void inode_sync_complete(struct inode *inode)
 {
        inode->i_state &= ~I_SYNC;
+       /* If inode is clean an unused, put it into LRU now... */
+       inode_add_lru(inode);
        /* Waiters must see I_SYNC cleared before being woken up */
        smp_mb();
        wake_up_bit(&inode->i_state, __I_SYNC);
index 0def0504afc1816ae40b55de02c07aa68cc3a003..e056b4ce487777bbe794d64a11e4cbe2756205d3 100644 (file)
@@ -516,15 +516,13 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma)
                struct gfs2_holder i_gh;
                int error;
 
-               gfs2_holder_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
-               error = gfs2_glock_nq(&i_gh);
-               if (error == 0) {
-                       file_accessed(file);
-                       gfs2_glock_dq(&i_gh);
-               }
-               gfs2_holder_uninit(&i_gh);
+               error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY,
+                                          &i_gh);
                if (error)
                        return error;
+               /* grab lock to update inode */
+               gfs2_glock_dq_uninit(&i_gh);
+               file_accessed(file);
        }
        vma->vm_ops = &gfs2_vm_ops;
 
@@ -677,10 +675,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        size_t writesize = iov_length(iov, nr_segs);
        struct dentry *dentry = file->f_dentry;
        struct gfs2_inode *ip = GFS2_I(dentry->d_inode);
-       struct gfs2_sbd *sdp;
        int ret;
 
-       sdp = GFS2_SB(file->f_mapping->host);
        ret = gfs2_rs_alloc(ip);
        if (ret)
                return ret;
index 8ff95a2d54ee7dae3de7a9ad6945b5a6c0f17b13..9ceccb1595a3d6f454dd0818eaea92cc8593114f 100644 (file)
@@ -393,12 +393,10 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct gfs2_meta_header *mh;
        struct gfs2_trans *tr;
 
-       lock_buffer(bd->bd_bh);
-       gfs2_log_lock(sdp);
        tr = current->journal_info;
        tr->tr_touched = 1;
        if (!list_empty(&bd->bd_list))
-               goto out;
+               return;
        set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
        set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
        mh = (struct gfs2_meta_header *)bd->bd_bh->b_data;
@@ -414,9 +412,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        sdp->sd_log_num_buf++;
        list_add(&bd->bd_list, &sdp->sd_log_le_buf);
        tr->tr_num_buf_new++;
-out:
-       gfs2_log_unlock(sdp);
-       unlock_buffer(bd->bd_bh);
 }
 
 static void gfs2_check_magic(struct buffer_head *bh)
@@ -621,7 +616,6 @@ static void revoke_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
 
 static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
 {
-       struct gfs2_log_descriptor *ld;
        struct gfs2_meta_header *mh;
        unsigned int offset;
        struct list_head *head = &sdp->sd_log_le_revoke;
@@ -634,7 +628,6 @@ static void revoke_lo_before_commit(struct gfs2_sbd *sdp)
 
        length = gfs2_struct2blk(sdp, sdp->sd_log_num_revoke, sizeof(u64));
        page = gfs2_get_log_desc(sdp, GFS2_LOG_DESC_REVOKE, length, sdp->sd_log_num_revoke);
-       ld = page_address(page);
        offset = sizeof(struct gfs2_log_descriptor);
 
        list_for_each_entry(bd, head, bd_list) {
@@ -777,12 +770,10 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        struct address_space *mapping = bd->bd_bh->b_page->mapping;
        struct gfs2_inode *ip = GFS2_I(mapping->host);
 
-       lock_buffer(bd->bd_bh);
-       gfs2_log_lock(sdp);
        if (tr)
                tr->tr_touched = 1;
        if (!list_empty(&bd->bd_list))
-               goto out;
+               return;
        set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags);
        set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags);
        if (gfs2_is_jdata(ip)) {
@@ -793,9 +784,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
        } else {
                list_add_tail(&bd->bd_list, &sdp->sd_log_le_ordered);
        }
-out:
-       gfs2_log_unlock(sdp);
-       unlock_buffer(bd->bd_bh);
 }
 
 /**
index 40c4b0d42fa8fea10b73102b4fd7d155ebf8daa0..c5af8e18f27af8a3b0c899ce1fe5404fede93831 100644 (file)
@@ -497,8 +497,11 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid)
        struct gfs2_quota_data **qd;
        int error;
 
-       if (ip->i_res == NULL)
-               gfs2_rs_alloc(ip);
+       if (ip->i_res == NULL) {
+               error = gfs2_rs_alloc(ip);
+               if (error)
+                       return error;
+       }
 
        qd = ip->i_res->rs_qa_qd;
 
index 3cc402ce6fea6b3957e82646851e9646fa7cd26b..38fe18f2f055af2e5e842573a475e7b6836bb940 100644 (file)
@@ -553,7 +553,6 @@ void gfs2_free_clones(struct gfs2_rgrpd *rgd)
  */
 int gfs2_rs_alloc(struct gfs2_inode *ip)
 {
-       int error = 0;
        struct gfs2_blkreserv *res;
 
        if (ip->i_res)
@@ -561,7 +560,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
 
        res = kmem_cache_zalloc(gfs2_rsrv_cachep, GFP_NOFS);
        if (!res)
-               error = -ENOMEM;
+               return -ENOMEM;
 
        RB_CLEAR_NODE(&res->rs_node);
 
@@ -571,7 +570,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
        else
                ip->i_res = res;
        up_write(&ip->i_rw_mutex);
-       return error;
+       return 0;
 }
 
 static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
@@ -1263,7 +1262,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        int ret = 0;
        u64 amt;
        u64 trimmed = 0;
+       u64 start, end, minlen;
        unsigned int x;
+       unsigned bs_shift = sdp->sd_sb.sb_bsize_shift;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
@@ -1271,19 +1272,25 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
        if (!blk_queue_discard(q))
                return -EOPNOTSUPP;
 
-       if (argp == NULL) {
-               r.start = 0;
-               r.len = ULLONG_MAX;
-               r.minlen = 0;
-       } else if (copy_from_user(&r, argp, sizeof(r)))
+       if (copy_from_user(&r, argp, sizeof(r)))
                return -EFAULT;
 
        ret = gfs2_rindex_update(sdp);
        if (ret)
                return ret;
 
-       rgd = gfs2_blk2rgrpd(sdp, r.start, 0);
-       rgd_end = gfs2_blk2rgrpd(sdp, r.start + r.len, 0);
+       start = r.start >> bs_shift;
+       end = start + (r.len >> bs_shift);
+       minlen = max_t(u64, r.minlen,
+                      q->limits.discard_granularity) >> bs_shift;
+
+       rgd = gfs2_blk2rgrpd(sdp, start, 0);
+       rgd_end = gfs2_blk2rgrpd(sdp, end - 1, 0);
+
+       if (end <= start ||
+           minlen > sdp->sd_max_rg_data ||
+           start > rgd_end->rd_data0 + rgd_end->rd_data)
+               return -EINVAL;
 
        while (1) {
 
@@ -1295,7 +1302,9 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
                        /* Trim each bitmap in the rgrp */
                        for (x = 0; x < rgd->rd_length; x++) {
                                struct gfs2_bitmap *bi = rgd->rd_bits + x;
-                               ret = gfs2_rgrp_send_discards(sdp, rgd->rd_data0, NULL, bi, r.minlen, &amt);
+                               ret = gfs2_rgrp_send_discards(sdp,
+                                               rgd->rd_data0, NULL, bi, minlen,
+                                               &amt);
                                if (ret) {
                                        gfs2_glock_dq_uninit(&gh);
                                        goto out;
@@ -1324,7 +1333,7 @@ int gfs2_fitrim(struct file *filp, void __user *argp)
 
 out:
        r.len = trimmed << 9;
-       if (argp && copy_to_user(argp, &r, sizeof(r)))
+       if (copy_to_user(argp, &r, sizeof(r)))
                return -EFAULT;
 
        return ret;
index bc737261f234872ad2df43411e6e74296b26b61c..d6488674d916273398b0bf8bd9cd3b2328c8a1fb 100644 (file)
@@ -810,7 +810,8 @@ static void gfs2_dirty_inode(struct inode *inode, int flags)
                        return;
                }
                need_unlock = 1;
-       }
+       } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE))
+               return;
 
        if (current->journal_info == NULL) {
                ret = gfs2_trans_begin(sdp, RES_DINODE, 0);
index adbd27875ef957e5b54846d8494865d51ff156be..413627072f368168814f0df6ba340103c45f9e10 100644 (file)
@@ -155,14 +155,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta)
        struct gfs2_sbd *sdp = gl->gl_sbd;
        struct gfs2_bufdata *bd;
 
+       lock_buffer(bh);
+       gfs2_log_lock(sdp);
        bd = bh->b_private;
        if (bd)
                gfs2_assert(sdp, bd->bd_gl == gl);
        else {
+               gfs2_log_unlock(sdp);
+               unlock_buffer(bh);
                gfs2_attach_bufdata(gl, bh, meta);
                bd = bh->b_private;
+               lock_buffer(bh);
+               gfs2_log_lock(sdp);
        }
        lops_add(sdp, bd);
+       gfs2_log_unlock(sdp);
+       unlock_buffer(bh);
 }
 
 void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
index b03c7195724685e74cba0275adaa718755eb5455..64999f144153d7740018203f884c24eb2a829f54 100644 (file)
@@ -408,6 +408,19 @@ static void inode_lru_list_add(struct inode *inode)
        spin_unlock(&inode->i_sb->s_inode_lru_lock);
 }
 
+/*
+ * Add inode to LRU if needed (inode is unused and clean).
+ *
+ * Needs inode->i_lock held.
+ */
+void inode_add_lru(struct inode *inode)
+{
+       if (!(inode->i_state & (I_DIRTY | I_SYNC | I_FREEING | I_WILL_FREE)) &&
+           !atomic_read(&inode->i_count) && inode->i_sb->s_flags & MS_ACTIVE)
+               inode_lru_list_add(inode);
+}
+
+
 static void inode_lru_list_del(struct inode *inode)
 {
        spin_lock(&inode->i_sb->s_inode_lru_lock);
@@ -1390,8 +1403,7 @@ static void iput_final(struct inode *inode)
 
        if (!drop && (sb->s_flags & MS_ACTIVE)) {
                inode->i_state |= I_REFERENCED;
-               if (!(inode->i_state & (I_DIRTY|I_SYNC)))
-                       inode_lru_list_add(inode);
+               inode_add_lru(inode);
                spin_unlock(&inode->i_lock);
                return;
        }
index 916b7cbf3e3e4fae7bc831c66373b5d5ea7a3c4a..2f6af7f645ebc3d8862da4edb1d71bc811c8d788 100644 (file)
@@ -110,6 +110,7 @@ extern int open_check_o_direct(struct file *f);
  * inode.c
  */
 extern spinlock_t inode_sb_list_lock;
+extern void inode_add_lru(struct inode *inode);
 
 /*
  * fs-writeback.c
index 78b7f84241d47b6b6503df68935f790bccd58ee9..7f5120bf0ec29cff214cc8ccb2a23bfb02ad3419 100644 (file)
@@ -1961,7 +1961,9 @@ retry:
                        spin_unlock(&journal->j_list_lock);
                        jbd_unlock_bh_state(bh);
                        spin_unlock(&journal->j_state_lock);
+                       unlock_buffer(bh);
                        log_wait_commit(journal, tid);
+                       lock_buffer(bh);
                        goto retry;
                }
                /*
index 60ef3fb707ffbfc6a77f1257efc82544cf0f9489..1506673c087e11ae820245baadc8ae74cb9f01b2 100644 (file)
@@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
        struct page *pg;
        struct inode *inode = mapping->host;
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_raw_inode ri;
+       uint32_t alloc_len = 0;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
        uint32_t pageofs = index << PAGE_CACHE_SHIFT;
        int ret = 0;
 
+       jffs2_dbg(1, "%s()\n", __func__);
+
+       if (pageofs > inode->i_size) {
+               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+               if (ret)
+                       return ret;
+       }
+
+       mutex_lock(&f->sem);
        pg = grab_cache_page_write_begin(mapping, index, flags);
-       if (!pg)
+       if (!pg) {
+               if (alloc_len)
+                       jffs2_complete_reservation(c);
+               mutex_unlock(&f->sem);
                return -ENOMEM;
+       }
        *pagep = pg;
 
-       jffs2_dbg(1, "%s()\n", __func__);
-
-       if (pageofs > inode->i_size) {
+       if (alloc_len) {
                /* Make new hole frag from old EOF to new page */
-               struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
-               struct jffs2_raw_inode ri;
                struct jffs2_full_dnode *fn;
-               uint32_t alloc_len;
 
                jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
                          (unsigned int)inode->i_size, pageofs);
 
-               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
-                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
-               if (ret)
-                       goto out_page;
-
-               mutex_lock(&f->sem);
                memset(&ri, 0, sizeof(ri));
 
                ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
                        jffs2_complete_reservation(c);
-                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                        jffs2_mark_node_obsolete(c, fn->raw);
                        jffs2_free_full_dnode(fn);
                        jffs2_complete_reservation(c);
-                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                jffs2_complete_reservation(c);
                inode->i_size = pageofs;
-               mutex_unlock(&f->sem);
        }
 
        /*
@@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
         * case of a short-copy.
         */
        if (!PageUptodate(pg)) {
-               mutex_lock(&f->sem);
                ret = jffs2_do_readpage_nolock(inode, pg);
-               mutex_unlock(&f->sem);
                if (ret)
                        goto out_page;
        }
+       mutex_unlock(&f->sem);
        jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
        return ret;
 
 out_page:
        unlock_page(pg);
        page_cache_release(pg);
+       mutex_unlock(&f->sem);
        return ret;
 }
 
index 9947563e41750223035daa3aeeaba785a9baf82c..dfcd5030455933bcfbc795c251bc3f0b6fa8e36a 100644 (file)
@@ -83,7 +83,7 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
        struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap;
        struct super_block *sb = ipbmap->i_sb;
        int agno, agno_end;
-       s64 start, end, minlen;
+       u64 start, end, minlen;
        u64 trimmed = 0;
 
        /**
@@ -93,15 +93,19 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)
         * minlen:      minimum extent length in Bytes
         */
        start = range->start >> sb->s_blocksize_bits;
-       if (start < 0)
-               start = 0;
        end = start + (range->len >> sb->s_blocksize_bits) - 1;
-       if (end >= bmp->db_mapsize)
-               end = bmp->db_mapsize - 1;
        minlen = range->minlen >> sb->s_blocksize_bits;
-       if (minlen <= 0)
+       if (minlen == 0)
                minlen = 1;
 
+       if (minlen > bmp->db_agsize ||
+           start >= bmp->db_mapsize ||
+           range->len < sb->s_blocksize)
+               return -EINVAL;
+
+       if (end >= bmp->db_mapsize)
+               end = bmp->db_mapsize - 1;
+
        /**
         * we trim all ag's within the range
         */
index d269ada7670e155c7544a2aa01ea0697e98f3991..982d2676e1f813b7e011b05223606af3a63451cc 100644 (file)
@@ -223,7 +223,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr,
 {
        __be32 *p;
 
-       BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
+       WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
        p = xdr_reserve_space(xdr, 4);
        *p = stat;
 }
index e4fb3ba5a58a3d50eb11a0f9533ca58ae5150283..3d7e09bcc0e9efad7418803737e385c76d22a776 100644 (file)
@@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net)
        return rpc_create(&args);
 }
 
+static struct rpc_clnt *nsm_client_set(struct lockd_net *ln,
+               struct rpc_clnt *clnt)
+{
+       spin_lock(&ln->nsm_clnt_lock);
+       if (ln->nsm_users == 0) {
+               if (clnt == NULL)
+                       goto out;
+               ln->nsm_clnt = clnt;
+       }
+       clnt = ln->nsm_clnt;
+       ln->nsm_users++;
+out:
+       spin_unlock(&ln->nsm_clnt_lock);
+       return clnt;
+}
+
 static struct rpc_clnt *nsm_client_get(struct net *net)
 {
-       static DEFINE_MUTEX(nsm_create_mutex);
-       struct rpc_clnt *clnt;
+       struct rpc_clnt *clnt, *new;
        struct lockd_net *ln = net_generic(net, lockd_net_id);
 
-       spin_lock(&ln->nsm_clnt_lock);
-       if (ln->nsm_users) {
-               ln->nsm_users++;
-               clnt = ln->nsm_clnt;
-               spin_unlock(&ln->nsm_clnt_lock);
+       clnt = nsm_client_set(ln, NULL);
+       if (clnt != NULL)
                goto out;
-       }
-       spin_unlock(&ln->nsm_clnt_lock);
 
-       mutex_lock(&nsm_create_mutex);
-       clnt = nsm_create(net);
-       if (!IS_ERR(clnt)) {
-               ln->nsm_clnt = clnt;
-               smp_wmb();
-               ln->nsm_users = 1;
-       }
-       mutex_unlock(&nsm_create_mutex);
+       clnt = new = nsm_create(net);
+       if (IS_ERR(clnt))
+               goto out;
+
+       clnt = nsm_client_set(ln, new);
+       if (clnt != new)
+               rpc_shutdown_client(new);
 out:
        return clnt;
 }
@@ -115,18 +124,16 @@ out:
 static void nsm_client_put(struct net *net)
 {
        struct lockd_net *ln = net_generic(net, lockd_net_id);
-       struct rpc_clnt *clnt = ln->nsm_clnt;
-       int shutdown = 0;
+       struct rpc_clnt *clnt = NULL;
 
        spin_lock(&ln->nsm_clnt_lock);
-       if (ln->nsm_users) {
-               if (--ln->nsm_users)
-                       ln->nsm_clnt = NULL;
-               shutdown = !ln->nsm_users;
+       ln->nsm_users--;
+       if (ln->nsm_users == 0) {
+               clnt = ln->nsm_clnt;
+               ln->nsm_clnt = NULL;
        }
        spin_unlock(&ln->nsm_clnt_lock);
-
-       if (shutdown)
+       if (clnt != NULL)
                rpc_shutdown_client(clnt);
 }
 
index 3009a365e082e37764ea817d070165c3b828146b..21171f0c6477560d7a5f6deb3e336e6c98581f96 100644 (file)
@@ -68,7 +68,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
 
        /* Obtain file pointer. Not used by FREE_ALL call. */
        if (filp != NULL) {
-               if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0)
+               error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh));
+               if (error != 0)
                        goto no_locks;
                *filp = file;
 
index d1895f30815670de8abd8a6c921443035c21a364..937f9d50c84bdead7516057fead3d5a702ead4b9 100644 (file)
@@ -705,8 +705,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
        path_put(link);
 }
 
-int sysctl_protected_symlinks __read_mostly = 1;
-int sysctl_protected_hardlinks __read_mostly = 1;
+int sysctl_protected_symlinks __read_mostly = 0;
+int sysctl_protected_hardlinks __read_mostly = 0;
 
 /**
  * may_follow_link - Check symlink following for unsafe situations
index 9a521fb3986955aab3f32e755bdef94e9c313aa2..5088b57b078a729d09ced36b3e491c01cba9cf4c 100644 (file)
@@ -241,7 +241,7 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
                svc_exit_thread(cb_info->rqst);
                cb_info->rqst = NULL;
                cb_info->task = NULL;
-               return PTR_ERR(cb_info->task);
+               return ret;
        }
        dprintk("nfs_callback_up: service started\n");
        return 0;
index 31c26c4dcc238110de0fa7374f1a2ab51a1541cd..ca4b11ec87a292e92e5d9496f8ac194d97a5bf9f 100644 (file)
@@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
 {
        char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];
        struct nfs_dns_ent key, *item;
-       unsigned long ttl;
+       unsigned int ttl;
        ssize_t len;
        int ret = -EINVAL;
 
@@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
        key.namelen = len;
        memset(&key.h, 0, sizeof(key.h));
 
-       ttl = get_expiry(&buf);
+       if (get_uint(&buf, &ttl) < 0)
+               goto out;
        if (ttl == 0)
                goto out;
        key.h.expiry_time = ttl + seconds_since_boot();
index 5c7325c5c5e66b23beacd6fb7485fda5a640dcd9..6fa01aea24889cae08385e5bfe0aab16c742adc8 100644 (file)
@@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
        if (ctx->cred != NULL)
                put_rpccred(ctx->cred);
        dput(ctx->dentry);
-       nfs_sb_deactive(sb);
+       if (is_sync)
+               nfs_sb_deactive(sb);
+       else
+               nfs_sb_deactive_async(sb);
        kfree(ctx->mdsthreshold);
        kfree(ctx);
 }
index 59b133c5d652df5d2397b1e24e22f390fed459fc..05521cadac2e9821292c8c4eeefa037f5ef0a726 100644 (file)
@@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void);
 extern void __exit unregister_nfs_fs(void);
 extern void nfs_sb_active(struct super_block *sb);
 extern void nfs_sb_deactive(struct super_block *sb);
+extern void nfs_sb_deactive_async(struct super_block *sb);
 
 /* namespace.c */
+#define NFS_PATH_CANONICAL 1
 extern char *nfs_path(char **p, struct dentry *dentry,
-                     char *buffer, ssize_t buflen);
+                     char *buffer, ssize_t buflen, unsigned flags);
 extern struct vfsmount *nfs_d_automount(struct path *path);
 struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,
                              struct nfs_fh *, struct nfs_fattr *);
@@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry,
                                char *buffer, ssize_t buflen)
 {
        char *dummy;
-       return nfs_path(&dummy, dentry, buffer, buflen);
+       return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);
 }
 
 /*
index 8e65c7f1f87c526707959c0e691e36532406d1fa..015f71f8f62c271ebcd6c6ec3949aeff446ce420 100644 (file)
@@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info)
        else
                msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT];
 
-       status = rpc_call_sync(mnt_clnt, &msg, 0);
+       status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);
        rpc_shutdown_client(mnt_clnt);
 
        if (status < 0)
index 655925373b9161c6a6c64ad157002d10cf8064e2..dd057bc6b65b28d3822229e0c0d5d0777b7955b9 100644 (file)
@@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * @dentry - pointer to dentry
  * @buffer - result buffer
  * @buflen - length of buffer
+ * @flags - options (see below)
  *
  * Helper function for constructing the server pathname
  * by arbitrary hashed dentry.
@@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;
  * This is mainly for use in figuring out the path on the
  * server side when automounting on top of an existing partition
  * and in generating /proc/mounts and friends.
+ *
+ * Supported flags:
+ * NFS_PATH_CANONICAL: ensure there is exactly one slash after
+ *                    the original device (export) name
+ *                    (if unset, the original name is returned verbatim)
  */
-char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen)
+char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen,
+              unsigned flags)
 {
        char *end;
        int namelen;
@@ -74,7 +81,7 @@ rename_retry:
                rcu_read_unlock();
                goto rename_retry;
        }
-       if (*end != '/') {
+       if ((flags & NFS_PATH_CANONICAL) && *end != '/') {
                if (--buflen < 0) {
                        spin_unlock(&dentry->d_lock);
                        rcu_read_unlock();
@@ -91,9 +98,11 @@ rename_retry:
                return end;
        }
        namelen = strlen(base);
-       /* Strip off excess slashes in base string */
-       while (namelen > 0 && base[namelen - 1] == '/')
-               namelen--;
+       if (flags & NFS_PATH_CANONICAL) {
+               /* Strip off excess slashes in base string */
+               while (namelen > 0 && base[namelen - 1] == '/')
+                       namelen--;
+       }
        buflen -= namelen;
        if (buflen < 0) {
                spin_unlock(&dentry->d_lock);
index 52d8472120663de91855690fa0996cdf03e4a8a4..2e45fd9c02a38cc9d7b3ee0ee87150fa3a8e7ea8 100644 (file)
@@ -122,12 +122,21 @@ static void filelayout_reset_read(struct nfs_read_data *data)
        }
 }
 
+static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo)
+{
+       if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+               return;
+       clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
+       pnfs_return_layout(inode);
+}
+
 static int filelayout_async_handle_error(struct rpc_task *task,
                                         struct nfs4_state *state,
                                         struct nfs_client *clp,
                                         struct pnfs_layout_segment *lseg)
 {
-       struct inode *inode = lseg->pls_layout->plh_inode;
+       struct pnfs_layout_hdr *lo = lseg->pls_layout;
+       struct inode *inode = lo->plh_inode;
        struct nfs_server *mds_server = NFS_SERVER(inode);
        struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg);
        struct nfs_client *mds_client = mds_server->nfs_client;
@@ -204,10 +213,8 @@ static int filelayout_async_handle_error(struct rpc_task *task,
                dprintk("%s DS connection error %d\n", __func__,
                        task->tk_status);
                nfs4_mark_deviceid_unavailable(devid);
-               clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
-               _pnfs_return_layout(inode);
+               set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
                rpc_wake_up(&tbl->slot_tbl_waitq);
-               nfs4_ds_disconnect(clp);
                /* fall through */
        default:
 reset:
@@ -331,7 +338,9 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data)
 static void filelayout_read_release(void *data)
 {
        struct nfs_read_data *rdata = data;
+       struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout;
 
+       filelayout_fenceme(lo->plh_inode, lo);
        nfs_put_client(rdata->ds_clp);
        rdata->header->mds_ops->rpc_release(data);
 }
@@ -429,7 +438,9 @@ static void filelayout_write_count_stats(struct rpc_task *task, void *data)
 static void filelayout_write_release(void *data)
 {
        struct nfs_write_data *wdata = data;
+       struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout;
 
+       filelayout_fenceme(lo->plh_inode, lo);
        nfs_put_client(wdata->ds_clp);
        wdata->header->mds_ops->rpc_release(data);
 }
@@ -739,7 +750,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                goto out_err;
 
        if (fl->num_fh > 0) {
-               fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+               fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]),
                                       gfp_flags);
                if (!fl->fh_array)
                        goto out_err;
index dca47d78671026810c67b139763cd1b27548d42d..8c07241fe52b0ac86c7d1ef241923f20f0d56a1e 100644 (file)
@@ -149,6 +149,5 @@ extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr);
 struct nfs4_file_layout_dsaddr *
 filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags);
-void nfs4_ds_disconnect(struct nfs_client *clp);
 
 #endif /* FS_NFS_NFS4FILELAYOUT_H */
index 3336d5eaf879adc07a2e95f64b512835935763a6..a8eaa9b7bb0f2c8fc704b8eb752c2ebc564b52bf 100644 (file)
@@ -148,28 +148,6 @@ _data_server_lookup_locked(const struct list_head *dsaddrs)
        return NULL;
 }
 
-/*
- * Lookup DS by nfs_client pointer. Zero data server client pointer
- */
-void nfs4_ds_disconnect(struct nfs_client *clp)
-{
-       struct nfs4_pnfs_ds *ds;
-       struct nfs_client *found = NULL;
-
-       dprintk("%s clp %p\n", __func__, clp);
-       spin_lock(&nfs4_ds_cache_lock);
-       list_for_each_entry(ds, &nfs4_data_server_cache, ds_node)
-               if (ds->ds_clp && ds->ds_clp == clp) {
-                       found = ds->ds_clp;
-                       ds->ds_clp = NULL;
-               }
-       spin_unlock(&nfs4_ds_cache_lock);
-       if (found) {
-               set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state);
-               nfs_put_client(clp);
-       }
-}
-
 /*
  * Create an rpc connection to the nfs4_pnfs_ds data server
  * Currently only supports IPv4 and IPv6 addresses
index 6a83780e0ce6b9a9888ce51dfd303ca454b54ea8..549462e5b9b0633239a1b2766ce17433446874dc 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <linux/nfs_fs.h>
 #include "nfs4_fs.h"
+#include "internal.h"
 
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
index 79fbb61ce202bcb90df2c8ad0f7f3ecf3bba7aac..1e09eb78543b2d50f9da025c733e52a99957ba64 100644 (file)
@@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end)
 static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)
 {
        char *limit;
-       char *path = nfs_path(&limit, dentry, buffer, buflen);
+       char *path = nfs_path(&limit, dentry, buffer, buflen,
+                             NFS_PATH_CANONICAL);
        if (!IS_ERR(path)) {
                char *path_component = nfs_path_component(path, limit);
                if (path_component)
index 68b21d81b7acfa79bef010023195c1f45023c82b..5eec4429970c6e98af7a18732794c6fceaba4951 100644 (file)
@@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
                        dprintk("%s ERROR: %d Reset session\n", __func__,
                                errorcode);
                        nfs4_schedule_session_recovery(clp->cl_session, errorcode);
-                       exception->retry = 1;
-                       break;
+                       goto wait_on_recovery;
 #endif /* defined(CONFIG_NFS_V4_1) */
                case -NFS4ERR_FILE_OPEN:
                        if (exception->timeout > HZ) {
@@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)
        data->timestamp = jiffies;
        if (nfs4_setup_sequence(data->o_arg.server,
                                &data->o_arg.seq_args,
-                               &data->o_res.seq_res, task))
-               return;
-       rpc_call_start(task);
+                               &data->o_res.seq_res,
+                               task) != 0)
+               nfs_release_seqid(data->o_arg.seqid);
+       else
+               rpc_call_start(task);
        return;
 unlock_no_action:
        rcu_read_unlock();
@@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
 
        /* even though OPEN succeeded, access is denied. Close the file */
        nfs4_close_state(state, fmode);
-       return -NFS4ERR_ACCESS;
+       return -EACCES;
 }
 
 /*
@@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data)
        nfs4_put_open_state(calldata->state);
        nfs_free_seqid(calldata->arg.seqid);
        nfs4_put_state_owner(sp);
-       nfs_sb_deactive(sb);
+       nfs_sb_deactive_async(sb);
        kfree(calldata);
 }
 
@@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
        if (nfs4_setup_sequence(NFS_SERVER(inode),
                                &calldata->arg.seq_args,
                                &calldata->res.seq_res,
-                               task))
-               goto out;
-       rpc_call_start(task);
+                               task) != 0)
+               nfs_release_seqid(calldata->arg.seqid);
+       else
+               rpc_call_start(task);
 out:
        dprintk("%s: done!\n", __func__);
 }
@@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
                        if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)
                                rpc_restart_call_prepare(task);
        }
+       nfs_release_seqid(calldata->arg.seqid);
 }
 
 static void nfs4_locku_prepare(struct rpc_task *task, void *data)
@@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
        calldata->timestamp = jiffies;
        if (nfs4_setup_sequence(calldata->server,
                                &calldata->arg.seq_args,
-                               &calldata->res.seq_res, task))
-               return;
-       rpc_call_start(task);
+                               &calldata->res.seq_res,
+                               task) != 0)
+               nfs_release_seqid(calldata->arg.seqid);
+       else
+               rpc_call_start(task);
 }
 
 static const struct rpc_call_ops nfs4_locku_ops = {
@@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        /* Do we need to do an open_to_lock_owner? */
        if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {
                if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0)
-                       return;
+                       goto out_release_lock_seqid;
                data->arg.open_stateid = &state->stateid;
                data->arg.new_lock_owner = 1;
                data->res.open_seqid = data->arg.open_seqid;
@@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)
        data->timestamp = jiffies;
        if (nfs4_setup_sequence(data->server,
                                &data->arg.seq_args,
-                               &data->res.seq_res, task))
+                               &data->res.seq_res,
+                               task) == 0) {
+               rpc_call_start(task);
                return;
-       rpc_call_start(task);
-       dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status);
+       }
+       nfs_release_seqid(data->arg.open_seqid);
+out_release_lock_seqid:
+       nfs_release_seqid(data->arg.lock_seqid);
+       dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);
 }
 
 static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata)
@@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,
                tbl->slots = new;
                tbl->max_slots = max_slots;
        }
-       tbl->highest_used_slotid = -1;  /* no slot is currently used */
+       tbl->highest_used_slotid = NFS4_NO_SLOT;
        for (i = 0; i < tbl->max_slots; i++)
                tbl->slots[i].seq_nr = ivalue;
        spin_unlock(&tbl->slot_tbl_lock);
index be731e6b7b9cc1781a0a1776f49f7e5aa8219a89..c6f990656f8905ed4911b471f7334e1a1a40582e 100644 (file)
@@ -369,7 +369,7 @@ void objio_free_result(struct objlayout_io_res *oir)
        kfree(objios);
 }
 
-enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
+static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
 {
        switch (oep) {
        case OSD_ERR_PRI_NO_ERROR:
@@ -574,7 +574,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
                        (unsigned long)pgio->pg_layout_private;
 }
 
-void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        pnfs_generic_pg_init_read(pgio, req);
        if (unlikely(pgio->pg_lseg == NULL))
@@ -604,7 +604,7 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,
        return false;
 }
 
-void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
+static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        unsigned long stripe_end = 0;
        u64 wb_size;
index fe624c91bd006ef11f839f61cab54f833286edfa..2878f97bd78d5cf5343b88cfcac9b5a48a1abe60 100644 (file)
@@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino,
        if (likely(nfsi->layout == NULL)) {     /* Won the race? */
                nfsi->layout = new;
                return new;
-       }
-       pnfs_free_layout_hdr(new);
+       } else if (new != NULL)
+               pnfs_free_layout_hdr(new);
 out_existing:
        pnfs_get_layout_hdr(nfsi->layout);
        return nfsi->layout;
index 2d722dba111181377e6f599adae06a8d341abe09..dbf7bba52da04086c0c0a2bbb8b4283b309b8758 100644 (file)
@@ -62,6 +62,7 @@ enum {
        NFS_LAYOUT_RW_FAILED,           /* get rw layout failed stop trying */
        NFS_LAYOUT_BULK_RECALL,         /* bulk recall affecting layout */
        NFS_LAYOUT_ROC,                 /* some lseg had roc bit set */
+       NFS_LAYOUT_RETURN,              /* Return this layout ASAP */
 };
 
 enum layoutdriver_policy_flags {
index e831bce497663e809e48bb7cc278f5ad6a74ba7b..652d3f7176a98fcc4e70e6f5e3d812e4b3d90b83 100644 (file)
@@ -54,6 +54,7 @@
 #include <linux/parser.h>
 #include <linux/nsproxy.h>
 #include <linux/rcupdate.h>
+#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 
@@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)
 }
 EXPORT_SYMBOL_GPL(nfs_sb_deactive);
 
+static int nfs_deactivate_super_async_work(void *ptr)
+{
+       struct super_block *sb = ptr;
+
+       deactivate_super(sb);
+       module_put_and_exit(0);
+       return 0;
+}
+
+/*
+ * same effect as deactivate_super, but will do final unmount in kthread
+ * context
+ */
+static void nfs_deactivate_super_async(struct super_block *sb)
+{
+       struct task_struct *task;
+       char buf[INET6_ADDRSTRLEN + 1];
+       struct nfs_server *server = NFS_SB(sb);
+       struct nfs_client *clp = server->nfs_client;
+
+       if (!atomic_add_unless(&sb->s_active, -1, 1)) {
+               rcu_read_lock();
+               snprintf(buf, sizeof(buf),
+                       rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR));
+               rcu_read_unlock();
+
+               __module_get(THIS_MODULE);
+               task = kthread_run(nfs_deactivate_super_async_work, sb,
+                               "%s-deactivate-super", buf);
+               if (IS_ERR(task)) {
+                       pr_err("%s: kthread_run: %ld\n",
+                               __func__, PTR_ERR(task));
+                       /* make synchronous call and hope for the best */
+                       deactivate_super(sb);
+                       module_put(THIS_MODULE);
+               }
+       }
+}
+
+void nfs_sb_deactive_async(struct super_block *sb)
+{
+       struct nfs_server *server = NFS_SB(sb);
+
+       if (atomic_dec_and_test(&server->active))
+               nfs_deactivate_super_async(sb);
+}
+EXPORT_SYMBOL_GPL(nfs_sb_deactive_async);
+
 /*
  * Deliver file system statistics to userspace
  */
@@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)
        int err = 0;
        if (!page)
                return -ENOMEM;
-       devname = nfs_path(&dummy, root, page, PAGE_SIZE);
+       devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);
        if (IS_ERR(devname))
                err = PTR_ERR(devname);
        else
index 13cea637eff82288f2f5508023a592e60db3fa7a..3f79c77153b8fe827cd24310209301e0132b96ad 100644 (file)
@@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata)
 
        nfs_dec_sillycount(data->dir);
        nfs_free_unlinkdata(data);
-       nfs_sb_deactive(sb);
+       nfs_sb_deactive_async(sb);
 }
 
 static void nfs_unlink_prepare(struct rpc_task *task, void *calldata)
index f35794b97e8e5cb5cc396af28206d69ca1202935..a50636025364214176fe7cec0cb80757ddc27171 100644 (file)
@@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new)
                        if ((old->path.mnt == new->path.mnt) &&
                            (old->path.dentry == new->path.dentry))
                                return true;
+                       break;
                case (FSNOTIFY_EVENT_NONE):
                        return true;
                default:
index 721d692fa8d4a20dd5bf593d3f732d8b3f913261..6fcaeb8c902e4c3bc862c6c81db0a884068274b7 100644 (file)
@@ -258,7 +258,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
        if (ret)
                goto out_close_fd;
 
-       fd_install(fd, f);
+       if (fd != FAN_NOFD)
+               fd_install(fd, f);
        return fanotify_event_metadata.event_len;
 
 out_close_fd:
index 144a96732dd7d602df0d5f8a504e435cfdb07229..9e28356a959a2f4f0aecddd6170ebacfa799a5b3 100644 (file)
@@ -873,6 +873,113 @@ static const struct file_operations proc_environ_operations = {
        .release        = mem_release,
 };
 
+static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
+                           loff_t *ppos)
+{
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+       char buffer[PROC_NUMBUF];
+       int oom_adj = OOM_ADJUST_MIN;
+       size_t len;
+       unsigned long flags;
+
+       if (!task)
+               return -ESRCH;
+       if (lock_task_sighand(task, &flags)) {
+               if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX)
+                       oom_adj = OOM_ADJUST_MAX;
+               else
+                       oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) /
+                                 OOM_SCORE_ADJ_MAX;
+               unlock_task_sighand(task, &flags);
+       }
+       put_task_struct(task);
+       len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj);
+       return simple_read_from_buffer(buf, count, ppos, buffer, len);
+}
+
+static ssize_t oom_adj_write(struct file *file, const char __user *buf,
+                            size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       char buffer[PROC_NUMBUF];
+       int oom_adj;
+       unsigned long flags;
+       int err;
+
+       memset(buffer, 0, sizeof(buffer));
+       if (count > sizeof(buffer) - 1)
+               count = sizeof(buffer) - 1;
+       if (copy_from_user(buffer, buf, count)) {
+               err = -EFAULT;
+               goto out;
+       }
+
+       err = kstrtoint(strstrip(buffer), 0, &oom_adj);
+       if (err)
+               goto out;
+       if ((oom_adj < OOM_ADJUST_MIN || oom_adj > OOM_ADJUST_MAX) &&
+            oom_adj != OOM_DISABLE) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       task = get_proc_task(file->f_path.dentry->d_inode);
+       if (!task) {
+               err = -ESRCH;
+               goto out;
+       }
+
+       task_lock(task);
+       if (!task->mm) {
+               err = -EINVAL;
+               goto err_task_lock;
+       }
+
+       if (!lock_task_sighand(task, &flags)) {
+               err = -ESRCH;
+               goto err_task_lock;
+       }
+
+       /*
+        * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum
+        * value is always attainable.
+        */
+       if (oom_adj == OOM_ADJUST_MAX)
+               oom_adj = OOM_SCORE_ADJ_MAX;
+       else
+               oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
+
+       if (oom_adj < task->signal->oom_score_adj &&
+           !capable(CAP_SYS_RESOURCE)) {
+               err = -EACCES;
+               goto err_sighand;
+       }
+
+       /*
+        * /proc/pid/oom_adj is provided for legacy purposes, ask users to use
+        * /proc/pid/oom_score_adj instead.
+        */
+       printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
+                 current->comm, task_pid_nr(current), task_pid_nr(task),
+                 task_pid_nr(task));
+
+       task->signal->oom_score_adj = oom_adj;
+       trace_oom_score_adj_update(task);
+err_sighand:
+       unlock_task_sighand(task, &flags);
+err_task_lock:
+       task_unlock(task);
+       put_task_struct(task);
+out:
+       return err < 0 ? err : count;
+}
+
+static const struct file_operations proc_oom_adj_operations = {
+       .read           = oom_adj_read,
+       .write          = oom_adj_write,
+       .llseek         = generic_file_llseek,
+};
+
 static ssize_t oom_score_adj_read(struct file *file, char __user *buf,
                                        size_t count, loff_t *ppos)
 {
@@ -1770,8 +1877,9 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
        if (!vma)
                goto out_no_vma;
 
-       result = proc_map_files_instantiate(dir, dentry, task,
-                       (void *)(unsigned long)vma->vm_file->f_mode);
+       if (vma->vm_file)
+               result = proc_map_files_instantiate(dir, dentry, task,
+                               (void *)(unsigned long)vma->vm_file->f_mode);
 
 out_no_vma:
        up_read(&mm->mmap_sem);
@@ -2598,6 +2706,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score",  S_IRUGO, proc_oom_score),
+       REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
@@ -2964,6 +3073,7 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score", S_IRUGO, proc_oom_score),
+       REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
index cceaab07ad549caaa124b71e3db01f126052ef59..43973b084abf25649fdb12e16ad3d169c0e29c9e 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 struct  ctl_table_header;
+struct  mempolicy;
 
 extern struct proc_dir_entry proc_root;
 #ifdef CONFIG_PROC_SYSCTL
@@ -74,6 +75,9 @@ struct proc_maps_private {
 #ifdef CONFIG_MMU
        struct vm_area_struct *tail_vma;
 #endif
+#ifdef CONFIG_NUMA
+       struct mempolicy *task_mempolicy;
+#endif
 };
 
 void proc_init_inodecache(void);
index a781bdf0669464ced3e213faad5ed6ab3a37a06b..701580ddfcc3c20a4476fe88a9e736b54ca7b858 100644 (file)
@@ -378,12 +378,13 @@ static int test_perm(int mode, int op)
        return -EACCES;
 }
 
-static int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
+static int sysctl_perm(struct ctl_table_header *head, struct ctl_table *table, int op)
 {
+       struct ctl_table_root *root = head->root;
        int mode;
 
        if (root->permissions)
-               mode = root->permissions(root, current->nsproxy, table);
+               mode = root->permissions(head, table);
        else
                mode = table->mode;
 
@@ -491,7 +492,7 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
         * and won't be until we finish.
         */
        error = -EPERM;
-       if (sysctl_perm(head->root, table, write ? MAY_WRITE : MAY_READ))
+       if (sysctl_perm(head, table, write ? MAY_WRITE : MAY_READ))
                goto out;
 
        /* if that can happen at all, it should be -EINVAL, not -EISDIR */
@@ -717,7 +718,7 @@ static int proc_sys_permission(struct inode *inode, int mask)
        if (!table) /* global root - r-xr-xr-x */
                error = mask & MAY_WRITE ? -EACCES : 0;
        else /* Use the permissions on the sysctl table entry */
-               error = sysctl_perm(head->root, table, mask & ~MAY_NOT_BLOCK);
+               error = sysctl_perm(head, table, mask & ~MAY_NOT_BLOCK);
 
        sysctl_head_finish(head);
        return error;
index 64c3b3172367abbd1c1464b9372f33ee4efa7acb..e296572c73ed651dd7d81cc33eb3dd1b64de5d0d 100644 (file)
@@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int cpu)
 
 static u64 get_idle_time(int cpu)
 {
-       u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL);
+       u64 idle, idle_time = -1ULL;
+
+       if (cpu_online(cpu))
+               idle_time = get_cpu_idle_time_us(cpu, NULL);
 
        if (idle_time == -1ULL)
-               /* !NO_HZ so we can rely on cpustat.idle */
+               /* !NO_HZ or cpu offline so we can rely on cpustat.idle */
                idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
        else
                idle = usecs_to_cputime64(idle_time);
@@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu)
 
 static u64 get_iowait_time(int cpu)
 {
-       u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL);
+       u64 iowait, iowait_time = -1ULL;
+
+       if (cpu_online(cpu))
+               iowait_time = get_cpu_iowait_time_us(cpu, NULL);
 
        if (iowait_time == -1ULL)
-               /* !NO_HZ so we can rely on cpustat.iowait */
+               /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */
                iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
        else
                iowait = usecs_to_cputime64(iowait_time);
index 79827ce03e3bc00208aced44caa7ae9fd2d08bd3..90c63f9392a595318c5d1e03e1d69305bf9413fa 100644 (file)
@@ -90,10 +90,55 @@ static void pad_len_spaces(struct seq_file *m, int len)
        seq_printf(m, "%*c", len, ' ');
 }
 
+#ifdef CONFIG_NUMA
+/*
+ * These functions are for numa_maps but called in generic **maps seq_file
+ * ->start(), ->stop() ops.
+ *
+ * numa_maps scans all vmas under mmap_sem and checks their mempolicy.
+ * Each mempolicy object is controlled by reference counting. The problem here
+ * is how to avoid accessing dead mempolicy object.
+ *
+ * Because we're holding mmap_sem while reading seq_file, it's safe to access
+ * each vma's mempolicy, no vma objects will never drop refs to mempolicy.
+ *
+ * A task's mempolicy (task->mempolicy) has different behavior. task->mempolicy
+ * is set and replaced under mmap_sem but unrefed and cleared under task_lock().
+ * So, without task_lock(), we cannot trust get_vma_policy() because we cannot
+ * gurantee the task never exits under us. But taking task_lock() around
+ * get_vma_plicy() causes lock order problem.
+ *
+ * To access task->mempolicy without lock, we hold a reference count of an
+ * object pointed by task->mempolicy and remember it. This will guarantee
+ * that task->mempolicy points to an alive object or NULL in numa_maps accesses.
+ */
+static void hold_task_mempolicy(struct proc_maps_private *priv)
+{
+       struct task_struct *task = priv->task;
+
+       task_lock(task);
+       priv->task_mempolicy = task->mempolicy;
+       mpol_get(priv->task_mempolicy);
+       task_unlock(task);
+}
+static void release_task_mempolicy(struct proc_maps_private *priv)
+{
+       mpol_put(priv->task_mempolicy);
+}
+#else
+static void hold_task_mempolicy(struct proc_maps_private *priv)
+{
+}
+static void release_task_mempolicy(struct proc_maps_private *priv)
+{
+}
+#endif
+
 static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)
 {
        if (vma && vma != priv->tail_vma) {
                struct mm_struct *mm = vma->vm_mm;
+               release_task_mempolicy(priv);
                up_read(&mm->mmap_sem);
                mmput(mm);
        }
@@ -132,7 +177,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 
        tail_vma = get_gate_vma(priv->task->mm);
        priv->tail_vma = tail_vma;
-
+       hold_task_mempolicy(priv);
        /* Start with last addr hint */
        vma = find_vma(mm, last_addr);
        if (last_addr && vma) {
@@ -159,6 +204,7 @@ out:
        if (vma)
                return vma;
 
+       release_task_mempolicy(priv);
        /* End of vmas has been reached */
        m->version = (tail_vma != NULL)? 0: -1UL;
        up_read(&mm->mmap_sem);
@@ -1158,6 +1204,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        struct vm_area_struct *vma = v;
        struct numa_maps *md = &numa_priv->md;
        struct file *file = vma->vm_file;
+       struct task_struct *task = proc_priv->task;
        struct mm_struct *mm = vma->vm_mm;
        struct mm_walk walk = {};
        struct mempolicy *pol;
@@ -1177,7 +1224,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        walk.private = md;
        walk.mm = mm;
 
-       pol = get_vma_policy(proc_priv->task, vma, vma->vm_start);
+       pol = get_vma_policy(task, vma, vma->vm_start);
        mpol_to_str(buffer, sizeof(buffer), pol, 0);
        mpol_cond_put(pol);
 
@@ -1189,7 +1236,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
        } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
                seq_printf(m, " heap");
        } else {
-               pid_t tid = vm_is_stack(proc_priv->task, vma, is_pid);
+               pid_t tid = vm_is_stack(task, vma, is_pid);
                if (tid != 0) {
                        /*
                         * Thread stack in /proc/PID/task/TID/maps or
index a40da07e93d68a88e670b5256a1c22c4badeb634..947fbe06c3b1f2ed0948b8fb050b43f2c48ff591 100644 (file)
@@ -161,6 +161,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
 
        while (s < e) {
                unsigned long flags;
+               u64 id;
 
                if (c > psinfo->bufsize)
                        c = psinfo->bufsize;
@@ -172,7 +173,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
                        spin_lock_irqsave(&psinfo->buf_lock, flags);
                }
                memcpy(psinfo->buf, s, c);
-               psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo);
+               psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo);
                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
                s += c;
                c = e - s;
index 557a9c20a2154856c1e1595e2d0e457d9487aaad..05ae3c97f7a5fc552e771f9cf7312e4b61cffc1f 100644 (file)
@@ -1160,6 +1160,8 @@ static int need_print_warning(struct dquot_warn *warn)
                        return uid_eq(current_fsuid(), warn->w_dq_id.uid);
                case GRPQUOTA:
                        return in_group_p(warn->w_dq_id.gid);
+               case PRJQUOTA:  /* Never taken... Just make gcc happy */
+                       return 0;
        }
        return 0;
 }
index f27f01a98aa2c9573c6cc61fe093c821ce6e107c..d83736fbc26cb4679cf074ee33263f125f13afa7 100644 (file)
@@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
        BUG_ON(!th->t_trans_id);
 
-       dquot_initialize(inode);
+       reiserfs_write_unlock(inode->i_sb);
        err = dquot_alloc_inode(inode);
+       reiserfs_write_lock(inode->i_sb);
        if (err)
                goto out_end_trans;
        if (!dir->i_nlink) {
@@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
       out_end_trans:
        journal_end(th, th->t_super, th->t_blocks_allocated);
+       reiserfs_write_unlock(inode->i_sb);
        /* Drop can be outside and it needs more credits so it's better to have it outside */
        dquot_drop(inode);
+       reiserfs_write_lock(inode->i_sb);
        inode->i_flags |= S_NOQUOTA;
        make_bad_inode(inode);
 
@@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
-       depth = reiserfs_write_lock_once(inode->i_sb);
        if (is_quota_modification(inode, attr))
                dquot_initialize(inode);
-
+       depth = reiserfs_write_lock_once(inode->i_sb);
        if (attr->ia_valid & ATTR_SIZE) {
                /* version 2 items will be caught by the s_maxbytes check
                 ** done for us in vmtruncate
@@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                error = journal_begin(&th, inode->i_sb, jbegin_count);
                if (error)
                        goto out;
+               reiserfs_write_unlock_once(inode->i_sb, depth);
                error = dquot_transfer(inode, attr);
+               depth = reiserfs_write_lock_once(inode->i_sb);
                if (error) {
                        journal_end(&th, inode->i_sb, jbegin_count);
                        goto out;
index f8afa4b162b8f026da18b1cf2364e7d1cd6f5116..2f40a4c70a4d9667ca34e00ef2b31888255276c2 100644 (file)
@@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
                       key2type(&(key->on_disk_key)));
 #endif
 
+       reiserfs_write_unlock(inode->i_sb);
        retval = dquot_alloc_space_nodirty(inode, pasted_size);
+       reiserfs_write_lock(inode->i_sb);
        if (retval) {
                pathrelse(search_path);
                return retval;
@@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
                               "reiserquota insert_item(): allocating %u id=%u type=%c",
                               quota_bytes, inode->i_uid, head2type(ih));
 #endif
+               reiserfs_write_unlock(inode->i_sb);
                /* We can't dirty inode here. It would be immediately written but
                 * appropriate stat item isn't inserted yet... */
                retval = dquot_alloc_space_nodirty(inode, quota_bytes);
+               reiserfs_write_lock(inode->i_sb);
                if (retval) {
                        pathrelse(path);
                        return retval;
index 1078ae179993bb12f105d39fb1d847eb84c12414..418bdc3a57da4e11092477fa1b3cbf2e37f71422 100644 (file)
@@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s)
                        retval = remove_save_link_only(s, &save_link_key, 0);
                        continue;
                }
+               reiserfs_write_unlock(s);
                dquot_initialize(inode);
+               reiserfs_write_lock(s);
 
                if (truncate && S_ISDIR(inode->i_mode)) {
                        /* We got a truncate request for a dir which is impossible.
@@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                                kfree(qf_names[i]);
 #endif
                err = -EINVAL;
-               goto out_err;
+               goto out_unlock;
        }
 #ifdef CONFIG_QUOTA
        handle_quota_files(s, qf_names, &qfmt);
@@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        if (blocks) {
                err = reiserfs_resize(s, blocks);
                if (err != 0)
-                       goto out_err;
+                       goto out_unlock;
        }
 
        if (*mount_flags & MS_RDONLY) {
@@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                        /* it is read-only already */
                        goto out_ok;
 
+               /*
+                * Drop write lock. Quota will retake it when needed and lock
+                * ordering requires calling dquot_suspend() without it.
+                */
+               reiserfs_write_unlock(s);
                err = dquot_suspend(s, -1);
                if (err < 0)
                        goto out_err;
+               reiserfs_write_lock(s);
 
                /* try to remount file system with read-only permissions */
                if (sb_umount_state(rs) == REISERFS_VALID_FS
@@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 
                err = journal_begin(&th, s, 10);
                if (err)
-                       goto out_err;
+                       goto out_unlock;
 
                /* Mounting a rw partition read-only. */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 
                if (reiserfs_is_journal_aborted(journal)) {
                        err = journal->j_errno;
-                       goto out_err;
+                       goto out_unlock;
                }
 
                handle_data_mode(s, mount_options);
@@ -1425,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                s->s_flags &= ~MS_RDONLY;       /* now it is safe to call journal_begin */
                err = journal_begin(&th, s, 10);
                if (err)
-                       goto out_err;
+                       goto out_unlock;
 
                /* Mount a partition which is read-only, read-write */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        SB_JOURNAL(s)->j_must_wait = 1;
        err = journal_end(&th, s, 10);
        if (err)
-               goto out_err;
+               goto out_unlock;
 
        if (!(*mount_flags & MS_RDONLY)) {
+               /*
+                * Drop write lock. Quota will retake it when needed and lock
+                * ordering requires calling dquot_resume() without it.
+                */
+               reiserfs_write_unlock(s);
                dquot_resume(s, -1);
+               reiserfs_write_lock(s);
                finish_unfinished(s);
                reiserfs_xattr_init(s, *mount_flags);
        }
@@ -1455,9 +1469,10 @@ out_ok:
        reiserfs_write_unlock(s);
        return 0;
 
+out_unlock:
+       reiserfs_write_unlock(s);
 out_err:
        kfree(new_opts);
-       reiserfs_write_unlock(s);
        return err;
 }
 
@@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot)
                          REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
        if (ret)
                goto out;
+       reiserfs_write_unlock(dquot->dq_sb);
        ret = dquot_commit(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(dquot->dq_sb);
        return ret;
 }
@@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
                          REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
        if (ret)
                goto out;
+       reiserfs_write_unlock(dquot->dq_sb);
        ret = dquot_acquire(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(dquot->dq_sb);
        return ret;
 }
@@ -2137,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot)
        ret =
            journal_begin(&th, dquot->dq_sb,
                          REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+       reiserfs_write_unlock(dquot->dq_sb);
        if (ret) {
                /* Release dquot anyway to avoid endless cycle in dqput() */
                dquot_release(dquot);
                goto out;
        }
        ret = dquot_release(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
        reiserfs_write_unlock(dquot->dq_sb);
+out:
        return ret;
 }
 
@@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type)
        ret = journal_begin(&th, sb, 2);
        if (ret)
                goto out;
+       reiserfs_write_unlock(sb);
        ret = dquot_commit_info(sb, type);
+       reiserfs_write_lock(sb);
        err = journal_end(&th, sb, 2);
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(sb);
        return ret;
 }
@@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
        struct reiserfs_transaction_handle th;
        int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
 
-       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
-               return -EINVAL;
+       reiserfs_write_lock(sb);
+       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) {
+               err = -EINVAL;
+               goto out;
+       }
 
        /* Quotafile not on the same filesystem? */
        if (path->dentry->d_sb != sb) {
@@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
                if (err)
                        goto out;
        }
-       err = dquot_quota_on(sb, type, format_id, path);
+       reiserfs_write_unlock(sb);
+       return dquot_quota_on(sb, type, format_id, path);
 out:
+       reiserfs_write_unlock(sb);
        return err;
 }
 
@@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                tocopy = sb->s_blocksize - offset < towrite ?
                    sb->s_blocksize - offset : towrite;
                tmp_bh.b_state = 0;
+               reiserfs_write_lock(sb);
                err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
+               reiserfs_write_unlock(sb);
                if (err)
                        goto out;
                if (offset || tocopy != sb->s_blocksize)
@@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                flush_dcache_page(bh->b_page);
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
+               reiserfs_write_lock(sb);
                reiserfs_prepare_for_journal(sb, bh, 1);
                journal_mark_dirty(current->journal_info, sb, bh);
                if (!journal_quota)
                        reiserfs_add_ordered_list(inode, bh);
+               reiserfs_write_unlock(sb);
                brelse(bh);
                offset = 0;
                towrite -= tocopy;
index 6b0bb00d4d2b6061add5a1f266371df257e5c4a9..2fbdff6be25ce3d546e17fa4e72783e9d3f03637 100644 (file)
@@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
 /**
  *     sysfs_pathname - return full path to sysfs dirent
  *     @sd: sysfs_dirent whose path we want
- *     @path: caller allocated buffer
+ *     @path: caller allocated buffer of size PATH_MAX
  *
  *     Gives the name "/" to the sysfs_root entry; any path returned
  *     is relative to wherever sysfs is mounted.
- *
- *     XXX: does no error checking on @path size
  */
 static char *sysfs_pathname(struct sysfs_dirent *sd, char *path)
 {
        if (sd->s_parent) {
                sysfs_pathname(sd->s_parent, path);
-               strcat(path, "/");
+               strlcat(path, "/", PATH_MAX);
        }
-       strcat(path, sd->s_name);
+       strlcat(path, sd->s_name, PATH_MAX);
        return path;
 }
 
@@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd)
                char *path = kzalloc(PATH_MAX, GFP_KERNEL);
                WARN(1, KERN_WARNING
                     "sysfs: cannot create duplicate filename '%s'\n",
-                    (path == NULL) ? sd->s_name :
-                    strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"),
-                           sd->s_name));
+                    (path == NULL) ? sd->s_name
+                                   : (sysfs_pathname(acxt->parent_sd, path),
+                                      strlcat(path, "/", PATH_MAX),
+                                      strlcat(path, sd->s_name, PATH_MAX),
+                                      path));
                kfree(path);
        }
 
index 28ec13af28d91c360c89c68f7af0f1957e79477a..2dcf3d473fec1d406bf0fc2d14d73828ff81f662 100644 (file)
@@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
        if (!lprops) {
                lprops = ubifs_fast_find_freeable(c);
                if (!lprops) {
-                       ubifs_assert(c->freeable_cnt == 0);
-                       if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+                       /*
+                        * The first condition means the following: go scan the
+                        * LPT if there are uncategorized lprops, which means
+                        * there may be freeable LEBs there (UBIFS does not
+                        * store the information about freeable LEBs in the
+                        * master node).
+                        */
+                       if (c->in_a_category_cnt != c->main_lebs ||
+                           c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+                               ubifs_assert(c->freeable_cnt == 0);
                                lprops = scan_for_leb_for_idx(c);
                                if (IS_ERR(lprops)) {
                                        err = PTR_ERR(lprops);
index e5a2a35a46dcc1fc3fb9178704cec947458bda2e..46190a7c42a6c113bcffe4f170800b98a22eaf01 100644 (file)
@@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
        default:
                ubifs_assert(0);
        }
+
        lprops->flags &= ~LPROPS_CAT_MASK;
        lprops->flags |= cat;
+       c->in_a_category_cnt += 1;
+       ubifs_assert(c->in_a_category_cnt <= c->main_lebs);
 }
 
 /**
@@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c,
        default:
                ubifs_assert(0);
        }
+
+       c->in_a_category_cnt -= 1;
+       ubifs_assert(c->in_a_category_cnt >= 0);
 }
 
 /**
index 5486346d0a3f9ec63ce10f9296ee0fbdec8732f1..d133c276fe05d526c647756c704ef37a8438612e 100644 (file)
@@ -1183,6 +1183,8 @@ struct ubifs_debug_info;
  * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size)
  * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size)
  * @freeable_cnt: number of freeable LEBs in @freeable_list
+ * @in_a_category_cnt: count of lprops which are in a certain category, which
+ *                     basically meants that they were loaded from the flash
  *
  * @ltab_lnum: LEB number of LPT's own lprops table
  * @ltab_offs: offset of LPT's own lprops table
@@ -1412,6 +1414,7 @@ struct ubifs_info {
        struct list_head freeable_list;
        struct list_head frdi_idx_list;
        int freeable_cnt;
+       int in_a_category_cnt;
 
        int ltab_lnum;
        int ltab_offs;
index e164dddb8e9660dc1de0cfb1d6a6abd3da13ed6b..e21c119f4f99d8512208a9c08983dd5f9c25d821 100644 (file)
@@ -846,7 +846,7 @@ static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
                              const void *value, size_t size, int flags)
 {
        struct simple_xattr *xattr;
-       struct simple_xattr *uninitialized_var(new_xattr);
+       struct simple_xattr *new_xattr = NULL;
        int err = 0;
 
        /* value == NULL means remove */
index 4f33c32affe3d2eb4bec9c5ca8d71a33bbc5032a..335206a9c6985fde106d164543efee515bba1433 100644 (file)
@@ -1866,6 +1866,7 @@ xfs_alloc_fix_freelist(
        /*
         * Initialize the args structure.
         */
+       memset(&targs, 0, sizeof(targs));
        targs.tp = tp;
        targs.mp = mp;
        targs.agbp = agbp;
@@ -2207,7 +2208,7 @@ xfs_alloc_read_agf(
  * group or loop over the allocation groups to find the result.
  */
 int                            /* error */
-__xfs_alloc_vextent(
+xfs_alloc_vextent(
        xfs_alloc_arg_t *args)  /* allocation argument structure */
 {
        xfs_agblock_t   agsize; /* allocation group size */
@@ -2417,46 +2418,6 @@ error0:
        return error;
 }
 
-static void
-xfs_alloc_vextent_worker(
-       struct work_struct      *work)
-{
-       struct xfs_alloc_arg    *args = container_of(work,
-                                               struct xfs_alloc_arg, work);
-       unsigned long           pflags;
-
-       /* we are in a transaction context here */
-       current_set_flags_nested(&pflags, PF_FSTRANS);
-
-       args->result = __xfs_alloc_vextent(args);
-       complete(args->done);
-
-       current_restore_flags_nested(&pflags, PF_FSTRANS);
-}
-
-/*
- * Data allocation requests often come in with little stack to work on. Push
- * them off to a worker thread so there is lots of stack to use. Metadata
- * requests, OTOH, are generally from low stack usage paths, so avoid the
- * context switch overhead here.
- */
-int
-xfs_alloc_vextent(
-       struct xfs_alloc_arg    *args)
-{
-       DECLARE_COMPLETION_ONSTACK(done);
-
-       if (!args->userdata)
-               return __xfs_alloc_vextent(args);
-
-
-       args->done = &done;
-       INIT_WORK_ONSTACK(&args->work, xfs_alloc_vextent_worker);
-       queue_work(xfs_alloc_wq, &args->work);
-       wait_for_completion(&done);
-       return args->result;
-}
-
 /*
  * Free an extent.
  * Just break up the extent address and hand off to xfs_free_ag_extent
index 93be4a667ca1692648aec03195b5747bac4239f2..feacb061bab78bb3492ee0ff37eed5cc0fb95894 100644 (file)
@@ -120,9 +120,6 @@ typedef struct xfs_alloc_arg {
        char            isfl;           /* set if is freelist blocks - !acctg */
        char            userdata;       /* set if this is user data */
        xfs_fsblock_t   firstblock;     /* io first block allocated */
-       struct completion *done;
-       struct work_struct work;
-       int             result;
 } xfs_alloc_arg_t;
 
 /*
index f1647caace8fe66eeda2bd51cf5e679028d7b50e..f7876c6d616553d222295624a20f4c168c4c021d 100644 (file)
@@ -121,6 +121,8 @@ xfs_allocbt_free_block(
        xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1,
                              XFS_EXTENT_BUSY_SKIP_DISCARD);
        xfs_trans_agbtree_delta(cur->bc_tp, -1);
+
+       xfs_trans_binval(cur->bc_tp, bp);
        return 0;
 }
 
index e562dd43f41fe762eb4d49c7814f1f002fe965c9..e57e2daa357c34fc9634871a1d41dd76569cf871 100644 (file)
@@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
  *
  * The fix is two passes across the ioend list - one to start writeback on the
  * buffer_heads, and then submit them for I/O on the second pass.
+ *
+ * If @fail is non-zero, it means that we have a situation where some part of
+ * the submission process has failed after we have marked paged for writeback
+ * and unlocked them. In this situation, we need to fail the ioend chain rather
+ * than submit it to IO. This typically only happens on a filesystem shutdown.
  */
 STATIC void
 xfs_submit_ioend(
        struct writeback_control *wbc,
-       xfs_ioend_t             *ioend)
+       xfs_ioend_t             *ioend,
+       int                     fail)
 {
        xfs_ioend_t             *head = ioend;
        xfs_ioend_t             *next;
@@ -506,6 +512,18 @@ xfs_submit_ioend(
                next = ioend->io_list;
                bio = NULL;
 
+               /*
+                * If we are failing the IO now, just mark the ioend with an
+                * error and finish it. This will run IO completion immediately
+                * as there is only one reference to the ioend at this point in
+                * time.
+                */
+               if (fail) {
+                       ioend->io_error = -fail;
+                       xfs_finish_ioend(ioend);
+                       continue;
+               }
+
                for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
 
                        if (!bio) {
@@ -1060,7 +1078,18 @@ xfs_vm_writepage(
 
        xfs_start_page_writeback(page, 1, count);
 
-       if (ioend && imap_valid) {
+       /* if there is no IO to be submitted for this page, we are done */
+       if (!ioend)
+               return 0;
+
+       ASSERT(iohead);
+
+       /*
+        * Any errors from this point onwards need tobe reported through the IO
+        * completion path as we have marked the initial page as under writeback
+        * and unlocked it.
+        */
+       if (imap_valid) {
                xfs_off_t               end_index;
 
                end_index = imap.br_startoff + imap.br_blockcount;
@@ -1079,20 +1108,15 @@ xfs_vm_writepage(
                                  wbc, end_index);
        }
 
-       if (iohead) {
-               /*
-                * Reserve log space if we might write beyond the on-disk
-                * inode size.
-                */
-               if (ioend->io_type != XFS_IO_UNWRITTEN &&
-                   xfs_ioend_is_append(ioend)) {
-                       err = xfs_setfilesize_trans_alloc(ioend);
-                       if (err)
-                               goto error;
-               }
 
-               xfs_submit_ioend(wbc, iohead);
-       }
+       /*
+        * Reserve log space if we might write beyond the on-disk inode size.
+        */
+       err = 0;
+       if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
+               err = xfs_setfilesize_trans_alloc(ioend);
+
+       xfs_submit_ioend(wbc, iohead, err);
 
        return 0;
 
index d330111ca738eef9ff86b5fd28723c0b63a9b379..70eec1829776309b3cba83e9a660aa6de5ad9693 100644 (file)
@@ -1291,6 +1291,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        leaf2 = blk2->bp->b_addr;
        ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+       ASSERT(leaf2->hdr.count == 0);
        args = state->args;
 
        trace_xfs_attr_leaf_rebalance(args);
@@ -1361,6 +1362,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
                 * I assert that since all callers pass in an empty
                 * second buffer, this code should never execute.
                 */
+               ASSERT(0);
 
                /*
                 * Figure the total bytes to be added to the destination leaf.
@@ -1422,10 +1424,24 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
                        args->index2 = 0;
                        args->blkno2 = blk2->blkno;
                } else {
+                       /*
+                        * On a double leaf split, the original attr location
+                        * is already stored in blkno2/index2, so don't
+                        * overwrite it overwise we corrupt the tree.
+                        */
                        blk2->index = blk1->index
                                    - be16_to_cpu(leaf1->hdr.count);
-                       args->index = args->index2 = blk2->index;
-                       args->blkno = args->blkno2 = blk2->blkno;
+                       args->index = blk2->index;
+                       args->blkno = blk2->blkno;
+                       if (!state->extravalid) {
+                               /*
+                                * set the new attr location to match the old
+                                * one and let the higher level split code
+                                * decide where in the leaf to place it.
+                                */
+                               args->index2 = blk2->index;
+                               args->blkno2 = blk2->blkno;
+                       }
                }
        } else {
                ASSERT(state->inleaf == 1);
index 848ffa77707b98bf272f61fc162f6e361504926e..83d0cf3df930794c307c4adcb33dceb8a5415f7e 100644 (file)
@@ -2437,6 +2437,7 @@ xfs_bmap_btalloc(
         * Normal allocation, done through xfs_alloc_vextent.
         */
        tryagain = isaligned = 0;
+       memset(&args, 0, sizeof(args));
        args.tp = ap->tp;
        args.mp = mp;
        args.fsbno = ap->blkno;
@@ -3082,6 +3083,7 @@ xfs_bmap_extents_to_btree(
         * Convert to a btree with two levels, one record in root.
         */
        XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE);
+       memset(&args, 0, sizeof(args));
        args.tp = tp;
        args.mp = mp;
        args.firstblock = *firstblock;
@@ -3237,6 +3239,7 @@ xfs_bmap_local_to_extents(
                xfs_buf_t       *bp;    /* buffer for extent block */
                xfs_bmbt_rec_host_t *ep;/* extent record pointer */
 
+               memset(&args, 0, sizeof(args));
                args.tp = tp;
                args.mp = ip->i_mount;
                args.firstblock = *firstblock;
@@ -4616,12 +4619,11 @@ xfs_bmapi_delay(
 
 
 STATIC int
-xfs_bmapi_allocate(
-       struct xfs_bmalloca     *bma,
-       int                     flags)
+__xfs_bmapi_allocate(
+       struct xfs_bmalloca     *bma)
 {
        struct xfs_mount        *mp = bma->ip->i_mount;
-       int                     whichfork = (flags & XFS_BMAPI_ATTRFORK) ?
+       int                     whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ?
                                                XFS_ATTR_FORK : XFS_DATA_FORK;
        struct xfs_ifork        *ifp = XFS_IFORK_PTR(bma->ip, whichfork);
        int                     tmp_logflags = 0;
@@ -4654,24 +4656,27 @@ xfs_bmapi_allocate(
         * Indicate if this is the first user data in the file, or just any
         * user data.
         */
-       if (!(flags & XFS_BMAPI_METADATA)) {
+       if (!(bma->flags & XFS_BMAPI_METADATA)) {
                bma->userdata = (bma->offset == 0) ?
                        XFS_ALLOC_INITIAL_USER_DATA : XFS_ALLOC_USERDATA;
        }
 
-       bma->minlen = (flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
+       bma->minlen = (bma->flags & XFS_BMAPI_CONTIG) ? bma->length : 1;
 
        /*
         * Only want to do the alignment at the eof if it is userdata and
         * allocation length is larger than a stripe unit.
         */
        if (mp->m_dalign && bma->length >= mp->m_dalign &&
-           !(flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
+           !(bma->flags & XFS_BMAPI_METADATA) && whichfork == XFS_DATA_FORK) {
                error = xfs_bmap_isaeof(bma, whichfork);
                if (error)
                        return error;
        }
 
+       if (bma->flags & XFS_BMAPI_STACK_SWITCH)
+               bma->stack_switch = 1;
+
        error = xfs_bmap_alloc(bma);
        if (error)
                return error;
@@ -4706,7 +4711,7 @@ xfs_bmapi_allocate(
         * A wasdelay extent has been initialized, so shouldn't be flagged
         * as unwritten.
         */
-       if (!bma->wasdel && (flags & XFS_BMAPI_PREALLOC) &&
+       if (!bma->wasdel && (bma->flags & XFS_BMAPI_PREALLOC) &&
            xfs_sb_version_hasextflgbit(&mp->m_sb))
                bma->got.br_state = XFS_EXT_UNWRITTEN;
 
@@ -4734,6 +4739,45 @@ xfs_bmapi_allocate(
        return 0;
 }
 
+static void
+xfs_bmapi_allocate_worker(
+       struct work_struct      *work)
+{
+       struct xfs_bmalloca     *args = container_of(work,
+                                               struct xfs_bmalloca, work);
+       unsigned long           pflags;
+
+       /* we are in a transaction context here */
+       current_set_flags_nested(&pflags, PF_FSTRANS);
+
+       args->result = __xfs_bmapi_allocate(args);
+       complete(args->done);
+
+       current_restore_flags_nested(&pflags, PF_FSTRANS);
+}
+
+/*
+ * Some allocation requests often come in with little stack to work on. Push
+ * them off to a worker thread so there is lots of stack to use. Otherwise just
+ * call directly to avoid the context switch overhead here.
+ */
+int
+xfs_bmapi_allocate(
+       struct xfs_bmalloca     *args)
+{
+       DECLARE_COMPLETION_ONSTACK(done);
+
+       if (!args->stack_switch)
+               return __xfs_bmapi_allocate(args);
+
+
+       args->done = &done;
+       INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
+       queue_work(xfs_alloc_wq, &args->work);
+       wait_for_completion(&done);
+       return args->result;
+}
+
 STATIC int
 xfs_bmapi_convert_unwritten(
        struct xfs_bmalloca     *bma,
@@ -4919,6 +4963,7 @@ xfs_bmapi_write(
                        bma.conv = !!(flags & XFS_BMAPI_CONVERT);
                        bma.wasdel = wasdelay;
                        bma.offset = bno;
+                       bma.flags = flags;
 
                        /*
                         * There's a 32/64 bit type mismatch between the
@@ -4934,7 +4979,7 @@ xfs_bmapi_write(
 
                        ASSERT(len > 0);
                        ASSERT(bma.length > 0);
-                       error = xfs_bmapi_allocate(&bma, flags);
+                       error = xfs_bmapi_allocate(&bma);
                        if (error)
                                goto error0;
                        if (bma.blkno == NULLFSBLOCK)
index 803b56d7ce16a97b7e5eb8075ba4e7853e4b8d30..5f469c3516ebc28bf836e86c974feb8c61373a4c 100644 (file)
@@ -77,6 +77,7 @@ typedef       struct xfs_bmap_free
  * from written to unwritten, otherwise convert from unwritten to written.
  */
 #define XFS_BMAPI_CONVERT      0x040
+#define XFS_BMAPI_STACK_SWITCH 0x080
 
 #define XFS_BMAPI_FLAGS \
        { XFS_BMAPI_ENTIRE,     "ENTIRE" }, \
@@ -85,7 +86,8 @@ typedef       struct xfs_bmap_free
        { XFS_BMAPI_PREALLOC,   "PREALLOC" }, \
        { XFS_BMAPI_IGSTATE,    "IGSTATE" }, \
        { XFS_BMAPI_CONTIG,     "CONTIG" }, \
-       { XFS_BMAPI_CONVERT,    "CONVERT" }
+       { XFS_BMAPI_CONVERT,    "CONVERT" }, \
+       { XFS_BMAPI_STACK_SWITCH, "STACK_SWITCH" }
 
 
 static inline int xfs_bmapi_aflag(int w)
@@ -133,6 +135,11 @@ typedef struct xfs_bmalloca {
        char                    userdata;/* set if is user data */
        char                    aeof;   /* allocated space at eof */
        char                    conv;   /* overwriting unwritten extents */
+       char                    stack_switch;
+       int                     flags;
+       struct completion       *done;
+       struct work_struct      work;
+       int                     result;
 } xfs_bmalloca_t;
 
 /*
index 933b7930b8636da970a627d571388b11e8dabde7..4b0b8dd1b7b0ea2bbc431ef523ec5412eb4fd584 100644 (file)
@@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io(
 {
        xfs_buf_t               *bp = (xfs_buf_t *)bio->bi_private;
 
-       xfs_buf_ioerror(bp, -error);
+       /*
+        * don't overwrite existing errors - otherwise we can lose errors on
+        * buffers that require multiple bios to complete.
+        */
+       if (!bp->b_error)
+               xfs_buf_ioerror(bp, -error);
 
-       if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+       if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
                invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
 
        _xfs_buf_ioend(bp, 1);
@@ -1279,6 +1284,11 @@ next_chunk:
                if (size)
                        goto next_chunk;
        } else {
+               /*
+                * This is guaranteed not to be the last io reference count
+                * because the caller (xfs_buf_iorequest) holds a count itself.
+                */
+               atomic_dec(&bp->b_io_remaining);
                xfs_buf_ioerror(bp, EIO);
                bio_put(bio);
        }
index a8d0ed911196120a80a26bb7232f79d3a5badee1..becf4a97efc65c95240e45c1b05b751919d51317 100644 (file)
@@ -526,7 +526,25 @@ xfs_buf_item_unpin(
                }
                xfs_buf_relse(bp);
        } else if (freed && remove) {
+               /*
+                * There are currently two references to the buffer - the active
+                * LRU reference and the buf log item. What we are about to do
+                * here - simulate a failed IO completion - requires 3
+                * references.
+                *
+                * The LRU reference is removed by the xfs_buf_stale() call. The
+                * buf item reference is removed by the xfs_buf_iodone()
+                * callback that is run by xfs_buf_do_callbacks() during ioend
+                * processing (via the bp->b_iodone callback), and then finally
+                * the ioend processing will drop the IO reference if the buffer
+                * is marked XBF_ASYNC.
+                *
+                * Hence we need to take an additional reference here so that IO
+                * completion processing doesn't free the buffer prematurely.
+                */
                xfs_buf_lock(bp);
+               xfs_buf_hold(bp);
+               bp->b_flags |= XBF_ASYNC;
                xfs_buf_ioerror(bp, EIO);
                XFS_BUF_UNDONE(bp);
                xfs_buf_stale(bp);
index c25b094efbf715186f39a9b7a44466eb0a910374..4beaede43277b15c8d5a28ffbaadb4b573d7a709 100644 (file)
@@ -399,9 +399,26 @@ xfs_growfs_data_private(
 
        /* update secondary superblocks. */
        for (agno = 1; agno < nagcount; agno++) {
-               error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
+               error = 0;
+               /*
+                * new secondary superblocks need to be zeroed, not read from
+                * disk as the contents of the new area we are growing into is
+                * completely unknown.
+                */
+               if (agno < oagcount) {
+                       error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp,
                                  XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
                                  XFS_FSS_TO_BB(mp, 1), 0, &bp);
+               } else {
+                       bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp,
+                                 XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
+                                 XFS_FSS_TO_BB(mp, 1), 0);
+                       if (bp)
+                               xfs_buf_zero(bp, 0, BBTOB(bp->b_length));
+                       else
+                               error = ENOMEM;
+               }
+
                if (error) {
                        xfs_warn(mp,
                "error %d reading secondary superblock for ag %d",
@@ -423,7 +440,7 @@ xfs_growfs_data_private(
                        break; /* no point in continuing */
                }
        }
-       return 0;
+       return error;
 
  error0:
        xfs_trans_cancel(tp, XFS_TRANS_ABORT);
index 445bf1aef31c16d9e6bd17a8b91e78d7f1763c05..c5c4ef4f2bdbec16d9eb07ff0188921f677384ff 100644 (file)
@@ -250,6 +250,7 @@ xfs_ialloc_ag_alloc(
                                        /* boundary */
        struct xfs_perag *pag;
 
+       memset(&args, 0, sizeof(args));
        args.tp = tp;
        args.mp = tp->t_mountp;
 
index 2778258fcfa239e07dbc79edf6cb4750b7e13dd8..1938b41ee9f51bfef8f0ffad3e8b83e059ebcf41 100644 (file)
@@ -1509,7 +1509,8 @@ xfs_ifree_cluster(
                 * to mark all the active inodes on the buffer stale.
                 */
                bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, blkno,
-                                       mp->m_bsize * blks_per_cluster, 0);
+                                       mp->m_bsize * blks_per_cluster,
+                                       XBF_UNMAPPED);
 
                if (!bp)
                        return ENOMEM;
index 8305f2ac6773a8ee5efd1b0e24546e4194807187..c1df3c623de203f7d941ef0b706c76de270ada68 100644 (file)
@@ -70,7 +70,7 @@ xfs_find_handle(
        int                     hsize;
        xfs_handle_t            handle;
        struct inode            *inode;
-       struct fd               f;
+       struct fd               f = {0};
        struct path             path;
        int                     error;
        struct xfs_inode        *ip;
index 973dff6ad93526292871d3452d758e86b3f077ac..7f537663365b08436f1ad29015b77df33f691109 100644 (file)
@@ -584,7 +584,9 @@ xfs_iomap_write_allocate(
                         * pointer that the caller gave to us.
                         */
                        error = xfs_bmapi_write(tp, ip, map_start_fsb,
-                                               count_fsb, 0, &first_block, 1,
+                                               count_fsb,
+                                               XFS_BMAPI_STACK_SWITCH,
+                                               &first_block, 1,
                                                imap, &nimaps, &free_list);
                        if (error)
                                goto trans_cancel;
index 7f4f9370d0e7438df3820fab9b0026b37292623b..4dad756962d02e1b29c703b5b54ccee07d91fabf 100644 (file)
@@ -2387,14 +2387,27 @@ xlog_state_do_callback(
 
 
                                /*
-                                * update the last_sync_lsn before we drop the
+                                * Completion of a iclog IO does not imply that
+                                * a transaction has completed, as transactions
+                                * can be large enough to span many iclogs. We
+                                * cannot change the tail of the log half way
+                                * through a transaction as this may be the only
+                                * transaction in the log and moving th etail to
+                                * point to the middle of it will prevent
+                                * recovery from finding the start of the
+                                * transaction. Hence we should only update the
+                                * last_sync_lsn if this iclog contains
+                                * transaction completion callbacks on it.
+                                *
+                                * We have to do this before we drop the
                                 * icloglock to ensure we are the only one that
                                 * can update it.
                                 */
                                ASSERT(XFS_LSN_CMP(atomic64_read(&log->l_last_sync_lsn),
                                        be64_to_cpu(iclog->ic_header.h_lsn)) <= 0);
-                               atomic64_set(&log->l_last_sync_lsn,
-                                       be64_to_cpu(iclog->ic_header.h_lsn));
+                               if (iclog->ic_callback)
+                                       atomic64_set(&log->l_last_sync_lsn,
+                                               be64_to_cpu(iclog->ic_header.h_lsn));
 
                        } else
                                ioerrors++;
index 5da3ace352bffe6ca32d16ae76fc131291914a00..d308749fabf126a5b318c5d55f0e58e5589ef14f 100644 (file)
@@ -3541,7 +3541,7 @@ xlog_do_recovery_pass(
                                 *   - order is important.
                                 */
                                error = xlog_bread_offset(log, 0,
-                                               bblks - split_bblks, hbp,
+                                               bblks - split_bblks, dbp,
                                                offset + BBTOB(split_bblks));
                                if (error)
                                        goto bread_err2;
index 8d226bfa2696a6f7a1dbefa4ccbf1bff4b391bf6..83256b64166a85380eb6a20adc357195ca8bfe77 100644 (file)
@@ -1,12 +1,8 @@
 # Top-level Makefile calls into asm-$(ARCH)
 # List only non-arch directories below
 
-header-y += asm-generic/
 header-y += linux/
 header-y += sound/
-header-y += mtd/
 header-y += rdma/
 header-y += video/
-header-y += drm/
-header-y += xen/
 header-y += scsi/
diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/drm/Kbuild b/include/drm/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index c78bb997e2c60846a1f5e261664d96ee1656fe6d..c5c35e629426b506d2e7d00fe876f2e528a48f80 100644 (file)
        {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \
index 5b57367e28db9b848de3e54c32830faa62793924..7fe2dae251e59a4b7313b914b6bcbfcf33fce283 100644 (file)
@@ -1,31 +1,5 @@
-header-y += byteorder/
-header-y += can/
-header-y += caif/
 header-y += dvb/
 header-y += hdlc/
 header-y += hsi/
-header-y += isdn/
-header-y += mmc/
-header-y += nfsd/
 header-y += raid/
-header-y += spi/
-header-y += sunrpc/
-header-y += tc_act/
-header-y += tc_ematch/
-header-y += netfilter/
-header-y += netfilter_arp/
-header-y += netfilter_bridge/
-header-y += netfilter_ipv4/
-header-y += netfilter_ipv6/
 header-y += usb/
-header-y += wimax/
-
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h \
-                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h),)
-endif
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h \
-                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h),)
-endif
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h \
-                 $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h),)
-endif
index 22ef21c33d0c600f5adf48d34e5bdde4687d76c4..c1da539f5e28a965702c39d21375923e8271f67f 100644 (file)
@@ -99,6 +99,7 @@ struct atm_vcc {
        struct atm_dev  *dev;           /* device back pointer */
        struct atm_qos  qos;            /* QOS */
        struct atm_sap  sap;            /* SAP */
+       void (*release_cb)(struct atm_vcc *vcc); /* release_sock callback */
        void (*push)(struct atm_vcc *vcc,struct sk_buff *skb);
        void (*pop)(struct atm_vcc *vcc,struct sk_buff *skb); /* optional */
        int (*push_oam)(struct atm_vcc *vcc,void *cell);
@@ -106,6 +107,7 @@ struct atm_vcc {
        void            *dev_data;      /* per-device data */
        void            *proto_data;    /* per-protocol data */
        struct k_atm_aal_stats *stats;  /* pointer to AAL stats group */
+       struct module *owner;           /* owner of ->push function */
        /* SVC part --- may move later ------------------------------------- */
        short           itf;            /* interface number */
        struct sockaddr_atmsvc local;
index aaac4bba6f5c7faa1d2b95b13983323658c8188c..b1cf40de847e42e0b1555252949a34a5f3a6e54a 100644 (file)
@@ -15,6 +15,7 @@ struct pt_regs;
 #define BUILD_BUG_ON_NOT_POWER_OF_2(n)
 #define BUILD_BUG_ON_ZERO(e) (0)
 #define BUILD_BUG_ON_NULL(e) ((void*)0)
+#define BUILD_BUG_ON_INVALID(e) (0)
 #define BUILD_BUG_ON(condition)
 #define BUILD_BUG() (0)
 #else /* __CHECKER__ */
diff --git a/include/linux/byteorder/Kbuild b/include/linux/byteorder/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/caif/Kbuild b/include/linux/caif/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/can/Kbuild b/include/linux/can/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index c127315829208046fbd9327488dfc258cc1d0372..f9f5e9eeb9dd1f37f59cc95cf1da0cdbd91b7001 100644 (file)
@@ -335,8 +335,8 @@ const char *__clk_get_name(struct clk *clk);
 struct clk_hw *__clk_get_hw(struct clk *clk);
 u8 __clk_get_num_parents(struct clk *clk);
 struct clk *__clk_get_parent(struct clk *clk);
-inline int __clk_get_enable_count(struct clk *clk);
-inline int __clk_get_prepare_count(struct clk *clk);
+int __clk_get_enable_count(struct clk *clk);
+int __clk_get_prepare_count(struct clk *clk);
 unsigned long __clk_get_rate(struct clk *clk);
 unsigned long __clk_get_flags(struct clk *clk);
 int __clk_is_enabled(struct clk *clk);
index 1775eb8acc03665d36bf8b094c440a41ba10764d..1d7399314a8933eab0516daf5ff4bf7f87777d88 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
+#include <asm/siginfo.h>
 
 /*
  * These are the only things you should do on a core-file: use only these
index f4dba8637f9807c999664d517ed2c7379eadca60..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,8 +0,0 @@
-header-y += audio.h
-header-y += ca.h
-header-y += dmx.h
-header-y += frontend.h
-header-y += net.h
-header-y += osd.h
-header-y += version.h
-header-y += video.h
diff --git a/include/linux/dvb/audio.h b/include/linux/dvb/audio.h
deleted file mode 100644 (file)
index d47bccd..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * audio.h
- *
- * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
- *                  & Marcus Metzler <marcus@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVBAUDIO_H_
-#define _DVBAUDIO_H_
-
-#include <linux/types.h>
-
-typedef enum {
-       AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
-       AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */
-} audio_stream_source_t;
-
-
-typedef enum {
-       AUDIO_STOPPED,      /* Device is stopped */
-       AUDIO_PLAYING,      /* Device is currently playing */
-       AUDIO_PAUSED        /* Device is paused */
-} audio_play_state_t;
-
-
-typedef enum {
-       AUDIO_STEREO,
-       AUDIO_MONO_LEFT,
-       AUDIO_MONO_RIGHT,
-       AUDIO_MONO,
-       AUDIO_STEREO_SWAPPED
-} audio_channel_select_t;
-
-
-typedef struct audio_mixer {
-       unsigned int volume_left;
-       unsigned int volume_right;
-  // what else do we need? bass, pass-through, ...
-} audio_mixer_t;
-
-
-typedef struct audio_status {
-       int                    AV_sync_state;  /* sync audio and video? */
-       int                    mute_state;     /* audio is muted */
-       audio_play_state_t     play_state;     /* current playback state */
-       audio_stream_source_t  stream_source;  /* current stream source */
-       audio_channel_select_t channel_select; /* currently selected channel */
-       int                    bypass_mode;    /* pass on audio data to */
-       audio_mixer_t          mixer_state;    /* current mixer state */
-} audio_status_t;                              /* separate decoder hardware */
-
-
-typedef
-struct audio_karaoke {  /* if Vocal1 or Vocal2 are non-zero, they get mixed  */
-       int vocal1;    /* into left and right t at 70% each */
-       int vocal2;    /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets*/
-       int melody;    /* mixed into the left channel and */
-                      /* Vocal2 into the right channel at 100% each. */
-                      /* if Melody is non-zero, the melody channel gets mixed*/
-} audio_karaoke_t;     /* into left and right  */
-
-
-typedef __u16 audio_attributes_t;
-/*   bits: descr. */
-/*   15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */
-/*   12    multichannel extension */
-/*   11-10 audio type (0=not spec, 1=language included) */
-/*    9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) */
-/*    7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit,  */
-/*    5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */
-/*    2- 0 number of audio channels (n+1 channels) */
-
-
-/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */
-#define AUDIO_CAP_DTS    1
-#define AUDIO_CAP_LPCM   2
-#define AUDIO_CAP_MP1    4
-#define AUDIO_CAP_MP2    8
-#define AUDIO_CAP_MP3   16
-#define AUDIO_CAP_AAC   32
-#define AUDIO_CAP_OGG   64
-#define AUDIO_CAP_SDDS 128
-#define AUDIO_CAP_AC3  256
-
-#define AUDIO_STOP                 _IO('o', 1)
-#define AUDIO_PLAY                 _IO('o', 2)
-#define AUDIO_PAUSE                _IO('o', 3)
-#define AUDIO_CONTINUE             _IO('o', 4)
-#define AUDIO_SELECT_SOURCE        _IO('o', 5)
-#define AUDIO_SET_MUTE             _IO('o', 6)
-#define AUDIO_SET_AV_SYNC          _IO('o', 7)
-#define AUDIO_SET_BYPASS_MODE      _IO('o', 8)
-#define AUDIO_CHANNEL_SELECT       _IO('o', 9)
-#define AUDIO_GET_STATUS           _IOR('o', 10, audio_status_t)
-
-#define AUDIO_GET_CAPABILITIES     _IOR('o', 11, unsigned int)
-#define AUDIO_CLEAR_BUFFER         _IO('o',  12)
-#define AUDIO_SET_ID               _IO('o', 13)
-#define AUDIO_SET_MIXER            _IOW('o', 14, audio_mixer_t)
-#define AUDIO_SET_STREAMTYPE       _IO('o', 15)
-#define AUDIO_SET_EXT_ID           _IO('o', 16)
-#define AUDIO_SET_ATTRIBUTES       _IOW('o', 17, audio_attributes_t)
-#define AUDIO_SET_KARAOKE          _IOW('o', 18, audio_karaoke_t)
-
-/**
- * AUDIO_GET_PTS
- *
- * Read the 33 bit presentation time stamp as defined
- * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
- *
- * The PTS should belong to the currently played
- * frame if possible, but may also be a value close to it
- * like the PTS of the last decoded frame or the last PTS
- * extracted by the PES parser.
- */
-#define AUDIO_GET_PTS              _IOR('o', 19, __u64)
-#define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20)
-
-#endif /* _DVBAUDIO_H_ */
diff --git a/include/linux/dvb/ca.h b/include/linux/dvb/ca.h
deleted file mode 100644 (file)
index c18537f..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * ca.h
- *
- * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
- *                  & Marcus Metzler <marcus@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVBCA_H_
-#define _DVBCA_H_
-
-/* slot interface types and info */
-
-typedef struct ca_slot_info {
-       int num;               /* slot number */
-
-       int type;              /* CA interface this slot supports */
-#define CA_CI            1     /* CI high level interface */
-#define CA_CI_LINK       2     /* CI link layer level interface */
-#define CA_CI_PHYS       4     /* CI physical layer level interface */
-#define CA_DESCR         8     /* built-in descrambler */
-#define CA_SC          128     /* simple smart card interface */
-
-       unsigned int flags;
-#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */
-#define CA_CI_MODULE_READY   2
-} ca_slot_info_t;
-
-
-/* descrambler types and info */
-
-typedef struct ca_descr_info {
-       unsigned int num;          /* number of available descramblers (keys) */
-       unsigned int type;         /* type of supported scrambling system */
-#define CA_ECD           1
-#define CA_NDS           2
-#define CA_DSS           4
-} ca_descr_info_t;
-
-typedef struct ca_caps {
-       unsigned int slot_num;     /* total number of CA card and module slots */
-       unsigned int slot_type;    /* OR of all supported types */
-       unsigned int descr_num;    /* total number of descrambler slots (keys) */
-       unsigned int descr_type;   /* OR of all supported types */
-} ca_caps_t;
-
-/* a message to/from a CI-CAM */
-typedef struct ca_msg {
-       unsigned int index;
-       unsigned int type;
-       unsigned int length;
-       unsigned char msg[256];
-} ca_msg_t;
-
-typedef struct ca_descr {
-       unsigned int index;
-       unsigned int parity;    /* 0 == even, 1 == odd */
-       unsigned char cw[8];
-} ca_descr_t;
-
-typedef struct ca_pid {
-       unsigned int pid;
-       int index;              /* -1 == disable*/
-} ca_pid_t;
-
-#define CA_RESET          _IO('o', 128)
-#define CA_GET_CAP        _IOR('o', 129, ca_caps_t)
-#define CA_GET_SLOT_INFO  _IOR('o', 130, ca_slot_info_t)
-#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
-#define CA_GET_MSG        _IOR('o', 132, ca_msg_t)
-#define CA_SEND_MSG       _IOW('o', 133, ca_msg_t)
-#define CA_SET_DESCR      _IOW('o', 134, ca_descr_t)
-#define CA_SET_PID        _IOW('o', 135, ca_pid_t)
-
-#endif
index f078f3ac82d4bc606c345926722fefce6fdb4abe..0be6d8f2b52b99f501eaac22fa9c7117749e60a7 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
  */
-
 #ifndef _DVBDMX_H_
 #define _DVBDMX_H_
 
-#include <linux/types.h>
-#ifdef __KERNEL__
 #include <linux/time.h>
-#else
-#include <time.h>
-#endif
-
-
-#define DMX_FILTER_SIZE 16
-
-typedef enum
-{
-       DMX_OUT_DECODER, /* Streaming directly to decoder. */
-       DMX_OUT_TAP,     /* Output going to a memory buffer */
-                        /* (to be retrieved via the read command).*/
-       DMX_OUT_TS_TAP,  /* Output multiplexed into a new TS  */
-                        /* (to be retrieved by reading from the */
-                        /* logical DVR device).                 */
-       DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
-} dmx_output_t;
-
-
-typedef enum
-{
-       DMX_IN_FRONTEND, /* Input from a front-end device.  */
-       DMX_IN_DVR       /* Input from the logical DVR device.  */
-} dmx_input_t;
-
-
-typedef enum
-{
-       DMX_PES_AUDIO0,
-       DMX_PES_VIDEO0,
-       DMX_PES_TELETEXT0,
-       DMX_PES_SUBTITLE0,
-       DMX_PES_PCR0,
-
-       DMX_PES_AUDIO1,
-       DMX_PES_VIDEO1,
-       DMX_PES_TELETEXT1,
-       DMX_PES_SUBTITLE1,
-       DMX_PES_PCR1,
-
-       DMX_PES_AUDIO2,
-       DMX_PES_VIDEO2,
-       DMX_PES_TELETEXT2,
-       DMX_PES_SUBTITLE2,
-       DMX_PES_PCR2,
-
-       DMX_PES_AUDIO3,
-       DMX_PES_VIDEO3,
-       DMX_PES_TELETEXT3,
-       DMX_PES_SUBTITLE3,
-       DMX_PES_PCR3,
-
-       DMX_PES_OTHER
-} dmx_pes_type_t;
-
-#define DMX_PES_AUDIO    DMX_PES_AUDIO0
-#define DMX_PES_VIDEO    DMX_PES_VIDEO0
-#define DMX_PES_TELETEXT DMX_PES_TELETEXT0
-#define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0
-#define DMX_PES_PCR      DMX_PES_PCR0
-
-
-typedef struct dmx_filter
-{
-       __u8  filter[DMX_FILTER_SIZE];
-       __u8  mask[DMX_FILTER_SIZE];
-       __u8  mode[DMX_FILTER_SIZE];
-} dmx_filter_t;
-
-
-struct dmx_sct_filter_params
-{
-       __u16          pid;
-       dmx_filter_t   filter;
-       __u32          timeout;
-       __u32          flags;
-#define DMX_CHECK_CRC       1
-#define DMX_ONESHOT         2
-#define DMX_IMMEDIATE_START 4
-#define DMX_KERNEL_CLIENT   0x8000
-};
-
-
-struct dmx_pes_filter_params
-{
-       __u16          pid;
-       dmx_input_t    input;
-       dmx_output_t   output;
-       dmx_pes_type_t pes_type;
-       __u32          flags;
-};
-
-typedef struct dmx_caps {
-       __u32 caps;
-       int num_decoders;
-} dmx_caps_t;
-
-typedef enum {
-       DMX_SOURCE_FRONT0 = 0,
-       DMX_SOURCE_FRONT1,
-       DMX_SOURCE_FRONT2,
-       DMX_SOURCE_FRONT3,
-       DMX_SOURCE_DVR0   = 16,
-       DMX_SOURCE_DVR1,
-       DMX_SOURCE_DVR2,
-       DMX_SOURCE_DVR3
-} dmx_source_t;
-
-struct dmx_stc {
-       unsigned int num;       /* input : which STC? 0..N */
-       unsigned int base;      /* output: divisor for stc to get 90 kHz clock */
-       __u64 stc;              /* output: stc in 'base'*90 kHz units */
-};
-
-
-#define DMX_START                _IO('o', 41)
-#define DMX_STOP                 _IO('o', 42)
-#define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
-#define DMX_SET_PES_FILTER       _IOW('o', 44, struct dmx_pes_filter_params)
-#define DMX_SET_BUFFER_SIZE      _IO('o', 45)
-#define DMX_GET_PES_PIDS         _IOR('o', 47, __u16[5])
-#define DMX_GET_CAPS             _IOR('o', 48, dmx_caps_t)
-#define DMX_SET_SOURCE           _IOW('o', 49, dmx_source_t)
-#define DMX_GET_STC              _IOWR('o', 50, struct dmx_stc)
-#define DMX_ADD_PID              _IOW('o', 51, __u16)
-#define DMX_REMOVE_PID           _IOW('o', 52, __u16)
+#include <uapi/linux/dvb/dmx.h>
 
 #endif /*_DVBDMX_H_*/
diff --git a/include/linux/dvb/frontend.h b/include/linux/dvb/frontend.h
deleted file mode 100644 (file)
index c12d452..0000000
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * frontend.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- *                 Ralph  Metzler <ralph@convergence.de>
- *                 Holger Waechtler <holger@convergence.de>
- *                 Andre Draszik <ad@convergence.de>
- *                 for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVBFRONTEND_H_
-#define _DVBFRONTEND_H_
-
-#include <linux/types.h>
-
-typedef enum fe_type {
-       FE_QPSK,
-       FE_QAM,
-       FE_OFDM,
-       FE_ATSC
-} fe_type_t;
-
-
-typedef enum fe_caps {
-       FE_IS_STUPID                    = 0,
-       FE_CAN_INVERSION_AUTO           = 0x1,
-       FE_CAN_FEC_1_2                  = 0x2,
-       FE_CAN_FEC_2_3                  = 0x4,
-       FE_CAN_FEC_3_4                  = 0x8,
-       FE_CAN_FEC_4_5                  = 0x10,
-       FE_CAN_FEC_5_6                  = 0x20,
-       FE_CAN_FEC_6_7                  = 0x40,
-       FE_CAN_FEC_7_8                  = 0x80,
-       FE_CAN_FEC_8_9                  = 0x100,
-       FE_CAN_FEC_AUTO                 = 0x200,
-       FE_CAN_QPSK                     = 0x400,
-       FE_CAN_QAM_16                   = 0x800,
-       FE_CAN_QAM_32                   = 0x1000,
-       FE_CAN_QAM_64                   = 0x2000,
-       FE_CAN_QAM_128                  = 0x4000,
-       FE_CAN_QAM_256                  = 0x8000,
-       FE_CAN_QAM_AUTO                 = 0x10000,
-       FE_CAN_TRANSMISSION_MODE_AUTO   = 0x20000,
-       FE_CAN_BANDWIDTH_AUTO           = 0x40000,
-       FE_CAN_GUARD_INTERVAL_AUTO      = 0x80000,
-       FE_CAN_HIERARCHY_AUTO           = 0x100000,
-       FE_CAN_8VSB                     = 0x200000,
-       FE_CAN_16VSB                    = 0x400000,
-       FE_HAS_EXTENDED_CAPS            = 0x800000,   /* We need more bitspace for newer APIs, indicate this. */
-       FE_CAN_MULTISTREAM              = 0x4000000,  /* frontend supports multistream filtering */
-       FE_CAN_TURBO_FEC                = 0x8000000,  /* frontend supports "turbo fec modulation" */
-       FE_CAN_2G_MODULATION            = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
-       FE_NEEDS_BENDING                = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
-       FE_CAN_RECOVER                  = 0x40000000, /* frontend can recover from a cable unplug automatically */
-       FE_CAN_MUTE_TS                  = 0x80000000  /* frontend can stop spurious TS data output */
-} fe_caps_t;
-
-
-struct dvb_frontend_info {
-       char       name[128];
-       fe_type_t  type;                        /* DEPRECATED. Use DTV_ENUM_DELSYS instead */
-       __u32      frequency_min;
-       __u32      frequency_max;
-       __u32      frequency_stepsize;
-       __u32      frequency_tolerance;
-       __u32      symbol_rate_min;
-       __u32      symbol_rate_max;
-       __u32      symbol_rate_tolerance;       /* ppm */
-       __u32      notifier_delay;              /* DEPRECATED */
-       fe_caps_t  caps;
-};
-
-
-/**
- *  Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for
- *  the meaning of this struct...
- */
-struct dvb_diseqc_master_cmd {
-       __u8 msg [6];   /*  { framing, address, command, data [3] } */
-       __u8 msg_len;   /*  valid values are 3...6  */
-};
-
-
-struct dvb_diseqc_slave_reply {
-       __u8 msg [4];   /*  { framing, data [3] } */
-       __u8 msg_len;   /*  valid values are 0...4, 0 means no msg  */
-       int  timeout;   /*  return from ioctl after timeout ms with */
-};                     /*  errorcode when no message was received  */
-
-
-typedef enum fe_sec_voltage {
-       SEC_VOLTAGE_13,
-       SEC_VOLTAGE_18,
-       SEC_VOLTAGE_OFF
-} fe_sec_voltage_t;
-
-
-typedef enum fe_sec_tone_mode {
-       SEC_TONE_ON,
-       SEC_TONE_OFF
-} fe_sec_tone_mode_t;
-
-
-typedef enum fe_sec_mini_cmd {
-       SEC_MINI_A,
-       SEC_MINI_B
-} fe_sec_mini_cmd_t;
-
-
-/**
- * enum fe_status - enumerates the possible frontend status
- * @FE_HAS_SIGNAL:     found something above the noise level
- * @FE_HAS_CARRIER:    found a DVB signal
- * @FE_HAS_VITERBI:    FEC is stable
- * @FE_HAS_SYNC:       found sync bytes
- * @FE_HAS_LOCK:       everything's working
- * @FE_TIMEDOUT:       no lock within the last ~2 seconds
- * @FE_REINIT:         frontend was reinitialized, application is recommended
- *                     to reset DiSEqC, tone and parameters
- */
-
-typedef enum fe_status {
-       FE_HAS_SIGNAL           = 0x01,
-       FE_HAS_CARRIER          = 0x02,
-       FE_HAS_VITERBI          = 0x04,
-       FE_HAS_SYNC             = 0x08,
-       FE_HAS_LOCK             = 0x10,
-       FE_TIMEDOUT             = 0x20,
-       FE_REINIT               = 0x40,
-} fe_status_t;
-
-typedef enum fe_spectral_inversion {
-       INVERSION_OFF,
-       INVERSION_ON,
-       INVERSION_AUTO
-} fe_spectral_inversion_t;
-
-
-typedef enum fe_code_rate {
-       FEC_NONE = 0,
-       FEC_1_2,
-       FEC_2_3,
-       FEC_3_4,
-       FEC_4_5,
-       FEC_5_6,
-       FEC_6_7,
-       FEC_7_8,
-       FEC_8_9,
-       FEC_AUTO,
-       FEC_3_5,
-       FEC_9_10,
-       FEC_2_5,
-} fe_code_rate_t;
-
-
-typedef enum fe_modulation {
-       QPSK,
-       QAM_16,
-       QAM_32,
-       QAM_64,
-       QAM_128,
-       QAM_256,
-       QAM_AUTO,
-       VSB_8,
-       VSB_16,
-       PSK_8,
-       APSK_16,
-       APSK_32,
-       DQPSK,
-       QAM_4_NR,
-} fe_modulation_t;
-
-typedef enum fe_transmit_mode {
-       TRANSMISSION_MODE_2K,
-       TRANSMISSION_MODE_8K,
-       TRANSMISSION_MODE_AUTO,
-       TRANSMISSION_MODE_4K,
-       TRANSMISSION_MODE_1K,
-       TRANSMISSION_MODE_16K,
-       TRANSMISSION_MODE_32K,
-       TRANSMISSION_MODE_C1,
-       TRANSMISSION_MODE_C3780,
-} fe_transmit_mode_t;
-
-#if defined(__DVB_CORE__) || !defined (__KERNEL__)
-typedef enum fe_bandwidth {
-       BANDWIDTH_8_MHZ,
-       BANDWIDTH_7_MHZ,
-       BANDWIDTH_6_MHZ,
-       BANDWIDTH_AUTO,
-       BANDWIDTH_5_MHZ,
-       BANDWIDTH_10_MHZ,
-       BANDWIDTH_1_712_MHZ,
-} fe_bandwidth_t;
-#endif
-
-typedef enum fe_guard_interval {
-       GUARD_INTERVAL_1_32,
-       GUARD_INTERVAL_1_16,
-       GUARD_INTERVAL_1_8,
-       GUARD_INTERVAL_1_4,
-       GUARD_INTERVAL_AUTO,
-       GUARD_INTERVAL_1_128,
-       GUARD_INTERVAL_19_128,
-       GUARD_INTERVAL_19_256,
-       GUARD_INTERVAL_PN420,
-       GUARD_INTERVAL_PN595,
-       GUARD_INTERVAL_PN945,
-} fe_guard_interval_t;
-
-
-typedef enum fe_hierarchy {
-       HIERARCHY_NONE,
-       HIERARCHY_1,
-       HIERARCHY_2,
-       HIERARCHY_4,
-       HIERARCHY_AUTO
-} fe_hierarchy_t;
-
-enum fe_interleaving {
-       INTERLEAVING_NONE,
-       INTERLEAVING_AUTO,
-       INTERLEAVING_240,
-       INTERLEAVING_720,
-};
-
-#if defined(__DVB_CORE__) || !defined (__KERNEL__)
-struct dvb_qpsk_parameters {
-       __u32           symbol_rate;  /* symbol rate in Symbols per second */
-       fe_code_rate_t  fec_inner;    /* forward error correction (see above) */
-};
-
-struct dvb_qam_parameters {
-       __u32           symbol_rate; /* symbol rate in Symbols per second */
-       fe_code_rate_t  fec_inner;   /* forward error correction (see above) */
-       fe_modulation_t modulation;  /* modulation type (see above) */
-};
-
-struct dvb_vsb_parameters {
-       fe_modulation_t modulation;  /* modulation type (see above) */
-};
-
-struct dvb_ofdm_parameters {
-       fe_bandwidth_t      bandwidth;
-       fe_code_rate_t      code_rate_HP;  /* high priority stream code rate */
-       fe_code_rate_t      code_rate_LP;  /* low priority stream code rate */
-       fe_modulation_t     constellation; /* modulation type (see above) */
-       fe_transmit_mode_t  transmission_mode;
-       fe_guard_interval_t guard_interval;
-       fe_hierarchy_t      hierarchy_information;
-};
-
-
-struct dvb_frontend_parameters {
-       __u32 frequency;     /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
-                            /* intermediate frequency in kHz for QPSK */
-       fe_spectral_inversion_t inversion;
-       union {
-               struct dvb_qpsk_parameters qpsk;
-               struct dvb_qam_parameters  qam;
-               struct dvb_ofdm_parameters ofdm;
-               struct dvb_vsb_parameters vsb;
-       } u;
-};
-
-struct dvb_frontend_event {
-       fe_status_t status;
-       struct dvb_frontend_parameters parameters;
-};
-#endif
-
-/* S2API Commands */
-#define DTV_UNDEFINED          0
-#define DTV_TUNE               1
-#define DTV_CLEAR              2
-#define DTV_FREQUENCY          3
-#define DTV_MODULATION         4
-#define DTV_BANDWIDTH_HZ       5
-#define DTV_INVERSION          6
-#define DTV_DISEQC_MASTER      7
-#define DTV_SYMBOL_RATE                8
-#define DTV_INNER_FEC          9
-#define DTV_VOLTAGE            10
-#define DTV_TONE               11
-#define DTV_PILOT              12
-#define DTV_ROLLOFF            13
-#define DTV_DISEQC_SLAVE_REPLY 14
-
-/* Basic enumeration set for querying unlimited capabilities */
-#define DTV_FE_CAPABILITY_COUNT        15
-#define DTV_FE_CAPABILITY      16
-#define DTV_DELIVERY_SYSTEM    17
-
-/* ISDB-T and ISDB-Tsb */
-#define DTV_ISDBT_PARTIAL_RECEPTION    18
-#define DTV_ISDBT_SOUND_BROADCASTING   19
-
-#define DTV_ISDBT_SB_SUBCHANNEL_ID     20
-#define DTV_ISDBT_SB_SEGMENT_IDX       21
-#define DTV_ISDBT_SB_SEGMENT_COUNT     22
-
-#define DTV_ISDBT_LAYERA_FEC                   23
-#define DTV_ISDBT_LAYERA_MODULATION            24
-#define DTV_ISDBT_LAYERA_SEGMENT_COUNT         25
-#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING     26
-
-#define DTV_ISDBT_LAYERB_FEC                   27
-#define DTV_ISDBT_LAYERB_MODULATION            28
-#define DTV_ISDBT_LAYERB_SEGMENT_COUNT         29
-#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING     30
-
-#define DTV_ISDBT_LAYERC_FEC                   31
-#define DTV_ISDBT_LAYERC_MODULATION            32
-#define DTV_ISDBT_LAYERC_SEGMENT_COUNT         33
-#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING     34
-
-#define DTV_API_VERSION                35
-
-#define DTV_CODE_RATE_HP       36
-#define DTV_CODE_RATE_LP       37
-#define DTV_GUARD_INTERVAL     38
-#define DTV_TRANSMISSION_MODE  39
-#define DTV_HIERARCHY          40
-
-#define DTV_ISDBT_LAYER_ENABLED        41
-
-#define DTV_STREAM_ID          42
-#define DTV_ISDBS_TS_ID_LEGACY DTV_STREAM_ID
-#define DTV_DVBT2_PLP_ID_LEGACY        43
-
-#define DTV_ENUM_DELSYS                44
-
-/* ATSC-MH */
-#define DTV_ATSCMH_FIC_VER             45
-#define DTV_ATSCMH_PARADE_ID           46
-#define DTV_ATSCMH_NOG                 47
-#define DTV_ATSCMH_TNOG                        48
-#define DTV_ATSCMH_SGN                 49
-#define DTV_ATSCMH_PRC                 50
-#define DTV_ATSCMH_RS_FRAME_MODE       51
-#define DTV_ATSCMH_RS_FRAME_ENSEMBLE   52
-#define DTV_ATSCMH_RS_CODE_MODE_PRI    53
-#define DTV_ATSCMH_RS_CODE_MODE_SEC    54
-#define DTV_ATSCMH_SCCC_BLOCK_MODE     55
-#define DTV_ATSCMH_SCCC_CODE_MODE_A    56
-#define DTV_ATSCMH_SCCC_CODE_MODE_B    57
-#define DTV_ATSCMH_SCCC_CODE_MODE_C    58
-#define DTV_ATSCMH_SCCC_CODE_MODE_D    59
-
-#define DTV_INTERLEAVING                       60
-#define DTV_LNA                                        61
-
-#define DTV_MAX_COMMAND                                DTV_LNA
-
-typedef enum fe_pilot {
-       PILOT_ON,
-       PILOT_OFF,
-       PILOT_AUTO,
-} fe_pilot_t;
-
-typedef enum fe_rolloff {
-       ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */
-       ROLLOFF_20,
-       ROLLOFF_25,
-       ROLLOFF_AUTO,
-} fe_rolloff_t;
-
-typedef enum fe_delivery_system {
-       SYS_UNDEFINED,
-       SYS_DVBC_ANNEX_A,
-       SYS_DVBC_ANNEX_B,
-       SYS_DVBT,
-       SYS_DSS,
-       SYS_DVBS,
-       SYS_DVBS2,
-       SYS_DVBH,
-       SYS_ISDBT,
-       SYS_ISDBS,
-       SYS_ISDBC,
-       SYS_ATSC,
-       SYS_ATSCMH,
-       SYS_DTMB,
-       SYS_CMMB,
-       SYS_DAB,
-       SYS_DVBT2,
-       SYS_TURBO,
-       SYS_DVBC_ANNEX_C,
-} fe_delivery_system_t;
-
-/* backward compatibility */
-#define SYS_DVBC_ANNEX_AC      SYS_DVBC_ANNEX_A
-#define SYS_DMBTH SYS_DTMB /* DMB-TH is legacy name, use DTMB instead */
-
-/* ATSC-MH */
-
-enum atscmh_sccc_block_mode {
-       ATSCMH_SCCC_BLK_SEP      = 0,
-       ATSCMH_SCCC_BLK_COMB     = 1,
-       ATSCMH_SCCC_BLK_RES      = 2,
-};
-
-enum atscmh_sccc_code_mode {
-       ATSCMH_SCCC_CODE_HLF     = 0,
-       ATSCMH_SCCC_CODE_QTR     = 1,
-       ATSCMH_SCCC_CODE_RES     = 2,
-};
-
-enum atscmh_rs_frame_ensemble {
-       ATSCMH_RSFRAME_ENS_PRI   = 0,
-       ATSCMH_RSFRAME_ENS_SEC   = 1,
-};
-
-enum atscmh_rs_frame_mode {
-       ATSCMH_RSFRAME_PRI_ONLY  = 0,
-       ATSCMH_RSFRAME_PRI_SEC   = 1,
-       ATSCMH_RSFRAME_RES       = 2,
-};
-
-enum atscmh_rs_code_mode {
-       ATSCMH_RSCODE_211_187    = 0,
-       ATSCMH_RSCODE_223_187    = 1,
-       ATSCMH_RSCODE_235_187    = 2,
-       ATSCMH_RSCODE_RES        = 3,
-};
-
-#define NO_STREAM_ID_FILTER    (~0U)
-#define LNA_AUTO                (~0U)
-
-struct dtv_cmds_h {
-       char    *name;          /* A display name for debugging purposes */
-
-       __u32   cmd;            /* A unique ID */
-
-       /* Flags */
-       __u32   set:1;          /* Either a set or get property */
-       __u32   buffer:1;       /* Does this property use the buffer? */
-       __u32   reserved:30;    /* Align */
-};
-
-struct dtv_property {
-       __u32 cmd;
-       __u32 reserved[3];
-       union {
-               __u32 data;
-               struct {
-                       __u8 data[32];
-                       __u32 len;
-                       __u32 reserved1[3];
-                       void *reserved2;
-               } buffer;
-       } u;
-       int result;
-} __attribute__ ((packed));
-
-/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
-#define DTV_IOCTL_MAX_MSGS 64
-
-struct dtv_properties {
-       __u32 num;
-       struct dtv_property *props;
-};
-
-#define FE_SET_PROPERTY                   _IOW('o', 82, struct dtv_properties)
-#define FE_GET_PROPERTY                   _IOR('o', 83, struct dtv_properties)
-
-
-/**
- * When set, this flag will disable any zigzagging or other "normal" tuning
- * behaviour. Additionally, there will be no automatic monitoring of the lock
- * status, and hence no frontend events will be generated. If a frontend device
- * is closed, this flag will be automatically turned off when the device is
- * reopened read-write.
- */
-#define FE_TUNE_MODE_ONESHOT 0x01
-
-
-#define FE_GET_INFO               _IOR('o', 61, struct dvb_frontend_info)
-
-#define FE_DISEQC_RESET_OVERLOAD   _IO('o', 62)
-#define FE_DISEQC_SEND_MASTER_CMD  _IOW('o', 63, struct dvb_diseqc_master_cmd)
-#define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply)
-#define FE_DISEQC_SEND_BURST       _IO('o', 65)  /* fe_sec_mini_cmd_t */
-
-#define FE_SET_TONE               _IO('o', 66)  /* fe_sec_tone_mode_t */
-#define FE_SET_VOLTAGE            _IO('o', 67)  /* fe_sec_voltage_t */
-#define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68)  /* int */
-
-#define FE_READ_STATUS            _IOR('o', 69, fe_status_t)
-#define FE_READ_BER               _IOR('o', 70, __u32)
-#define FE_READ_SIGNAL_STRENGTH    _IOR('o', 71, __u16)
-#define FE_READ_SNR               _IOR('o', 72, __u16)
-#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32)
-
-#define FE_SET_FRONTEND                   _IOW('o', 76, struct dvb_frontend_parameters)
-#define FE_GET_FRONTEND                   _IOR('o', 77, struct dvb_frontend_parameters)
-#define FE_SET_FRONTEND_TUNE_MODE  _IO('o', 81) /* unsigned int */
-#define FE_GET_EVENT              _IOR('o', 78, struct dvb_frontend_event)
-
-#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
-
-#endif /*_DVBFRONTEND_H_*/
diff --git a/include/linux/dvb/net.h b/include/linux/dvb/net.h
deleted file mode 100644 (file)
index f451e7e..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * net.h
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- *                  & Ralph  Metzler <ralph@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVBNET_H_
-#define _DVBNET_H_
-
-#include <linux/types.h>
-
-struct dvb_net_if {
-       __u16 pid;
-       __u16 if_num;
-       __u8  feedtype;
-#define DVB_NET_FEEDTYPE_MPE 0 /* multi protocol encapsulation */
-#define DVB_NET_FEEDTYPE_ULE 1 /* ultra lightweight encapsulation */
-};
-
-
-#define NET_ADD_IF    _IOWR('o', 52, struct dvb_net_if)
-#define NET_REMOVE_IF _IO('o', 53)
-#define NET_GET_IF    _IOWR('o', 54, struct dvb_net_if)
-
-
-/* binary compatibility cruft: */
-struct __dvb_net_if_old {
-       __u16 pid;
-       __u16 if_num;
-};
-#define __NET_ADD_IF_OLD _IOWR('o', 52, struct __dvb_net_if_old)
-#define __NET_GET_IF_OLD _IOWR('o', 54, struct __dvb_net_if_old)
-
-
-#endif /*_DVBNET_H_*/
diff --git a/include/linux/dvb/osd.h b/include/linux/dvb/osd.h
deleted file mode 100644 (file)
index 880e684..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * osd.h
- *
- * Copyright (C) 2001 Ralph  Metzler <ralph@convergence.de>
- *                  & Marcus Metzler <marcus@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVBOSD_H_
-#define _DVBOSD_H_
-
-#include <linux/compiler.h>
-
-typedef enum {
-  // All functions return -2 on "not open"
-  OSD_Close=1,    // ()
-  // Disables OSD and releases the buffers
-  // returns 0 on success
-  OSD_Open,       // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0))
-  // Opens OSD with this size and bit depth
-  // returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
-  OSD_Show,       // ()
-  // enables OSD mode
-  // returns 0 on success
-  OSD_Hide,       // ()
-  // disables OSD mode
-  // returns 0 on success
-  OSD_Clear,      // ()
-  // Sets all pixel to color 0
-  // returns 0 on success
-  OSD_Fill,       // (color)
-  // Sets all pixel to color <col>
-  // returns 0 on success
-  OSD_SetColor,   // (color,R{x0},G{y0},B{x1},opacity{y1})
-  // set palette entry <num> to <r,g,b>, <mix> and <trans> apply
-  // R,G,B: 0..255
-  // R=Red, G=Green, B=Blue
-  // opacity=0:      pixel opacity 0% (only video pixel shows)
-  // opacity=1..254: pixel opacity as specified in header
-  // opacity=255:    pixel opacity 100% (only OSD pixel shows)
-  // returns 0 on success, -1 on error
-  OSD_SetPalette, // (firstcolor{color},lastcolor{x0},data)
-  // Set a number of entries in the palette
-  // sets the entries "firstcolor" through "lastcolor" from the array "data"
-  // data has 4 byte for each color:
-  // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
-  OSD_SetTrans,   // (transparency{color})
-  // Sets transparency of mixed pixel (0..15)
-  // returns 0 on success
-  OSD_SetPixel,   // (x0,y0,color)
-  // sets pixel <x>,<y> to color number <col>
-  // returns 0 on success, -1 on error
-  OSD_GetPixel,   // (x0,y0)
-  // returns color number of pixel <x>,<y>,  or -1
-  OSD_SetRow,     // (x0,y0,x1,data)
-  // fills pixels x0,y through  x1,y with the content of data[]
-  // returns 0 on success, -1 on clipping all pixel (no pixel drawn)
-  OSD_SetBlock,   // (x0,y0,x1,y1,increment{color},data)
-  // fills pixels x0,y0 through  x1,y1 with the content of data[]
-  // inc contains the width of one line in the data block,
-  // inc<=0 uses blockwidth as linewidth
-  // returns 0 on success, -1 on clipping all pixel
-  OSD_FillRow,    // (x0,y0,x1,color)
-  // fills pixels x0,y through  x1,y with the color <col>
-  // returns 0 on success, -1 on clipping all pixel
-  OSD_FillBlock,  // (x0,y0,x1,y1,color)
-  // fills pixels x0,y0 through  x1,y1 with the color <col>
-  // returns 0 on success, -1 on clipping all pixel
-  OSD_Line,       // (x0,y0,x1,y1,color)
-  // draw a line from x0,y0 to x1,y1 with the color <col>
-  // returns 0 on success
-  OSD_Query,      // (x0,y0,x1,y1,xasp{color}}), yasp=11
-  // fills parameters with the picture dimensions and the pixel aspect ratio
-  // returns 0 on success
-  OSD_Test,       // ()
-  // draws a test picture. for debugging purposes only
-  // returns 0 on success
-// TODO: remove "test" in final version
-  OSD_Text,       // (x0,y0,size,color,text)
-  OSD_SetWindow, //  (x0) set window with number 0<x0<8 as current
-  OSD_MoveWindow, //  move current window to (x0, y0)
-  OSD_OpenRaw, // Open other types of OSD windows
-} OSD_Command;
-
-typedef struct osd_cmd_s {
-       OSD_Command cmd;
-       int x0;
-       int y0;
-       int x1;
-       int y1;
-       int color;
-       void __user *data;
-} osd_cmd_t;
-
-/* OSD_OpenRaw: set 'color' to desired window type */
-typedef enum {
-       OSD_BITMAP1,           /* 1 bit bitmap */
-       OSD_BITMAP2,           /* 2 bit bitmap */
-       OSD_BITMAP4,           /* 4 bit bitmap */
-       OSD_BITMAP8,           /* 8 bit bitmap */
-       OSD_BITMAP1HR,         /* 1 Bit bitmap half resolution */
-       OSD_BITMAP2HR,         /* 2 bit bitmap half resolution */
-       OSD_BITMAP4HR,         /* 4 bit bitmap half resolution */
-       OSD_BITMAP8HR,         /* 8 bit bitmap half resolution */
-       OSD_YCRCB422,          /* 4:2:2 YCRCB Graphic Display */
-       OSD_YCRCB444,          /* 4:4:4 YCRCB Graphic Display */
-       OSD_YCRCB444HR,        /* 4:4:4 YCRCB graphic half resolution */
-       OSD_VIDEOTSIZE,        /* True Size Normal MPEG Video Display */
-       OSD_VIDEOHSIZE,        /* MPEG Video Display Half Resolution */
-       OSD_VIDEOQSIZE,        /* MPEG Video Display Quarter Resolution */
-       OSD_VIDEODSIZE,        /* MPEG Video Display Double Resolution */
-       OSD_VIDEOTHSIZE,       /* True Size MPEG Video Display Half Resolution */
-       OSD_VIDEOTQSIZE,       /* True Size MPEG Video Display Quarter Resolution*/
-       OSD_VIDEOTDSIZE,       /* True Size MPEG Video Display Double Resolution */
-       OSD_VIDEONSIZE,        /* Full Size MPEG Video Display */
-       OSD_CURSOR             /* Cursor */
-} osd_raw_window_t;
-
-typedef struct osd_cap_s {
-       int  cmd;
-#define OSD_CAP_MEMSIZE         1  /* memory size */
-       long val;
-} osd_cap_t;
-
-
-#define OSD_SEND_CMD            _IOW('o', 160, osd_cmd_t)
-#define OSD_GET_CAPABILITY      _IOR('o', 161, osd_cap_t)
-
-#endif
diff --git a/include/linux/dvb/version.h b/include/linux/dvb/version.h
deleted file mode 100644 (file)
index 827cce7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * version.h
- *
- * Copyright (C) 2000 Holger Waechtler <holger@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * 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 Lesser General Public 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 _DVBVERSION_H_
-#define _DVBVERSION_H_
-
-#define DVB_API_VERSION 5
-#define DVB_API_VERSION_MINOR 9
-
-#endif /*_DVBVERSION_H_*/
index 1d750c0fd86e1622505c4761fef63ec383b4dba9..85c20d925696d56c33ad2f7683b919ab2b3ff7df 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  *
  */
-
 #ifndef _DVBVIDEO_H_
 #define _DVBVIDEO_H_
 
-#include <linux/types.h>
-#ifdef __KERNEL__
 #include <linux/compiler.h>
-#else
-#include <stdint.h>
-#include <time.h>
-#endif
-
-typedef enum {
-       VIDEO_FORMAT_4_3,     /* Select 4:3 format */
-       VIDEO_FORMAT_16_9,    /* Select 16:9 format. */
-       VIDEO_FORMAT_221_1    /* 2.21:1 */
-} video_format_t;
-
-
-typedef enum {
-        VIDEO_SYSTEM_PAL,
-        VIDEO_SYSTEM_NTSC,
-        VIDEO_SYSTEM_PALN,
-        VIDEO_SYSTEM_PALNc,
-        VIDEO_SYSTEM_PALM,
-        VIDEO_SYSTEM_NTSC60,
-        VIDEO_SYSTEM_PAL60,
-        VIDEO_SYSTEM_PALM60
-} video_system_t;
-
-
-typedef enum {
-       VIDEO_PAN_SCAN,       /* use pan and scan format */
-       VIDEO_LETTER_BOX,     /* use letterbox format */
-       VIDEO_CENTER_CUT_OUT  /* use center cut out format */
-} video_displayformat_t;
-
-typedef struct {
-       int w;
-       int h;
-       video_format_t aspect_ratio;
-} video_size_t;
-
-typedef enum {
-       VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
-       VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
-                              comes from the user through the write
-                              system call */
-} video_stream_source_t;
-
-
-typedef enum {
-       VIDEO_STOPPED, /* Video is stopped */
-       VIDEO_PLAYING, /* Video is currently playing */
-       VIDEO_FREEZED  /* Video is freezed */
-} video_play_state_t;
-
-
-/* Decoder commands */
-#define VIDEO_CMD_PLAY        (0)
-#define VIDEO_CMD_STOP        (1)
-#define VIDEO_CMD_FREEZE      (2)
-#define VIDEO_CMD_CONTINUE    (3)
-
-/* Flags for VIDEO_CMD_FREEZE */
-#define VIDEO_CMD_FREEZE_TO_BLACK      (1 << 0)
-
-/* Flags for VIDEO_CMD_STOP */
-#define VIDEO_CMD_STOP_TO_BLACK        (1 << 0)
-#define VIDEO_CMD_STOP_IMMEDIATELY             (1 << 1)
-
-/* Play input formats: */
-/* The decoder has no special format requirements */
-#define VIDEO_PLAY_FMT_NONE         (0)
-/* The decoder requires full GOPs */
-#define VIDEO_PLAY_FMT_GOP          (1)
-
-/* The structure must be zeroed before use by the application
-   This ensures it can be extended safely in the future. */
-struct video_command {
-       __u32 cmd;
-       __u32 flags;
-       union {
-               struct {
-                       __u64 pts;
-               } stop;
-
-               struct {
-                       /* 0 or 1000 specifies normal speed,
-                          1 specifies forward single stepping,
-                          -1 specifies backward single stepping,
-                          >1: playback at speed/1000 of the normal speed,
-                          <-1: reverse playback at (-speed/1000) of the normal speed. */
-                       __s32 speed;
-                       __u32 format;
-               } play;
-
-               struct {
-                       __u32 data[16];
-               } raw;
-       };
-};
-
-/* FIELD_UNKNOWN can be used if the hardware does not know whether
-   the Vsync is for an odd, even or progressive (i.e. non-interlaced)
-   field. */
-#define VIDEO_VSYNC_FIELD_UNKNOWN      (0)
-#define VIDEO_VSYNC_FIELD_ODD          (1)
-#define VIDEO_VSYNC_FIELD_EVEN         (2)
-#define VIDEO_VSYNC_FIELD_PROGRESSIVE  (3)
-
-struct video_event {
-       __s32 type;
-#define VIDEO_EVENT_SIZE_CHANGED       1
-#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
-#define VIDEO_EVENT_DECODER_STOPPED    3
-#define VIDEO_EVENT_VSYNC              4
-       __kernel_time_t timestamp;
-       union {
-               video_size_t size;
-               unsigned int frame_rate;        /* in frames per 1000sec */
-               unsigned char vsync_field;      /* unknown/odd/even/progressive */
-       } u;
-};
-
-
-struct video_status {
-       int                   video_blank;   /* blank video on freeze? */
-       video_play_state_t    play_state;    /* current state of playback */
-       video_stream_source_t stream_source; /* current source (demux/memory) */
-       video_format_t        video_format;  /* current aspect ratio of stream*/
-       video_displayformat_t display_format;/* selected cropping mode */
-};
-
-
-struct video_still_picture {
-       char __user *iFrame;        /* pointer to a single iframe in memory */
-       __s32 size;
-};
-
-
-typedef
-struct video_highlight {
-       int     active;      /*    1=show highlight, 0=hide highlight */
-       __u8    contrast1;   /*    7- 4  Pattern pixel contrast */
-                            /*    3- 0  Background pixel contrast */
-       __u8    contrast2;   /*    7- 4  Emphasis pixel-2 contrast */
-                            /*    3- 0  Emphasis pixel-1 contrast */
-       __u8    color1;      /*    7- 4  Pattern pixel color */
-                            /*    3- 0  Background pixel color */
-       __u8    color2;      /*    7- 4  Emphasis pixel-2 color */
-                            /*    3- 0  Emphasis pixel-1 color */
-       __u32    ypos;       /*   23-22  auto action mode */
-                            /*   21-12  start y */
-                            /*    9- 0  end y */
-       __u32    xpos;       /*   23-22  button color number */
-                            /*   21-12  start x */
-                            /*    9- 0  end x */
-} video_highlight_t;
-
-
-typedef struct video_spu {
-       int active;
-       int stream_id;
-} video_spu_t;
-
-
-typedef struct video_spu_palette {      /* SPU Palette information */
-       int length;
-       __u8 __user *palette;
-} video_spu_palette_t;
-
-
-typedef struct video_navi_pack {
-       int length;          /* 0 ... 1024 */
-       __u8 data[1024];
-} video_navi_pack_t;
-
-
-typedef __u16 video_attributes_t;
-/*   bits: descr. */
-/*   15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
-/*   13-12 TV system (0=525/60, 1=625/50) */
-/*   11-10 Aspect ratio (0=4:3, 3=16:9) */
-/*    9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */
-/*    7    line 21-1 data present in GOP (1=yes, 0=no) */
-/*    6    line 21-2 data present in GOP (1=yes, 0=no) */
-/*    5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */
-/*    2    source letterboxed (1=yes, 0=no) */
-/*    0    film/camera mode (0=camera, 1=film (625/50 only)) */
-
-
-/* bit definitions for capabilities: */
-/* can the hardware decode MPEG1 and/or MPEG2? */
-#define VIDEO_CAP_MPEG1   1
-#define VIDEO_CAP_MPEG2   2
-/* can you send a system and/or program stream to video device?
-   (you still have to open the video and the audio device but only
-    send the stream to the video device) */
-#define VIDEO_CAP_SYS     4
-#define VIDEO_CAP_PROG    8
-/* can the driver also handle SPU, NAVI and CSS encoded data?
-   (CSS API is not present yet) */
-#define VIDEO_CAP_SPU    16
-#define VIDEO_CAP_NAVI   32
-#define VIDEO_CAP_CSS    64
-
-
-#define VIDEO_STOP                 _IO('o', 21)
-#define VIDEO_PLAY                 _IO('o', 22)
-#define VIDEO_FREEZE               _IO('o', 23)
-#define VIDEO_CONTINUE             _IO('o', 24)
-#define VIDEO_SELECT_SOURCE        _IO('o', 25)
-#define VIDEO_SET_BLANK            _IO('o', 26)
-#define VIDEO_GET_STATUS           _IOR('o', 27, struct video_status)
-#define VIDEO_GET_EVENT            _IOR('o', 28, struct video_event)
-#define VIDEO_SET_DISPLAY_FORMAT   _IO('o', 29)
-#define VIDEO_STILLPICTURE         _IOW('o', 30, struct video_still_picture)
-#define VIDEO_FAST_FORWARD         _IO('o', 31)
-#define VIDEO_SLOWMOTION           _IO('o', 32)
-#define VIDEO_GET_CAPABILITIES     _IOR('o', 33, unsigned int)
-#define VIDEO_CLEAR_BUFFER         _IO('o',  34)
-#define VIDEO_SET_ID               _IO('o', 35)
-#define VIDEO_SET_STREAMTYPE       _IO('o', 36)
-#define VIDEO_SET_FORMAT           _IO('o', 37)
-#define VIDEO_SET_SYSTEM           _IO('o', 38)
-#define VIDEO_SET_HIGHLIGHT        _IOW('o', 39, video_highlight_t)
-#define VIDEO_SET_SPU              _IOW('o', 50, video_spu_t)
-#define VIDEO_SET_SPU_PALETTE      _IOW('o', 51, video_spu_palette_t)
-#define VIDEO_GET_NAVI             _IOR('o', 52, video_navi_pack_t)
-#define VIDEO_SET_ATTRIBUTES       _IO('o', 53)
-#define VIDEO_GET_SIZE             _IOR('o', 55, video_size_t)
-#define VIDEO_GET_FRAME_RATE       _IOR('o', 56, unsigned int)
-
-/**
- * VIDEO_GET_PTS
- *
- * Read the 33 bit presentation time stamp as defined
- * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
- *
- * The PTS should belong to the currently played
- * frame if possible, but may also be a value close to it
- * like the PTS of the last decoded frame or the last PTS
- * extracted by the PES parser.
- */
-#define VIDEO_GET_PTS              _IOR('o', 57, __u64)
-
-/* Read the number of displayed frames since the decoder was started */
-#define VIDEO_GET_FRAME_COUNT             _IOR('o', 58, __u64)
-
-#define VIDEO_COMMAND             _IOWR('o', 59, struct video_command)
-#define VIDEO_TRY_COMMAND         _IOWR('o', 60, struct video_command)
+#include <uapi/linux/dvb/video.h>
 
 #endif /*_DVBVIDEO_H_*/
index c18257b0fa7219df00fb5c991cfcfe7c8f5e135a..6dd4787a798a2a561afefbe39021bea303bd785c 100644 (file)
@@ -61,7 +61,7 @@ int __dynamic_netdev_dbg(struct _ddebug *descriptor,
                         const char *fmt, ...);
 
 #define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt)               \
-       static struct _ddebug __used __aligned(8)               \
+       static struct _ddebug  __aligned(8)                     \
        __attribute__((section("__verbose"))) name = {          \
                .modname = KBUILD_MODNAME,                      \
                .function = __func__,                           \
diff --git a/include/linux/elf-fdpic.h b/include/linux/elf-fdpic.h
new file mode 100644 (file)
index 0000000..3864403
--- /dev/null
@@ -0,0 +1,51 @@
+/* FDPIC ELF load map
+ *
+ * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_ELF_FDPIC_H
+#define _LINUX_ELF_FDPIC_H
+
+#include <uapi/linux/elf-fdpic.h>
+
+/*
+ * binfmt binary parameters structure
+ */
+struct elf_fdpic_params {
+       struct elfhdr                   hdr;            /* ref copy of ELF header */
+       struct elf_phdr                 *phdrs;         /* ref copy of PT_PHDR table */
+       struct elf32_fdpic_loadmap      *loadmap;       /* loadmap to be passed to userspace */
+       unsigned long                   elfhdr_addr;    /* mapped ELF header user address */
+       unsigned long                   ph_addr;        /* mapped PT_PHDR user address */
+       unsigned long                   map_addr;       /* mapped loadmap user address */
+       unsigned long                   entry_addr;     /* mapped entry user address */
+       unsigned long                   stack_size;     /* stack size requested (PT_GNU_STACK) */
+       unsigned long                   dynamic_addr;   /* mapped PT_DYNAMIC user address */
+       unsigned long                   load_addr;      /* user address at which to map binary */
+       unsigned long                   flags;
+#define ELF_FDPIC_FLAG_ARRANGEMENT     0x0000000f      /* PT_LOAD arrangement flags */
+#define ELF_FDPIC_FLAG_INDEPENDENT     0x00000000      /* PT_LOADs can be put anywhere */
+#define ELF_FDPIC_FLAG_HONOURVADDR     0x00000001      /* PT_LOAD.vaddr must be honoured */
+#define ELF_FDPIC_FLAG_CONSTDISP       0x00000002      /* PT_LOADs require constant
+                                                        * displacement */
+#define ELF_FDPIC_FLAG_CONTIGUOUS      0x00000003      /* PT_LOADs should be contiguous */
+#define ELF_FDPIC_FLAG_EXEC_STACK      0x00000010      /* T if stack to be executable */
+#define ELF_FDPIC_FLAG_NOEXEC_STACK    0x00000020      /* T if stack not to be executable */
+#define ELF_FDPIC_FLAG_EXECUTABLE      0x00000040      /* T if this object is the executable */
+#define ELF_FDPIC_FLAG_PRESENT         0x80000000      /* T if this object is present */
+};
+
+#ifdef CONFIG_MMU
+extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
+                                     struct elf_fdpic_params *interp_params,
+                                     unsigned long *start_stack,
+                                     unsigned long *start_brk);
+#endif
+
+#endif /* _LINUX_ELF_FDPIC_H */
index b006ba0a9f4269e79d8bfae11415e8b3c8785f69..243eea1e33d8021b685f46a736e726c74e083a22 100644 (file)
@@ -51,6 +51,26 @@ extern struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,
 #define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1)
 #define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count)
 
+/* Reserved Ethernet Addresses per IEEE 802.1Q */
+static const u8 eth_reserved_addr_base[ETH_ALEN] __aligned(2) =
+{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
+
+/**
+ * is_link_local_ether_addr - Determine if given Ethernet address is link-local
+ * @addr: Pointer to a six-byte array containing the Ethernet address
+ *
+ * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
+ * IEEE 802.1Q 8.6.3 Frame filtering.
+ */
+static inline bool is_link_local_ether_addr(const u8 *addr)
+{
+       __be16 *a = (__be16 *)addr;
+       static const __be16 *b = (const __be16 *)eth_reserved_addr_base;
+       static const __be16 m = cpu_to_be16(0xfff0);
+
+       return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
+}
+
 /**
  * is_zero_ether_addr - Determine if give Ethernet address is all zeros.
  * @addr: Pointer to a six-byte array containing the Ethernet address
index 7443a560c9d059d106e7ce18dcf8813b18502c65..2c26c14cd7100d79ff046b9187409e2f430571eb 100644 (file)
@@ -68,7 +68,7 @@ enum extcon_cable_name {
        EXTCON_VIDEO_OUT,
        EXTCON_MECHANICAL,
 };
-extern const char *extcon_cable_name[];
+extern const char extcon_cable_name[][CABLE_NAME_MAX + 1];
 
 struct extcon_cable;
 
index 24d251f3bab0711c26231d67352df1ca140e608a..c45eabc135e1f00b7825d017b37df1666acb203e 100644 (file)
@@ -45,6 +45,7 @@ extern void sk_unattached_filter_destroy(struct sk_filter *fp);
 extern int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk);
 extern int sk_detach_filter(struct sock *sk);
 extern int sk_chk_filter(struct sock_filter *filter, unsigned int flen);
+extern int sk_get_filter(struct sock *sk, struct sock_filter __user *filter, unsigned len);
 
 #ifdef CONFIG_BPF_JIT
 extern void bpf_jit_compile(struct sk_filter *fp);
@@ -123,6 +124,8 @@ enum {
        BPF_S_ANC_CPU,
        BPF_S_ANC_ALU_XOR_X,
        BPF_S_ANC_SECCOMP_LD_W,
+       BPF_S_ANC_VLAN_TAG,
+       BPF_S_ANC_VLAN_TAG_PRESENT,
 };
 
 #endif /* __LINUX_FILTER_H__ */
index 001c7cff2d4826e4e54b6395596483030c86fc11..b33cfc97b9caef81de7e525c44e23c4db6a5ba18 100644 (file)
@@ -64,6 +64,73 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
                        ssize_t bytes, void *private, int ret,
                        bool is_async);
 
+#define MAY_EXEC               0x00000001
+#define MAY_WRITE              0x00000002
+#define MAY_READ               0x00000004
+#define MAY_APPEND             0x00000008
+#define MAY_ACCESS             0x00000010
+#define MAY_OPEN               0x00000020
+#define MAY_CHDIR              0x00000040
+/* called from RCU mode, don't block */
+#define MAY_NOT_BLOCK          0x00000080
+
+/*
+ * flags in file.f_mode.  Note that FMODE_READ and FMODE_WRITE must correspond
+ * to O_WRONLY and O_RDWR via the strange trick in __dentry_open()
+ */
+
+/* file is open for reading */
+#define FMODE_READ             ((__force fmode_t)0x1)
+/* file is open for writing */
+#define FMODE_WRITE            ((__force fmode_t)0x2)
+/* file is seekable */
+#define FMODE_LSEEK            ((__force fmode_t)0x4)
+/* file can be accessed using pread */
+#define FMODE_PREAD            ((__force fmode_t)0x8)
+/* file can be accessed using pwrite */
+#define FMODE_PWRITE           ((__force fmode_t)0x10)
+/* File is opened for execution with sys_execve / sys_uselib */
+#define FMODE_EXEC             ((__force fmode_t)0x20)
+/* File is opened with O_NDELAY (only set for block devices) */
+#define FMODE_NDELAY           ((__force fmode_t)0x40)
+/* File is opened with O_EXCL (only set for block devices) */
+#define FMODE_EXCL             ((__force fmode_t)0x80)
+/* File is opened using open(.., 3, ..) and is writeable only for ioctls
+   (specialy hack for floppy.c) */
+#define FMODE_WRITE_IOCTL      ((__force fmode_t)0x100)
+/* 32bit hashes as llseek() offset (for directories) */
+#define FMODE_32BITHASH         ((__force fmode_t)0x200)
+/* 64bit hashes as llseek() offset (for directories) */
+#define FMODE_64BITHASH         ((__force fmode_t)0x400)
+
+/*
+ * Don't update ctime and mtime.
+ *
+ * Currently a special hack for the XFS open_by_handle ioctl, but we'll
+ * hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon.
+ */
+#define FMODE_NOCMTIME         ((__force fmode_t)0x800)
+
+/* Expect random access pattern */
+#define FMODE_RANDOM           ((__force fmode_t)0x1000)
+
+/* File is huge (eg. /dev/kmem): treat loff_t as unsigned */
+#define FMODE_UNSIGNED_OFFSET  ((__force fmode_t)0x2000)
+
+/* File is opened with O_PATH; almost nothing can be done with it */
+#define FMODE_PATH             ((__force fmode_t)0x4000)
+
+/* File was opened by fanotify and shouldn't generate fanotify events */
+#define FMODE_NONOTIFY         ((__force fmode_t)0x1000000)
+
+/*
+ * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
+ * that indicates that they should check the contents of the iovec are
+ * valid, but not check the memory that the iovec elements
+ * points too.
+ */
+#define CHECK_IOVEC_ONLY -1
+
 /*
  * The below are the various read and write types that we support. Some of
  * them include behavioral modifiers that send information down to the
@@ -1556,6 +1623,60 @@ struct super_operations {
        void (*free_cached_objects)(struct super_block *, int);
 };
 
+/*
+ * Inode flags - they have no relation to superblock flags now
+ */
+#define S_SYNC         1       /* Writes are synced at once */
+#define S_NOATIME      2       /* Do not update access times */
+#define S_APPEND       4       /* Append-only file */
+#define S_IMMUTABLE    8       /* Immutable file */
+#define S_DEAD         16      /* removed, but still open directory */
+#define S_NOQUOTA      32      /* Inode is not counted to quota */
+#define S_DIRSYNC      64      /* Directory modifications are synchronous */
+#define S_NOCMTIME     128     /* Do not update file c/mtime */
+#define S_SWAPFILE     256     /* Do not truncate: swapon got its bmaps */
+#define S_PRIVATE      512     /* Inode is fs-internal */
+#define S_IMA          1024    /* Inode has an associated IMA struct */
+#define S_AUTOMOUNT    2048    /* Automount/referral quasi-directory */
+#define S_NOSEC                4096    /* no suid or xattr security attributes */
+
+/*
+ * Note that nosuid etc flags are inode-specific: setting some file-system
+ * flags just means all the inodes inherit those flags by default. It might be
+ * possible to override it selectively if you really wanted to with some
+ * ioctl() that is not currently implemented.
+ *
+ * Exception: MS_RDONLY is always applied to the entire file system.
+ *
+ * Unfortunately, it is possible to change a filesystems flags with it mounted
+ * with files in use.  This means that all of the inodes will not have their
+ * i_flags updated.  Hence, i_flags no longer inherit the superblock mount
+ * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org
+ */
+#define __IS_FLG(inode, flg)   ((inode)->i_sb->s_flags & (flg))
+
+#define IS_RDONLY(inode)       ((inode)->i_sb->s_flags & MS_RDONLY)
+#define IS_SYNC(inode)         (__IS_FLG(inode, MS_SYNCHRONOUS) || \
+                                       ((inode)->i_flags & S_SYNC))
+#define IS_DIRSYNC(inode)      (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \
+                                       ((inode)->i_flags & (S_SYNC|S_DIRSYNC)))
+#define IS_MANDLOCK(inode)     __IS_FLG(inode, MS_MANDLOCK)
+#define IS_NOATIME(inode)      __IS_FLG(inode, MS_RDONLY|MS_NOATIME)
+#define IS_I_VERSION(inode)    __IS_FLG(inode, MS_I_VERSION)
+
+#define IS_NOQUOTA(inode)      ((inode)->i_flags & S_NOQUOTA)
+#define IS_APPEND(inode)       ((inode)->i_flags & S_APPEND)
+#define IS_IMMUTABLE(inode)    ((inode)->i_flags & S_IMMUTABLE)
+#define IS_POSIXACL(inode)     __IS_FLG(inode, MS_POSIXACL)
+
+#define IS_DEADDIR(inode)      ((inode)->i_flags & S_DEAD)
+#define IS_NOCMTIME(inode)     ((inode)->i_flags & S_NOCMTIME)
+#define IS_SWAPFILE(inode)     ((inode)->i_flags & S_SWAPFILE)
+#define IS_PRIVATE(inode)      ((inode)->i_flags & S_PRIVATE)
+#define IS_IMA(inode)          ((inode)->i_flags & S_IMA)
+#define IS_AUTOMOUNT(inode)    ((inode)->i_flags & S_AUTOMOUNT)
+#define IS_NOSEC(inode)                ((inode)->i_flags & S_NOSEC)
+
 /*
  * Inode state bits.  Protected by inode->i_lock
  *
@@ -1688,6 +1809,11 @@ int sync_inode_metadata(struct inode *inode, int wait);
 struct file_system_type {
        const char *name;
        int fs_flags;
+#define FS_REQUIRES_DEV                1 
+#define FS_BINARY_MOUNTDATA    2
+#define FS_HAS_SUBTYPE         4
+#define FS_REVAL_DOT           16384   /* Check the paths ".", ".." for staleness */
+#define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move() during rename() internally. */
        struct dentry *(*mount) (struct file_system_type *, int,
                       const char *, void *);
        void (*kill_sb) (struct super_block *);
index 02c1c9710be0e5fea029fd4462fe57793154216e..d0a79678f169f8c9a7675e4343419975cbb29142 100644 (file)
@@ -31,6 +31,7 @@ struct vm_area_struct;
 #define ___GFP_THISNODE                0x40000u
 #define ___GFP_RECLAIMABLE     0x80000u
 #define ___GFP_NOTRACK         0x200000u
+#define ___GFP_NO_KSWAPD       0x400000u
 #define ___GFP_OTHER_NODE      0x800000u
 #define ___GFP_WRITE           0x1000000u
 
@@ -85,6 +86,7 @@ struct vm_area_struct;
 #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */
 #define __GFP_NOTRACK  ((__force gfp_t)___GFP_NOTRACK)  /* Don't track with kmemcheck */
 
+#define __GFP_NO_KSWAPD        ((__force gfp_t)___GFP_NO_KSWAPD)
 #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
 #define __GFP_WRITE    ((__force gfp_t)___GFP_WRITE)   /* Allocator intends to dirty page */
 
@@ -114,7 +116,8 @@ struct vm_area_struct;
                                 __GFP_MOVABLE)
 #define GFP_IOFS       (__GFP_IO | __GFP_FS)
 #define GFP_TRANSHUGE  (GFP_HIGHUSER_MOVABLE | __GFP_COMP | \
-                        __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN)
+                        __GFP_NOMEMALLOC | __GFP_NORETRY | __GFP_NOWARN | \
+                        __GFP_NO_KSWAPD)
 
 #ifdef CONFIG_NUMA
 #define GFP_THISNODE   (__GFP_THISNODE | __GFP_NOWARN | __GFP_NORETRY)
diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h
new file mode 100644 (file)
index 0000000..227c624
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Statically sized hash table implementation
+ * (C) 2012  Sasha Levin <levinsasha928@gmail.com>
+ */
+
+#ifndef _LINUX_HASHTABLE_H
+#define _LINUX_HASHTABLE_H
+
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/hash.h>
+#include <linux/rculist.h>
+
+#define DEFINE_HASHTABLE(name, bits)                                           \
+       struct hlist_head name[1 << (bits)] =                                   \
+                       { [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT }
+
+#define DECLARE_HASHTABLE(name, bits)                                          \
+       struct hlist_head name[1 << (bits)]
+
+#define HASH_SIZE(name) (ARRAY_SIZE(name))
+#define HASH_BITS(name) ilog2(HASH_SIZE(name))
+
+/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */
+#define hash_min(val, bits)                                                    \
+       (sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits))
+
+static inline void __hash_init(struct hlist_head *ht, unsigned int sz)
+{
+       unsigned int i;
+
+       for (i = 0; i < sz; i++)
+               INIT_HLIST_HEAD(&ht[i]);
+}
+
+/**
+ * hash_init - initialize a hash table
+ * @hashtable: hashtable to be initialized
+ *
+ * Calculates the size of the hashtable from the given parameter, otherwise
+ * same as hash_init_size.
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_add - add an object to a hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add(hashtable, node, key)                                         \
+       hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_add_rcu - add an object to a rcu enabled hashtable
+ * @hashtable: hashtable to add to
+ * @node: the &struct hlist_node of the object to be added
+ * @key: the key of the object to be added
+ */
+#define hash_add_rcu(hashtable, node, key)                                     \
+       hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))])
+
+/**
+ * hash_hashed - check whether an object is in any hashtable
+ * @node: the &struct hlist_node of the object to be checked
+ */
+static inline bool hash_hashed(struct hlist_node *node)
+{
+       return !hlist_unhashed(node);
+}
+
+static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz)
+{
+       unsigned int i;
+
+       for (i = 0; i < sz; i++)
+               if (!hlist_empty(&ht[i]))
+                       return false;
+
+       return true;
+}
+
+/**
+ * hash_empty - check whether a hashtable is empty
+ * @hashtable: hashtable to check
+ *
+ * This has to be a macro since HASH_BITS() will not work on pointers since
+ * it calculates the size during preprocessing.
+ */
+#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable))
+
+/**
+ * hash_del - remove an object from a hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del(struct hlist_node *node)
+{
+       hlist_del_init(node);
+}
+
+/**
+ * hash_del_rcu - remove an object from a rcu enabled hashtable
+ * @node: &struct hlist_node of the object to remove
+ */
+static inline void hash_del_rcu(struct hlist_node *node)
+{
+       hlist_del_init_rcu(node);
+}
+
+/**
+ * hash_for_each - iterate over a hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each(name, bkt, node, obj, member)                            \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_rcu - iterate over a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_rcu(name, bkt, node, obj, member)                                \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry_rcu(obj, node, &name[bkt], member)
+
+/**
+ * hash_for_each_safe - iterate over a hashtable safe against removal of
+ * hash entry
+ * @name: hashtable to iterate
+ * @bkt: integer to use as bucket loop cursor
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @obj: the type * to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ */
+#define hash_for_each_safe(name, bkt, node, tmp, obj, member)                  \
+       for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\
+               hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member)
+
+/**
+ * hash_for_each_possible - iterate over all possible objects hashing to the
+ * same bucket
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible(name, obj, node, member, key)                   \
+       hlist_for_each_entry(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_rcu - iterate over all possible objects hashing to the
+ * same bucket in an rcu enabled hashtable
+ * in a rcu enabled hashtable
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_rcu(name, obj, node, member, key)               \
+       hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member)
+
+/**
+ * hash_for_each_possible_safe - iterate over all possible objects hashing to the
+ * same bucket safe against removals
+ * @name: hashtable to iterate
+ * @obj: the type * to use as a loop cursor for each entry
+ * @node: the &struct list_head to use as a loop cursor for each entry
+ * @tmp: a &struct used for temporary storage
+ * @member: the name of the hlist_node within the struct
+ * @key: the key of the objects to iterate over
+ */
+#define hash_for_each_possible_safe(name, obj, node, tmp, member, key)         \
+       hlist_for_each_entry_safe(obj, node, tmp,                               \
+               &name[hash_min(key, HASH_BITS(name))], member)
+
+
+#endif
index 1fb26448faa9ccb2a7ca85c9dcca74d52413f87c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-header-y += ioctl.h
diff --git a/include/linux/hdlc/ioctl.h b/include/linux/hdlc/ioctl.h
deleted file mode 100644 (file)
index 5839723..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef __HDLC_IOCTL_H__
-#define __HDLC_IOCTL_H__
-
-
-#define GENERIC_HDLC_VERSION 4 /* For synchronization with sethdlc utility */
-
-#define CLOCK_DEFAULT   0      /* Default setting */
-#define CLOCK_EXT      1       /* External TX and RX clock - DTE */
-#define CLOCK_INT      2       /* Internal TX and RX clock - DCE */
-#define CLOCK_TXINT    3       /* Internal TX and external RX clock */
-#define CLOCK_TXFROMRX 4       /* TX clock derived from external RX clock */
-
-
-#define ENCODING_DEFAULT       0 /* Default setting */
-#define ENCODING_NRZ           1
-#define ENCODING_NRZI          2
-#define ENCODING_FM_MARK       3
-#define ENCODING_FM_SPACE      4
-#define ENCODING_MANCHESTER    5
-
-
-#define PARITY_DEFAULT         0 /* Default setting */
-#define PARITY_NONE            1 /* No parity */
-#define PARITY_CRC16_PR0       2 /* CRC16, initial value 0x0000 */
-#define PARITY_CRC16_PR1       3 /* CRC16, initial value 0xFFFF */
-#define PARITY_CRC16_PR0_CCITT 4 /* CRC16, initial 0x0000, ITU-T version */
-#define PARITY_CRC16_PR1_CCITT 5 /* CRC16, initial 0xFFFF, ITU-T version */
-#define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */
-#define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */
-
-#define LMI_DEFAULT            0 /* Default setting */
-#define LMI_NONE               1 /* No LMI, all PVCs are static */
-#define LMI_ANSI               2 /* ANSI Annex D */
-#define LMI_CCITT              3 /* ITU-T Annex A */
-#define LMI_CISCO              4 /* The "original" LMI, aka Gang of Four */
-
-typedef struct { 
-       unsigned int clock_rate; /* bits per second */
-       unsigned int clock_type; /* internal, external, TX-internal etc. */
-       unsigned short loopback;
-} sync_serial_settings;          /* V.35, V.24, X.21 */
-
-typedef struct { 
-       unsigned int clock_rate; /* bits per second */
-       unsigned int clock_type; /* internal, external, TX-internal etc. */
-       unsigned short loopback;
-       unsigned int slot_map;
-} te1_settings;                  /* T1, E1 */
-
-typedef struct {
-       unsigned short encoding;
-       unsigned short parity;
-} raw_hdlc_proto;
-
-typedef struct {
-       unsigned int t391;
-       unsigned int t392;
-       unsigned int n391;
-       unsigned int n392;
-       unsigned int n393;
-       unsigned short lmi;
-       unsigned short dce; /* 1 for DCE (network side) operation */
-} fr_proto;
-
-typedef struct {
-       unsigned int dlci;
-} fr_proto_pvc;          /* for creating/deleting FR PVCs */
-
-typedef struct {
-       unsigned int dlci;
-       char master[IFNAMSIZ];  /* Name of master FRAD device */
-}fr_proto_pvc_info;            /* for returning PVC information only */
-
-typedef struct {
-    unsigned int interval;
-    unsigned int timeout;
-} cisco_proto;
-
-/* PPP doesn't need any info now - supply length = 0 to ioctl */
-
-#endif /* __HDLC_IOCTL_H__ */
index 271a770b47843934075c64ed8893144a0fd570d7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-header-y += hsi_char.h
diff --git a/include/linux/hsi/hsi_char.h b/include/linux/hsi/hsi_char.h
deleted file mode 100644 (file)
index 76160b4..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Part of the HSI character device driver.
- *
- * Copyright (C) 2010 Nokia Corporation. All rights reserved.
- *
- * Contact: Andras Domokos <andras.domokos at nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- */
-
-
-#ifndef __HSI_CHAR_H
-#define __HSI_CHAR_H
-
-#define HSI_CHAR_MAGIC         'k'
-#define HSC_IOW(num, dtype)    _IOW(HSI_CHAR_MAGIC, num, dtype)
-#define HSC_IOR(num, dtype)    _IOR(HSI_CHAR_MAGIC, num, dtype)
-#define HSC_IOWR(num, dtype)   _IOWR(HSI_CHAR_MAGIC, num, dtype)
-#define HSC_IO(num)            _IO(HSI_CHAR_MAGIC, num)
-
-#define HSC_RESET              HSC_IO(16)
-#define HSC_SET_PM             HSC_IO(17)
-#define HSC_SEND_BREAK         HSC_IO(18)
-#define HSC_SET_RX             HSC_IOW(19, struct hsc_rx_config)
-#define HSC_GET_RX             HSC_IOW(20, struct hsc_rx_config)
-#define HSC_SET_TX             HSC_IOW(21, struct hsc_tx_config)
-#define HSC_GET_TX             HSC_IOW(22, struct hsc_tx_config)
-
-#define HSC_PM_DISABLE         0
-#define HSC_PM_ENABLE          1
-
-#define HSC_MODE_STREAM                1
-#define HSC_MODE_FRAME         2
-#define HSC_FLOW_SYNC          0
-#define HSC_ARB_RR             0
-#define HSC_ARB_PRIO           1
-
-struct hsc_rx_config {
-       uint32_t mode;
-       uint32_t flow;
-       uint32_t channels;
-};
-
-struct hsc_tx_config {
-       uint32_t mode;
-       uint32_t channels;
-       uint32_t speed;
-       uint32_t arb_mode;
-};
-
-#endif /* __HSI_CHAR_H */
index df804ba73e0b2ae97d935ba2c3797cd36b1499de..92a0dc75bc74661541e5b5c15f4cdd095c922b38 100644 (file)
@@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data {
        u32             clkrate;
        u32             rev;
        u32             flags;
+       void            (*set_mpu_wkup_lat)(struct device *dev, long set);
 };
 
 #endif
index 1cc595a67cc900b18afe694ca712700fba7e5c2e..f4e56ecd0b1ab49b0e09594e16fe996165168d11 100644 (file)
@@ -4,5 +4,22 @@
 #include <linux/ip.h>
 #include <linux/in6.h>
 #include <uapi/linux/if_tunnel.h>
+#include <linux/u64_stats_sync.h>
+
+/*
+ * Locking : hash tables are protected by RCU and RTNL
+ */
+
+#define for_each_ip_tunnel_rcu(pos, start) \
+       for (pos = rcu_dereference(start); pos; pos = rcu_dereference(pos->next))
+
+/* often modified stats are per cpu, other are shared (netdev->stats) */
+struct pcpu_tstats {
+       u64     rx_packets;
+       u64     rx_bytes;
+       u64     tx_packets;
+       u64     tx_bytes;
+       struct u64_stats_sync   syncp;
+};
 
 #endif /* _IF_TUNNEL_H_ */
index c0ae76ac4e0b87e905d358e846bd8459f0f10023..7806c24e5bc8173a004597a1dd266f8e14900de6 100644 (file)
@@ -618,4 +618,20 @@ static inline struct dentry *iio_get_debugfs_dentry(struct iio_dev *indio_dev)
 };
 #endif
 
+/**
+ * IIO_DEGREE_TO_RAD() - Convert degree to rad
+ * @deg: A value in degree
+ *
+ * Returns the given value converted from degree to rad
+ */
+#define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
+
+/**
+ * IIO_G_TO_M_S_2() - Convert g to meter / second**2
+ * @g: A value in g
+ *
+ * Returns the given value converted from g to meter / second**2
+ */
+#define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
+
 #endif /* _INDUSTRIAL_IO_H_ */
index d032780d0ce50849c5441aae24025b2cc2f80cc3..a9d828976a77a56b400ffd3f4e7a56915f3762a5 100644 (file)
@@ -171,6 +171,9 @@ struct in_ifaddr {
 extern int register_inetaddr_notifier(struct notifier_block *nb);
 extern int unregister_inetaddr_notifier(struct notifier_block *nb);
 
+extern void inet_netconf_notify_devconf(struct net *net, int type, int ifindex,
+                                       struct ipv4_devconf *devconf);
+
 extern struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref);
 static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
 {
index 58b82a22a52b90288566eaa36e9d2bf8095a363c..492bc6513533cf8d09fdfe667711ab0b78c3a0d2 100644 (file)
@@ -25,6 +25,11 @@ static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
        return (struct iphdr *)skb_network_header(skb);
 }
 
+static inline struct iphdr *inner_ip_hdr(const struct sk_buff *skb)
+{
+       return (struct iphdr *)skb_inner_network_header(skb);
+}
+
 static inline struct iphdr *ipip_hdr(const struct sk_buff *skb)
 {
        return (struct iphdr *)skb_transport_header(skb);
index bcba48a97868e9b38d6a92f38e5175b2474df330..faed1e357dd6c605cdea3445a803e167d17d3e0c 100644 (file)
@@ -47,6 +47,7 @@ struct ipv6_devconf {
        __s32           disable_ipv6;
        __s32           accept_dad;
        __s32           force_tllao;
+       __s32           ndisc_notify;
        void            *sysctl;
 };
 
@@ -66,6 +67,11 @@ static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
        return (struct ipv6hdr *)skb_network_header(skb);
 }
 
+static inline struct ipv6hdr *inner_ipv6_hdr(const struct sk_buff *skb)
+{
+       return (struct ipv6hdr *)skb_inner_network_header(skb);
+}
+
 static inline struct ipv6hdr *ipipv6_hdr(const struct sk_buff *skb)
 {
        return (struct ipv6hdr *)skb_transport_header(skb);
@@ -363,20 +369,22 @@ static inline struct raw6_sock *raw6_sk(const struct sock *sk)
 #define inet_v6_ipv6only(__sk)         0
 #endif /* IS_ENABLED(CONFIG_IPV6) */
 
-#define INET6_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif)\
-       (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)   && \
-        ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \
-        ((__sk)->sk_family             == AF_INET6)            && \
-        ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))     && \
-        ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
-        (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-
-#define INET6_TW_MATCH(__sk, __net, __hash, __saddr, __daddr, __ports, __dif) \
-       (((__sk)->sk_hash == (__hash)) && sock_net((__sk)) == (__net)   && \
-        (*((__portpair *)&(inet_twsk(__sk)->tw_dport)) == (__ports))   && \
-        ((__sk)->sk_family            == PF_INET6)                     && \
-        (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr)))   && \
-        (ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr))) && \
-        (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET6_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif)     \
+       ((inet_sk(__sk)->inet_portpair == (__ports))            &&      \
+        ((__sk)->sk_family == AF_INET6)                        &&      \
+        ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))     &&      \
+        ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) &&      \
+        (!(__sk)->sk_bound_dev_if      ||                              \
+          ((__sk)->sk_bound_dev_if == (__dif)))                &&      \
+        net_eq(sock_net(__sk), (__net)))
+
+#define INET6_TW_MATCH(__sk, __net, __saddr, __daddr, __ports, __dif)     \
+       ((inet_twsk(__sk)->tw_portpair == (__ports))                    && \
+        ((__sk)->sk_family == AF_INET6)                                && \
+        ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_daddr, (__saddr))     && \
+        ipv6_addr_equal(&inet6_twsk(__sk)->tw_v6_rcv_saddr, (__daddr)) && \
+        (!(__sk)->sk_bound_dev_if      ||                                 \
+         ((__sk)->sk_bound_dev_if == (__dif)))                         && \
+        net_eq(sock_net(__sk), (__net)))
 
 #endif /* _IPV6_H */
diff --git a/include/linux/isdn/Kbuild b/include/linux/isdn/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 06177ba10a1617461dbe6803efc22ba6dfb43304..e83512f63df550a64cba3fb74c51c5c3b5dc9030 100644 (file)
@@ -282,6 +282,25 @@ static inline int ktime_equal(const ktime_t cmp1, const ktime_t cmp2)
        return cmp1.tv64 == cmp2.tv64;
 }
 
+/**
+ * ktime_compare - Compares two ktime_t variables for less, greater or equal
+ * @cmp1:      comparable1
+ * @cmp2:      comparable2
+ *
+ * Returns ...
+ *   cmp1  < cmp2: return <0
+ *   cmp1 == cmp2: return 0
+ *   cmp1  > cmp2: return >0
+ */
+static inline int ktime_compare(const ktime_t cmp1, const ktime_t cmp2)
+{
+       if (cmp1.tv64 < cmp2.tv64)
+               return -1;
+       if (cmp1.tv64 > cmp2.tv64)
+               return 1;
+       return 0;
+}
+
 static inline s64 ktime_to_us(const ktime_t kt)
 {
        struct timeval tv = ktime_to_timeval(kt);
index 93bfc9f9815c7fa178ad70b555e7a2afb86b3f02..ecc554374e440a73df8aaf5b5787f86705e647b0 100644 (file)
  */
 #define KVM_MEMSLOT_INVALID    (1UL << 16)
 
-/*
- * If we support unaligned MMIO, at most one fragment will be split into two:
- */
-#ifdef KVM_UNALIGNED_MMIO
-#  define KVM_EXTRA_MMIO_FRAGMENTS 1
-#else
-#  define KVM_EXTRA_MMIO_FRAGMENTS 0
-#endif
-
-#define KVM_USER_MMIO_SIZE 8
-
-#define KVM_MAX_MMIO_FRAGMENTS \
-       (KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS)
+/* Two fragments for cross MMIO pages. */
+#define KVM_MAX_MMIO_FRAGMENTS 2
 
 /*
  * For the normal pfn, the highest 12 bits should be zero,
index 569d67d4243ed99c4b896fac81442531b9d05cbc..d452ee191066456278080c92322e093986baa1fb 100644 (file)
@@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size);
 int memblock_remove(phys_addr_t base, phys_addr_t size);
 int memblock_free(phys_addr_t base, phys_addr_t size);
 int memblock_reserve(phys_addr_t base, phys_addr_t size);
+void memblock_trim_memory(phys_addr_t align);
 
 #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
 void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
index 1d28ae90384ed42e9c43a63a01d3a63c91a9c812..fe03b2d35d4f39178a9227a5eeeeeb7355e19192 100644 (file)
 #ifndef __LINUX_MFD_MAX77693_H
 #define __LINUX_MFD_MAX77693_H
 
+struct max77693_reg_data {
+       u8 addr;
+       u8 data;
+};
+
+struct max77693_muic_platform_data {
+       struct max77693_reg_data *init_data;
+       int num_init_data;
+};
+
 struct max77693_platform_data {
        int wakeup;
+
+       /* muic data */
+       struct max77693_muic_platform_data *muic_data;
 };
 #endif /* __LINUX_MFD_MAX77693_H */
index de201203bc7c833a09651f75678b833cfac0b880..adfe8c058f298ffb4f619688676423ea67838997 100644 (file)
@@ -15,6 +15,7 @@
 
 #define MICREL_PHY_ID_MASK     0x00fffff0
 
+#define PHY_ID_KSZ8873MLL      0x000e7237
 #define PHY_ID_KSZ9021         0x00221610
 #define PHY_ID_KS8737          0x00221720
 #define PHY_ID_KSZ8021         0x00221555
index fa068040273893c27d71461e459e2eb268739396..bcaab4e6fe913ac6e3f2ef0a6c83ea24d8972867 100644 (file)
@@ -1684,9 +1684,5 @@ static inline unsigned int debug_guardpage_minorder(void) { return 0; }
 static inline bool page_is_guard(struct page *page) { return false; }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
-extern void reset_zone_present_pages(void);
-extern void fixup_zone_present_pages(int nid, unsigned long start_pfn,
-                               unsigned long end_pfn);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff --git a/include/linux/mmc/Kbuild b/include/linux/mmc/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 7c6a1139d8faf9ad54af671c68cd81ea3dcebf2f..96531664a0612dc6bc006cad026cd795cf6a9aea 100644 (file)
@@ -137,7 +137,7 @@ struct dw_mci {
 
        dma_addr_t              sg_dma;
        void                    *sg_cpu;
-       struct dw_mci_dma_ops   *dma_ops;
+       const struct dw_mci_dma_ops     *dma_ops;
 #ifdef CONFIG_MMC_DW_IDMAC
        unsigned int            ring_size;
 #else
@@ -162,7 +162,7 @@ struct dw_mci {
        u16                     data_offset;
        struct device           *dev;
        struct dw_mci_board     *pdata;
-       struct dw_mci_drv_data  *drv_data;
+       const struct dw_mci_drv_data    *drv_data;
        void                    *priv;
        struct clk              *biu_clk;
        struct clk              *ciu_clk;
@@ -186,7 +186,7 @@ struct dw_mci {
 
        struct regulator        *vmmc;  /* Power regulator */
        unsigned long           irq_flags; /* IRQ flags */
-       unsigned int            irq;
+       int                     irq;
 };
 
 /* DMA ops for Internal/External DMAC interface */
index fa8529a859b8b7637a6b25e76e15ba7848cd9f79..1edcb4dad8c464a7910d126ebcf1b36bcefacb36 100644 (file)
@@ -91,6 +91,7 @@ struct sdhci_host {
        unsigned int quirks2;   /* More deviations from spec. */
 
 #define SDHCI_QUIRK2_HOST_OFF_CARD_ON                  (1<<0)
+#define SDHCI_QUIRK2_HOST_NO_CMD23                     (1<<1)
 
        int irq;                /* Device IRQ */
        void __iomem *ioaddr;   /* Mapped address */
index 50aaca81f63d6db3914b7858f0209fed036a5971..a23923ba8263b18dac16ec73971d19bed719d015 100644 (file)
@@ -752,7 +752,7 @@ extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn,
                                     unsigned long size,
                                     enum memmap_context context);
 
-extern void lruvec_init(struct lruvec *lruvec, struct zone *zone);
+extern void lruvec_init(struct lruvec *lruvec);
 
 static inline struct zone *lruvec_zone(struct lruvec *lruvec)
 {
index f8eda0276f03fadf3be56e8e70f928f792714406..c6a14d4d1396d4cbf2e70d1755dbfffd248b0ea7 100644 (file)
@@ -887,6 +887,10 @@ struct netdev_fcoe_hbainfo {
  *                    struct net_device *dev, int idx)
  *     Used to add FDB entries to dump requests. Implementers should add
  *     entries to skb and update idx with the number of entries.
+ *
+ * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh)
+ * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
+ *                          struct net_device *dev)
  */
 struct net_device_ops {
        int                     (*ndo_init)(struct net_device *dev);
@@ -998,6 +1002,12 @@ struct net_device_ops {
                                                struct netlink_callback *cb,
                                                struct net_device *dev,
                                                int idx);
+
+       int                     (*ndo_bridge_setlink)(struct net_device *dev,
+                                                     struct nlmsghdr *nlh);
+       int                     (*ndo_bridge_getlink)(struct sk_buff *skb,
+                                                     u32 pid, u32 seq,
+                                                     struct net_device *dev);
 };
 
 /*
@@ -1053,6 +1063,12 @@ struct net_device {
        netdev_features_t       wanted_features;
        /* mask of features inheritable by VLAN devices */
        netdev_features_t       vlan_features;
+       /* mask of features inherited by encapsulating devices
+        * This field indicates what encapsulation offloads
+        * the hardware is capable of doing, and drivers will
+        * need to set them appropriately.
+        */
+       netdev_features_t       hw_enc_features;
 
        /* Interface index. Unique device identifier    */
        int                     ifindex;
@@ -1499,16 +1515,25 @@ struct packet_type {
                                         struct net_device *,
                                         struct packet_type *,
                                         struct net_device *);
+       bool                    (*id_match)(struct packet_type *ptype,
+                                           struct sock *sk);
+       void                    *af_packet_priv;
+       struct list_head        list;
+};
+
+struct offload_callbacks {
        struct sk_buff          *(*gso_segment)(struct sk_buff *skb,
                                                netdev_features_t features);
        int                     (*gso_send_check)(struct sk_buff *skb);
        struct sk_buff          **(*gro_receive)(struct sk_buff **head,
                                               struct sk_buff *skb);
        int                     (*gro_complete)(struct sk_buff *skb);
-       bool                    (*id_match)(struct packet_type *ptype,
-                                           struct sock *sk);
-       void                    *af_packet_priv;
-       struct list_head        list;
+};
+
+struct packet_offload {
+       __be16                   type;  /* This is really htons(ether_type). */
+       struct offload_callbacks callbacks;
+       struct list_head         list;
 };
 
 #include <linux/notifier.h>
@@ -1548,6 +1573,8 @@ extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
 
 extern rwlock_t                                dev_base_lock;          /* Device list lock */
 
+extern seqlock_t       devnet_rename_seq;      /* Device rename lock */
+
 
 #define for_each_netdev(net, d)                \
                list_for_each_entry(d, &(net)->dev_base_head, dev_list)
@@ -1605,6 +1632,9 @@ extern struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short
 extern void            dev_add_pack(struct packet_type *pt);
 extern void            dev_remove_pack(struct packet_type *pt);
 extern void            __dev_remove_pack(struct packet_type *pt);
+extern void            dev_add_offload(struct packet_offload *po);
+extern void            dev_remove_offload(struct packet_offload *po);
+extern void            __dev_remove_offload(struct packet_offload *po);
 
 extern struct net_device       *dev_get_by_flags_rcu(struct net *net, unsigned short flags,
                                                      unsigned short mask);
@@ -2129,16 +2159,10 @@ extern void dev_kfree_skb_any(struct sk_buff *skb);
 extern int             netif_rx(struct sk_buff *skb);
 extern int             netif_rx_ni(struct sk_buff *skb);
 extern int             netif_receive_skb(struct sk_buff *skb);
-extern gro_result_t    dev_gro_receive(struct napi_struct *napi,
-                                       struct sk_buff *skb);
-extern gro_result_t    napi_skb_finish(gro_result_t ret, struct sk_buff *skb);
 extern gro_result_t    napi_gro_receive(struct napi_struct *napi,
                                         struct sk_buff *skb);
 extern void            napi_gro_flush(struct napi_struct *napi, bool flush_old);
 extern struct sk_buff *        napi_get_frags(struct napi_struct *napi);
-extern gro_result_t    napi_frags_finish(struct napi_struct *napi,
-                                         struct sk_buff *skb,
-                                         gro_result_t ret);
 extern gro_result_t    napi_gro_frags(struct napi_struct *napi);
 
 static inline void napi_free_frags(struct napi_struct *napi)
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild
deleted file mode 100644 (file)
index b332202..0000000
+++ /dev/null
@@ -1 +0,0 @@
-header-y += ipset/
diff --git a/include/linux/netfilter/ipset/Kbuild b/include/linux/netfilter/ipset/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/netfilter_arp/Kbuild b/include/linux/netfilter_arp/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/netfilter_bridge/Kbuild b/include/linux/netfilter_bridge/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/netfilter_ipv6/Kbuild b/include/linux/netfilter_ipv6/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 5f84c6229dc619e65ed0ec4a9dc65187c3daccf0..610208b18c05819dc4cfecc0554574269157f90f 100644 (file)
@@ -47,15 +47,6 @@ ip6t_ext_hdr(u8 nexthdr)
               (nexthdr == IPPROTO_DSTOPTS);
 }
 
-enum {
-       IP6T_FH_F_FRAG  = (1 << 0),
-       IP6T_FH_F_AUTH  = (1 << 1),
-};
-
-/* find specified header and get offset to it */
-extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
-                        int target, unsigned short *fragoff, int *fragflg);
-
 #ifdef CONFIG_COMPAT
 #include <net/compat.h>
 
diff --git a/include/linux/nfsd/Kbuild b/include/linux/nfsd/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 72843b72a2b2619a5343be071d1ad104a9cb75af..b4e50d56fc7440b1b1d03849e33b77acf7ee41b6 100644 (file)
@@ -331,6 +331,13 @@ static inline bool of_have_populated_dt(void)
 #define for_each_child_of_node(parent, child) \
        while (0)
 
+static inline struct device_node *of_get_child_by_name(
+                                       const struct device_node *node,
+                                       const char *name)
+{
+       return NULL;
+}
+
 static inline int of_get_child_count(const struct device_node *np)
 {
        return 0;
index c3cdc1025c30694eee350d9cd62609e4db40de02..0506eb53519b635286be2b2c54b8a4c7e524a3d7 100644 (file)
@@ -19,7 +19,7 @@ extern void __iomem *of_iomap(struct device_node *device, int index);
  * the address space flags too. The PCI version uses a BAR number
  * instead of an absolute index
  */
-extern const u32 *of_get_address(struct device_node *dev, int index,
+extern const __be32 *of_get_address(struct device_node *dev, int index,
                           u64 *size, unsigned int *flags);
 
 #ifndef pci_address_to_pio
@@ -28,11 +28,13 @@ static inline unsigned long pci_address_to_pio(phys_addr_t addr) { return -1; }
 #endif
 
 #else /* CONFIG_OF_ADDRESS */
+#ifndef of_address_to_resource
 static inline int of_address_to_resource(struct device_node *dev, int index,
                                         struct resource *r)
 {
        return -EINVAL;
 }
+#endif
 static inline struct device_node *of_find_matching_node_by_address(
                                        struct device_node *from,
                                        const struct of_device_id *matches,
@@ -40,11 +42,13 @@ static inline struct device_node *of_find_matching_node_by_address(
 {
        return NULL;
 }
+#ifndef of_iomap
 static inline void __iomem *of_iomap(struct device_node *device, int index)
 {
        return NULL;
 }
-static inline const u32 *of_get_address(struct device_node *dev, int index,
+#endif
+static inline const __be32 *of_get_address(struct device_node *dev, int index,
                                        u64 *size, unsigned int *flags)
 {
        return NULL;
index b8e241125201d6a4ed29bfb30fded26e5d711654..535cecf1e02f7823a1ec3f416c3b06382ea6d8fa 100644 (file)
@@ -58,8 +58,8 @@ static inline int of_irq_map_oldworld(struct device_node *device, int index,
 #endif /* CONFIG_PPC32 && CONFIG_PPC_PMAC */
 
 
-extern int of_irq_map_raw(struct device_node *parent, const u32 *intspec,
-                         u32 ointsize, const u32 *addr,
+extern int of_irq_map_raw(struct device_node *parent, const __be32 *intspec,
+                         u32 ointsize, const __be32 *addr,
                          struct of_irq *out_irq);
 extern int of_irq_map_one(struct device_node *device, int index,
                          struct of_irq *out_irq);
index eb1efa54fe842186893e1080e63a8db64f63098f..d42e174bd0c85860de4521c0c67df289c7e4489e 100644 (file)
@@ -243,6 +243,7 @@ enum ovs_key_attr {
        OVS_KEY_ATTR_ICMPV6,    /* struct ovs_key_icmpv6 */
        OVS_KEY_ATTR_ARP,       /* struct ovs_key_arp */
        OVS_KEY_ATTR_ND,        /* struct ovs_key_nd */
+       OVS_KEY_ATTR_SKB_MARK,  /* u32 skb mark */
        __OVS_KEY_ATTR_MAX
 };
 
index ee2179546c63b98c2fb8441e03a1f9481ef592b2..9cbd6705d033ddea48ab3def08d7afd0c61084b7 100644 (file)
@@ -603,6 +603,20 @@ struct pci_driver {
        .vendor = (vend), .device = (dev), \
        .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID
 
+/**
+ * PCI_DEVICE_SUB - macro used to describe a specific pci device with subsystem
+ * @vend: the 16 bit PCI Vendor ID
+ * @dev: the 16 bit PCI Device ID
+ * @subvend: the 16 bit PCI Subvendor ID
+ * @subdev: the 16 bit PCI Subdevice ID
+ *
+ * This macro is used to create a struct pci_device_id that matches a
+ * specific device with subsystem information.
+ */
+#define PCI_DEVICE_SUB(vend, dev, subvend, subdev) \
+       .vendor = (vend), .device = (dev), \
+       .subvendor = (subvend), .subdevice = (subdev)
+
 /**
  * PCI_DEVICE_CLASS - macro used to describe a specific pci device class
  * @dev_class: the class, subclass, prog-if triple for this device
index cf80f7e5277f14dcce2931232a808e592344e7aa..bd1e86071e57c27219b2746ab715d419c60fcc2c 100644 (file)
@@ -12,34 +12,27 @@ struct percpu_rw_semaphore {
        struct mutex mtx;
 };
 
+#define light_mb()     barrier()
+#define heavy_mb()     synchronize_sched_expedited()
+
 static inline void percpu_down_read(struct percpu_rw_semaphore *p)
 {
-       rcu_read_lock();
+       rcu_read_lock_sched();
        if (unlikely(p->locked)) {
-               rcu_read_unlock();
+               rcu_read_unlock_sched();
                mutex_lock(&p->mtx);
                this_cpu_inc(*p->counters);
                mutex_unlock(&p->mtx);
                return;
        }
        this_cpu_inc(*p->counters);
-       rcu_read_unlock();
+       rcu_read_unlock_sched();
+       light_mb(); /* A, between read of p->locked and read of data, paired with D */
 }
 
 static inline void percpu_up_read(struct percpu_rw_semaphore *p)
 {
-       /*
-        * On X86, write operation in this_cpu_dec serves as a memory unlock
-        * barrier (i.e. memory accesses may be moved before the write, but
-        * no memory accesses are moved past the write).
-        * On other architectures this may not be the case, so we need smp_mb()
-        * there.
-        */
-#if defined(CONFIG_X86) && (!defined(CONFIG_X86_PPRO_FENCE) && !defined(CONFIG_X86_OOSTORE))
-       barrier();
-#else
-       smp_mb();
-#endif
+       light_mb(); /* B, between read of the data and write to p->counter, paired with C */
        this_cpu_dec(*p->counters);
 }
 
@@ -58,14 +51,15 @@ static inline void percpu_down_write(struct percpu_rw_semaphore *p)
 {
        mutex_lock(&p->mtx);
        p->locked = true;
-       synchronize_rcu();
+       synchronize_sched_expedited(); /* make sure that all readers exit the rcu_read_lock_sched region */
        while (__percpu_count(p->counters))
                msleep(1);
-       smp_rmb(); /* paired with smp_mb() in percpu_sem_up_read() */
+       heavy_mb(); /* C, between read of p->counter and write to data, paired with B */
 }
 
 static inline void percpu_up_write(struct percpu_rw_semaphore *p)
 {
+       heavy_mb(); /* D, between write to data and write to p->locked, paired with A */
        p->locked = false;
        mutex_unlock(&p->mtx);
 }
index 2e902359aee596f128dee568d06e0e0ab3149dfe..6bfb2faa0b1937555f5ca8fa937c7007bf5b3bc4 100644 (file)
@@ -803,12 +803,16 @@ static inline void perf_event_task_tick(void)                             { }
 do {                                                                   \
        static struct notifier_block fn##_nb __cpuinitdata =            \
                { .notifier_call = fn, .priority = CPU_PRI_PERF };      \
+       unsigned long cpu = smp_processor_id();                         \
+       unsigned long flags;                                            \
        fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE,                     \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
+       local_irq_save(flags);                                          \
        fn(&fn##_nb, (unsigned long)CPU_STARTING,                       \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
+       local_irq_restore(flags);                                       \
        fn(&fn##_nb, (unsigned long)CPU_ONLINE,                         \
-               (void *)(unsigned long)smp_processor_id());             \
+               (void *)(unsigned long)cpu);                            \
        register_cpu_notifier(&fn##_nb);                                \
 } while (0)
 
index 00474b047145ed1f54f3003fe597873a4665cc48..65e3e87eacc59aab1d95a8bd1a14a2e61f29c1f3 100644 (file)
@@ -47,15 +47,9 @@ static inline struct pid_namespace *get_pid_ns(struct pid_namespace *ns)
 }
 
 extern struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *ns);
-extern void free_pid_ns(struct kref *kref);
 extern void zap_pid_ns_processes(struct pid_namespace *pid_ns);
 extern int reboot_pid_ns(struct pid_namespace *pid_ns, int cmd);
-
-static inline void put_pid_ns(struct pid_namespace *ns)
-{
-       if (ns != &init_pid_ns)
-               kref_put(&ns->kref, free_pid_ns);
-}
+extern void put_pid_ns(struct pid_namespace *ns);
 
 #else /* !CONFIG_PID_NS */
 #include <linux/err.h>
index c4e23d0294987a64a3fbc6202df4bb3dbe6f8ff5..24368a2e8b8713dcd9678dfa9045834b8d00f465 100644 (file)
@@ -18,9 +18,7 @@
 #include <linux/if_ether.h>
 
 struct cpsw_slave_data {
-       u32             slave_reg_ofs;
-       u32             sliver_reg_ofs;
-       const char      *phy_id;
+       char            phy_id[MII_BUS_ID_SIZE];
        int             phy_if;
        u8              mac_addr[ETH_ALEN];
 };
@@ -28,27 +26,14 @@ struct cpsw_slave_data {
 struct cpsw_platform_data {
        u32     ss_reg_ofs;     /* Subsystem control register offset */
        u32     channels;       /* number of cpdma channels (symmetric) */
-       u32     cpdma_reg_ofs;  /* cpdma register offset */
-       u32     cpdma_sram_ofs; /* cpdma sram offset */
-
        u32     slaves;         /* number of slave cpgmac ports */
        struct cpsw_slave_data  *slave_data;
-
-       u32     ale_reg_ofs;    /* address lookup engine reg offset */
+       u32     cpts_active_slave; /* time stamping slave */
+       u32     cpts_clock_mult;  /* convert input clock ticks to nanoseconds */
+       u32     cpts_clock_shift; /* convert input clock ticks to nanoseconds */
        u32     ale_entries;    /* ale table size */
-
-       u32     host_port_reg_ofs; /* cpsw cpdma host port registers */
-       u32     host_port_num; /* The port number for the host port */
-
-       u32     hw_stats_reg_ofs;  /* cpsw hardware statistics counters */
-
-       u32     bd_ram_ofs;   /* embedded buffer descriptor RAM offset*/
        u32     bd_ram_size;  /*buffer descriptor ram size */
-       u32     hw_ram_addr; /*if the HW address for BD RAM is different */
-       bool    no_bd_ram; /* no embedded BD ram*/
-
        u32     rx_descs;       /* Number of Rx Descriptios */
-
        u32     mac_control;    /* Mac control register */
 };
 
index b081c7245ec8a94cd7ed3664c1f91a0e15814897..044a124bfbbc6b313d96f187a598fcb1438b8cc6 100644 (file)
@@ -12,6 +12,7 @@ struct macb_platform_data {
        u32             phy_mask;
        int             phy_irq_pin;    /* PHY IRQ */
        u8              is_rmii;        /* using RMII interface? */
+       u8              rev_eth_addr;   /* reverse Ethernet address byte order */
 };
 
 #endif /* __MACB_PDATA_H__ */
diff --git a/include/linux/platform_data/omap_ocp2scp.h b/include/linux/platform_data/omap_ocp2scp.h
new file mode 100644 (file)
index 0000000..5c6c393
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * omap_ocp2scp.h -- ocp2scp header file
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 __DRIVERS_OMAP_OCP2SCP_H
+#define __DRIVERS_OMAP_OCP2SCP_H
+
+struct omap_ocp2scp_dev {
+       const char                      *drv_name;
+       struct resource                 *res;
+};
+
+struct omap_ocp2scp_platform_data {
+       int                             dev_cnt;
+       struct omap_ocp2scp_dev         **devices;
+};
+#endif /* __DRIVERS_OMAP_OCP2SCP_H */
index f2dc6d8fc680f7ae02596558ce4571a675fb3bce..38a99350832744231042de3d1d45f0fc11f3471f 100644 (file)
@@ -54,7 +54,8 @@ struct ptp_clock_request {
  * clock operations
  *
  * @adjfreq:  Adjusts the frequency of the hardware clock.
- *            parameter delta: Desired period change in parts per billion.
+ *            parameter delta: Desired frequency offset from nominal frequency
+ *            in parts per billion
  *
  * @adjtime:  Shifts the time of the hardware clock.
  *            parameter delta: Desired change in nanoseconds.
index 2415a64c5e51d937ba0fc7d20cf78011b1b77dd6..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,2 +0,0 @@
-header-y += md_p.h
-header-y += md_u.h
diff --git a/include/linux/raid/md_p.h b/include/linux/raid/md_p.h
deleted file mode 100644 (file)
index ee75353..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-/*
-   md_p.h : physical layout of Linux RAID devices
-          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
-         
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-   
-   You should have received a copy of the GNU General Public License
-   (for example /usr/src/linux/COPYING); if not, write to the Free
-   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
-*/
-
-#ifndef _MD_P_H
-#define _MD_P_H
-
-#include <linux/types.h>
-
-/*
- * RAID superblock.
- *
- * The RAID superblock maintains some statistics on each RAID configuration.
- * Each real device in the RAID set contains it near the end of the device.
- * Some of the ideas are copied from the ext2fs implementation.
- *
- * We currently use 4096 bytes as follows:
- *
- *     word offset     function
- *
- *        0  -    31   Constant generic RAID device information.
- *        32  -    63   Generic state information.
- *       64  -   127   Personality specific information.
- *      128  -   511   12 32-words descriptors of the disks in the raid set.
- *      512  -   911   Reserved.
- *      912  -  1023   Disk specific descriptor.
- */
-
-/*
- * If x is the real device size in bytes, we return an apparent size of:
- *
- *     y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
- *
- * and place the 4kB superblock at offset y.
- */
-#define MD_RESERVED_BYTES              (64 * 1024)
-#define MD_RESERVED_SECTORS            (MD_RESERVED_BYTES / 512)
-
-#define MD_NEW_SIZE_SECTORS(x)         ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
-
-#define MD_SB_BYTES                    4096
-#define MD_SB_WORDS                    (MD_SB_BYTES / 4)
-#define MD_SB_SECTORS                  (MD_SB_BYTES / 512)
-
-/*
- * The following are counted in 32-bit words
- */
-#define        MD_SB_GENERIC_OFFSET            0
-#define MD_SB_PERSONALITY_OFFSET       64
-#define MD_SB_DISKS_OFFSET             128
-#define MD_SB_DESCRIPTOR_OFFSET                992
-
-#define MD_SB_GENERIC_CONSTANT_WORDS   32
-#define MD_SB_GENERIC_STATE_WORDS      32
-#define MD_SB_GENERIC_WORDS            (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
-#define MD_SB_PERSONALITY_WORDS                64
-#define MD_SB_DESCRIPTOR_WORDS         32
-#define MD_SB_DISKS                    27
-#define MD_SB_DISKS_WORDS              (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
-#define MD_SB_RESERVED_WORDS           (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
-#define MD_SB_EQUAL_WORDS              (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
-
-/*
- * Device "operational" state bits
- */
-#define MD_DISK_FAULTY         0 /* disk is faulty / operational */
-#define MD_DISK_ACTIVE         1 /* disk is running or spare disk */
-#define MD_DISK_SYNC           2 /* disk is in sync with the raid set */
-#define MD_DISK_REMOVED                3 /* disk is in sync with the raid set */
-
-#define        MD_DISK_WRITEMOSTLY     9 /* disk is "write-mostly" is RAID1 config.
-                                  * read requests will only be sent here in
-                                  * dire need
-                                  */
-
-typedef struct mdp_device_descriptor_s {
-       __u32 number;           /* 0 Device number in the entire set          */
-       __u32 major;            /* 1 Device major number                      */
-       __u32 minor;            /* 2 Device minor number                      */
-       __u32 raid_disk;        /* 3 The role of the device in the raid set   */
-       __u32 state;            /* 4 Operational state                        */
-       __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
-} mdp_disk_t;
-
-#define MD_SB_MAGIC            0xa92b4efc
-
-/*
- * Superblock state bits
- */
-#define MD_SB_CLEAN            0
-#define MD_SB_ERRORS           1
-
-#define        MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
-
-/*
- * Notes:
- * - if an array is being reshaped (restriped) in order to change the
- *   the number of active devices in the array, 'raid_disks' will be
- *   the larger of the old and new numbers.  'delta_disks' will
- *   be the "new - old".  So if +ve, raid_disks is the new value, and
- *   "raid_disks-delta_disks" is the old.  If -ve, raid_disks is the
- *   old value and "raid_disks+delta_disks" is the new (smaller) value.
- */
-
-
-typedef struct mdp_superblock_s {
-       /*
-        * Constant generic information
-        */
-       __u32 md_magic;         /*  0 MD identifier                           */
-       __u32 major_version;    /*  1 major version to which the set conforms */
-       __u32 minor_version;    /*  2 minor version ...                       */
-       __u32 patch_version;    /*  3 patchlevel version ...                  */
-       __u32 gvalid_words;     /*  4 Number of used words in this section    */
-       __u32 set_uuid0;        /*  5 Raid set identifier                     */
-       __u32 ctime;            /*  6 Creation time                           */
-       __u32 level;            /*  7 Raid personality                        */
-       __u32 size;             /*  8 Apparent size of each individual disk   */
-       __u32 nr_disks;         /*  9 total disks in the raid set             */
-       __u32 raid_disks;       /* 10 disks in a fully functional raid set    */
-       __u32 md_minor;         /* 11 preferred MD minor device number        */
-       __u32 not_persistent;   /* 12 does it have a persistent superblock    */
-       __u32 set_uuid1;        /* 13 Raid set identifier #2                  */
-       __u32 set_uuid2;        /* 14 Raid set identifier #3                  */
-       __u32 set_uuid3;        /* 15 Raid set identifier #4                  */
-       __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
-
-       /*
-        * Generic state information
-        */
-       __u32 utime;            /*  0 Superblock update time                  */
-       __u32 state;            /*  1 State bits (clean, ...)                 */
-       __u32 active_disks;     /*  2 Number of currently active disks        */
-       __u32 working_disks;    /*  3 Number of working disks                 */
-       __u32 failed_disks;     /*  4 Number of failed disks                  */
-       __u32 spare_disks;      /*  5 Number of spare disks                   */
-       __u32 sb_csum;          /*  6 checksum of the whole superblock        */
-#ifdef __BIG_ENDIAN
-       __u32 events_hi;        /*  7 high-order of superblock update count   */
-       __u32 events_lo;        /*  8 low-order of superblock update count    */
-       __u32 cp_events_hi;     /*  9 high-order of checkpoint update count   */
-       __u32 cp_events_lo;     /* 10 low-order of checkpoint update count    */
-#else
-       __u32 events_lo;        /*  7 low-order of superblock update count    */
-       __u32 events_hi;        /*  8 high-order of superblock update count   */
-       __u32 cp_events_lo;     /*  9 low-order of checkpoint update count    */
-       __u32 cp_events_hi;     /* 10 high-order of checkpoint update count   */
-#endif
-       __u32 recovery_cp;      /* 11 recovery checkpoint sector count        */
-       /* There are only valid for minor_version > 90 */
-       __u64 reshape_position; /* 12,13 next address in array-space for reshape */
-       __u32 new_level;        /* 14 new level we are reshaping to           */
-       __u32 delta_disks;      /* 15 change in number of raid_disks          */
-       __u32 new_layout;       /* 16 new layout                              */
-       __u32 new_chunk;        /* 17 new chunk size (bytes)                  */
-       __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
-
-       /*
-        * Personality information
-        */
-       __u32 layout;           /*  0 the array's physical layout             */
-       __u32 chunk_size;       /*  1 chunk size in bytes                     */
-       __u32 root_pv;          /*  2 LV root PV */
-       __u32 root_block;       /*  3 LV root block */
-       __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
-
-       /*
-        * Disks information
-        */
-       mdp_disk_t disks[MD_SB_DISKS];
-
-       /*
-        * Reserved
-        */
-       __u32 reserved[MD_SB_RESERVED_WORDS];
-
-       /*
-        * Active descriptor
-        */
-       mdp_disk_t this_disk;
-
-} mdp_super_t;
-
-static inline __u64 md_event(mdp_super_t *sb) {
-       __u64 ev = sb->events_hi;
-       return (ev<<32)| sb->events_lo;
-}
-
-#define MD_SUPERBLOCK_1_TIME_SEC_MASK ((1ULL<<40) - 1)
-
-/*
- * The version-1 superblock :
- * All numeric fields are little-endian.
- *
- * total size: 256 bytes plus 2 per device.
- *  1K allows 384 devices.
- */
-struct mdp_superblock_1 {
-       /* constant array information - 128 bytes */
-       __le32  magic;          /* MD_SB_MAGIC: 0xa92b4efc - little endian */
-       __le32  major_version;  /* 1 */
-       __le32  feature_map;    /* bit 0 set if 'bitmap_offset' is meaningful */
-       __le32  pad0;           /* always set to 0 when writing */
-
-       __u8    set_uuid[16];   /* user-space generated. */
-       char    set_name[32];   /* set and interpreted by user-space */
-
-       __le64  ctime;          /* lo 40 bits are seconds, top 24 are microseconds or 0*/
-       __le32  level;          /* -4 (multipath), -1 (linear), 0,1,4,5 */
-       __le32  layout;         /* only for raid5 and raid10 currently */
-       __le64  size;           /* used size of component devices, in 512byte sectors */
-
-       __le32  chunksize;      /* in 512byte sectors */
-       __le32  raid_disks;
-       __le32  bitmap_offset;  /* sectors after start of superblock that bitmap starts
-                                * NOTE: signed, so bitmap can be before superblock
-                                * only meaningful of feature_map[0] is set.
-                                */
-
-       /* These are only valid with feature bit '4' */
-       __le32  new_level;      /* new level we are reshaping to                */
-       __le64  reshape_position;       /* next address in array-space for reshape */
-       __le32  delta_disks;    /* change in number of raid_disks               */
-       __le32  new_layout;     /* new layout                                   */
-       __le32  new_chunk;      /* new chunk size (512byte sectors)             */
-       __le32  new_offset;     /* signed number to add to data_offset in new
-                                * layout.  0 == no-change.  This can be
-                                * different on each device in the array.
-                                */
-
-       /* constant this-device information - 64 bytes */
-       __le64  data_offset;    /* sector start of data, often 0 */
-       __le64  data_size;      /* sectors in this device that can be used for data */
-       __le64  super_offset;   /* sector start of this superblock */
-       __le64  recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
-       __le32  dev_number;     /* permanent identifier of this  device - not role in raid */
-       __le32  cnt_corrected_read; /* number of read errors that were corrected by re-writing */
-       __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
-       __u8    devflags;       /* per-device flags.  Only one defined...*/
-#define        WriteMostly1    1       /* mask for writemostly flag in above */
-       /* Bad block log.  If there are any bad blocks the feature flag is set.
-        * If offset and size are non-zero, that space is reserved and available
-        */
-       __u8    bblog_shift;    /* shift from sectors to block size */
-       __le16  bblog_size;     /* number of sectors reserved for list */
-       __le32  bblog_offset;   /* sector offset from superblock to bblog,
-                                * signed - not unsigned */
-
-       /* array state information - 64 bytes */
-       __le64  utime;          /* 40 bits second, 24 bits microseconds */
-       __le64  events;         /* incremented when superblock updated */
-       __le64  resync_offset;  /* data before this offset (from data_offset) known to be in sync */
-       __le32  sb_csum;        /* checksum up to devs[max_dev] */
-       __le32  max_dev;        /* size of devs[] array to consider */
-       __u8    pad3[64-32];    /* set to 0 when writing */
-
-       /* device state information. Indexed by dev_number.
-        * 2 bytes per device
-        * Note there are no per-device state flags. State information is rolled
-        * into the 'roles' value.  If a device is spare or faulty, then it doesn't
-        * have a meaningful role.
-        */
-       __le16  dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
-};
-
-/* feature_map bits */
-#define MD_FEATURE_BITMAP_OFFSET       1
-#define        MD_FEATURE_RECOVERY_OFFSET      2 /* recovery_offset is present and
-                                          * must be honoured
-                                          */
-#define        MD_FEATURE_RESHAPE_ACTIVE       4
-#define        MD_FEATURE_BAD_BLOCKS           8 /* badblock list is not empty */
-#define        MD_FEATURE_REPLACEMENT          16 /* This device is replacing an
-                                           * active device with same 'role'.
-                                           * 'recovery_offset' is also set.
-                                           */
-#define        MD_FEATURE_RESHAPE_BACKWARDS    32 /* Reshape doesn't change number
-                                           * of devices, but is going
-                                           * backwards anyway.
-                                           */
-#define        MD_FEATURE_NEW_OFFSET           64 /* new_offset must be honoured */
-#define        MD_FEATURE_ALL                  (MD_FEATURE_BITMAP_OFFSET       \
-                                       |MD_FEATURE_RECOVERY_OFFSET     \
-                                       |MD_FEATURE_RESHAPE_ACTIVE      \
-                                       |MD_FEATURE_BAD_BLOCKS          \
-                                       |MD_FEATURE_REPLACEMENT         \
-                                       |MD_FEATURE_RESHAPE_BACKWARDS   \
-                                       |MD_FEATURE_NEW_OFFSET          \
-                                       )
-
-#endif 
index fb1abb3367e9520a7e68cf738709e7510abe80f0..358c04bfbe2ad31c691ac07e87b5988395f2c2f3 100644 (file)
    (for example /usr/src/linux/COPYING); if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
 */
-
 #ifndef _MD_U_H
 #define _MD_U_H
 
-/*
- * Different major versions are not compatible.
- * Different minor versions are only downward compatible.
- * Different patchlevel versions are downward and upward compatible.
- */
-#define MD_MAJOR_VERSION                0
-#define MD_MINOR_VERSION                90
-/*
- * MD_PATCHLEVEL_VERSION indicates kernel functionality.
- * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
- *     and major_version/minor_version accordingly
- * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
- *     in the super status byte
- * >=3 means that bitmap superblock version 4 is supported, which uses
- *     little-ending representation rather than host-endian
- */
-#define MD_PATCHLEVEL_VERSION           3
-
-/* ioctls */
-
-/* status */
-#define RAID_VERSION           _IOR (MD_MAJOR, 0x10, mdu_version_t)
-#define GET_ARRAY_INFO         _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
-#define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
-#define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
-#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
-#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
-
-/* configuration */
-#define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
-#define ADD_NEW_DISK           _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
-#define HOT_REMOVE_DISK                _IO (MD_MAJOR, 0x22)
-#define SET_ARRAY_INFO         _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
-#define SET_DISK_INFO          _IO (MD_MAJOR, 0x24)
-#define WRITE_RAID_INFO                _IO (MD_MAJOR, 0x25)
-#define UNPROTECT_ARRAY                _IO (MD_MAJOR, 0x26)
-#define PROTECT_ARRAY          _IO (MD_MAJOR, 0x27)
-#define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
-#define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
-#define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
-#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
+#include <uapi/linux/raid/md_u.h>
 
-/* usage */
-#define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
-/*  0x31 was START_ARRAY  */
-#define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
-#define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
-#define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
-
-/* 63 partitions with the alternate major number (mdp) */
-#define MdpMinorShift 6
-#ifdef __KERNEL__
 extern int mdp_major;
-#endif
-
-typedef struct mdu_version_s {
-       int major;
-       int minor;
-       int patchlevel;
-} mdu_version_t;
-
-typedef struct mdu_array_info_s {
-       /*
-        * Generic constant information
-        */
-       int major_version;
-       int minor_version;
-       int patch_version;
-       int ctime;
-       int level;
-       int size;
-       int nr_disks;
-       int raid_disks;
-       int md_minor;
-       int not_persistent;
-
-       /*
-        * Generic state information
-        */
-       int utime;              /*  0 Superblock update time                  */
-       int state;              /*  1 State bits (clean, ...)                 */
-       int active_disks;       /*  2 Number of currently active disks        */
-       int working_disks;      /*  3 Number of working disks                 */
-       int failed_disks;       /*  4 Number of failed disks                  */
-       int spare_disks;        /*  5 Number of spare disks                   */
-
-       /*
-        * Personality information
-        */
-       int layout;             /*  0 the array's physical layout             */
-       int chunk_size; /*  1 chunk size in bytes                     */
-
-} mdu_array_info_t;
-
-/* non-obvious values for 'level' */
-#define        LEVEL_MULTIPATH         (-4)
-#define        LEVEL_LINEAR            (-1)
-#define        LEVEL_FAULTY            (-5)
-
-/* we need a value for 'no level specified' and 0
- * means 'raid0', so we need something else.  This is
- * for internal use only
- */
-#define        LEVEL_NONE              (-1000000)
-
-typedef struct mdu_disk_info_s {
-       /*
-        * configuration/status of one particular disk
-        */
-       int number;
-       int major;
-       int minor;
-       int raid_disk;
-       int state;
-
-} mdu_disk_info_t;
-
-typedef struct mdu_start_info_s {
-       /*
-        * configuration/status of one particular disk
-        */
-       int major;
-       int minor;
-       int raid_disk;
-       int state;
-
-} mdu_start_info_t;
-
-typedef struct mdu_bitmap_file_s
-{
-       char pathname[4096];
-} mdu_bitmap_file_t;
-
-typedef struct mdu_param_s
-{
-       int                     personality;    /* 1,2,3,4 */
-       int                     chunk_size;     /* in bytes */
-       int                     max_fault;      /* unused for now */
-} mdu_param_t;
-
 #endif 
-
index e11ccb4cf48dd5f6874322f375ce1537d007974c..0a260d8a18bf92dc3b8d4b582d3506e169d9dac5 100644 (file)
@@ -46,20 +46,17 @@ extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
 #define WARN_ON_RATELIMIT(condition, state)                    \
                WARN_ON((condition) && __ratelimit(state))
 
-#define __WARN_RATELIMIT(condition, state, format...)          \
-({                                                             \
-       int rtn = 0;                                            \
-       if (unlikely(__ratelimit(state)))                       \
-               rtn = WARN(condition, format);                  \
-       rtn;                                                    \
-})
-
-#define WARN_RATELIMIT(condition, format...)                   \
+#define WARN_RATELIMIT(condition, format, ...)                 \
 ({                                                             \
        static DEFINE_RATELIMIT_STATE(_rs,                      \
                                      DEFAULT_RATELIMIT_INTERVAL,       \
                                      DEFAULT_RATELIMIT_BURST); \
-       __WARN_RATELIMIT(condition, &_rs, format);              \
+       int rtn = !!(condition);                                \
+                                                               \
+       if (unlikely(rtn && __ratelimit(&_rs)))                 \
+               WARN(rtn, format, ##__VA_ARGS__);               \
+                                                               \
+       rtn;                                                    \
 })
 
 #else
@@ -67,15 +64,9 @@ extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
 #define WARN_ON_RATELIMIT(condition, state)                    \
        WARN_ON(condition)
 
-#define __WARN_RATELIMIT(condition, state, format...)          \
-({                                                             \
-       int rtn = WARN(condition, format);                      \
-       rtn;                                                    \
-})
-
-#define WARN_RATELIMIT(condition, format...)                   \
+#define WARN_RATELIMIT(condition, format, ...)                 \
 ({                                                             \
-       int rtn = WARN(condition, format);                      \
+       int rtn = WARN(condition, format, ##__VA_ARGS__);       \
        rtn;                                                    \
 })
 
index 214caa33433b9a58d4635d1f3214b099c515c8e5..2ac60c9cf6448fac839074e752d61f2de7b56c0a 100644 (file)
@@ -24,6 +24,7 @@
 #ifndef _LINUX_RBTREE_AUGMENTED_H
 #define _LINUX_RBTREE_AUGMENTED_H
 
+#include <linux/compiler.h>
 #include <linux/rbtree.h>
 
 /*
index 4187da51100631f157d508a1c121609a89204872..a3e7842786679567185ecdbc8835fd5936fb36f4 100644 (file)
@@ -275,9 +275,11 @@ struct rio_id_table {
  * struct rio_net - RIO network info
  * @node: Node in global list of RIO networks
  * @devices: List of devices in this network
+ * @switches: List of switches in this netowrk
  * @mports: List of master ports accessing this network
  * @hport: Default port for accessing this network
  * @id: RIO network ID
+ * @destid_table: destID allocation table
  */
 struct rio_net {
        struct list_head node;  /* node in list of networks */
index 7002bbfd5d4a55e76041e146cd268a9d027ed6ed..489dd7bb28ecf2920e545bf65cdb29d64aab9bdd 100644 (file)
@@ -69,4 +69,7 @@ extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
                             struct netlink_callback *cb,
                             struct net_device *dev,
                             int idx);
+
+extern int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+                                  struct net_device *dev, u16 mode);
 #endif /* __LINUX_RTNETLINK_H */
index 6a2c34e6d962658d0a1532959a06b5ddebe65087..320e976d5ab861b9e143476ae7dcd4b87956854e 100644 (file)
@@ -235,11 +235,13 @@ enum {
 /*
  * The callback notifies userspace to release buffers when skb DMA is done in
  * lower device, the skb last reference should be 0 when calling this.
+ * The zerocopy_success argument is true if zero copy transmit occurred,
+ * false on data copy or out of memory error caused by data copy attempt.
  * The ctx field is used to track device context.
  * The desc field is used to track userspace buffer index.
  */
 struct ubuf_info {
-       void (*callback)(struct ubuf_info *);
+       void (*callback)(struct ubuf_info *, bool zerocopy_success);
        void *ctx;
        unsigned long desc;
 };
@@ -374,6 +376,8 @@ typedef unsigned char *sk_buff_data_t;
  *     @mark: Generic packet mark
  *     @dropcount: total number of sk_receive_queue overflows
  *     @vlan_tci: vlan tag control information
+ *     @inner_transport_header: Inner transport layer header (encapsulation)
+ *     @inner_network_header: Network layer header (encapsulation)
  *     @transport_header: Transport layer header
  *     @network_header: Network layer header
  *     @mac_header: Link layer header
@@ -469,7 +473,13 @@ struct sk_buff {
        __u8                    wifi_acked:1;
        __u8                    no_fcs:1;
        __u8                    head_frag:1;
-       /* 8/10 bit hole (depending on ndisc_nodetype presence) */
+       /* Encapsulation protocol and NIC drivers should use
+        * this flag to indicate to each other if the skb contains
+        * encapsulated packet or not and maybe use the inner packet
+        * headers if needed
+        */
+       __u8                    encapsulation:1;
+       /* 7/9 bit hole (depending on ndisc_nodetype presence) */
        kmemcheck_bitfield_end(flags2);
 
 #ifdef CONFIG_NET_DMA
@@ -484,6 +494,8 @@ struct sk_buff {
                __u32           avail_size;
        };
 
+       sk_buff_data_t          inner_transport_header;
+       sk_buff_data_t          inner_network_header;
        sk_buff_data_t          transport_header;
        sk_buff_data_t          network_header;
        sk_buff_data_t          mac_header;
@@ -566,6 +578,7 @@ static inline struct rtable *skb_rtable(const struct sk_buff *skb)
 }
 
 extern void kfree_skb(struct sk_buff *skb);
+extern void skb_tx_error(struct sk_buff *skb);
 extern void consume_skb(struct sk_buff *skb);
 extern void           __kfree_skb(struct sk_buff *skb);
 extern struct kmem_cache *skbuff_head_cache;
@@ -643,7 +656,7 @@ extern unsigned int   skb_find_text(struct sk_buff *skb, unsigned int from,
 extern void __skb_get_rxhash(struct sk_buff *skb);
 static inline __u32 skb_get_rxhash(struct sk_buff *skb)
 {
-       if (!skb->rxhash)
+       if (!skb->l4_rxhash)
                __skb_get_rxhash(skb);
 
        return skb->rxhash;
@@ -1432,12 +1445,53 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
        skb->tail += len;
 }
 
+static inline void skb_reset_inner_headers(struct sk_buff *skb)
+{
+       skb->inner_network_header = skb->network_header;
+       skb->inner_transport_header = skb->transport_header;
+}
+
 static inline void skb_reset_mac_len(struct sk_buff *skb)
 {
        skb->mac_len = skb->network_header - skb->mac_header;
 }
 
 #ifdef NET_SKBUFF_DATA_USES_OFFSET
+static inline unsigned char *skb_inner_transport_header(const struct sk_buff
+                                                       *skb)
+{
+       return skb->head + skb->inner_transport_header;
+}
+
+static inline void skb_reset_inner_transport_header(struct sk_buff *skb)
+{
+       skb->inner_transport_header = skb->data - skb->head;
+}
+
+static inline void skb_set_inner_transport_header(struct sk_buff *skb,
+                                                  const int offset)
+{
+       skb_reset_inner_transport_header(skb);
+       skb->inner_transport_header += offset;
+}
+
+static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
+{
+       return skb->head + skb->inner_network_header;
+}
+
+static inline void skb_reset_inner_network_header(struct sk_buff *skb)
+{
+       skb->inner_network_header = skb->data - skb->head;
+}
+
+static inline void skb_set_inner_network_header(struct sk_buff *skb,
+                                               const int offset)
+{
+       skb_reset_inner_network_header(skb);
+       skb->inner_network_header += offset;
+}
+
 static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
 {
        return skb->head + skb->transport_header;
@@ -1493,6 +1547,38 @@ static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
 }
 
 #else /* NET_SKBUFF_DATA_USES_OFFSET */
+static inline unsigned char *skb_inner_transport_header(const struct sk_buff
+                                                       *skb)
+{
+       return skb->inner_transport_header;
+}
+
+static inline void skb_reset_inner_transport_header(struct sk_buff *skb)
+{
+       skb->inner_transport_header = skb->data;
+}
+
+static inline void skb_set_inner_transport_header(struct sk_buff *skb,
+                                                  const int offset)
+{
+       skb->inner_transport_header = skb->data + offset;
+}
+
+static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
+{
+       return skb->inner_network_header;
+}
+
+static inline void skb_reset_inner_network_header(struct sk_buff *skb)
+{
+       skb->inner_network_header = skb->data;
+}
+
+static inline void skb_set_inner_network_header(struct sk_buff *skb,
+                                               const int offset)
+{
+       skb->inner_network_header = skb->data + offset;
+}
 
 static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
 {
@@ -1571,11 +1657,21 @@ static inline u32 skb_network_header_len(const struct sk_buff *skb)
        return skb->transport_header - skb->network_header;
 }
 
+static inline u32 skb_inner_network_header_len(const struct sk_buff *skb)
+{
+       return skb->inner_transport_header - skb->inner_network_header;
+}
+
 static inline int skb_network_offset(const struct sk_buff *skb)
 {
        return skb_network_header(skb) - skb->data;
 }
 
+static inline int skb_inner_network_offset(const struct sk_buff *skb)
+{
+       return skb_inner_network_header(skb) - skb->data;
+}
+
 static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len)
 {
        return pskb_may_pull(skb, skb_network_offset(skb) + len);
index ce718cbce435f4ca2a52e1bac32b60631455bce0..f4bf16e16e166fce6ea13bb92b759a00d48f0ecb 100644 (file)
@@ -4,6 +4,7 @@
 #define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
 #define MII_LAN83C185_IM  30 /* Interrupt Mask */
 #define MII_LAN83C185_CTRL_STATUS 17 /* Mode/Status Register */
+#define MII_LAN83C185_SPECIAL_MODES 18 /* Special Modes Register */
 
 #define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
 #define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
@@ -22,4 +23,8 @@
 #define MII_LAN83C185_EDPWRDOWN (1 << 13) /* EDPWRDOWN */
 #define MII_LAN83C185_ENERGYON  (1 << 1)  /* ENERGYON */
 
+#define MII_LAN83C185_MODE_MASK      0xE0
+#define MII_LAN83C185_MODE_POWERDOWN 0xC0 /* Power Down mode */
+#define MII_LAN83C185_MODE_ALL       0xE0 /* All capable mode */
+
 #endif /* __LINUX_SMSCPHY_H__ */
diff --git a/include/linux/spi/Kbuild b/include/linux/spi/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index c64de9dd7631bb44232eeca7d8080c62521c5b1e..2f694f3846a9ad1a5d052e96d5f68cd9a152c313 100644 (file)
@@ -46,8 +46,9 @@ struct ads7846_platform_data {
        u16     debounce_rep;           /* additional consecutive good readings
                                         * required after the first two */
        int     gpio_pendown;           /* the GPIO used to decide the pendown
-                                        * state if get_pendown_state == NULL
-                                        */
+                                        * state if get_pendown_state == NULL */
+       int     gpio_pendown_debounce;  /* platform specific debounce time for
+                                        * the gpio_pendown */
        int     (*get_pendown_state)(void);
        int     (*filter_init)  (const struct ads7846_platform_data *pdata,
                                 void **filter_data);
index d9b0c84220c73897630f7cc7d35864c4eeeadb69..8f721e465e05b968ed1b5223c4b1e7eb61be78e2 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright (C) 2009-2010 Nokia Corporation
  *
- * Contact: Aaro Koskinen <aaro.koskinen@nokia.com>
- *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
index a1547ea3920d226cf56286b119c0e72d7a5b8712..de5b2f8176ce27d5c1dad489129585e3296d0d0a 100644 (file)
@@ -104,6 +104,7 @@ struct plat_stmmacenet_data {
        int bugged_jumbo;
        int pmt;
        int force_sf_dma_mode;
+       int riwt_off;
        void (*fix_mac_speed)(void *priv, unsigned int speed);
        void (*bus_setup)(void __iomem *ioaddr);
        int (*init)(struct platform_device *pdev);
diff --git a/include/linux/sunrpc/Kbuild b/include/linux/sunrpc/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index cd844a6a8d5f9f766503f91d229694918cbe14fc..14a8ff2de11e54907ff63d20ee23c7d4c29896fa 100644 (file)
@@ -158,8 +158,7 @@ struct ctl_table_root {
        struct ctl_table_set default_set;
        struct ctl_table_set *(*lookup)(struct ctl_table_root *root,
                                           struct nsproxy *namespaces);
-       int (*permissions)(struct ctl_table_root *root,
-                       struct nsproxy *namespaces, struct ctl_table *table);
+       int (*permissions)(struct ctl_table_header *head, struct ctl_table *table);
 };
 
 /* struct ctl_path describes where in the hierarchy a table is added */
diff --git a/include/linux/tc_act/Kbuild b/include/linux/tc_act/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/include/linux/tc_ematch/Kbuild b/include/linux/tc_ematch/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 8a7fc4be2d75f11d0ff774e727940dd16a2c64aa..4e1d2283e3ccfda3f754229d7272e540c086d139 100644 (file)
@@ -35,6 +35,16 @@ static inline unsigned int tcp_hdrlen(const struct sk_buff *skb)
        return tcp_hdr(skb)->doff * 4;
 }
 
+static inline struct tcphdr *inner_tcp_hdr(const struct sk_buff *skb)
+{
+       return (struct tcphdr *)skb_inner_transport_header(skb);
+}
+
+static inline unsigned int inner_tcp_hdrlen(const struct sk_buff *skb)
+{
+       return inner_tcp_hdr(skb)->doff * 4;
+}
+
 static inline unsigned int tcp_optlen(const struct sk_buff *skb)
 {
        return (tcp_hdr(skb)->doff - 5) * 4;
@@ -191,7 +201,8 @@ struct tcp_sock {
        u8      do_early_retrans:1,/* Enable RFC5827 early-retransmit  */
                early_retrans_delayed:1, /* Delayed ER timer installed */
                syn_data:1,     /* SYN includes data */
-               syn_fastopen:1; /* SYN includes Fast Open option */
+               syn_fastopen:1, /* SYN includes Fast Open option */
+               syn_data_acked:1;/* data in SYN is acked by SYN-ACK */
 
 /* RTT measurement */
        u32     srtt;           /* smoothed round trip time << 3        */
diff --git a/include/linux/timecompare.h b/include/linux/timecompare.h
deleted file mode 100644 (file)
index 546e223..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Utility code which helps transforming between two different time
- * bases, called "source" and "target" time in this code.
- *
- * Source time has to be provided via the timecounter API while target
- * time is accessed via a function callback whose prototype
- * intentionally matches ktime_get() and ktime_get_real(). These
- * interfaces where chosen like this so that the code serves its
- * initial purpose without additional glue code.
- *
- * This purpose is synchronizing a hardware clock in a NIC with system
- * time, in order to implement the Precision Time Protocol (PTP,
- * IEEE1588) with more accurate hardware assisted time stamping.  In
- * that context only synchronization against system time (=
- * ktime_get_real()) is currently needed. But this utility code might
- * become useful in other situations, which is why it was written as
- * general purpose utility code.
- *
- * The source timecounter is assumed to return monotonically
- * increasing time (but this code does its best to compensate if that
- * is not the case) whereas target time may jump.
- *
- * The target time corresponding to a source time is determined by
- * reading target time, reading source time, reading target time
- * again, then assuming that average target time corresponds to source
- * time. In other words, the assumption is that reading the source
- * time is slow and involves equal time for sending the request and
- * receiving the reply, whereas reading target time is assumed to be
- * fast.
- *
- * Copyright (C) 2009 Intel Corporation.
- * Author: Patrick Ohly <patrick.ohly@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-#ifndef _LINUX_TIMECOMPARE_H
-#define _LINUX_TIMECOMPARE_H
-
-#include <linux/clocksource.h>
-#include <linux/ktime.h>
-
-/**
- * struct timecompare - stores state and configuration for the two clocks
- *
- * Initialize to zero, then set source/target/num_samples.
- *
- * Transformation between source time and target time is done with:
- * target_time = source_time + offset +
- *               (source_time - last_update) * skew /
- *               TIMECOMPARE_SKEW_RESOLUTION
- *
- * @source:          used to get source time stamps via timecounter_read()
- * @target:          function returning target time (for example, ktime_get
- *                   for monotonic time, or ktime_get_real for wall clock)
- * @num_samples:     number of times that source time and target time are to
- *                   be compared when determining their offset
- * @offset:          (target time - source time) at the time of the last update
- * @skew:            average (target time - source time) / delta source time *
- *                   TIMECOMPARE_SKEW_RESOLUTION
- * @last_update:     last source time stamp when time offset was measured
- */
-struct timecompare {
-       struct timecounter *source;
-       ktime_t (*target)(void);
-       int num_samples;
-
-       s64 offset;
-       s64 skew;
-       u64 last_update;
-};
-
-/**
- * timecompare_transform - transform source time stamp into target time base
- * @sync:            context for time sync
- * @source_tstamp:   the result of timecounter_read() or
- *                   timecounter_cyc2time()
- */
-extern ktime_t timecompare_transform(struct timecompare *sync,
-                                    u64 source_tstamp);
-
-/**
- * timecompare_offset - measure current (target time - source time) offset
- * @sync:            context for time sync
- * @offset:          average offset during sample period returned here
- * @source_tstamp:   average source time during sample period returned here
- *
- * Returns number of samples used. Might be zero (= no result) in the
- * unlikely case that target time was monotonically decreasing for all
- * samples (= broken).
- */
-extern int timecompare_offset(struct timecompare *sync,
-                             s64 *offset,
-                             u64 *source_tstamp);
-
-extern void __timecompare_update(struct timecompare *sync,
-                                u64 source_tstamp);
-
-/**
- * timecompare_update - update offset and skew by measuring current offset
- * @sync:            context for time sync
- * @source_tstamp:   the result of timecounter_read() or
- *                   timecounter_cyc2time(), pass zero to force update
- *
- * Updates are only done at most once per second.
- */
-static inline void timecompare_update(struct timecompare *sync,
-                                     u64 source_tstamp)
-{
-       if (!source_tstamp ||
-           (s64)(source_tstamp - sync->last_update) >= NSEC_PER_SEC)
-               __timecompare_update(sync, source_tstamp);
-}
-
-#endif /* _LINUX_TIMECOMPARE_H */
index 0b67d77935204b2ae7dab682270cc30a1b1da6d6..9d81de123c9017f4463ba4fa09a61b8b7425a8bf 100644 (file)
@@ -27,6 +27,11 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
        return (struct udphdr *)skb_transport_header(skb);
 }
 
+static inline struct udphdr *inner_udp_hdr(const struct sk_buff *skb)
+{
+       return (struct udphdr *)skb_inner_transport_header(skb);
+}
+
 #define UDP_HTABLE_SIZE_MIN            (CONFIG_BASE_SMALL ? 128 : 256)
 
 static inline int udp_hashfn(struct net *net, unsigned num, unsigned mask)
index e6f0331e3d456281c87370e8c0275961c04ca084..24594571c5a3aa8a094d9cca3795420e32cb4ce0 100644 (file)
@@ -35,16 +35,6 @@ struct inode;
 # include <asm/uprobes.h>
 #endif
 
-/* flags that denote/change uprobes behaviour */
-
-/* Have a copy of original instruction */
-#define UPROBE_COPY_INSN       0x1
-
-/* Dont run handlers when first register/ last unregister in progress*/
-#define UPROBE_RUN_HANDLER     0x2
-/* Can skip singlestep */
-#define UPROBE_SKIP_SSTEP      0x4
-
 struct uprobe_consumer {
        int (*handler)(struct uprobe_consumer *self, struct pt_regs *regs);
        /*
@@ -59,7 +49,6 @@ struct uprobe_consumer {
 #ifdef CONFIG_UPROBES
 enum uprobe_task_state {
        UTASK_RUNNING,
-       UTASK_BP_HIT,
        UTASK_SSTEP,
        UTASK_SSTEP_ACK,
        UTASK_SSTEP_TRAPPED,
index 07915a32fb9dcda932989cb495798cdc48bb1059..10278d18709cf439d3fc2aeea2b7057f22eee16a 100644 (file)
@@ -1778,17 +1778,6 @@ static inline int usb_translate_errors(int error_code)
 extern void usb_register_notify(struct notifier_block *nb);
 extern void usb_unregister_notify(struct notifier_block *nb);
 
-#ifdef DEBUG
-#define dbg(format, arg...)                                            \
-       printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg)
-#else
-#define dbg(format, arg...)                                            \
-do {                                                                   \
-       if (0)                                                          \
-               printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \
-} while (0)
-#endif
-
 /* debugfs stuff */
 extern struct dentry *usb_debug_root;
 
index b607f3532e880011453fd04462cbe90801538a6d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,10 +0,0 @@
-header-y += audio.h
-header-y += cdc.h
-header-y += ch9.h
-header-y += ch11.h
-header-y += functionfs.h
-header-y += gadgetfs.h
-header-y += midi.h
-header-y += g_printer.h
-header-y += tmc.h
-header-y += video.h
index a54b8255d75f099259c8e77ced1c8eef9aeb1158..3d84619110a4691f6d49900538f93077aa65251b 100644 (file)
  * Types and defines in this file are either specific to version 1.0 of
  * this standard or common for newer versions.
  */
-
 #ifndef __LINUX_USB_AUDIO_H
 #define __LINUX_USB_AUDIO_H
 
-#include <linux/types.h>
-
-/* bInterfaceProtocol values to denote the version of the standard used */
-#define UAC_VERSION_1                  0x00
-#define UAC_VERSION_2                  0x20
-
-/* A.2 Audio Interface Subclass Codes */
-#define USB_SUBCLASS_AUDIOCONTROL      0x01
-#define USB_SUBCLASS_AUDIOSTREAMING    0x02
-#define USB_SUBCLASS_MIDISTREAMING     0x03
-
-/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */
-#define UAC_HEADER                     0x01
-#define UAC_INPUT_TERMINAL             0x02
-#define UAC_OUTPUT_TERMINAL            0x03
-#define UAC_MIXER_UNIT                 0x04
-#define UAC_SELECTOR_UNIT              0x05
-#define UAC_FEATURE_UNIT               0x06
-#define UAC1_PROCESSING_UNIT           0x07
-#define UAC1_EXTENSION_UNIT            0x08
-
-/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */
-#define UAC_AS_GENERAL                 0x01
-#define UAC_FORMAT_TYPE                        0x02
-#define UAC_FORMAT_SPECIFIC            0x03
-
-/* A.7 Processing Unit Process Types */
-#define UAC_PROCESS_UNDEFINED          0x00
-#define UAC_PROCESS_UP_DOWNMIX         0x01
-#define UAC_PROCESS_DOLBY_PROLOGIC     0x02
-#define UAC_PROCESS_STEREO_EXTENDER    0x03
-#define UAC_PROCESS_REVERB             0x04
-#define UAC_PROCESS_CHORUS             0x05
-#define UAC_PROCESS_DYN_RANGE_COMP     0x06
-
-/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */
-#define UAC_EP_GENERAL                 0x01
-
-/* A.9 Audio Class-Specific Request Codes */
-#define UAC_SET_                       0x00
-#define UAC_GET_                       0x80
-
-#define UAC__CUR                       0x1
-#define UAC__MIN                       0x2
-#define UAC__MAX                       0x3
-#define UAC__RES                       0x4
-#define UAC__MEM                       0x5
-
-#define UAC_SET_CUR                    (UAC_SET_ | UAC__CUR)
-#define UAC_GET_CUR                    (UAC_GET_ | UAC__CUR)
-#define UAC_SET_MIN                    (UAC_SET_ | UAC__MIN)
-#define UAC_GET_MIN                    (UAC_GET_ | UAC__MIN)
-#define UAC_SET_MAX                    (UAC_SET_ | UAC__MAX)
-#define UAC_GET_MAX                    (UAC_GET_ | UAC__MAX)
-#define UAC_SET_RES                    (UAC_SET_ | UAC__RES)
-#define UAC_GET_RES                    (UAC_GET_ | UAC__RES)
-#define UAC_SET_MEM                    (UAC_SET_ | UAC__MEM)
-#define UAC_GET_MEM                    (UAC_GET_ | UAC__MEM)
-
-#define UAC_GET_STAT                   0xff
-
-/* A.10 Control Selector Codes */
-
-/* A.10.1 Terminal Control Selectors */
-#define UAC_TERM_COPY_PROTECT          0x01
-
-/* A.10.2 Feature Unit Control Selectors */
-#define UAC_FU_MUTE                    0x01
-#define UAC_FU_VOLUME                  0x02
-#define UAC_FU_BASS                    0x03
-#define UAC_FU_MID                     0x04
-#define UAC_FU_TREBLE                  0x05
-#define UAC_FU_GRAPHIC_EQUALIZER       0x06
-#define UAC_FU_AUTOMATIC_GAIN          0x07
-#define UAC_FU_DELAY                   0x08
-#define UAC_FU_BASS_BOOST              0x09
-#define UAC_FU_LOUDNESS                        0x0a
-
-#define UAC_CONTROL_BIT(CS)    (1 << ((CS) - 1))
-
-/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */
-#define UAC_UD_ENABLE                  0x01
-#define UAC_UD_MODE_SELECT             0x02
-
-/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */
-#define UAC_DP_ENABLE                  0x01
-#define UAC_DP_MODE_SELECT             0x02
-
-/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */
-#define UAC_3D_ENABLE                  0x01
-#define UAC_3D_SPACE                   0x02
-
-/* A.10.3.4 Reverberation Processing Unit Control Selectors */
-#define UAC_REVERB_ENABLE              0x01
-#define UAC_REVERB_LEVEL               0x02
-#define UAC_REVERB_TIME                        0x03
-#define UAC_REVERB_FEEDBACK            0x04
-
-/* A.10.3.5 Chorus Processing Unit Control Selectors */
-#define UAC_CHORUS_ENABLE              0x01
-#define UAC_CHORUS_LEVEL               0x02
-#define UAC_CHORUS_RATE                        0x03
-#define UAC_CHORUS_DEPTH               0x04
-
-/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */
-#define UAC_DCR_ENABLE                 0x01
-#define UAC_DCR_RATE                   0x02
-#define UAC_DCR_MAXAMPL                        0x03
-#define UAC_DCR_THRESHOLD              0x04
-#define UAC_DCR_ATTACK_TIME            0x05
-#define UAC_DCR_RELEASE_TIME           0x06
-
-/* A.10.4 Extension Unit Control Selectors */
-#define UAC_XU_ENABLE                  0x01
-
-/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */
-#define UAC_MS_HEADER                  0x01
-#define UAC_MIDI_IN_JACK               0x02
-#define UAC_MIDI_OUT_JACK              0x03
-
-/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */
-#define UAC_MS_GENERAL                 0x01
-
-/* Terminals - 2.1 USB Terminal Types */
-#define UAC_TERMINAL_UNDEFINED         0x100
-#define UAC_TERMINAL_STREAMING         0x101
-#define UAC_TERMINAL_VENDOR_SPEC       0x1FF
-
-/* Terminal Control Selectors */
-/* 4.3.2  Class-Specific AC Interface Descriptor */
-struct uac1_ac_header_descriptor {
-       __u8  bLength;                  /* 8 + n */
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* UAC_MS_HEADER */
-       __le16 bcdADC;                  /* 0x0100 */
-       __le16 wTotalLength;            /* includes Unit and Terminal desc. */
-       __u8  bInCollection;            /* n */
-       __u8  baInterfaceNr[];          /* [n] */
-} __attribute__ ((packed));
-
-#define UAC_DT_AC_HEADER_SIZE(n)       (8 + (n))
-
-/* As above, but more useful for defining your own descriptors: */
-#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n)                    \
-struct uac1_ac_header_descriptor_##n {                 \
-       __u8  bLength;                                          \
-       __u8  bDescriptorType;                                  \
-       __u8  bDescriptorSubtype;                               \
-       __le16 bcdADC;                                          \
-       __le16 wTotalLength;                                    \
-       __u8  bInCollection;                                    \
-       __u8  baInterfaceNr[n];                                 \
-} __attribute__ ((packed))
-
-/* 4.3.2.1 Input Terminal Descriptor */
-struct uac_input_terminal_descriptor {
-       __u8  bLength;                  /* in bytes: 12 */
-       __u8  bDescriptorType;          /* CS_INTERFACE descriptor type */
-       __u8  bDescriptorSubtype;       /* INPUT_TERMINAL descriptor subtype */
-       __u8  bTerminalID;              /* Constant uniquely terminal ID */
-       __le16 wTerminalType;           /* USB Audio Terminal Types */
-       __u8  bAssocTerminal;           /* ID of the Output Terminal associated */
-       __u8  bNrChannels;              /* Number of logical output channels */
-       __le16 wChannelConfig;
-       __u8  iChannelNames;
-       __u8  iTerminal;
-} __attribute__ ((packed));
-
-#define UAC_DT_INPUT_TERMINAL_SIZE                     12
-
-/* Terminals - 2.2 Input Terminal Types */
-#define UAC_INPUT_TERMINAL_UNDEFINED                   0x200
-#define UAC_INPUT_TERMINAL_MICROPHONE                  0x201
-#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE          0x202
-#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE         0x203
-#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE         0x204
-#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY            0x205
-#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY       0x206
-
-/* Terminals - control selectors */
-
-#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL           0x01
-
-/* 4.3.2.2 Output Terminal Descriptor */
-struct uac1_output_terminal_descriptor {
-       __u8  bLength;                  /* in bytes: 9 */
-       __u8  bDescriptorType;          /* CS_INTERFACE descriptor type */
-       __u8  bDescriptorSubtype;       /* OUTPUT_TERMINAL descriptor subtype */
-       __u8  bTerminalID;              /* Constant uniquely terminal ID */
-       __le16 wTerminalType;           /* USB Audio Terminal Types */
-       __u8  bAssocTerminal;           /* ID of the Input Terminal associated */
-       __u8  bSourceID;                /* ID of the connected Unit or Terminal*/
-       __u8  iTerminal;
-} __attribute__ ((packed));
-
-#define UAC_DT_OUTPUT_TERMINAL_SIZE                    9
-
-/* Terminals - 2.3 Output Terminal Types */
-#define UAC_OUTPUT_TERMINAL_UNDEFINED                  0x300
-#define UAC_OUTPUT_TERMINAL_SPEAKER                    0x301
-#define UAC_OUTPUT_TERMINAL_HEADPHONES                 0x302
-#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303
-#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER            0x304
-#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER               0x305
-#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER      0x306
-#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER   0x307
-
-/* Set bControlSize = 2 as default setting */
-#define UAC_DT_FEATURE_UNIT_SIZE(ch)           (7 + ((ch) + 1) * 2)
-
-/* As above, but more useful for defining your own descriptors: */
-#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch)                        \
-struct uac_feature_unit_descriptor_##ch {                      \
-       __u8  bLength;                                          \
-       __u8  bDescriptorType;                                  \
-       __u8  bDescriptorSubtype;                               \
-       __u8  bUnitID;                                          \
-       __u8  bSourceID;                                        \
-       __u8  bControlSize;                                     \
-       __le16 bmaControls[ch + 1];                             \
-       __u8  iFeature;                                         \
-} __attribute__ ((packed))
-
-/* 4.3.2.3 Mixer Unit Descriptor */
-struct uac_mixer_unit_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bUnitID;
-       __u8 bNrInPins;
-       __u8 baSourceID[];
-} __attribute__ ((packed));
+#include <uapi/linux/usb/audio.h>
 
-static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc)
-{
-       return desc->baSourceID[desc->bNrInPins];
-}
-
-static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc,
-                                                 int protocol)
-{
-       if (protocol == UAC_VERSION_1)
-               return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
-                       desc->baSourceID[desc->bNrInPins + 1];
-       else
-               return  (desc->baSourceID[desc->bNrInPins + 4] << 24) |
-                       (desc->baSourceID[desc->bNrInPins + 3] << 16) |
-                       (desc->baSourceID[desc->bNrInPins + 2] << 8)  |
-                       (desc->baSourceID[desc->bNrInPins + 1]);
-}
-
-static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc,
-                                               int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               desc->baSourceID[desc->bNrInPins + 3] :
-               desc->baSourceID[desc->bNrInPins + 5];
-}
-
-static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
-                                             int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               &desc->baSourceID[desc->bNrInPins + 4] :
-               &desc->baSourceID[desc->bNrInPins + 6];
-}
-
-static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
-{
-       __u8 *raw = (__u8 *) desc;
-       return raw[desc->bLength - 1];
-}
-
-/* 4.3.2.4 Selector Unit Descriptor */
-struct uac_selector_unit_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bUintID;
-       __u8 bNrInPins;
-       __u8 baSourceID[];
-} __attribute__ ((packed));
-
-static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc)
-{
-       __u8 *raw = (__u8 *) desc;
-       return raw[desc->bLength - 1];
-}
-
-/* 4.3.2.5 Feature Unit Descriptor */
-struct uac_feature_unit_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bUnitID;
-       __u8 bSourceID;
-       __u8 bControlSize;
-       __u8 bmaControls[0]; /* variable length */
-} __attribute__((packed));
-
-static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc)
-{
-       __u8 *raw = (__u8 *) desc;
-       return raw[desc->bLength - 1];
-}
-
-/* 4.3.2.6 Processing Unit Descriptors */
-struct uac_processing_unit_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bUnitID;
-       __u16 wProcessType;
-       __u8 bNrInPins;
-       __u8 baSourceID[];
-} __attribute__ ((packed));
-
-static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc)
-{
-       return desc->baSourceID[desc->bNrInPins];
-}
-
-static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc,
-                                                      int protocol)
-{
-       if (protocol == UAC_VERSION_1)
-               return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
-                       desc->baSourceID[desc->bNrInPins + 1];
-       else
-               return  (desc->baSourceID[desc->bNrInPins + 4] << 24) |
-                       (desc->baSourceID[desc->bNrInPins + 3] << 16) |
-                       (desc->baSourceID[desc->bNrInPins + 2] << 8)  |
-                       (desc->baSourceID[desc->bNrInPins + 1]);
-}
-
-static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc,
-                                                    int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               desc->baSourceID[desc->bNrInPins + 3] :
-               desc->baSourceID[desc->bNrInPins + 5];
-}
-
-static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
-                                                   int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               desc->baSourceID[desc->bNrInPins + 4] :
-               desc->baSourceID[desc->bNrInPins + 6];
-}
-
-static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc,
-                                                  int protocol)
-{
-       return (protocol == UAC_VERSION_1) ?
-               &desc->baSourceID[desc->bNrInPins + 5] :
-               &desc->baSourceID[desc->bNrInPins + 7];
-}
-
-static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc,
-                                                  int protocol)
-{
-       __u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-       return desc->baSourceID[desc->bNrInPins + control_size];
-}
-
-static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc,
-                                                int protocol)
-{
-       __u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
-       return &desc->baSourceID[desc->bNrInPins + control_size + 1];
-}
-
-/* 4.5.2 Class-Specific AS Interface Descriptor */
-struct uac1_as_header_descriptor {
-       __u8  bLength;                  /* in bytes: 7 */
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* AS_GENERAL */
-       __u8  bTerminalLink;            /* Terminal ID of connected Terminal */
-       __u8  bDelay;                   /* Delay introduced by the data path */
-       __le16 wFormatTag;              /* The Audio Data Format */
-} __attribute__ ((packed));
-
-#define UAC_DT_AS_HEADER_SIZE          7
-
-/* Formats - A.1.1 Audio Data Format Type I Codes */
-#define UAC_FORMAT_TYPE_I_UNDEFINED    0x0
-#define UAC_FORMAT_TYPE_I_PCM          0x1
-#define UAC_FORMAT_TYPE_I_PCM8         0x2
-#define UAC_FORMAT_TYPE_I_IEEE_FLOAT   0x3
-#define UAC_FORMAT_TYPE_I_ALAW         0x4
-#define UAC_FORMAT_TYPE_I_MULAW                0x5
-
-struct uac_format_type_i_continuous_descriptor {
-       __u8  bLength;                  /* in bytes: 8 + (ns * 3) */
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* FORMAT_TYPE */
-       __u8  bFormatType;              /* FORMAT_TYPE_1 */
-       __u8  bNrChannels;              /* physical channels in the stream */
-       __u8  bSubframeSize;            /* */
-       __u8  bBitResolution;
-       __u8  bSamFreqType;
-       __u8  tLowerSamFreq[3];
-       __u8  tUpperSamFreq[3];
-} __attribute__ ((packed));
-
-#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14
-
-struct uac_format_type_i_discrete_descriptor {
-       __u8  bLength;                  /* in bytes: 8 + (ns * 3) */
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* FORMAT_TYPE */
-       __u8  bFormatType;              /* FORMAT_TYPE_1 */
-       __u8  bNrChannels;              /* physical channels in the stream */
-       __u8  bSubframeSize;            /* */
-       __u8  bBitResolution;
-       __u8  bSamFreqType;
-       __u8  tSamFreq[][3];
-} __attribute__ ((packed));
-
-#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n)             \
-struct uac_format_type_i_discrete_descriptor_##n {             \
-       __u8  bLength;                                          \
-       __u8  bDescriptorType;                                  \
-       __u8  bDescriptorSubtype;                               \
-       __u8  bFormatType;                                      \
-       __u8  bNrChannels;                                      \
-       __u8  bSubframeSize;                                    \
-       __u8  bBitResolution;                                   \
-       __u8  bSamFreqType;                                     \
-       __u8  tSamFreq[n][3];                                   \
-} __attribute__ ((packed))
-
-#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n)        (8 + (n * 3))
-
-struct uac_format_type_i_ext_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bFormatType;
-       __u8 bSubslotSize;
-       __u8 bBitResolution;
-       __u8 bHeaderLength;
-       __u8 bControlSize;
-       __u8 bSideBandProtocol;
-} __attribute__((packed));
-
-/* Formats - Audio Data Format Type I Codes */
-
-#define UAC_FORMAT_TYPE_II_MPEG        0x1001
-#define UAC_FORMAT_TYPE_II_AC3 0x1002
-
-struct uac_format_type_ii_discrete_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bFormatType;
-       __le16 wMaxBitRate;
-       __le16 wSamplesPerFrame;
-       __u8 bSamFreqType;
-       __u8 tSamFreq[][3];
-} __attribute__((packed));
-
-struct uac_format_type_ii_ext_descriptor {
-       __u8 bLength;
-       __u8 bDescriptorType;
-       __u8 bDescriptorSubtype;
-       __u8 bFormatType;
-       __u16 wMaxBitRate;
-       __u16 wSamplesPerFrame;
-       __u8 bHeaderLength;
-       __u8 bSideBandProtocol;
-} __attribute__((packed));
-
-/* type III */
-#define UAC_FORMAT_TYPE_III_IEC1937_AC3        0x2001
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1       0x2002
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT        0x2003
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT  0x2004
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS    0x2005
-#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS   0x2006
-
-/* Formats - A.2 Format Type Codes */
-#define UAC_FORMAT_TYPE_UNDEFINED      0x0
-#define UAC_FORMAT_TYPE_I              0x1
-#define UAC_FORMAT_TYPE_II             0x2
-#define UAC_FORMAT_TYPE_III            0x3
-#define UAC_EXT_FORMAT_TYPE_I          0x81
-#define UAC_EXT_FORMAT_TYPE_II         0x82
-#define UAC_EXT_FORMAT_TYPE_III                0x83
-
-struct uac_iso_endpoint_descriptor {
-       __u8  bLength;                  /* in bytes: 7 */
-       __u8  bDescriptorType;          /* USB_DT_CS_ENDPOINT */
-       __u8  bDescriptorSubtype;       /* EP_GENERAL */
-       __u8  bmAttributes;
-       __u8  bLockDelayUnits;
-       __le16 wLockDelay;
-} __attribute__((packed));
-#define UAC_ISO_ENDPOINT_DESC_SIZE     7
-
-#define UAC_EP_CS_ATTR_SAMPLE_RATE     0x01
-#define UAC_EP_CS_ATTR_PITCH_CONTROL   0x02
-#define UAC_EP_CS_ATTR_FILL_MAX                0x80
-
-/* status word format (3.7.1.1) */
-
-#define UAC1_STATUS_TYPE_ORIG_MASK             0x0f
-#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0
-#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF  0x1
-#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP  0x2
-
-#define UAC1_STATUS_TYPE_IRQ_PENDING           (1 << 7)
-#define UAC1_STATUS_TYPE_MEM_CHANGED           (1 << 6)
-
-struct uac1_status_word {
-       __u8 bStatusType;
-       __u8 bOriginator;
-} __attribute__((packed));
-
-#ifdef __KERNEL__
 
 struct usb_audio_control {
        struct list_head list;
@@ -561,6 +41,4 @@ struct usb_audio_control_selector {
        struct usb_descriptor_header *desc;
 };
 
-#endif /* __KERNEL__ */
-
 #endif /* __LINUX_USB_AUDIO_H */
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
deleted file mode 100644 (file)
index 81a9279..0000000
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * USB Communications Device Class (CDC) definitions
- *
- * CDC says how to talk to lots of different types of network adapters,
- * notably ethernet adapters and various modems.  It's used mostly with
- * firmware based USB peripherals.
- */
-
-#ifndef __LINUX_USB_CDC_H
-#define __LINUX_USB_CDC_H
-
-#include <linux/types.h>
-
-#define USB_CDC_SUBCLASS_ACM                   0x02
-#define USB_CDC_SUBCLASS_ETHERNET              0x06
-#define USB_CDC_SUBCLASS_WHCM                  0x08
-#define USB_CDC_SUBCLASS_DMM                   0x09
-#define USB_CDC_SUBCLASS_MDLM                  0x0a
-#define USB_CDC_SUBCLASS_OBEX                  0x0b
-#define USB_CDC_SUBCLASS_EEM                   0x0c
-#define USB_CDC_SUBCLASS_NCM                   0x0d
-
-#define USB_CDC_PROTO_NONE                     0
-
-#define USB_CDC_ACM_PROTO_AT_V25TER            1
-#define USB_CDC_ACM_PROTO_AT_PCCA101           2
-#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE      3
-#define USB_CDC_ACM_PROTO_AT_GSM               4
-#define USB_CDC_ACM_PROTO_AT_3G                        5
-#define USB_CDC_ACM_PROTO_AT_CDMA              6
-#define USB_CDC_ACM_PROTO_VENDOR               0xff
-
-#define USB_CDC_PROTO_EEM                      7
-
-#define USB_CDC_NCM_PROTO_NTB                  1
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Class-Specific descriptors ... there are a couple dozen of them
- */
-
-#define USB_CDC_HEADER_TYPE            0x00    /* header_desc */
-#define USB_CDC_CALL_MANAGEMENT_TYPE   0x01    /* call_mgmt_descriptor */
-#define USB_CDC_ACM_TYPE               0x02    /* acm_descriptor */
-#define USB_CDC_UNION_TYPE             0x06    /* union_desc */
-#define USB_CDC_COUNTRY_TYPE           0x07
-#define USB_CDC_NETWORK_TERMINAL_TYPE  0x0a    /* network_terminal_desc */
-#define USB_CDC_ETHERNET_TYPE          0x0f    /* ether_desc */
-#define USB_CDC_WHCM_TYPE              0x11
-#define USB_CDC_MDLM_TYPE              0x12    /* mdlm_desc */
-#define USB_CDC_MDLM_DETAIL_TYPE       0x13    /* mdlm_detail_desc */
-#define USB_CDC_DMM_TYPE               0x14
-#define USB_CDC_OBEX_TYPE              0x15
-#define USB_CDC_NCM_TYPE               0x1a
-
-/* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
-struct usb_cdc_header_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __le16  bcdCDC;
-} __attribute__ ((packed));
-
-/* "Call Management Descriptor" from CDC spec  5.2.3.2 */
-struct usb_cdc_call_mgmt_descriptor {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __u8    bmCapabilities;
-#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT                0x01
-#define USB_CDC_CALL_MGMT_CAP_DATA_INTF                0x02
-
-       __u8    bDataInterface;
-} __attribute__ ((packed));
-
-/* "Abstract Control Management Descriptor" from CDC spec  5.2.3.3 */
-struct usb_cdc_acm_descriptor {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __u8    bmCapabilities;
-} __attribute__ ((packed));
-
-/* capabilities from 5.2.3.3 */
-
-#define USB_CDC_COMM_FEATURE   0x01
-#define USB_CDC_CAP_LINE       0x02
-#define USB_CDC_CAP_BRK                0x04
-#define USB_CDC_CAP_NOTIFY     0x08
-
-/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
-struct usb_cdc_union_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __u8    bMasterInterface0;
-       __u8    bSlaveInterface0;
-       /* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-/* "Country Selection Functional Descriptor" from CDC spec 5.2.3.9 */
-struct usb_cdc_country_functional_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __u8    iCountryCodeRelDate;
-       __le16  wCountyCode0;
-       /* ... and there can be a lot of country codes */
-} __attribute__ ((packed));
-
-/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */
-struct usb_cdc_network_terminal_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __u8    bEntityId;
-       __u8    iName;
-       __u8    bChannelIndex;
-       __u8    bPhysicalInterface;
-} __attribute__ ((packed));
-
-/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
-struct usb_cdc_ether_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __u8    iMACAddress;
-       __le32  bmEthernetStatistics;
-       __le16  wMaxSegmentSize;
-       __le16  wNumberMCFilters;
-       __u8    bNumberPowerFilters;
-} __attribute__ ((packed));
-
-/* "Telephone Control Model Functional Descriptor" from CDC WMC spec 6.3..3 */
-struct usb_cdc_dmm_desc {
-       __u8    bFunctionLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubtype;
-       __u16   bcdVersion;
-       __le16  wMaxCommand;
-} __attribute__ ((packed));
-
-/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
-struct usb_cdc_mdlm_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __le16  bcdVersion;
-       __u8    bGUID[16];
-} __attribute__ ((packed));
-
-/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
-struct usb_cdc_mdlm_detail_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       /* type is associated with mdlm_desc.bGUID */
-       __u8    bGuidDescriptorType;
-       __u8    bDetailData[0];
-} __attribute__ ((packed));
-
-/* "OBEX Control Model Functional Descriptor" */
-struct usb_cdc_obex_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __le16  bcdVersion;
-} __attribute__ ((packed));
-
-/* "NCM Control Model Functional Descriptor" */
-struct usb_cdc_ncm_desc {
-       __u8    bLength;
-       __u8    bDescriptorType;
-       __u8    bDescriptorSubType;
-
-       __le16  bcdNcmVersion;
-       __u8    bmNetworkCapabilities;
-} __attribute__ ((packed));
-/*-------------------------------------------------------------------------*/
-
-/*
- * Class-Specific Control Requests (6.2)
- *
- * section 3.6.2.1 table 4 has the ACM profile, for modems.
- * section 3.8.2 table 10 has the ethernet profile.
- *
- * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant,
- * heavily dependent on the encapsulated (proprietary) command mechanism.
- */
-
-#define USB_CDC_SEND_ENCAPSULATED_COMMAND      0x00
-#define USB_CDC_GET_ENCAPSULATED_RESPONSE      0x01
-#define USB_CDC_REQ_SET_LINE_CODING            0x20
-#define USB_CDC_REQ_GET_LINE_CODING            0x21
-#define USB_CDC_REQ_SET_CONTROL_LINE_STATE     0x22
-#define USB_CDC_REQ_SEND_BREAK                 0x23
-#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
-#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41
-#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42
-#define USB_CDC_SET_ETHERNET_PACKET_FILTER     0x43
-#define USB_CDC_GET_ETHERNET_STATISTIC         0x44
-#define USB_CDC_GET_NTB_PARAMETERS             0x80
-#define USB_CDC_GET_NET_ADDRESS                        0x81
-#define USB_CDC_SET_NET_ADDRESS                        0x82
-#define USB_CDC_GET_NTB_FORMAT                 0x83
-#define USB_CDC_SET_NTB_FORMAT                 0x84
-#define USB_CDC_GET_NTB_INPUT_SIZE             0x85
-#define USB_CDC_SET_NTB_INPUT_SIZE             0x86
-#define USB_CDC_GET_MAX_DATAGRAM_SIZE          0x87
-#define USB_CDC_SET_MAX_DATAGRAM_SIZE          0x88
-#define USB_CDC_GET_CRC_MODE                   0x89
-#define USB_CDC_SET_CRC_MODE                   0x8a
-
-/* Line Coding Structure from CDC spec 6.2.13 */
-struct usb_cdc_line_coding {
-       __le32  dwDTERate;
-       __u8    bCharFormat;
-#define USB_CDC_1_STOP_BITS                    0
-#define USB_CDC_1_5_STOP_BITS                  1
-#define USB_CDC_2_STOP_BITS                    2
-
-       __u8    bParityType;
-#define USB_CDC_NO_PARITY                      0
-#define USB_CDC_ODD_PARITY                     1
-#define USB_CDC_EVEN_PARITY                    2
-#define USB_CDC_MARK_PARITY                    3
-#define USB_CDC_SPACE_PARITY                   4
-
-       __u8    bDataBits;
-} __attribute__ ((packed));
-
-/* table 62; bits in multicast filter */
-#define        USB_CDC_PACKET_TYPE_PROMISCUOUS         (1 << 0)
-#define        USB_CDC_PACKET_TYPE_ALL_MULTICAST       (1 << 1) /* no filter */
-#define        USB_CDC_PACKET_TYPE_DIRECTED            (1 << 2)
-#define        USB_CDC_PACKET_TYPE_BROADCAST           (1 << 3)
-#define        USB_CDC_PACKET_TYPE_MULTICAST           (1 << 4) /* filtered */
-
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Class-Specific Notifications (6.3) sent by interrupt transfers
- *
- * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
- * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
- * RNDIS also defines its own bit-incompatible notifications
- */
-
-#define USB_CDC_NOTIFY_NETWORK_CONNECTION      0x00
-#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE      0x01
-#define USB_CDC_NOTIFY_SERIAL_STATE            0x20
-#define USB_CDC_NOTIFY_SPEED_CHANGE            0x2a
-
-struct usb_cdc_notification {
-       __u8    bmRequestType;
-       __u8    bNotificationType;
-       __le16  wValue;
-       __le16  wIndex;
-       __le16  wLength;
-} __attribute__ ((packed));
-
-struct usb_cdc_speed_change {
-       __le32  DLBitRRate;     /* contains the downlink bit rate (IN pipe) */
-       __le32  ULBitRate;      /* contains the uplink bit rate (OUT pipe) */
-} __attribute__ ((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * Class Specific structures and constants
- *
- * CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1
- *
- */
-
-struct usb_cdc_ncm_ntb_parameters {
-       __le16  wLength;
-       __le16  bmNtbFormatsSupported;
-       __le32  dwNtbInMaxSize;
-       __le16  wNdpInDivisor;
-       __le16  wNdpInPayloadRemainder;
-       __le16  wNdpInAlignment;
-       __le16  wPadding1;
-       __le32  dwNtbOutMaxSize;
-       __le16  wNdpOutDivisor;
-       __le16  wNdpOutPayloadRemainder;
-       __le16  wNdpOutAlignment;
-       __le16  wNtbOutMaxDatagrams;
-} __attribute__ ((packed));
-
-/*
- * CDC NCM transfer headers, CDC NCM subclass 3.2
- */
-
-#define USB_CDC_NCM_NTH16_SIGN         0x484D434E /* NCMH */
-#define USB_CDC_NCM_NTH32_SIGN         0x686D636E /* ncmh */
-
-struct usb_cdc_ncm_nth16 {
-       __le32  dwSignature;
-       __le16  wHeaderLength;
-       __le16  wSequence;
-       __le16  wBlockLength;
-       __le16  wNdpIndex;
-} __attribute__ ((packed));
-
-struct usb_cdc_ncm_nth32 {
-       __le32  dwSignature;
-       __le16  wHeaderLength;
-       __le16  wSequence;
-       __le32  dwBlockLength;
-       __le32  dwNdpIndex;
-} __attribute__ ((packed));
-
-/*
- * CDC NCM datagram pointers, CDC NCM subclass 3.3
- */
-
-#define USB_CDC_NCM_NDP16_CRC_SIGN     0x314D434E /* NCM1 */
-#define USB_CDC_NCM_NDP16_NOCRC_SIGN   0x304D434E /* NCM0 */
-#define USB_CDC_NCM_NDP32_CRC_SIGN     0x316D636E /* ncm1 */
-#define USB_CDC_NCM_NDP32_NOCRC_SIGN   0x306D636E /* ncm0 */
-
-/* 16-bit NCM Datagram Pointer Entry */
-struct usb_cdc_ncm_dpe16 {
-       __le16  wDatagramIndex;
-       __le16  wDatagramLength;
-} __attribute__((__packed__));
-
-/* 16-bit NCM Datagram Pointer Table */
-struct usb_cdc_ncm_ndp16 {
-       __le32  dwSignature;
-       __le16  wLength;
-       __le16  wNextNdpIndex;
-       struct  usb_cdc_ncm_dpe16 dpe16[0];
-} __attribute__ ((packed));
-
-/* 32-bit NCM Datagram Pointer Entry */
-struct usb_cdc_ncm_dpe32 {
-       __le32  dwDatagramIndex;
-       __le32  dwDatagramLength;
-} __attribute__((__packed__));
-
-/* 32-bit NCM Datagram Pointer Table */
-struct usb_cdc_ncm_ndp32 {
-       __le32  dwSignature;
-       __le16  wLength;
-       __le16  wReserved6;
-       __le32  dwNextNdpIndex;
-       __le32  dwReserved12;
-       struct  usb_cdc_ncm_dpe32 dpe32[0];
-} __attribute__ ((packed));
-
-/* CDC NCM subclass 3.2.1 and 3.2.2 */
-#define USB_CDC_NCM_NDP16_INDEX_MIN                    0x000C
-#define USB_CDC_NCM_NDP32_INDEX_MIN                    0x0010
-
-/* CDC NCM subclass 3.3.3 Datagram Formatting */
-#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC                        0x30
-#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC              0X31
-
-/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */
-#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS       0x00
-#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO            0xFE
-
-/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */
-#define USB_CDC_NCM_NCAP_ETH_FILTER                    (1 << 0)
-#define USB_CDC_NCM_NCAP_NET_ADDRESS                   (1 << 1)
-#define USB_CDC_NCM_NCAP_ENCAP_COMMAND                 (1 << 2)
-#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE             (1 << 3)
-#define USB_CDC_NCM_NCAP_CRC_MODE                      (1 << 4)
-#define        USB_CDC_NCM_NCAP_NTB_INPUT_SIZE                 (1 << 5)
-
-/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
-#define USB_CDC_NCM_NTB16_SUPPORTED                    (1 << 0)
-#define USB_CDC_NCM_NTB32_SUPPORTED                    (1 << 1)
-
-/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
-#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE                 0x04
-#define USB_CDC_NCM_NTB_MAX_LENGTH                     0x1C
-
-/* CDC NCM subclass 6.2.5 SetNtbFormat */
-#define USB_CDC_NCM_NTB16_FORMAT                       0x00
-#define USB_CDC_NCM_NTB32_FORMAT                       0x01
-
-/* CDC NCM subclass 6.2.7 SetNtbInputSize */
-#define USB_CDC_NCM_NTB_MIN_IN_SIZE                    2048
-#define USB_CDC_NCM_NTB_MIN_OUT_SIZE                   2048
-
-/* NTB Input Size Structure */
-struct usb_cdc_ncm_ndp_input_size {
-       __le32  dwNtbInMaxSize;
-       __le16  wNtbInMaxDatagrams;
-       __le16  wReserved;
-} __attribute__ ((packed));
-
-/* CDC NCM subclass 6.2.11 SetCrcMode */
-#define USB_CDC_NCM_CRC_NOT_APPENDED                   0x00
-#define USB_CDC_NCM_CRC_APPENDED                       0x01
-
-#endif /* __LINUX_USB_CDC_H */
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h
new file mode 100644 (file)
index 0000000..3b8f9d4
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) ST-Ericsson 2010-2012
+ * Contact: Alexey Orishko <alexey.orishko@stericsson.com>
+ * Original author: Hans Petter Selasky <hans.petter.selasky@stericsson.com>
+ *
+ * USB Host Driver for Network Control Model (NCM)
+ * http://www.usb.org/developers/devclass_docs/NCM10.zip
+ *
+ * The NCM encoding, decoding and initialization logic
+ * derives from FreeBSD 8.x. if_cdce.c and if_cdcereg.h
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose this file to be licensed under the terms
+ * of the GNU General Public License (GPL) Version 2 or the 2-clause
+ * BSD license listed below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define CDC_NCM_COMM_ALTSETTING_NCM            0
+#define CDC_NCM_COMM_ALTSETTING_MBIM           1
+
+#define CDC_NCM_DATA_ALTSETTING_NCM            1
+#define CDC_NCM_DATA_ALTSETTING_MBIM           2
+
+/* CDC NCM subclass 3.2.1 */
+#define USB_CDC_NCM_NDP16_LENGTH_MIN           0x10
+
+/* Maximum NTB length */
+#define        CDC_NCM_NTB_MAX_SIZE_TX                 32768   /* bytes */
+#define        CDC_NCM_NTB_MAX_SIZE_RX                 32768   /* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 6.2.9 */
+#define        CDC_NCM_MIN_DATAGRAM_SIZE               1514    /* bytes */
+
+/* Minimum value for MaxDatagramSize, ch. 8.1.3 */
+#define CDC_MBIM_MIN_DATAGRAM_SIZE             2048    /* bytes */
+
+#define        CDC_NCM_MIN_TX_PKT                      512     /* bytes */
+
+/* Default value for MaxDatagramSize */
+#define        CDC_NCM_MAX_DATAGRAM_SIZE               8192    /* bytes */
+
+/*
+ * Maximum amount of datagrams in NCM Datagram Pointer Table, not counting
+ * the last NULL entry.
+ */
+#define        CDC_NCM_DPT_DATAGRAMS_MAX               40
+
+/* Restart the timer, if amount of datagrams is less than given value */
+#define        CDC_NCM_RESTART_TIMER_DATAGRAM_CNT      3
+#define        CDC_NCM_TIMER_PENDING_CNT               2
+#define CDC_NCM_TIMER_INTERVAL                 (400UL * NSEC_PER_USEC)
+
+/* The following macro defines the minimum header space */
+#define        CDC_NCM_MIN_HDR_SIZE \
+       (sizeof(struct usb_cdc_ncm_nth16) + sizeof(struct usb_cdc_ncm_ndp16) + \
+       (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+#define CDC_NCM_NDP_SIZE \
+       (sizeof(struct usb_cdc_ncm_ndp16) +                             \
+             (CDC_NCM_DPT_DATAGRAMS_MAX + 1) * sizeof(struct usb_cdc_ncm_dpe16))
+
+#define cdc_ncm_comm_intf_is_mbim(x)  ((x)->desc.bInterfaceSubClass == USB_CDC_SUBCLASS_MBIM && \
+                                      (x)->desc.bInterfaceProtocol == USB_CDC_PROTO_NONE)
+#define cdc_ncm_data_intf_is_mbim(x)  ((x)->desc.bInterfaceProtocol == USB_CDC_MBIM_PROTO_NTB)
+
+struct cdc_ncm_ctx {
+       struct usb_cdc_ncm_ntb_parameters ncm_parm;
+       struct hrtimer tx_timer;
+       struct tasklet_struct bh;
+
+       const struct usb_cdc_ncm_desc *func_desc;
+       const struct usb_cdc_mbim_desc   *mbim_desc;
+       const struct usb_cdc_header_desc *header_desc;
+       const struct usb_cdc_union_desc *union_desc;
+       const struct usb_cdc_ether_desc *ether_desc;
+
+       struct net_device *netdev;
+       struct usb_device *udev;
+       struct usb_host_endpoint *in_ep;
+       struct usb_host_endpoint *out_ep;
+       struct usb_host_endpoint *status_ep;
+       struct usb_interface *intf;
+       struct usb_interface *control;
+       struct usb_interface *data;
+
+       struct sk_buff *tx_curr_skb;
+       struct sk_buff *tx_rem_skb;
+       __le32 tx_rem_sign;
+
+       spinlock_t mtx;
+       atomic_t stop;
+
+       u32 tx_timer_pending;
+       u32 tx_curr_frame_num;
+       u32 rx_speed;
+       u32 tx_speed;
+       u32 rx_max;
+       u32 tx_max;
+       u32 max_datagram_size;
+       u16 tx_max_datagrams;
+       u16 tx_remainder;
+       u16 tx_modulus;
+       u16 tx_ndp_modulus;
+       u16 tx_seq;
+       u16 rx_seq;
+       u16 connected;
+};
+
+extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
+extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
+extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign);
+extern int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in);
+extern int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset);
diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h
deleted file mode 100644 (file)
index 7692dc6..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/*
- * This file holds Hub protocol constants and data structures that are
- * defined in chapter 11 (Hub Specification) of the USB 2.0 specification.
- *
- * It is used/shared between the USB core, the HCDs and couple of other USB
- * drivers.
- */
-
-#ifndef __LINUX_CH11_H
-#define __LINUX_CH11_H
-
-#include <linux/types.h>       /* __u8 etc */
-
-/*
- * Hub request types
- */
-
-#define USB_RT_HUB     (USB_TYPE_CLASS | USB_RECIP_DEVICE)
-#define USB_RT_PORT    (USB_TYPE_CLASS | USB_RECIP_OTHER)
-
-/*
- * Hub class requests
- * See USB 2.0 spec Table 11-16
- */
-#define HUB_CLEAR_TT_BUFFER    8
-#define HUB_RESET_TT           9
-#define HUB_GET_TT_STATE       10
-#define HUB_STOP_TT            11
-
-/*
- * Hub class additional requests defined by USB 3.0 spec
- * See USB 3.0 spec Table 10-6
- */
-#define HUB_SET_DEPTH          12
-#define HUB_GET_PORT_ERR_COUNT 13
-
-/*
- * Hub Class feature numbers
- * See USB 2.0 spec Table 11-17
- */
-#define C_HUB_LOCAL_POWER      0
-#define C_HUB_OVER_CURRENT     1
-
-/*
- * Port feature numbers
- * See USB 2.0 spec Table 11-17
- */
-#define USB_PORT_FEAT_CONNECTION       0
-#define USB_PORT_FEAT_ENABLE           1
-#define USB_PORT_FEAT_SUSPEND          2       /* L2 suspend */
-#define USB_PORT_FEAT_OVER_CURRENT     3
-#define USB_PORT_FEAT_RESET            4
-#define USB_PORT_FEAT_L1               5       /* L1 suspend */
-#define USB_PORT_FEAT_POWER            8
-#define USB_PORT_FEAT_LOWSPEED         9       /* Should never be used */
-#define USB_PORT_FEAT_C_CONNECTION     16
-#define USB_PORT_FEAT_C_ENABLE         17
-#define USB_PORT_FEAT_C_SUSPEND                18
-#define USB_PORT_FEAT_C_OVER_CURRENT   19
-#define USB_PORT_FEAT_C_RESET          20
-#define USB_PORT_FEAT_TEST              21
-#define USB_PORT_FEAT_INDICATOR         22
-#define USB_PORT_FEAT_C_PORT_L1         23
-
-/*
- * Port feature selectors added by USB 3.0 spec.
- * See USB 3.0 spec Table 10-7
- */
-#define USB_PORT_FEAT_LINK_STATE               5
-#define USB_PORT_FEAT_U1_TIMEOUT               23
-#define USB_PORT_FEAT_U2_TIMEOUT               24
-#define USB_PORT_FEAT_C_PORT_LINK_STATE                25
-#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR      26
-#define USB_PORT_FEAT_REMOTE_WAKE_MASK         27
-#define USB_PORT_FEAT_BH_PORT_RESET            28
-#define USB_PORT_FEAT_C_BH_PORT_RESET          29
-#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT      30
-
-#define USB_PORT_LPM_TIMEOUT(p)                        (((p) & 0xff) << 8)
-
-/* USB 3.0 hub remote wake mask bits, see table 10-14 */
-#define USB_PORT_FEAT_REMOTE_WAKE_CONNECT      (1 << 8)
-#define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT   (1 << 9)
-#define USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT (1 << 10)
-
-/*
- * Hub Status and Hub Change results
- * See USB 2.0 spec Table 11-19 and Table 11-20
- */
-struct usb_port_status {
-       __le16 wPortStatus;
-       __le16 wPortChange;
-} __attribute__ ((packed));
-
-/*
- * wPortStatus bit field
- * See USB 2.0 spec Table 11-21
- */
-#define USB_PORT_STAT_CONNECTION       0x0001
-#define USB_PORT_STAT_ENABLE           0x0002
-#define USB_PORT_STAT_SUSPEND          0x0004
-#define USB_PORT_STAT_OVERCURRENT      0x0008
-#define USB_PORT_STAT_RESET            0x0010
-#define USB_PORT_STAT_L1               0x0020
-/* bits 6 to 7 are reserved */
-#define USB_PORT_STAT_POWER            0x0100
-#define USB_PORT_STAT_LOW_SPEED                0x0200
-#define USB_PORT_STAT_HIGH_SPEED        0x0400
-#define USB_PORT_STAT_TEST              0x0800
-#define USB_PORT_STAT_INDICATOR         0x1000
-/* bits 13 to 15 are reserved */
-
-/*
- * Additions to wPortStatus bit field from USB 3.0
- * See USB 3.0 spec Table 10-10
- */
-#define USB_PORT_STAT_LINK_STATE       0x01e0
-#define USB_SS_PORT_STAT_POWER         0x0200
-#define USB_SS_PORT_STAT_SPEED         0x1c00
-#define USB_PORT_STAT_SPEED_5GBPS      0x0000
-/* Valid only if port is enabled */
-/* Bits that are the same from USB 2.0 */
-#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION |          \
-                               USB_PORT_STAT_ENABLE |      \
-                               USB_PORT_STAT_OVERCURRENT | \
-                               USB_PORT_STAT_RESET)
-
-/*
- * Definitions for PORT_LINK_STATE values
- * (bits 5-8) in wPortStatus
- */
-#define USB_SS_PORT_LS_U0              0x0000
-#define USB_SS_PORT_LS_U1              0x0020
-#define USB_SS_PORT_LS_U2              0x0040
-#define USB_SS_PORT_LS_U3              0x0060
-#define USB_SS_PORT_LS_SS_DISABLED     0x0080
-#define USB_SS_PORT_LS_RX_DETECT       0x00a0
-#define USB_SS_PORT_LS_SS_INACTIVE     0x00c0
-#define USB_SS_PORT_LS_POLLING         0x00e0
-#define USB_SS_PORT_LS_RECOVERY                0x0100
-#define USB_SS_PORT_LS_HOT_RESET       0x0120
-#define USB_SS_PORT_LS_COMP_MOD                0x0140
-#define USB_SS_PORT_LS_LOOPBACK                0x0160
-
-/*
- * wPortChange bit field
- * See USB 2.0 spec Table 11-22 and USB 2.0 LPM ECN Table-4.10
- * Bits 0 to 5 shown, bits 6 to 15 are reserved
- */
-#define USB_PORT_STAT_C_CONNECTION     0x0001
-#define USB_PORT_STAT_C_ENABLE         0x0002
-#define USB_PORT_STAT_C_SUSPEND                0x0004
-#define USB_PORT_STAT_C_OVERCURRENT    0x0008
-#define USB_PORT_STAT_C_RESET          0x0010
-#define USB_PORT_STAT_C_L1             0x0020
-/*
- * USB 3.0 wPortChange bit fields
- * See USB 3.0 spec Table 10-11
- */
-#define USB_PORT_STAT_C_BH_RESET       0x0020
-#define USB_PORT_STAT_C_LINK_STATE     0x0040
-#define USB_PORT_STAT_C_CONFIG_ERROR   0x0080
-
-/*
- * wHubCharacteristics (masks)
- * See USB 2.0 spec Table 11-13, offset 3
- */
-#define HUB_CHAR_LPSM          0x0003 /* Logical Power Switching Mode mask */
-#define HUB_CHAR_COMMON_LPSM   0x0000 /* All ports power control at once */
-#define HUB_CHAR_INDV_PORT_LPSM        0x0001 /* per-port power control */
-#define HUB_CHAR_NO_LPSM       0x0002 /* no power switching */
-
-#define HUB_CHAR_COMPOUND      0x0004 /* hub is part of a compound device */
-
-#define HUB_CHAR_OCPM          0x0018 /* Over-Current Protection Mode mask */
-#define HUB_CHAR_COMMON_OCPM   0x0000 /* All ports Over-Current reporting */
-#define HUB_CHAR_INDV_PORT_OCPM        0x0008 /* per-port Over-current reporting */
-#define HUB_CHAR_NO_OCPM       0x0010 /* No Over-current Protection support */
-
-#define HUB_CHAR_TTTT          0x0060 /* TT Think Time mask */
-#define HUB_CHAR_PORTIND       0x0080 /* per-port indicators (LEDs) */
-
-struct usb_hub_status {
-       __le16 wHubStatus;
-       __le16 wHubChange;
-} __attribute__ ((packed));
-
-/*
- * Hub Status & Hub Change bit masks
- * See USB 2.0 spec Table 11-19 and Table 11-20
- * Bits 0 and 1 for wHubStatus and wHubChange
- * Bits 2 to 15 are reserved for both
- */
-#define HUB_STATUS_LOCAL_POWER 0x0001
-#define HUB_STATUS_OVERCURRENT 0x0002
-#define HUB_CHANGE_LOCAL_POWER 0x0001
-#define HUB_CHANGE_OVERCURRENT 0x0002
-
-
-/*
- * Hub descriptor
- * See USB 2.0 spec Table 11-13
- */
-
-#define USB_DT_HUB                     (USB_TYPE_CLASS | 0x09)
-#define USB_DT_SS_HUB                  (USB_TYPE_CLASS | 0x0a)
-#define USB_DT_HUB_NONVAR_SIZE         7
-#define USB_DT_SS_HUB_SIZE              12
-
-/*
- * Hub Device descriptor
- * USB Hub class device protocols
- */
-
-#define USB_HUB_PR_FS          0 /* Full speed hub */
-#define USB_HUB_PR_HS_NO_TT    0 /* Hi-speed hub without TT */
-#define USB_HUB_PR_HS_SINGLE_TT        1 /* Hi-speed hub with single TT */
-#define USB_HUB_PR_HS_MULTI_TT 2 /* Hi-speed hub with multiple TT */
-#define USB_HUB_PR_SS          3 /* Super speed hub */
-
-struct usb_hub_descriptor {
-       __u8  bDescLength;
-       __u8  bDescriptorType;
-       __u8  bNbrPorts;
-       __le16 wHubCharacteristics;
-       __u8  bPwrOn2PwrGood;
-       __u8  bHubContrCurrent;
-
-       /* 2.0 and 3.0 hubs differ here */
-       union {
-               struct {
-                       /* add 1 bit for hub status change; round to bytes */
-                       __u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
-                       __u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
-               }  __attribute__ ((packed)) hs;
-
-               struct {
-                       __u8 bHubHdrDecLat;
-                       __le16 wHubDelay;
-                       __le16 DeviceRemovable;
-               }  __attribute__ ((packed)) ss;
-       } u;
-} __attribute__ ((packed));
-
-/* port indicator status selectors, tables 11-7 and 11-25 */
-#define HUB_LED_AUTO   0
-#define HUB_LED_AMBER  1
-#define HUB_LED_GREEN  2
-#define HUB_LED_OFF    3
-
-enum hub_led_mode {
-       INDICATOR_AUTO = 0,
-       INDICATOR_CYCLE,
-       /* software blinks for attention:  software, hardware, reserved */
-       INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF,
-       INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF,
-       INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF
-} __attribute__ ((packed));
-
-/* Transaction Translator Think Times, in bits */
-#define HUB_TTTT_8_BITS                0x00
-#define HUB_TTTT_16_BITS       0x20
-#define HUB_TTTT_24_BITS       0x40
-#define HUB_TTTT_32_BITS       0x60
-
-#endif /* __LINUX_CH11_H */
index d1d732c2838d3a48788c16fe87bd9552a8558ab8..9c210f2283dfd0268e1e7e580b1b6b3091801429 100644 (file)
  *     someone that the two other points are non-issues for that
  *     particular descriptor type.
  */
-
 #ifndef __LINUX_USB_CH9_H
 #define __LINUX_USB_CH9_H
 
-#include <linux/types.h>       /* __u8 etc */
-#include <asm/byteorder.h>     /* le16_to_cpu */
-
-/*-------------------------------------------------------------------------*/
-
-/* CONTROL REQUEST SUPPORT */
-
-/*
- * USB directions
- *
- * This bit flag is used in endpoint descriptors' bEndpointAddress field.
- * It's also one of three fields in control requests bRequestType.
- */
-#define USB_DIR_OUT                    0               /* to device */
-#define USB_DIR_IN                     0x80            /* to host */
-
-/*
- * USB types, the second of three bRequestType fields
- */
-#define USB_TYPE_MASK                  (0x03 << 5)
-#define USB_TYPE_STANDARD              (0x00 << 5)
-#define USB_TYPE_CLASS                 (0x01 << 5)
-#define USB_TYPE_VENDOR                        (0x02 << 5)
-#define USB_TYPE_RESERVED              (0x03 << 5)
-
-/*
- * USB recipients, the third of three bRequestType fields
- */
-#define USB_RECIP_MASK                 0x1f
-#define USB_RECIP_DEVICE               0x00
-#define USB_RECIP_INTERFACE            0x01
-#define USB_RECIP_ENDPOINT             0x02
-#define USB_RECIP_OTHER                        0x03
-/* From Wireless USB 1.0 */
-#define USB_RECIP_PORT                 0x04
-#define USB_RECIP_RPIPE                0x05
-
-/*
- * Standard requests, for the bRequest field of a SETUP packet.
- *
- * These are qualified by the bRequestType field, so that for example
- * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
- * by a GET_STATUS request.
- */
-#define USB_REQ_GET_STATUS             0x00
-#define USB_REQ_CLEAR_FEATURE          0x01
-#define USB_REQ_SET_FEATURE            0x03
-#define USB_REQ_SET_ADDRESS            0x05
-#define USB_REQ_GET_DESCRIPTOR         0x06
-#define USB_REQ_SET_DESCRIPTOR         0x07
-#define USB_REQ_GET_CONFIGURATION      0x08
-#define USB_REQ_SET_CONFIGURATION      0x09
-#define USB_REQ_GET_INTERFACE          0x0A
-#define USB_REQ_SET_INTERFACE          0x0B
-#define USB_REQ_SYNCH_FRAME            0x0C
-#define USB_REQ_SET_SEL                        0x30
-#define USB_REQ_SET_ISOCH_DELAY                0x31
-
-#define USB_REQ_SET_ENCRYPTION         0x0D    /* Wireless USB */
-#define USB_REQ_GET_ENCRYPTION         0x0E
-#define USB_REQ_RPIPE_ABORT            0x0E
-#define USB_REQ_SET_HANDSHAKE          0x0F
-#define USB_REQ_RPIPE_RESET            0x0F
-#define USB_REQ_GET_HANDSHAKE          0x10
-#define USB_REQ_SET_CONNECTION         0x11
-#define USB_REQ_SET_SECURITY_DATA      0x12
-#define USB_REQ_GET_SECURITY_DATA      0x13
-#define USB_REQ_SET_WUSB_DATA          0x14
-#define USB_REQ_LOOPBACK_DATA_WRITE    0x15
-#define USB_REQ_LOOPBACK_DATA_READ     0x16
-#define USB_REQ_SET_INTERFACE_DS       0x17
-
-/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command,
- * used by hubs to put ports into a new L1 suspend state, except that it
- * forgot to define its number ...
- */
-
-/*
- * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
- * are read as a bit array returned by USB_REQ_GET_STATUS.  (So there
- * are at most sixteen features of each type.)  Hubs may also support a
- * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
- */
-#define USB_DEVICE_SELF_POWERED                0       /* (read only) */
-#define USB_DEVICE_REMOTE_WAKEUP       1       /* dev may initiate wakeup */
-#define USB_DEVICE_TEST_MODE           2       /* (wired high speed only) */
-#define USB_DEVICE_BATTERY             2       /* (wireless) */
-#define USB_DEVICE_B_HNP_ENABLE                3       /* (otg) dev may initiate HNP */
-#define USB_DEVICE_WUSB_DEVICE         3       /* (wireless)*/
-#define USB_DEVICE_A_HNP_SUPPORT       4       /* (otg) RH port supports HNP */
-#define USB_DEVICE_A_ALT_HNP_SUPPORT   5       /* (otg) other RH port does */
-#define USB_DEVICE_DEBUG_MODE          6       /* (special devices only) */
-
-/*
- * Test Mode Selectors
- * See USB 2.0 spec Table 9-7
- */
-#define        TEST_J          1
-#define        TEST_K          2
-#define        TEST_SE0_NAK    3
-#define        TEST_PACKET     4
-#define        TEST_FORCE_EN   5
-
-/*
- * New Feature Selectors as added by USB 3.0
- * See USB 3.0 spec Table 9-6
- */
-#define USB_DEVICE_U1_ENABLE   48      /* dev may initiate U1 transition */
-#define USB_DEVICE_U2_ENABLE   49      /* dev may initiate U2 transition */
-#define USB_DEVICE_LTM_ENABLE  50      /* dev may send LTM */
-#define USB_INTRF_FUNC_SUSPEND 0       /* function suspend */
-
-#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00
-/*
- * Suspend Options, Table 9-7 USB 3.0 spec
- */
-#define USB_INTRF_FUNC_SUSPEND_LP      (1 << (8 + 0))
-#define USB_INTRF_FUNC_SUSPEND_RW      (1 << (8 + 1))
-
-#define USB_ENDPOINT_HALT              0       /* IN/OUT will STALL */
-
-/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
-#define USB_DEV_STAT_U1_ENABLED                2       /* transition into U1 state */
-#define USB_DEV_STAT_U2_ENABLED                3       /* transition into U2 state */
-#define USB_DEV_STAT_LTM_ENABLED       4       /* Latency tolerance messages */
-
-/**
- * struct usb_ctrlrequest - SETUP data for a USB device control request
- * @bRequestType: matches the USB bmRequestType field
- * @bRequest: matches the USB bRequest field
- * @wValue: matches the USB wValue field (le16 byte order)
- * @wIndex: matches the USB wIndex field (le16 byte order)
- * @wLength: matches the USB wLength field (le16 byte order)
- *
- * This structure is used to send control requests to a USB device.  It matches
- * the different fields of the USB 2.0 Spec section 9.3, table 9-2.  See the
- * USB spec for a fuller description of the different fields, and what they are
- * used for.
- *
- * Note that the driver for any interface can issue control requests.
- * For most devices, interfaces don't coordinate with each other, so
- * such requests may be made at any time.
- */
-struct usb_ctrlrequest {
-       __u8 bRequestType;
-       __u8 bRequest;
-       __le16 wValue;
-       __le16 wIndex;
-       __le16 wLength;
-} __attribute__ ((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
- * (rarely) accepted by SET_DESCRIPTOR.
- *
- * Note that all multi-byte values here are encoded in little endian
- * byte order "on the wire".  Within the kernel and when exposed
- * through the Linux-USB APIs, they are not converted to cpu byte
- * order; it is the responsibility of the client code to do this.
- * The single exception is when device and configuration descriptors (but
- * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD);
- * in this case the fields are converted to host endianness by the kernel.
- */
-
-/*
- * Descriptor types ... USB 2.0 spec table 9.5
- */
-#define USB_DT_DEVICE                  0x01
-#define USB_DT_CONFIG                  0x02
-#define USB_DT_STRING                  0x03
-#define USB_DT_INTERFACE               0x04
-#define USB_DT_ENDPOINT                        0x05
-#define USB_DT_DEVICE_QUALIFIER                0x06
-#define USB_DT_OTHER_SPEED_CONFIG      0x07
-#define USB_DT_INTERFACE_POWER         0x08
-/* these are from a minor usb 2.0 revision (ECN) */
-#define USB_DT_OTG                     0x09
-#define USB_DT_DEBUG                   0x0a
-#define USB_DT_INTERFACE_ASSOCIATION   0x0b
-/* these are from the Wireless USB spec */
-#define USB_DT_SECURITY                        0x0c
-#define USB_DT_KEY                     0x0d
-#define USB_DT_ENCRYPTION_TYPE         0x0e
-#define USB_DT_BOS                     0x0f
-#define USB_DT_DEVICE_CAPABILITY       0x10
-#define USB_DT_WIRELESS_ENDPOINT_COMP  0x11
-#define USB_DT_WIRE_ADAPTER            0x21
-#define USB_DT_RPIPE                   0x22
-#define USB_DT_CS_RADIO_CONTROL                0x23
-/* From the T10 UAS specification */
-#define USB_DT_PIPE_USAGE              0x24
-/* From the USB 3.0 spec */
-#define        USB_DT_SS_ENDPOINT_COMP         0x30
-
-/* Conventional codes for class-specific descriptors.  The convention is
- * defined in the USB "Common Class" Spec (3.11).  Individual class specs
- * are authoritative for their usage, not the "common class" writeup.
- */
-#define USB_DT_CS_DEVICE               (USB_TYPE_CLASS | USB_DT_DEVICE)
-#define USB_DT_CS_CONFIG               (USB_TYPE_CLASS | USB_DT_CONFIG)
-#define USB_DT_CS_STRING               (USB_TYPE_CLASS | USB_DT_STRING)
-#define USB_DT_CS_INTERFACE            (USB_TYPE_CLASS | USB_DT_INTERFACE)
-#define USB_DT_CS_ENDPOINT             (USB_TYPE_CLASS | USB_DT_ENDPOINT)
-
-/* All standard descriptors have these 2 fields at the beginning */
-struct usb_descriptor_header {
-       __u8  bLength;
-       __u8  bDescriptorType;
-} __attribute__ ((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_DEVICE: Device descriptor */
-struct usb_device_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 bcdUSB;
-       __u8  bDeviceClass;
-       __u8  bDeviceSubClass;
-       __u8  bDeviceProtocol;
-       __u8  bMaxPacketSize0;
-       __le16 idVendor;
-       __le16 idProduct;
-       __le16 bcdDevice;
-       __u8  iManufacturer;
-       __u8  iProduct;
-       __u8  iSerialNumber;
-       __u8  bNumConfigurations;
-} __attribute__ ((packed));
-
-#define USB_DT_DEVICE_SIZE             18
-
-
-/*
- * Device and/or Interface Class codes
- * as found in bDeviceClass or bInterfaceClass
- * and defined by www.usb.org documents
- */
-#define USB_CLASS_PER_INTERFACE                0       /* for DeviceClass */
-#define USB_CLASS_AUDIO                        1
-#define USB_CLASS_COMM                 2
-#define USB_CLASS_HID                  3
-#define USB_CLASS_PHYSICAL             5
-#define USB_CLASS_STILL_IMAGE          6
-#define USB_CLASS_PRINTER              7
-#define USB_CLASS_MASS_STORAGE         8
-#define USB_CLASS_HUB                  9
-#define USB_CLASS_CDC_DATA             0x0a
-#define USB_CLASS_CSCID                        0x0b    /* chip+ smart card */
-#define USB_CLASS_CONTENT_SEC          0x0d    /* content security */
-#define USB_CLASS_VIDEO                        0x0e
-#define USB_CLASS_WIRELESS_CONTROLLER  0xe0
-#define USB_CLASS_MISC                 0xef
-#define USB_CLASS_APP_SPEC             0xfe
-#define USB_CLASS_VENDOR_SPEC          0xff
-
-#define USB_SUBCLASS_VENDOR_SPEC       0xff
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_CONFIG: Configuration descriptor information.
- *
- * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
- * descriptor type is different.  Highspeed-capable devices can look
- * different depending on what speed they're currently running.  Only
- * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
- * descriptors.
- */
-struct usb_config_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 wTotalLength;
-       __u8  bNumInterfaces;
-       __u8  bConfigurationValue;
-       __u8  iConfiguration;
-       __u8  bmAttributes;
-       __u8  bMaxPower;
-} __attribute__ ((packed));
-
-#define USB_DT_CONFIG_SIZE             9
-
-/* from config descriptor bmAttributes */
-#define USB_CONFIG_ATT_ONE             (1 << 7)        /* must be set */
-#define USB_CONFIG_ATT_SELFPOWER       (1 << 6)        /* self powered */
-#define USB_CONFIG_ATT_WAKEUP          (1 << 5)        /* can wakeup */
-#define USB_CONFIG_ATT_BATTERY         (1 << 4)        /* battery powered */
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_STRING: String descriptor */
-struct usb_string_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 wData[1];                /* UTF-16LE encoded */
-} __attribute__ ((packed));
-
-/* note that "string" zero is special, it holds language codes that
- * the device supports, not Unicode characters.
- */
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_INTERFACE: Interface descriptor */
-struct usb_interface_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bInterfaceNumber;
-       __u8  bAlternateSetting;
-       __u8  bNumEndpoints;
-       __u8  bInterfaceClass;
-       __u8  bInterfaceSubClass;
-       __u8  bInterfaceProtocol;
-       __u8  iInterface;
-} __attribute__ ((packed));
-
-#define USB_DT_INTERFACE_SIZE          9
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_ENDPOINT: Endpoint descriptor */
-struct usb_endpoint_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bEndpointAddress;
-       __u8  bmAttributes;
-       __le16 wMaxPacketSize;
-       __u8  bInterval;
-
-       /* NOTE:  these two are _only_ in audio endpoints. */
-       /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
-       __u8  bRefresh;
-       __u8  bSynchAddress;
-} __attribute__ ((packed));
-
-#define USB_DT_ENDPOINT_SIZE           7
-#define USB_DT_ENDPOINT_AUDIO_SIZE     9       /* Audio extension */
-
-
-/*
- * Endpoints
- */
-#define USB_ENDPOINT_NUMBER_MASK       0x0f    /* in bEndpointAddress */
-#define USB_ENDPOINT_DIR_MASK          0x80
-
-#define USB_ENDPOINT_XFERTYPE_MASK     0x03    /* in bmAttributes */
-#define USB_ENDPOINT_XFER_CONTROL      0
-#define USB_ENDPOINT_XFER_ISOC         1
-#define USB_ENDPOINT_XFER_BULK         2
-#define USB_ENDPOINT_XFER_INT          3
-#define USB_ENDPOINT_MAX_ADJUSTABLE    0x80
-
-/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
-#define USB_ENDPOINT_INTRTYPE          0x30
-#define USB_ENDPOINT_INTR_PERIODIC     (0 << 4)
-#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4)
-
-#define USB_ENDPOINT_SYNCTYPE          0x0c
-#define USB_ENDPOINT_SYNC_NONE         (0 << 2)
-#define USB_ENDPOINT_SYNC_ASYNC                (1 << 2)
-#define USB_ENDPOINT_SYNC_ADAPTIVE     (2 << 2)
-#define USB_ENDPOINT_SYNC_SYNC         (3 << 2)
-
-#define USB_ENDPOINT_USAGE_MASK                0x30
-#define USB_ENDPOINT_USAGE_DATA                0x00
-#define USB_ENDPOINT_USAGE_FEEDBACK    0x10
-#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20    /* Implicit feedback Data endpoint */
-
-/*-------------------------------------------------------------------------*/
-
-/**
- * usb_endpoint_num - get the endpoint's number
- * @epd: endpoint to be checked
- *
- * Returns @epd's number: 0 to 15.
- */
-static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
-{
-       return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-}
-
-/**
- * usb_endpoint_type - get the endpoint's transfer type
- * @epd: endpoint to be checked
- *
- * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
- * to @epd's transfer type.
- */
-static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
-{
-       return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
-}
-
-/**
- * usb_endpoint_dir_in - check if the endpoint has IN direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type IN, otherwise it returns false.
- */
-static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
-}
-
-/**
- * usb_endpoint_dir_out - check if the endpoint has OUT direction
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type OUT, otherwise it returns false.
- */
-static inline int usb_endpoint_dir_out(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
-}
-
-/**
- * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type bulk, otherwise it returns false.
- */
-static inline int usb_endpoint_xfer_bulk(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_BULK);
-}
-
-/**
- * usb_endpoint_xfer_control - check if the endpoint has control transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type control, otherwise it returns false.
- */
-static inline int usb_endpoint_xfer_control(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_CONTROL);
-}
-
-/**
- * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type interrupt, otherwise it returns
- * false.
- */
-static inline int usb_endpoint_xfer_int(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_INT);
-}
-
-/**
- * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint is of type isochronous, otherwise it returns
- * false.
- */
-static inline int usb_endpoint_xfer_isoc(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
-               USB_ENDPOINT_XFER_ISOC);
-}
-
-/**
- * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_bulk_in(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd);
-}
-
-/**
- * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has bulk transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_bulk_out(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd);
-}
-
-/**
- * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_int_in(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd);
-}
-
-/**
- * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has interrupt transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_int_out(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd);
-}
-
-/**
- * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and IN direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_isoc_in(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd);
-}
-
-/**
- * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
- * @epd: endpoint to be checked
- *
- * Returns true if the endpoint has isochronous transfer type and OUT direction,
- * otherwise it returns false.
- */
-static inline int usb_endpoint_is_isoc_out(
-                               const struct usb_endpoint_descriptor *epd)
-{
-       return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd);
-}
-
-/**
- * usb_endpoint_maxp - get endpoint's max packet size
- * @epd: endpoint to be checked
- *
- * Returns @epd's max packet
- */
-static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
-{
-       return __le16_to_cpu(epd->wMaxPacketSize);
-}
-
-static inline int usb_endpoint_interrupt_type(
-               const struct usb_endpoint_descriptor *epd)
-{
-       return epd->bmAttributes & USB_ENDPOINT_INTRTYPE;
-}
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
-struct usb_ss_ep_comp_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bMaxBurst;
-       __u8  bmAttributes;
-       __le16 wBytesPerInterval;
-} __attribute__ ((packed));
-
-#define USB_DT_SS_EP_COMP_SIZE         6
-
-/* Bits 4:0 of bmAttributes if this is a bulk endpoint */
-static inline int
-usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp)
-{
-       int             max_streams;
-
-       if (!comp)
-               return 0;
-
-       max_streams = comp->bmAttributes & 0x1f;
-
-       if (!max_streams)
-               return 0;
-
-       max_streams = 1 << max_streams;
-
-       return max_streams;
-}
-
-/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
-#define USB_SS_MULT(p)                 (1 + ((p) & 0x3))
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
-struct usb_qualifier_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 bcdUSB;
-       __u8  bDeviceClass;
-       __u8  bDeviceSubClass;
-       __u8  bDeviceProtocol;
-       __u8  bMaxPacketSize0;
-       __u8  bNumConfigurations;
-       __u8  bRESERVED;
-} __attribute__ ((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_OTG (from OTG 1.0a supplement) */
-struct usb_otg_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bmAttributes;     /* support for HNP, SRP, etc */
-} __attribute__ ((packed));
-
-/* from usb_otg_descriptor.bmAttributes */
-#define USB_OTG_SRP            (1 << 0)
-#define USB_OTG_HNP            (1 << 1)        /* swap host/device roles */
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_DEBUG:  for special highspeed devices, replacing serial console */
-struct usb_debug_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       /* bulk endpoints with 8 byte maxpacket */
-       __u8  bDebugInEndpoint;
-       __u8  bDebugOutEndpoint;
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
-struct usb_interface_assoc_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bFirstInterface;
-       __u8  bInterfaceCount;
-       __u8  bFunctionClass;
-       __u8  bFunctionSubClass;
-       __u8  bFunctionProtocol;
-       __u8  iFunction;
-} __attribute__ ((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_SECURITY:  group of wireless security descriptors, including
- * encryption types available for setting up a CC/association.
- */
-struct usb_security_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 wTotalLength;
-       __u8  bNumEncryptionTypes;
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_KEY:  used with {GET,SET}_SECURITY_DATA; only public keys
- * may be retrieved.
- */
-struct usb_key_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  tTKID[3];
-       __u8  bReserved;
-       __u8  bKeyData[0];
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_ENCRYPTION_TYPE:  bundled in DT_SECURITY groups */
-struct usb_encryption_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bEncryptionType;
-#define        USB_ENC_TYPE_UNSECURE           0
-#define        USB_ENC_TYPE_WIRED              1       /* non-wireless mode */
-#define        USB_ENC_TYPE_CCM_1              2       /* aes128/cbc session */
-#define        USB_ENC_TYPE_RSA_1              3       /* rsa3072/sha1 auth */
-       __u8  bEncryptionValue;         /* use in SET_ENCRYPTION */
-       __u8  bAuthKeyIndex;
-} __attribute__((packed));
-
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_BOS:  group of device-level capabilities */
-struct usb_bos_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __le16 wTotalLength;
-       __u8  bNumDeviceCaps;
-} __attribute__((packed));
-
-#define USB_DT_BOS_SIZE                5
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_DEVICE_CAPABILITY:  grouped with BOS */
-struct usb_dev_cap_header {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-} __attribute__((packed));
-
-#define        USB_CAP_TYPE_WIRELESS_USB       1
-
-struct usb_wireless_cap_descriptor {   /* Ultra Wide Band */
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-
-       __u8  bmAttributes;
-#define        USB_WIRELESS_P2P_DRD            (1 << 1)
-#define        USB_WIRELESS_BEACON_MASK        (3 << 2)
-#define        USB_WIRELESS_BEACON_SELF        (1 << 2)
-#define        USB_WIRELESS_BEACON_DIRECTED    (2 << 2)
-#define        USB_WIRELESS_BEACON_NONE        (3 << 2)
-       __le16 wPHYRates;       /* bit rates, Mbps */
-#define        USB_WIRELESS_PHY_53             (1 << 0)        /* always set */
-#define        USB_WIRELESS_PHY_80             (1 << 1)
-#define        USB_WIRELESS_PHY_107            (1 << 2)        /* always set */
-#define        USB_WIRELESS_PHY_160            (1 << 3)
-#define        USB_WIRELESS_PHY_200            (1 << 4)        /* always set */
-#define        USB_WIRELESS_PHY_320            (1 << 5)
-#define        USB_WIRELESS_PHY_400            (1 << 6)
-#define        USB_WIRELESS_PHY_480            (1 << 7)
-       __u8  bmTFITXPowerInfo; /* TFI power levels */
-       __u8  bmFFITXPowerInfo; /* FFI power levels */
-       __le16 bmBandGroup;
-       __u8  bReserved;
-} __attribute__((packed));
-
-/* USB 2.0 Extension descriptor */
-#define        USB_CAP_TYPE_EXT                2
-
-struct usb_ext_cap_descriptor {                /* Link Power Management */
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-       __le32 bmAttributes;
-#define USB_LPM_SUPPORT                        (1 << 1)        /* supports LPM */
-#define USB_BESL_SUPPORT               (1 << 2)        /* supports BESL */
-#define USB_BESL_BASELINE_VALID                (1 << 3)        /* Baseline BESL valid*/
-#define USB_BESL_DEEP_VALID            (1 << 4)        /* Deep BESL valid */
-#define USB_GET_BESL_BASELINE(p)       (((p) & (0xf << 8)) >> 8)
-#define USB_GET_BESL_DEEP(p)           (((p) & (0xf << 12)) >> 12)
-} __attribute__((packed));
-
-#define USB_DT_USB_EXT_CAP_SIZE        7
-
-/*
- * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB
- * specific device level capabilities
- */
-#define                USB_SS_CAP_TYPE         3
-struct usb_ss_cap_descriptor {         /* Link Power Management */
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-       __u8  bmAttributes;
-#define USB_LTM_SUPPORT                        (1 << 1) /* supports LTM */
-       __le16 wSpeedSupported;
-#define USB_LOW_SPEED_OPERATION                (1)      /* Low speed operation */
-#define USB_FULL_SPEED_OPERATION       (1 << 1) /* Full speed operation */
-#define USB_HIGH_SPEED_OPERATION       (1 << 2) /* High speed operation */
-#define USB_5GBPS_OPERATION            (1 << 3) /* Operation at 5Gbps */
-       __u8  bFunctionalitySupport;
-       __u8  bU1devExitLat;
-       __le16 bU2DevExitLat;
-} __attribute__((packed));
-
-#define USB_DT_USB_SS_CAP_SIZE 10
-
-/*
- * Container ID Capability descriptor: Defines the instance unique ID used to
- * identify the instance across all operating modes
- */
-#define        CONTAINER_ID_TYPE       4
-struct usb_ss_container_id_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDevCapabilityType;
-       __u8  bReserved;
-       __u8  ContainerID[16]; /* 128-bit number */
-} __attribute__((packed));
-
-#define USB_DT_USB_SS_CONTN_ID_SIZE    20
-/*-------------------------------------------------------------------------*/
-
-/* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
- * each endpoint descriptor for a wireless device
- */
-struct usb_wireless_ep_comp_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bMaxBurst;
-       __u8  bMaxSequence;
-       __le16 wMaxStreamDelay;
-       __le16 wOverTheAirPacketSize;
-       __u8  bOverTheAirInterval;
-       __u8  bmCompAttributes;
-#define USB_ENDPOINT_SWITCH_MASK       0x03    /* in bmCompAttributes */
-#define USB_ENDPOINT_SWITCH_NO         0
-#define USB_ENDPOINT_SWITCH_SWITCH     1
-#define USB_ENDPOINT_SWITCH_SCALE      2
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless
- * host and a device for connection set up, mutual authentication, and
- * exchanging short lived session keys.  The handshake depends on a CC.
- */
-struct usb_handshake {
-       __u8 bMessageNumber;
-       __u8 bStatus;
-       __u8 tTKID[3];
-       __u8 bReserved;
-       __u8 CDID[16];
-       __u8 nonce[16];
-       __u8 MIC[8];
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
-
-/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).
- * A CC may also be set up using non-wireless secure channels (including
- * wired USB!), and some devices may support CCs with multiple hosts.
- */
-struct usb_connection_context {
-       __u8 CHID[16];          /* persistent host id */
-       __u8 CDID[16];          /* device id (unique w/in host context) */
-       __u8 CK[16];            /* connection key */
-} __attribute__((packed));
-
-/*-------------------------------------------------------------------------*/
+#include <uapi/linux/usb/ch9.h>
 
-/* USB 2.0 defines three speeds, here's how Linux identifies them */
-
-enum usb_device_speed {
-       USB_SPEED_UNKNOWN = 0,                  /* enumerating */
-       USB_SPEED_LOW, USB_SPEED_FULL,          /* usb 1.1 */
-       USB_SPEED_HIGH,                         /* usb 2.0 */
-       USB_SPEED_WIRELESS,                     /* wireless (usb 2.5) */
-       USB_SPEED_SUPER,                        /* usb 3.0 */
-};
-
-#ifdef __KERNEL__
 
 /**
  * usb_speed_string() - Returns human readable-name of the speed.
@@ -919,86 +43,4 @@ enum usb_device_speed {
  */
 extern const char *usb_speed_string(enum usb_device_speed speed);
 
-#endif
-
-enum usb_device_state {
-       /* NOTATTACHED isn't in the USB spec, and this state acts
-        * the same as ATTACHED ... but it's clearer this way.
-        */
-       USB_STATE_NOTATTACHED = 0,
-
-       /* chapter 9 and authentication (wireless) device states */
-       USB_STATE_ATTACHED,
-       USB_STATE_POWERED,                      /* wired */
-       USB_STATE_RECONNECTING,                 /* auth */
-       USB_STATE_UNAUTHENTICATED,              /* auth */
-       USB_STATE_DEFAULT,                      /* limited function */
-       USB_STATE_ADDRESS,
-       USB_STATE_CONFIGURED,                   /* most functions */
-
-       USB_STATE_SUSPENDED
-
-       /* NOTE:  there are actually four different SUSPENDED
-        * states, returning to POWERED, DEFAULT, ADDRESS, or
-        * CONFIGURED respectively when SOF tokens flow again.
-        * At this level there's no difference between L1 and L2
-        * suspend states.  (L2 being original USB 1.1 suspend.)
-        */
-};
-
-enum usb3_link_state {
-       USB3_LPM_U0 = 0,
-       USB3_LPM_U1,
-       USB3_LPM_U2,
-       USB3_LPM_U3
-};
-
-/*
- * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1.
- * 0xff means the parent hub will accept transitions to U1, but will not
- * initiate a transition.
- *
- * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to
- * U1 after that many microseconds.  Timeouts of 0x80 to 0xFE are reserved
- * values.
- *
- * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2.
- * 0xff means the parent hub will accept transitions to U2, but will not
- * initiate a transition.
- *
- * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to
- * U2 after N*256 microseconds.  Therefore a U2 timeout value of 0x1 means a U2
- * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means
- * 65.024ms.
- */
-#define USB3_LPM_DISABLED              0x0
-#define USB3_LPM_U1_MAX_TIMEOUT                0x7F
-#define USB3_LPM_U2_MAX_TIMEOUT                0xFE
-#define USB3_LPM_DEVICE_INITIATED      0xFF
-
-struct usb_set_sel_req {
-       __u8    u1_sel;
-       __u8    u1_pel;
-       __le16  u2_sel;
-       __le16  u2_pel;
-} __attribute__ ((packed));
-
-/*
- * The Set System Exit Latency control transfer provides one byte each for
- * U1 SEL and U1 PEL, so the max exit latency is 0xFF.  U2 SEL and U2 PEL each
- * are two bytes long.
- */
-#define USB3_LPM_MAX_U1_SEL_PEL                0xFF
-#define USB3_LPM_MAX_U2_SEL_PEL                0xFFFF
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * As per USB compliance update, a device that is actively drawing
- * more than 100mA from USB must report itself as bus-powered in
- * the GetStatus(DEVICE) call.
- * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34
- */
-#define USB_SELF_POWER_VBUS_MAX_DRAW           100
-
 #endif /* __LINUX_USB_CH9_H */
index a843d085136459974720cc6c9f5149406c6877c6..65d0a88dbc675c8bb7d2bfe6256183cfd8a18ec0 100644 (file)
@@ -1,171 +1,8 @@
 #ifndef __LINUX_FUNCTIONFS_H__
 #define __LINUX_FUNCTIONFS_H__ 1
 
+#include <uapi/linux/usb/functionfs.h>
 
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#include <linux/usb/ch9.h>
-
-
-enum {
-       FUNCTIONFS_DESCRIPTORS_MAGIC = 1,
-       FUNCTIONFS_STRINGS_MAGIC     = 2
-};
-
-
-#ifndef __KERNEL__
-
-/* Descriptor of an non-audio endpoint */
-struct usb_endpoint_descriptor_no_audio {
-       __u8  bLength;
-       __u8  bDescriptorType;
-
-       __u8  bEndpointAddress;
-       __u8  bmAttributes;
-       __le16 wMaxPacketSize;
-       __u8  bInterval;
-} __attribute__((packed));
-
-
-/*
- * All numbers must be in little endian order.
- */
-
-struct usb_functionfs_descs_head {
-       __le32 magic;
-       __le32 length;
-       __le32 fs_count;
-       __le32 hs_count;
-} __attribute__((packed));
-
-/*
- * Descriptors format:
- *
- * | off | name      | type         | description                          |
- * |-----+-----------+--------------+--------------------------------------|
- * |   0 | magic     | LE32         | FUNCTIONFS_{FS,HS}_DESCRIPTORS_MAGIC |
- * |   4 | length    | LE32         | length of the whole data chunk       |
- * |   8 | fs_count  | LE32         | number of full-speed descriptors     |
- * |  12 | hs_count  | LE32         | number of high-speed descriptors     |
- * |  16 | fs_descrs | Descriptor[] | list of full-speed descriptors       |
- * |     | hs_descrs | Descriptor[] | list of high-speed descriptors       |
- *
- * descs are just valid USB descriptors and have the following format:
- *
- * | off | name            | type | description              |
- * |-----+-----------------+------+--------------------------|
- * |   0 | bLength         | U8   | length of the descriptor |
- * |   1 | bDescriptorType | U8   | descriptor type          |
- * |   2 | payload         |      | descriptor's payload     |
- */
-
-struct usb_functionfs_strings_head {
-       __le32 magic;
-       __le32 length;
-       __le32 str_count;
-       __le32 lang_count;
-} __attribute__((packed));
-
-/*
- * Strings format:
- *
- * | off | name       | type                  | description                |
- * |-----+------------+-----------------------+----------------------------|
- * |   0 | magic      | LE32                  | FUNCTIONFS_STRINGS_MAGIC   |
- * |   4 | length     | LE32                  | length of the data chunk   |
- * |   8 | str_count  | LE32                  | number of strings          |
- * |  12 | lang_count | LE32                  | number of languages        |
- * |  16 | stringtab  | StringTab[lang_count] | table of strings per lang  |
- *
- * For each language there is one stringtab entry (ie. there are lang_count
- * stringtab entires).  Each StringTab has following format:
- *
- * | off | name    | type              | description                        |
- * |-----+---------+-------------------+------------------------------------|
- * |   0 | lang    | LE16              | language code                      |
- * |   2 | strings | String[str_count] | array of strings in given language |
- *
- * For each string there is one strings entry (ie. there are str_count
- * string entries).  Each String is a NUL terminated string encoded in
- * UTF-8.
- */
-
-#endif
-
-
-/*
- * Events are delivered on the ep0 file descriptor, when the user mode driver
- * reads from this file descriptor after writing the descriptors.  Don't
- * stop polling this descriptor.
- */
-
-enum usb_functionfs_event_type {
-       FUNCTIONFS_BIND,
-       FUNCTIONFS_UNBIND,
-
-       FUNCTIONFS_ENABLE,
-       FUNCTIONFS_DISABLE,
-
-       FUNCTIONFS_SETUP,
-
-       FUNCTIONFS_SUSPEND,
-       FUNCTIONFS_RESUME
-};
-
-/* NOTE:  this structure must stay the same size and layout on
- * both 32-bit and 64-bit kernels.
- */
-struct usb_functionfs_event {
-       union {
-               /* SETUP: packet; DATA phase i/o precedes next event
-                *(setup.bmRequestType & USB_DIR_IN) flags direction */
-               struct usb_ctrlrequest  setup;
-       } __attribute__((packed)) u;
-
-       /* enum usb_functionfs_event_type */
-       __u8                            type;
-       __u8                            _pad[3];
-} __attribute__((packed));
-
-
-/* Endpoint ioctls */
-/* The same as in gadgetfs */
-
-/* IN transfers may be reported to the gadget driver as complete
- *     when the fifo is loaded, before the host reads the data;
- * OUT transfers may be reported to the host's "client" driver as
- *     complete when they're sitting in the FIFO unread.
- * THIS returns how many bytes are "unclaimed" in the endpoint fifo
- * (needed for precise fault handling, when the hardware allows it)
- */
-#define        FUNCTIONFS_FIFO_STATUS  _IO('g', 1)
-
-/* discards any unclaimed data in the fifo. */
-#define        FUNCTIONFS_FIFO_FLUSH   _IO('g', 2)
-
-/* resets endpoint halt+toggle; used to implement set_interface.
- * some hardware (like pxa2xx) can't support this.
- */
-#define        FUNCTIONFS_CLEAR_HALT   _IO('g', 3)
-
-/* Specific for functionfs */
-
-/*
- * Returns reverse mapping of an interface.  Called on EP0.  If there
- * is no such interface returns -EDOM.  If function is not active
- * returns -ENODEV.
- */
-#define        FUNCTIONFS_INTERFACE_REVMAP     _IO('g', 128)
-
-/*
- * Returns real bEndpointAddress of an endpoint.  If function is not
- * active returns -ENODEV.
- */
-#define        FUNCTIONFS_ENDPOINT_REVMAP      _IO('g', 129)
-
-
-#ifdef __KERNEL__
 
 struct ffs_data;
 struct usb_composite_dev;
@@ -197,5 +34,3 @@ static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
 
 
 #endif
-
-#endif
diff --git a/include/linux/usb/g_printer.h b/include/linux/usb/g_printer.h
deleted file mode 100644 (file)
index 6178fde..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * g_printer.h -- Header file for USB Printer gadget driver
- *
- * Copyright (C) 2007 Craig W. Nadler
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __LINUX_USB_G_PRINTER_H
-#define __LINUX_USB_G_PRINTER_H
-
-#define PRINTER_NOT_ERROR      0x08
-#define PRINTER_SELECTED       0x10
-#define PRINTER_PAPER_EMPTY    0x20
-
-/* The 'g' code is also used by gadgetfs ioctl requests.
- * Don't add any colliding codes to either driver, and keep
- * them in unique ranges (size 0x20 for now).
- */
-#define GADGET_GET_PRINTER_STATUS      _IOR('g', 0x21, unsigned char)
-#define GADGET_SET_PRINTER_STATUS      _IOWR('g', 0x22, unsigned char)
-
-#endif /* __LINUX_USB_G_PRINTER_H */
diff --git a/include/linux/usb/gadgetfs.h b/include/linux/usb/gadgetfs.h
deleted file mode 100644 (file)
index 0bb12e0..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Filesystem based user-mode API to USB Gadget controller hardware
- *
- * Other than ep0 operations, most things are done by read() and write()
- * on endpoint files found in one directory.  They are configured by
- * writing descriptors, and then may be used for normal stream style
- * i/o requests.  When ep0 is configured, the device can enumerate;
- * when it's closed, the device disconnects from usb.  Operations on
- * ep0 require ioctl() operations.
- *
- * Configuration and device descriptors get written to /dev/gadget/$CHIP,
- * which may then be used to read usb_gadgetfs_event structs.  The driver
- * may activate endpoints as it handles SET_CONFIGURATION setup events,
- * or earlier; writing endpoint descriptors to /dev/gadget/$ENDPOINT
- * then performing data transfers by reading or writing.
- */
-
-#ifndef __LINUX_USB_GADGETFS_H
-#define __LINUX_USB_GADGETFS_H
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#include <linux/usb/ch9.h>
-
-/*
- * Events are delivered on the ep0 file descriptor, when the user mode driver
- * reads from this file descriptor after writing the descriptors.  Don't
- * stop polling this descriptor.
- */
-
-enum usb_gadgetfs_event_type {
-       GADGETFS_NOP = 0,
-
-       GADGETFS_CONNECT,
-       GADGETFS_DISCONNECT,
-       GADGETFS_SETUP,
-       GADGETFS_SUSPEND,
-       /* and likely more ! */
-};
-
-/* NOTE:  this structure must stay the same size and layout on
- * both 32-bit and 64-bit kernels.
- */
-struct usb_gadgetfs_event {
-       union {
-               /* NOP, DISCONNECT, SUSPEND: nothing
-                * ... some hardware can't report disconnection
-                */
-
-               /* CONNECT: just the speed */
-               enum usb_device_speed   speed;
-
-               /* SETUP: packet; DATA phase i/o precedes next event
-                *(setup.bmRequestType & USB_DIR_IN) flags direction
-                * ... includes SET_CONFIGURATION, SET_INTERFACE
-                */
-               struct usb_ctrlrequest  setup;
-       } u;
-       enum usb_gadgetfs_event_type    type;
-};
-
-
-/* The 'g' code is also used by printer gadget ioctl requests.
- * Don't add any colliding codes to either driver, and keep
- * them in unique ranges (size 0x20 for now).
- */
-
-/* endpoint ioctls */
-
-/* IN transfers may be reported to the gadget driver as complete
- *     when the fifo is loaded, before the host reads the data;
- * OUT transfers may be reported to the host's "client" driver as
- *     complete when they're sitting in the FIFO unread.
- * THIS returns how many bytes are "unclaimed" in the endpoint fifo
- * (needed for precise fault handling, when the hardware allows it)
- */
-#define        GADGETFS_FIFO_STATUS    _IO('g', 1)
-
-/* discards any unclaimed data in the fifo. */
-#define        GADGETFS_FIFO_FLUSH     _IO('g', 2)
-
-/* resets endpoint halt+toggle; used to implement set_interface.
- * some hardware (like pxa2xx) can't support this.
- */
-#define        GADGETFS_CLEAR_HALT     _IO('g', 3)
-
-#endif /* __LINUX_USB_GADGETFS_H */
diff --git a/include/linux/usb/midi.h b/include/linux/usb/midi.h
deleted file mode 100644 (file)
index c8c52e3..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * <linux/usb/midi.h> -- USB MIDI definitions.
- *
- * Copyright (C) 2006 Thumtronics Pty Ltd.
- * Developed for Thumtronics by Grey Innovation
- * Ben Williamson <ben.williamson@greyinnovation.com>
- *
- * This software is distributed under the terms of the GNU General Public
- * License ("GPL") version 2, as published by the Free Software Foundation.
- *
- * This file holds USB constants and structures defined
- * by the USB Device Class Definition for MIDI Devices.
- * Comments below reference relevant sections of that document:
- *
- * http://www.usb.org/developers/devclass_docs/midi10.pdf
- */
-
-#ifndef __LINUX_USB_MIDI_H
-#define __LINUX_USB_MIDI_H
-
-#include <linux/types.h>
-
-/* A.1  MS Class-Specific Interface Descriptor Subtypes */
-#define USB_MS_HEADER          0x01
-#define USB_MS_MIDI_IN_JACK    0x02
-#define USB_MS_MIDI_OUT_JACK   0x03
-#define USB_MS_ELEMENT         0x04
-
-/* A.2  MS Class-Specific Endpoint Descriptor Subtypes */
-#define USB_MS_GENERAL         0x01
-
-/* A.3  MS MIDI IN and OUT Jack Types */
-#define USB_MS_EMBEDDED                0x01
-#define USB_MS_EXTERNAL                0x02
-
-/* 6.1.2.1  Class-Specific MS Interface Header Descriptor */
-struct usb_ms_header_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubtype;
-       __le16 bcdMSC;
-       __le16 wTotalLength;
-} __attribute__ ((packed));
-
-#define USB_DT_MS_HEADER_SIZE  7
-
-/* 6.1.2.2  MIDI IN Jack Descriptor */
-struct usb_midi_in_jack_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* USB_MS_MIDI_IN_JACK */
-       __u8  bJackType;                /* USB_MS_EMBEDDED/EXTERNAL */
-       __u8  bJackID;
-       __u8  iJack;
-} __attribute__ ((packed));
-
-#define USB_DT_MIDI_IN_SIZE    6
-
-struct usb_midi_source_pin {
-       __u8  baSourceID;
-       __u8  baSourcePin;
-} __attribute__ ((packed));
-
-/* 6.1.2.3  MIDI OUT Jack Descriptor */
-struct usb_midi_out_jack_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
-       __u8  bDescriptorSubtype;       /* USB_MS_MIDI_OUT_JACK */
-       __u8  bJackType;                /* USB_MS_EMBEDDED/EXTERNAL */
-       __u8  bJackID;
-       __u8  bNrInputPins;             /* p */
-       struct usb_midi_source_pin pins[]; /* [p] */
-       /*__u8  iJack;  -- omitted due to variable-sized pins[] */
-} __attribute__ ((packed));
-
-#define USB_DT_MIDI_OUT_SIZE(p)        (7 + 2 * (p))
-
-/* As above, but more useful for defining your own descriptors: */
-#define DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(p)                        \
-struct usb_midi_out_jack_descriptor_##p {                      \
-       __u8  bLength;                                          \
-       __u8  bDescriptorType;                                  \
-       __u8  bDescriptorSubtype;                               \
-       __u8  bJackType;                                        \
-       __u8  bJackID;                                          \
-       __u8  bNrInputPins;                                     \
-       struct usb_midi_source_pin pins[p];                     \
-       __u8  iJack;                                            \
-} __attribute__ ((packed))
-
-/* 6.2.2  Class-Specific MS Bulk Data Endpoint Descriptor */
-struct usb_ms_endpoint_descriptor {
-       __u8  bLength;                  /* 4+n */
-       __u8  bDescriptorType;          /* USB_DT_CS_ENDPOINT */
-       __u8  bDescriptorSubtype;       /* USB_MS_GENERAL */
-       __u8  bNumEmbMIDIJack;          /* n */
-       __u8  baAssocJackID[];          /* [n] */
-} __attribute__ ((packed));
-
-#define USB_DT_MS_ENDPOINT_SIZE(n)     (4 + (n))
-
-/* As above, but more useful for defining your own descriptors: */
-#define DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(n)                  \
-struct usb_ms_endpoint_descriptor_##n {                                \
-       __u8  bLength;                                          \
-       __u8  bDescriptorType;                                  \
-       __u8  bDescriptorSubtype;                               \
-       __u8  bNumEmbMIDIJack;                                  \
-       __u8  baAssocJackID[n];                                 \
-} __attribute__ ((packed))
-
-#endif /* __LINUX_USB_MIDI_H */
diff --git a/include/linux/usb/tmc.h b/include/linux/usb/tmc.h
deleted file mode 100644 (file)
index c045ae1..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany
- * Copyright (C) 2008 Novell, Inc.
- * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de>
- *
- * This file holds USB constants defined by the USB Device Class
- * Definition for Test and Measurement devices published by the USB-IF.
- *
- * It also has the ioctl definitions for the usbtmc kernel driver that
- * userspace needs to know about.
- */
-
-#ifndef __LINUX_USB_TMC_H
-#define __LINUX_USB_TMC_H
-
-/* USB TMC status values */
-#define USBTMC_STATUS_SUCCESS                          0x01
-#define USBTMC_STATUS_PENDING                          0x02
-#define USBTMC_STATUS_FAILED                           0x80
-#define USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS         0x81
-#define USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS            0x82
-#define USBTMC_STATUS_SPLIT_IN_PROGRESS                        0x83
-
-/* USB TMC requests values */
-#define USBTMC_REQUEST_INITIATE_ABORT_BULK_OUT         1
-#define USBTMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS     2
-#define USBTMC_REQUEST_INITIATE_ABORT_BULK_IN          3
-#define USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS      4
-#define USBTMC_REQUEST_INITIATE_CLEAR                  5
-#define USBTMC_REQUEST_CHECK_CLEAR_STATUS              6
-#define USBTMC_REQUEST_GET_CAPABILITIES                        7
-#define USBTMC_REQUEST_INDICATOR_PULSE                 64
-
-/* Request values for USBTMC driver's ioctl entry point */
-#define USBTMC_IOC_NR                  91
-#define USBTMC_IOCTL_INDICATOR_PULSE   _IO(USBTMC_IOC_NR, 1)
-#define USBTMC_IOCTL_CLEAR             _IO(USBTMC_IOC_NR, 2)
-#define USBTMC_IOCTL_ABORT_BULK_OUT    _IO(USBTMC_IOC_NR, 3)
-#define USBTMC_IOCTL_ABORT_BULK_IN     _IO(USBTMC_IOC_NR, 4)
-#define USBTMC_IOCTL_CLEAR_OUT_HALT    _IO(USBTMC_IOC_NR, 6)
-#define USBTMC_IOCTL_CLEAR_IN_HALT     _IO(USBTMC_IOC_NR, 7)
-
-#endif
index ddbbb7de894b4039d70003197737d5591649ad15..9bbeabf66c54d59cede412db6084c1e4315f2d48 100644 (file)
@@ -163,6 +163,16 @@ extern int usbnet_resume(struct usb_interface *);
 extern void usbnet_disconnect(struct usb_interface *);
 extern void usbnet_device_suggests_idle(struct usbnet *dev);
 
+extern int usbnet_read_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+                   u16 value, u16 index, void *data, u16 size);
+extern int usbnet_write_cmd(struct usbnet *dev, u8 cmd, u8 reqtype,
+                   u16 value, u16 index, const void *data, u16 size);
+extern int usbnet_read_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+                   u16 value, u16 index, void *data, u16 size);
+extern int usbnet_write_cmd_nopm(struct usbnet *dev, u8 cmd, u8 reqtype,
+                   u16 value, u16 index, const void *data, u16 size);
+extern int usbnet_write_cmd_async(struct usbnet *dev, u8 cmd, u8 reqtype,
+                   u16 value, u16 index, const void *data, u16 size);
 
 /* Drivers that reuse some of the standard USB CDC infrastructure
  * (notably, using multiple interfaces according to the CDC
diff --git a/include/linux/usb/video.h b/include/linux/usb/video.h
deleted file mode 100644 (file)
index 3b3b95e..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * USB Video Class definitions.
- *
- * Copyright (C) 2009 Laurent Pinchart <laurent.pinchart@skynet.be>
- *
- * This file holds USB constants and structures defined by the USB Device
- * Class Definition for Video Devices. Unless otherwise stated, comments
- * below reference relevant sections of the USB Video Class 1.1 specification
- * available at
- *
- * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip
- */
-
-#ifndef __LINUX_USB_VIDEO_H
-#define __LINUX_USB_VIDEO_H
-
-#include <linux/types.h>
-
-/* --------------------------------------------------------------------------
- * UVC constants
- */
-
-/* A.2. Video Interface Subclass Codes */
-#define UVC_SC_UNDEFINED                               0x00
-#define UVC_SC_VIDEOCONTROL                            0x01
-#define UVC_SC_VIDEOSTREAMING                          0x02
-#define UVC_SC_VIDEO_INTERFACE_COLLECTION              0x03
-
-/* A.3. Video Interface Protocol Codes */
-#define UVC_PC_PROTOCOL_UNDEFINED                      0x00
-
-/* A.5. Video Class-Specific VC Interface Descriptor Subtypes */
-#define UVC_VC_DESCRIPTOR_UNDEFINED                    0x00
-#define UVC_VC_HEADER                                  0x01
-#define UVC_VC_INPUT_TERMINAL                          0x02
-#define UVC_VC_OUTPUT_TERMINAL                         0x03
-#define UVC_VC_SELECTOR_UNIT                           0x04
-#define UVC_VC_PROCESSING_UNIT                         0x05
-#define UVC_VC_EXTENSION_UNIT                          0x06
-
-/* A.6. Video Class-Specific VS Interface Descriptor Subtypes */
-#define UVC_VS_UNDEFINED                               0x00
-#define UVC_VS_INPUT_HEADER                            0x01
-#define UVC_VS_OUTPUT_HEADER                           0x02
-#define UVC_VS_STILL_IMAGE_FRAME                       0x03
-#define UVC_VS_FORMAT_UNCOMPRESSED                     0x04
-#define UVC_VS_FRAME_UNCOMPRESSED                      0x05
-#define UVC_VS_FORMAT_MJPEG                            0x06
-#define UVC_VS_FRAME_MJPEG                             0x07
-#define UVC_VS_FORMAT_MPEG2TS                          0x0a
-#define UVC_VS_FORMAT_DV                               0x0c
-#define UVC_VS_COLORFORMAT                             0x0d
-#define UVC_VS_FORMAT_FRAME_BASED                      0x10
-#define UVC_VS_FRAME_FRAME_BASED                       0x11
-#define UVC_VS_FORMAT_STREAM_BASED                     0x12
-
-/* A.7. Video Class-Specific Endpoint Descriptor Subtypes */
-#define UVC_EP_UNDEFINED                               0x00
-#define UVC_EP_GENERAL                                 0x01
-#define UVC_EP_ENDPOINT                                        0x02
-#define UVC_EP_INTERRUPT                               0x03
-
-/* A.8. Video Class-Specific Request Codes */
-#define UVC_RC_UNDEFINED                               0x00
-#define UVC_SET_CUR                                    0x01
-#define UVC_GET_CUR                                    0x81
-#define UVC_GET_MIN                                    0x82
-#define UVC_GET_MAX                                    0x83
-#define UVC_GET_RES                                    0x84
-#define UVC_GET_LEN                                    0x85
-#define UVC_GET_INFO                                   0x86
-#define UVC_GET_DEF                                    0x87
-
-/* A.9.1. VideoControl Interface Control Selectors */
-#define UVC_VC_CONTROL_UNDEFINED                       0x00
-#define UVC_VC_VIDEO_POWER_MODE_CONTROL                        0x01
-#define UVC_VC_REQUEST_ERROR_CODE_CONTROL              0x02
-
-/* A.9.2. Terminal Control Selectors */
-#define UVC_TE_CONTROL_UNDEFINED                       0x00
-
-/* A.9.3. Selector Unit Control Selectors */
-#define UVC_SU_CONTROL_UNDEFINED                       0x00
-#define UVC_SU_INPUT_SELECT_CONTROL                    0x01
-
-/* A.9.4. Camera Terminal Control Selectors */
-#define UVC_CT_CONTROL_UNDEFINED                       0x00
-#define UVC_CT_SCANNING_MODE_CONTROL                   0x01
-#define UVC_CT_AE_MODE_CONTROL                         0x02
-#define UVC_CT_AE_PRIORITY_CONTROL                     0x03
-#define UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL          0x04
-#define UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL          0x05
-#define UVC_CT_FOCUS_ABSOLUTE_CONTROL                  0x06
-#define UVC_CT_FOCUS_RELATIVE_CONTROL                  0x07
-#define UVC_CT_FOCUS_AUTO_CONTROL                      0x08
-#define UVC_CT_IRIS_ABSOLUTE_CONTROL                   0x09
-#define UVC_CT_IRIS_RELATIVE_CONTROL                   0x0a
-#define UVC_CT_ZOOM_ABSOLUTE_CONTROL                   0x0b
-#define UVC_CT_ZOOM_RELATIVE_CONTROL                   0x0c
-#define UVC_CT_PANTILT_ABSOLUTE_CONTROL                        0x0d
-#define UVC_CT_PANTILT_RELATIVE_CONTROL                        0x0e
-#define UVC_CT_ROLL_ABSOLUTE_CONTROL                   0x0f
-#define UVC_CT_ROLL_RELATIVE_CONTROL                   0x10
-#define UVC_CT_PRIVACY_CONTROL                         0x11
-
-/* A.9.5. Processing Unit Control Selectors */
-#define UVC_PU_CONTROL_UNDEFINED                       0x00
-#define UVC_PU_BACKLIGHT_COMPENSATION_CONTROL          0x01
-#define UVC_PU_BRIGHTNESS_CONTROL                      0x02
-#define UVC_PU_CONTRAST_CONTROL                                0x03
-#define UVC_PU_GAIN_CONTROL                            0x04
-#define UVC_PU_POWER_LINE_FREQUENCY_CONTROL            0x05
-#define UVC_PU_HUE_CONTROL                             0x06
-#define UVC_PU_SATURATION_CONTROL                      0x07
-#define UVC_PU_SHARPNESS_CONTROL                       0x08
-#define UVC_PU_GAMMA_CONTROL                           0x09
-#define UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL       0x0a
-#define UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL  0x0b
-#define UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL         0x0c
-#define UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL    0x0d
-#define UVC_PU_DIGITAL_MULTIPLIER_CONTROL              0x0e
-#define UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL                0x0f
-#define UVC_PU_HUE_AUTO_CONTROL                                0x10
-#define UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL           0x11
-#define UVC_PU_ANALOG_LOCK_STATUS_CONTROL              0x12
-
-/* A.9.7. VideoStreaming Interface Control Selectors */
-#define UVC_VS_CONTROL_UNDEFINED                       0x00
-#define UVC_VS_PROBE_CONTROL                           0x01
-#define UVC_VS_COMMIT_CONTROL                          0x02
-#define UVC_VS_STILL_PROBE_CONTROL                     0x03
-#define UVC_VS_STILL_COMMIT_CONTROL                    0x04
-#define UVC_VS_STILL_IMAGE_TRIGGER_CONTROL             0x05
-#define UVC_VS_STREAM_ERROR_CODE_CONTROL               0x06
-#define UVC_VS_GENERATE_KEY_FRAME_CONTROL              0x07
-#define UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL            0x08
-#define UVC_VS_SYNC_DELAY_CONTROL                      0x09
-
-/* B.1. USB Terminal Types */
-#define UVC_TT_VENDOR_SPECIFIC                         0x0100
-#define UVC_TT_STREAMING                               0x0101
-
-/* B.2. Input Terminal Types */
-#define UVC_ITT_VENDOR_SPECIFIC                                0x0200
-#define UVC_ITT_CAMERA                                 0x0201
-#define UVC_ITT_MEDIA_TRANSPORT_INPUT                  0x0202
-
-/* B.3. Output Terminal Types */
-#define UVC_OTT_VENDOR_SPECIFIC                                0x0300
-#define UVC_OTT_DISPLAY                                        0x0301
-#define UVC_OTT_MEDIA_TRANSPORT_OUTPUT                 0x0302
-
-/* B.4. External Terminal Types */
-#define UVC_EXTERNAL_VENDOR_SPECIFIC                   0x0400
-#define UVC_COMPOSITE_CONNECTOR                                0x0401
-#define UVC_SVIDEO_CONNECTOR                           0x0402
-#define UVC_COMPONENT_CONNECTOR                                0x0403
-
-/* 2.4.2.2. Status Packet Type */
-#define UVC_STATUS_TYPE_CONTROL                                1
-#define UVC_STATUS_TYPE_STREAMING                      2
-
-/* 2.4.3.3. Payload Header Information */
-#define UVC_STREAM_EOH                                 (1 << 7)
-#define UVC_STREAM_ERR                                 (1 << 6)
-#define UVC_STREAM_STI                                 (1 << 5)
-#define UVC_STREAM_RES                                 (1 << 4)
-#define UVC_STREAM_SCR                                 (1 << 3)
-#define UVC_STREAM_PTS                                 (1 << 2)
-#define UVC_STREAM_EOF                                 (1 << 1)
-#define UVC_STREAM_FID                                 (1 << 0)
-
-/* 4.1.2. Control Capabilities */
-#define UVC_CONTROL_CAP_GET                            (1 << 0)
-#define UVC_CONTROL_CAP_SET                            (1 << 1)
-#define UVC_CONTROL_CAP_DISABLED                       (1 << 2)
-#define UVC_CONTROL_CAP_AUTOUPDATE                     (1 << 3)
-#define UVC_CONTROL_CAP_ASYNCHRONOUS                   (1 << 4)
-
-/* ------------------------------------------------------------------------
- * UVC structures
- */
-
-/* All UVC descriptors have these 3 fields at the beginning */
-struct uvc_descriptor_header {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-} __attribute__((packed));
-
-/* 3.7.2. Video Control Interface Header Descriptor */
-struct uvc_header_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u16 bcdUVC;
-       __u16 wTotalLength;
-       __u32 dwClockFrequency;
-       __u8  bInCollection;
-       __u8  baInterfaceNr[];
-} __attribute__((__packed__));
-
-#define UVC_DT_HEADER_SIZE(n)                          (12+(n))
-
-#define UVC_HEADER_DESCRIPTOR(n) \
-       uvc_header_descriptor_##n
-
-#define DECLARE_UVC_HEADER_DESCRIPTOR(n)               \
-struct UVC_HEADER_DESCRIPTOR(n) {                      \
-       __u8  bLength;                                  \
-       __u8  bDescriptorType;                          \
-       __u8  bDescriptorSubType;                       \
-       __u16 bcdUVC;                                   \
-       __u16 wTotalLength;                             \
-       __u32 dwClockFrequency;                         \
-       __u8  bInCollection;                            \
-       __u8  baInterfaceNr[n];                         \
-} __attribute__ ((packed))
-
-/* 3.7.2.1. Input Terminal Descriptor */
-struct uvc_input_terminal_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bTerminalID;
-       __u16 wTerminalType;
-       __u8  bAssocTerminal;
-       __u8  iTerminal;
-} __attribute__((__packed__));
-
-#define UVC_DT_INPUT_TERMINAL_SIZE                     8
-
-/* 3.7.2.2. Output Terminal Descriptor */
-struct uvc_output_terminal_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bTerminalID;
-       __u16 wTerminalType;
-       __u8  bAssocTerminal;
-       __u8  bSourceID;
-       __u8  iTerminal;
-} __attribute__((__packed__));
-
-#define UVC_DT_OUTPUT_TERMINAL_SIZE                    9
-
-/* 3.7.2.3. Camera Terminal Descriptor */
-struct uvc_camera_terminal_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bTerminalID;
-       __u16 wTerminalType;
-       __u8  bAssocTerminal;
-       __u8  iTerminal;
-       __u16 wObjectiveFocalLengthMin;
-       __u16 wObjectiveFocalLengthMax;
-       __u16 wOcularFocalLength;
-       __u8  bControlSize;
-       __u8  bmControls[3];
-} __attribute__((__packed__));
-
-#define UVC_DT_CAMERA_TERMINAL_SIZE(n)                 (15+(n))
-
-/* 3.7.2.4. Selector Unit Descriptor */
-struct uvc_selector_unit_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bUnitID;
-       __u8  bNrInPins;
-       __u8  baSourceID[0];
-       __u8  iSelector;
-} __attribute__((__packed__));
-
-#define UVC_DT_SELECTOR_UNIT_SIZE(n)                   (6+(n))
-
-#define UVC_SELECTOR_UNIT_DESCRIPTOR(n)        \
-       uvc_selector_unit_descriptor_##n
-
-#define DECLARE_UVC_SELECTOR_UNIT_DESCRIPTOR(n)        \
-struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) {               \
-       __u8  bLength;                                  \
-       __u8  bDescriptorType;                          \
-       __u8  bDescriptorSubType;                       \
-       __u8  bUnitID;                                  \
-       __u8  bNrInPins;                                \
-       __u8  baSourceID[n];                            \
-       __u8  iSelector;                                \
-} __attribute__ ((packed))
-
-/* 3.7.2.5. Processing Unit Descriptor */
-struct uvc_processing_unit_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bUnitID;
-       __u8  bSourceID;
-       __u16 wMaxMultiplier;
-       __u8  bControlSize;
-       __u8  bmControls[2];
-       __u8  iProcessing;
-} __attribute__((__packed__));
-
-#define UVC_DT_PROCESSING_UNIT_SIZE(n)                 (9+(n))
-
-/* 3.7.2.6. Extension Unit Descriptor */
-struct uvc_extension_unit_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bUnitID;
-       __u8  guidExtensionCode[16];
-       __u8  bNumControls;
-       __u8  bNrInPins;
-       __u8  baSourceID[0];
-       __u8  bControlSize;
-       __u8  bmControls[0];
-       __u8  iExtension;
-} __attribute__((__packed__));
-
-#define UVC_DT_EXTENSION_UNIT_SIZE(p, n)               (24+(p)+(n))
-
-#define UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
-       uvc_extension_unit_descriptor_##p_##n
-
-#define DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(p, n)    \
-struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) {           \
-       __u8  bLength;                                  \
-       __u8  bDescriptorType;                          \
-       __u8  bDescriptorSubType;                       \
-       __u8  bUnitID;                                  \
-       __u8  guidExtensionCode[16];                    \
-       __u8  bNumControls;                             \
-       __u8  bNrInPins;                                \
-       __u8  baSourceID[p];                            \
-       __u8  bControlSize;                             \
-       __u8  bmControls[n];                            \
-       __u8  iExtension;                               \
-} __attribute__ ((packed))
-
-/* 3.8.2.2. Video Control Interrupt Endpoint Descriptor */
-struct uvc_control_endpoint_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u16 wMaxTransferSize;
-} __attribute__((__packed__));
-
-#define UVC_DT_CONTROL_ENDPOINT_SIZE                   5
-
-/* 3.9.2.1. Input Header Descriptor */
-struct uvc_input_header_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bNumFormats;
-       __u16 wTotalLength;
-       __u8  bEndpointAddress;
-       __u8  bmInfo;
-       __u8  bTerminalLink;
-       __u8  bStillCaptureMethod;
-       __u8  bTriggerSupport;
-       __u8  bTriggerUsage;
-       __u8  bControlSize;
-       __u8  bmaControls[];
-} __attribute__((__packed__));
-
-#define UVC_DT_INPUT_HEADER_SIZE(n, p)                 (13+(n*p))
-
-#define UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
-       uvc_input_header_descriptor_##n_##p
-
-#define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p)      \
-struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) {             \
-       __u8  bLength;                                  \
-       __u8  bDescriptorType;                          \
-       __u8  bDescriptorSubType;                       \
-       __u8  bNumFormats;                              \
-       __u16 wTotalLength;                             \
-       __u8  bEndpointAddress;                         \
-       __u8  bmInfo;                                   \
-       __u8  bTerminalLink;                            \
-       __u8  bStillCaptureMethod;                      \
-       __u8  bTriggerSupport;                          \
-       __u8  bTriggerUsage;                            \
-       __u8  bControlSize;                             \
-       __u8  bmaControls[p][n];                        \
-} __attribute__ ((packed))
-
-/* 3.9.2.2. Output Header Descriptor */
-struct uvc_output_header_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bNumFormats;
-       __u16 wTotalLength;
-       __u8  bEndpointAddress;
-       __u8  bTerminalLink;
-       __u8  bControlSize;
-       __u8  bmaControls[];
-} __attribute__((__packed__));
-
-#define UVC_DT_OUTPUT_HEADER_SIZE(n, p)                        (9+(n*p))
-
-#define UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
-       uvc_output_header_descriptor_##n_##p
-
-#define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p)     \
-struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) {            \
-       __u8  bLength;                                  \
-       __u8  bDescriptorType;                          \
-       __u8  bDescriptorSubType;                       \
-       __u8  bNumFormats;                              \
-       __u16 wTotalLength;                             \
-       __u8  bEndpointAddress;                         \
-       __u8  bTerminalLink;                            \
-       __u8  bControlSize;                             \
-       __u8  bmaControls[p][n];                        \
-} __attribute__ ((packed))
-
-/* 3.9.2.6. Color matching descriptor */
-struct uvc_color_matching_descriptor {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bColorPrimaries;
-       __u8  bTransferCharacteristics;
-       __u8  bMatrixCoefficients;
-} __attribute__((__packed__));
-
-#define UVC_DT_COLOR_MATCHING_SIZE                     6
-
-/* 4.3.1.1. Video Probe and Commit Controls */
-struct uvc_streaming_control {
-       __u16 bmHint;
-       __u8  bFormatIndex;
-       __u8  bFrameIndex;
-       __u32 dwFrameInterval;
-       __u16 wKeyFrameRate;
-       __u16 wPFrameRate;
-       __u16 wCompQuality;
-       __u16 wCompWindowSize;
-       __u16 wDelay;
-       __u32 dwMaxVideoFrameSize;
-       __u32 dwMaxPayloadTransferSize;
-       __u32 dwClockFrequency;
-       __u8  bmFramingInfo;
-       __u8  bPreferedVersion;
-       __u8  bMinVersion;
-       __u8  bMaxVersion;
-} __attribute__((__packed__));
-
-/* Uncompressed Payload - 3.1.1. Uncompressed Video Format Descriptor */
-struct uvc_format_uncompressed {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bFormatIndex;
-       __u8  bNumFrameDescriptors;
-       __u8  guidFormat[16];
-       __u8  bBitsPerPixel;
-       __u8  bDefaultFrameIndex;
-       __u8  bAspectRatioX;
-       __u8  bAspectRatioY;
-       __u8  bmInterfaceFlags;
-       __u8  bCopyProtect;
-} __attribute__((__packed__));
-
-#define UVC_DT_FORMAT_UNCOMPRESSED_SIZE                        27
-
-/* Uncompressed Payload - 3.1.2. Uncompressed Video Frame Descriptor */
-struct uvc_frame_uncompressed {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bFrameIndex;
-       __u8  bmCapabilities;
-       __u16 wWidth;
-       __u16 wHeight;
-       __u32 dwMinBitRate;
-       __u32 dwMaxBitRate;
-       __u32 dwMaxVideoFrameBufferSize;
-       __u32 dwDefaultFrameInterval;
-       __u8  bFrameIntervalType;
-       __u32 dwFrameInterval[];
-} __attribute__((__packed__));
-
-#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n)              (26+4*(n))
-
-#define UVC_FRAME_UNCOMPRESSED(n) \
-       uvc_frame_uncompressed_##n
-
-#define DECLARE_UVC_FRAME_UNCOMPRESSED(n)              \
-struct UVC_FRAME_UNCOMPRESSED(n) {                     \
-       __u8  bLength;                                  \
-       __u8  bDescriptorType;                          \
-       __u8  bDescriptorSubType;                       \
-       __u8  bFrameIndex;                              \
-       __u8  bmCapabilities;                           \
-       __u16 wWidth;                                   \
-       __u16 wHeight;                                  \
-       __u32 dwMinBitRate;                             \
-       __u32 dwMaxBitRate;                             \
-       __u32 dwMaxVideoFrameBufferSize;                \
-       __u32 dwDefaultFrameInterval;                   \
-       __u8  bFrameIntervalType;                       \
-       __u32 dwFrameInterval[n];                       \
-} __attribute__ ((packed))
-
-/* MJPEG Payload - 3.1.1. MJPEG Video Format Descriptor */
-struct uvc_format_mjpeg {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bFormatIndex;
-       __u8  bNumFrameDescriptors;
-       __u8  bmFlags;
-       __u8  bDefaultFrameIndex;
-       __u8  bAspectRatioX;
-       __u8  bAspectRatioY;
-       __u8  bmInterfaceFlags;
-       __u8  bCopyProtect;
-} __attribute__((__packed__));
-
-#define UVC_DT_FORMAT_MJPEG_SIZE                       11
-
-/* MJPEG Payload - 3.1.2. MJPEG Video Frame Descriptor */
-struct uvc_frame_mjpeg {
-       __u8  bLength;
-       __u8  bDescriptorType;
-       __u8  bDescriptorSubType;
-       __u8  bFrameIndex;
-       __u8  bmCapabilities;
-       __u16 wWidth;
-       __u16 wHeight;
-       __u32 dwMinBitRate;
-       __u32 dwMaxBitRate;
-       __u32 dwMaxVideoFrameBufferSize;
-       __u32 dwDefaultFrameInterval;
-       __u8  bFrameIntervalType;
-       __u32 dwFrameInterval[];
-} __attribute__((__packed__));
-
-#define UVC_DT_FRAME_MJPEG_SIZE(n)                     (26+4*(n))
-
-#define UVC_FRAME_MJPEG(n) \
-       uvc_frame_mjpeg_##n
-
-#define DECLARE_UVC_FRAME_MJPEG(n)                     \
-struct UVC_FRAME_MJPEG(n) {                            \
-       __u8  bLength;                                  \
-       __u8  bDescriptorType;                          \
-       __u8  bDescriptorSubType;                       \
-       __u8  bFrameIndex;                              \
-       __u8  bmCapabilities;                           \
-       __u16 wWidth;                                   \
-       __u16 wHeight;                                  \
-       __u32 dwMinBitRate;                             \
-       __u32 dwMaxBitRate;                             \
-       __u32 dwMaxVideoFrameBufferSize;                \
-       __u32 dwDefaultFrameInterval;                   \
-       __u8  bFrameIntervalType;                       \
-       __u32 dwFrameInterval[n];                       \
-} __attribute__ ((packed))
-
-#endif /* __LINUX_USB_VIDEO_H */
-
diff --git a/include/linux/wimax/Kbuild b/include/linux/wimax/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 171b957db74399ac1f82f2efe22a70857452156b..dc004bc926c92154729fd89b9c88a1a93d579092 100644 (file)
@@ -40,14 +40,6 @@ enum adv7604_op_ch_sel {
        ADV7604_OP_CH_SEL_RBG = 5,
 };
 
-/* Primary mode (IO register 0x01, [3:0]) */
-enum adv7604_prim_mode {
-       ADV7604_PRIM_MODE_COMP = 1,
-       ADV7604_PRIM_MODE_RGB = 2,
-       ADV7604_PRIM_MODE_HDMI_COMP = 5,
-       ADV7604_PRIM_MODE_HDMI_GR = 6,
-};
-
 /* Input Color Space (IO register 0x02, [7:4]) */
 enum adv7604_inp_color_space {
        ADV7604_INP_COLOR_SPACE_LIM_RGB = 0,
@@ -103,9 +95,6 @@ struct adv7604_platform_data {
        /* Bus rotation and reordering */
        enum adv7604_op_ch_sel op_ch_sel;
 
-       /* Primary mode */
-       enum adv7604_prim_mode prim_mode;
-
        /* Select output format */
        enum adv7604_op_format_sel op_format_sel;
 
@@ -142,6 +131,16 @@ struct adv7604_platform_data {
        u8 i2c_vdp;
 };
 
+/*
+ * Mode of operation.
+ * This is used as the input argument of the s_routing video op.
+ */
+enum adv7604_mode {
+       ADV7604_MODE_COMP,
+       ADV7604_MODE_GR,
+       ADV7604_MODE_HDMI,
+};
+
 #define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE  (V4L2_CID_DV_CLASS_BASE + 0x1000)
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL  (V4L2_CID_DV_CLASS_BASE + 0x1001)
 #define V4L2_CID_ADV_RX_FREE_RUN_COLOR         (V4L2_CID_DV_CLASS_BASE + 0x1002)
diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 9e63e76b20e7e0ce4b60aa5daf0e113b6985ae16..df4ef945338425d7fc6d64a858dd706d2628ea28 100644 (file)
@@ -172,6 +172,9 @@ extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
 extern int register_inet6addr_notifier(struct notifier_block *nb);
 extern int unregister_inet6addr_notifier(struct notifier_block *nb);
 
+extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+                                        struct ipv6_devconf *devconf);
+
 /**
  * __in6_dev_get - get inet6_dev pointer from netdevice
  * @dev: network device
index b5f8988e42837b6d703783f6f94dd6b9e4b09cba..0a996a3517edd2e652bb389ca4093d9928e7b974 100644 (file)
@@ -53,7 +53,6 @@ struct unix_sock {
        struct path             path;
        struct mutex            readlock;
        struct sock             *peer;
-       struct sock             *other;
        struct list_head        link;
        atomic_long_t           inflight;
        spinlock_t              lock;
index b6a6eeb3905f15d956fd1190cf6c415508cea0bf..2581638f4a3d6ac803d156ec4dd333eaf1a0cdc6 100644 (file)
@@ -24,12 +24,12 @@ struct cgroup_cls_state
        u32 classid;
 };
 
-extern void sock_update_classid(struct sock *sk);
+extern void sock_update_classid(struct sock *sk, struct task_struct *task);
 
 #if IS_BUILTIN(CONFIG_NET_CLS_CGROUP)
 static inline u32 task_cls_classid(struct task_struct *p)
 {
-       int classid;
+       u32 classid;
 
        if (in_interrupt())
                return 0;
@@ -61,7 +61,7 @@ static inline u32 task_cls_classid(struct task_struct *p)
 }
 #endif
 #else /* !CGROUP_NET_CLS_CGROUP */
-static inline void sock_update_classid(struct sock *sk)
+static inline void sock_update_classid(struct sock *sk, struct task_struct *task)
 {
 }
 
index 4fd8a4b4b7eeee98198c2e999d2a72951d95f8fa..e5062c955ea6594c3d7bd7850b76bce6a3640b5a 100644 (file)
@@ -17,7 +17,6 @@ struct gro_cells {
 
 static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
 {
-       unsigned long flags;
        struct gro_cell *cell = gcells->cells;
        struct net_device *dev = skb->dev;
 
@@ -35,32 +34,37 @@ static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *s
                return;
        }
 
-       spin_lock_irqsave(&cell->napi_skbs.lock, flags);
+       /* We run in BH context */
+       spin_lock(&cell->napi_skbs.lock);
 
        __skb_queue_tail(&cell->napi_skbs, skb);
        if (skb_queue_len(&cell->napi_skbs) == 1)
                napi_schedule(&cell->napi);
 
-       spin_unlock_irqrestore(&cell->napi_skbs.lock, flags);
+       spin_unlock(&cell->napi_skbs.lock);
 }
 
+/* called unser BH context */
 static inline int gro_cell_poll(struct napi_struct *napi, int budget)
 {
        struct gro_cell *cell = container_of(napi, struct gro_cell, napi);
        struct sk_buff *skb;
        int work_done = 0;
 
+       spin_lock(&cell->napi_skbs.lock);
        while (work_done < budget) {
-               skb = skb_dequeue(&cell->napi_skbs);
+               skb = __skb_dequeue(&cell->napi_skbs);
                if (!skb)
                        break;
-
+               spin_unlock(&cell->napi_skbs.lock);
                napi_gro_receive(napi, skb);
                work_done++;
+               spin_lock(&cell->napi_skbs.lock);
        }
 
        if (work_done < budget)
                napi_complete(napi);
+       spin_unlock(&cell->napi_skbs.lock);
        return work_done;
 }
 
index 54be0287eb982cb55f7d26973ae7aa281de8a72c..67a8fa098e3a2b0d456996f78af4ff845db4d079 100644 (file)
@@ -277,7 +277,6 @@ static inline struct sock *inet_lookup_listener(struct net *net,
    On 64bit targets we combine comparisons with pair of adjacent __be32
    fields in the same way.
 */
-typedef __u32 __bitwise __portpair;
 #ifdef __BIG_ENDIAN
 #define INET_COMBINED_PORTS(__sport, __dport) \
        ((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport)))
@@ -287,7 +286,6 @@ typedef __u32 __bitwise __portpair;
 #endif
 
 #if (BITS_PER_LONG == 64)
-typedef __u64 __bitwise __addrpair;
 #ifdef __BIG_ENDIAN
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
        const __addrpair __name = (__force __addrpair) ( \
@@ -299,30 +297,34 @@ typedef __u64 __bitwise __addrpair;
                                   (((__force __u64)(__be32)(__daddr)) << 32) | \
                                   ((__force __u64)(__be32)(__saddr)));
 #endif /* __BIG_ENDIAN */
-#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
-       (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) &&    \
-        ((*((__addrpair *)&(inet_sk(__sk)->inet_daddr))) == (__cookie))  &&    \
-        ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports))   &&    \
-        (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
-       (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) &&    \
-        ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&     \
-        ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
-        (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif)    \
+       ((inet_sk(__sk)->inet_portpair == (__ports))            &&      \
+        (inet_sk(__sk)->inet_addrpair == (__cookie))           &&      \
+        (!(__sk)->sk_bound_dev_if      ||                              \
+          ((__sk)->sk_bound_dev_if == (__dif)))                &&      \
+        net_eq(sock_net(__sk), (__net)))
+#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif)\
+       ((inet_twsk(__sk)->tw_portpair == (__ports))    &&              \
+        (inet_twsk(__sk)->tw_addrpair == (__cookie))   &&              \
+        (!(__sk)->sk_bound_dev_if      ||                              \
+          ((__sk)->sk_bound_dev_if == (__dif)))        &&              \
+        net_eq(sock_net(__sk), (__net)))
 #else /* 32-bit arch */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
-#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)    \
-       (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net))       &&      \
-        (inet_sk(__sk)->inet_daddr     == (__saddr))           &&      \
-        (inet_sk(__sk)->inet_rcv_saddr == (__daddr))           &&      \
-        ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) &&      \
-        (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif)  \
-       (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net))       &&      \
-        (inet_twsk(__sk)->tw_daddr     == (__saddr))           &&      \
-        (inet_twsk(__sk)->tw_rcv_saddr == (__daddr))           &&      \
-        ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&      \
-        (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+       ((inet_sk(__sk)->inet_portpair == (__ports))    &&              \
+        (inet_sk(__sk)->inet_daddr     == (__saddr))   &&              \
+        (inet_sk(__sk)->inet_rcv_saddr == (__daddr))   &&              \
+        (!(__sk)->sk_bound_dev_if      ||                              \
+          ((__sk)->sk_bound_dev_if == (__dif)))        &&              \
+        net_eq(sock_net(__sk), (__net)))
+#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+       ((inet_twsk(__sk)->tw_portpair == (__ports))    &&              \
+        (inet_twsk(__sk)->tw_daddr     == (__saddr))   &&              \
+        (inet_twsk(__sk)->tw_rcv_saddr == (__daddr))   &&              \
+        (!(__sk)->sk_bound_dev_if      ||                              \
+          ((__sk)->sk_bound_dev_if == (__dif)))        &&              \
+        net_eq(sock_net(__sk), (__net)))
 #endif /* 64-bit arch */
 
 /*
index 256c1ed2d69afc06cfbc8b51550c7b374a166afe..a4196cbc84eca774d45a2d275f4a38eb5be775f3 100644 (file)
@@ -144,9 +144,11 @@ struct inet_sock {
        /* Socket demultiplex comparisons on incoming packets. */
 #define inet_daddr             sk.__sk_common.skc_daddr
 #define inet_rcv_saddr         sk.__sk_common.skc_rcv_saddr
+#define inet_addrpair          sk.__sk_common.skc_addrpair
+#define inet_dport             sk.__sk_common.skc_dport
+#define inet_num               sk.__sk_common.skc_num
+#define inet_portpair          sk.__sk_common.skc_portpair
 
-       __be16                  inet_dport;
-       __u16                   inet_num;
        __be32                  inet_saddr;
        __s16                   uc_ttl;
        __u16                   cmsg_flags;
@@ -154,6 +156,7 @@ struct inet_sock {
        __u16                   inet_id;
 
        struct ip_options_rcu __rcu     *inet_opt;
+       int                     rx_dst_ifindex;
        __u8                    tos;
        __u8                    min_ttl;
        __u8                    mc_ttl;
@@ -170,7 +173,6 @@ struct inet_sock {
        int                     uc_index;
        int                     mc_index;
        __be32                  mc_addr;
-       int                     rx_dst_ifindex;
        struct ip_mc_socklist __rcu     *mc_list;
        struct inet_cork_full   cork;
 };
index ba52c830a7a54569795dcd30a32813e1dc580a75..7d658d5773681347bb3e799990dd9947c73e8e32 100644 (file)
@@ -112,6 +112,11 @@ struct inet_timewait_sock {
 #define tw_net                 __tw_common.skc_net
 #define tw_daddr               __tw_common.skc_daddr
 #define tw_rcv_saddr           __tw_common.skc_rcv_saddr
+#define tw_addrpair            __tw_common.skc_addrpair
+#define tw_dport               __tw_common.skc_dport
+#define tw_num                 __tw_common.skc_num
+#define tw_portpair            __tw_common.skc_portpair
+
        int                     tw_timeout;
        volatile unsigned char  tw_substate;
        unsigned char           tw_rcv_wscale;
@@ -119,8 +124,6 @@ struct inet_timewait_sock {
        /* Socket demultiplex comparisons on incoming packets. */
        /* these three are in inet_sock */
        __be16                  tw_sport;
-       __be16                  tw_dport;
-       __u16                   tw_num;
        kmemcheck_bitfield_begin(flags);
        /* And these are ours. */
        unsigned int            tw_ipv6only     : 1,
index bc1b0fda2b0452d7cadd32a30f6df0e2a697d99e..652d3d309357c8d587c313817c61261479c78e0e 100644 (file)
@@ -31,6 +31,8 @@
 #include <net/ip.h>
 #include <asm/checksum.h>
 #include <linux/in6.h>
+#include <linux/tcp.h>
+#include <linux/ipv6.h>
 
 #ifndef _HAVE_ARCH_IPV6_CSUM
 
@@ -91,4 +93,37 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
 }
 
 #endif
+
+static __inline__ __sum16 tcp_v6_check(int len,
+                                  const struct in6_addr *saddr,
+                                  const struct in6_addr *daddr,
+                                  __wsum base)
+{
+       return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
+}
+
+static inline void __tcp_v6_send_check(struct sk_buff *skb,
+                                      const struct in6_addr *saddr,
+                                      const struct in6_addr *daddr)
+{
+       struct tcphdr *th = tcp_hdr(skb);
+
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
+               skb->csum_start = skb_transport_header(skb) - skb->head;
+               skb->csum_offset = offsetof(struct tcphdr, check);
+       } else {
+               th->check = tcp_v6_check(skb->len, saddr, daddr,
+                                        csum_partial(th, th->doff << 2,
+                                                     skb->csum));
+       }
+}
+
+static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
+{
+       struct ipv6_pinfo *np = inet6_sk(sk);
+
+       __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
+}
+
 #endif
index 8a2a203eb15d087c4838e80aa52e55208cbee1d5..fdc48a94a063ae8ce746c501a477ab3471ab028e 100644 (file)
@@ -47,6 +47,8 @@ struct fib6_config {
        unsigned long   fc_expires;
        struct nlattr   *fc_mx;
        int             fc_mx_len;
+       int             fc_mp_len;
+       struct nlattr   *fc_mp;
 
        struct nl_info  fc_nlinfo;
 };
@@ -99,6 +101,14 @@ struct rt6_info {
 
        struct in6_addr                 rt6i_gateway;
 
+       /* Multipath routes:
+        * siblings is a list of rt6_info that have the the same metric/weight,
+        * destination, but not the same gateway. nsiblings is just a cache
+        * to speed up lookup.
+        */
+       struct list_head                rt6i_siblings;
+       unsigned int                    rt6i_nsiblings;
+
        atomic_t                        rt6i_ref;
 
        /* These are in a separate cache line. */
@@ -107,7 +117,6 @@ struct rt6_info {
        struct rt6key                   rt6i_src;
        struct rt6key                   rt6i_prefsrc;
        u32                             rt6i_metric;
-       u32                             rt6i_peer_genid;
 
        struct inet6_dev                *rt6i_idev;
        unsigned long                   _rt6i_peer;
@@ -203,6 +212,15 @@ static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
        dst_hold(new);
 }
 
+static inline void ip6_rt_put(struct rt6_info *rt)
+{
+       /* dst_release() accepts a NULL parameter.
+        * We rely on dst being first structure in struct rt6_info
+        */
+       BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
+       dst_release(&rt->dst);
+}
+
 struct fib6_walker_t {
        struct list_head lh;
        struct fib6_node *root, *node;
index 5fa2af00634a4c52131d17b57639eb2358dd82c8..27d83183e615ef0029150d58858e7828a06e6921 100644 (file)
@@ -1,9 +1,6 @@
 #ifndef _NET_IP6_ROUTE_H
 #define _NET_IP6_ROUTE_H
 
-#define IP6_RT_PRIO_USER       1024
-#define IP6_RT_PRIO_ADDRCONF   256
-
 struct route_info {
        __u8                    type;
        __u8                    length;
index ee75ccdf5188cbf4eac840714a22b456d6700ad6..68c69d54d39281ee033d765a1b9b66567c55d06f 100644 (file)
 #include <linux/ip.h>
 #include <linux/ipv6.h>                        /* for struct ipv6hdr */
 #include <net/ipv6.h>
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_IP_VS_IPV6)
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#endif
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
 #include <net/netfilter/nf_conntrack.h>
 #endif
 #include <net/net_namespace.h>         /* Netw namespace */
@@ -103,30 +106,117 @@ static inline struct net *seq_file_single_net(struct seq_file *seq)
 /* Connections' size value needed by ip_vs_ctl.c */
 extern int ip_vs_conn_tab_size;
 
-
 struct ip_vs_iphdr {
-       int len;
-       __u8 protocol;
+       __u32 len;      /* IPv4 simply where L4 starts
+                          IPv6 where L4 Transport Header starts */
+       __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
+       __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
+       __s16 protocol;
+       __s32 flags;
        union nf_inet_addr saddr;
        union nf_inet_addr daddr;
 };
 
+/* Dependency to module: nf_defrag_ipv6 */
+#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+       return skb->nfct_reasm;
+}
+static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+                                     int len, void *buffer,
+                                     const struct ip_vs_iphdr *ipvsh)
+{
+       if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
+               return skb_header_pointer(skb_nfct_reasm(skb),
+                                         ipvsh->thoff_reasm, len, buffer);
+
+       return skb_header_pointer(skb, offset, len, buffer);
+}
+#else
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+       return NULL;
+}
+static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+                                     int len, void *buffer,
+                                     const struct ip_vs_iphdr *ipvsh)
+{
+       return skb_header_pointer(skb, offset, len, buffer);
+}
+#endif
+
 static inline void
-ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr)
+ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
+{
+       const struct iphdr *iph = nh;
+
+       iphdr->len      = iph->ihl * 4;
+       iphdr->fragoffs = 0;
+       iphdr->protocol = iph->protocol;
+       iphdr->saddr.ip = iph->saddr;
+       iphdr->daddr.ip = iph->daddr;
+}
+
+/* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6.
+ * IPv6 requires some extra work, as finding proper header position,
+ * depend on the IPv6 extension headers.
+ */
+static inline void
+ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
 {
 #ifdef CONFIG_IP_VS_IPV6
        if (af == AF_INET6) {
-               const struct ipv6hdr *iph = nh;
-               iphdr->len = sizeof(struct ipv6hdr);
-               iphdr->protocol = iph->nexthdr;
+               const struct ipv6hdr *iph =
+                       (struct ipv6hdr *)skb_network_header(skb);
                iphdr->saddr.in6 = iph->saddr;
                iphdr->daddr.in6 = iph->daddr;
+               /* ipv6_find_hdr() updates len, flags, thoff_reasm */
+               iphdr->thoff_reasm = 0;
+               iphdr->len       = 0;
+               iphdr->flags     = 0;
+               iphdr->protocol  = ipv6_find_hdr(skb, &iphdr->len, -1,
+                                                &iphdr->fragoffs,
+                                                &iphdr->flags);
+               /* get proto from re-assembled packet and it's offset */
+               if (skb_nfct_reasm(skb))
+                       iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
+                                                       &iphdr->thoff_reasm,
+                                                       -1, NULL, NULL);
+
        } else
 #endif
        {
-               const struct iphdr *iph = nh;
-               iphdr->len = iph->ihl * 4;
-               iphdr->protocol = iph->protocol;
+               const struct iphdr *iph =
+                       (struct iphdr *)skb_network_header(skb);
+               iphdr->len      = iph->ihl * 4;
+               iphdr->fragoffs = 0;
+               iphdr->protocol = iph->protocol;
+               iphdr->saddr.ip = iph->saddr;
+               iphdr->daddr.ip = iph->daddr;
+       }
+}
+
+/* This function is a faster version of ip_vs_fill_iph_skb().
+ * Where we only populate {s,d}addr (and avoid calling ipv6_find_hdr()).
+ * This is used by the some of the ip_vs_*_schedule() functions.
+ * (Mostly done to avoid ABI breakage of external schedulers)
+ */
+static inline void
+ip_vs_fill_iph_addr_only(int af, const struct sk_buff *skb,
+                        struct ip_vs_iphdr *iphdr)
+{
+#ifdef CONFIG_IP_VS_IPV6
+       if (af == AF_INET6) {
+               const struct ipv6hdr *iph =
+                       (struct ipv6hdr *)skb_network_header(skb);
+               iphdr->saddr.in6 = iph->saddr;
+               iphdr->daddr.in6 = iph->daddr;
+       } else
+#endif
+       {
+               const struct iphdr *iph =
+                       (struct iphdr *)skb_network_header(skb);
                iphdr->saddr.ip = iph->saddr;
                iphdr->daddr.ip = iph->daddr;
        }
@@ -165,7 +255,7 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
        int len;
 #ifdef CONFIG_IP_VS_IPV6
        if (af == AF_INET6)
-               len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6]",
+               len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6c]",
                               &addr->in6) + 1;
        else
 #endif
@@ -398,27 +488,26 @@ struct ip_vs_protocol {
 
        int (*conn_schedule)(int af, struct sk_buff *skb,
                             struct ip_vs_proto_data *pd,
-                            int *verdict, struct ip_vs_conn **cpp);
+                            int *verdict, struct ip_vs_conn **cpp,
+                            struct ip_vs_iphdr *iph);
 
        struct ip_vs_conn *
        (*conn_in_get)(int af,
                       const struct sk_buff *skb,
                       const struct ip_vs_iphdr *iph,
-                      unsigned int proto_off,
                       int inverse);
 
        struct ip_vs_conn *
        (*conn_out_get)(int af,
                        const struct sk_buff *skb,
                        const struct ip_vs_iphdr *iph,
-                       unsigned int proto_off,
                        int inverse);
 
-       int (*snat_handler)(struct sk_buff *skb,
-                           struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+       int (*snat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                           struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
 
-       int (*dnat_handler)(struct sk_buff *skb,
-                           struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+       int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                           struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
 
        int (*csum_check)(int af, struct sk_buff *skb,
                          struct ip_vs_protocol *pp);
@@ -518,7 +607,7 @@ struct ip_vs_conn {
           NF_ACCEPT can be returned when destination is local.
         */
        int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp,
-                          struct ip_vs_protocol *pp);
+                          struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
 
        /* Note: we can group the following members into a structure,
           in order to save more space, and the following members are
@@ -769,13 +858,11 @@ struct ip_vs_app {
 
        struct ip_vs_conn *
        (*conn_in_get)(const struct sk_buff *skb, struct ip_vs_app *app,
-                      const struct iphdr *iph, unsigned int proto_off,
-                      int inverse);
+                      const struct iphdr *iph, int inverse);
 
        struct ip_vs_conn *
        (*conn_out_get)(const struct sk_buff *skb, struct ip_vs_app *app,
-                       const struct iphdr *iph, unsigned int proto_off,
-                       int inverse);
+                       const struct iphdr *iph, int inverse);
 
        int (*state_transition)(struct ip_vs_conn *cp, int direction,
                                const struct sk_buff *skb,
@@ -1074,14 +1161,12 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
 
 struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
                                            const struct ip_vs_iphdr *iph,
-                                           unsigned int proto_off,
                                            int inverse);
 
 struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
 
 struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
                                             const struct ip_vs_iphdr *iph,
-                                            unsigned int proto_off,
                                             int inverse);
 
 /* put back the conn without restarting its timer */
@@ -1254,9 +1339,10 @@ extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
 extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
 extern struct ip_vs_conn *
 ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
-              struct ip_vs_proto_data *pd, int *ignored);
+              struct ip_vs_proto_data *pd, int *ignored,
+              struct ip_vs_iphdr *iph);
 extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
-                       struct ip_vs_proto_data *pd);
+                       struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph);
 
 extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
 
@@ -1315,33 +1401,38 @@ extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
 /*
  *     Various IPVS packet transmitters (from ip_vs_xmit.c)
  */
-extern int ip_vs_null_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_bypass_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_nat_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_tunnel_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_dr_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_icmp_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
- int offset, unsigned int hooknum);
+extern int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+                          struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+                            struct ip_vs_protocol *pp,
+                            struct ip_vs_iphdr *iph);
+extern int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+                         struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+                            struct ip_vs_protocol *pp,
+                            struct ip_vs_iphdr *iph);
+extern int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+                        struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+                          struct ip_vs_protocol *pp, int offset,
+                          unsigned int hooknum, struct ip_vs_iphdr *iph);
 extern void ip_vs_dst_reset(struct ip_vs_dest *dest);
 
 #ifdef CONFIG_IP_VS_IPV6
-extern int ip_vs_bypass_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_nat_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_tunnel_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_dr_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_icmp_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
- int offset, unsigned int hooknum);
+extern int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+                               struct ip_vs_protocol *pp,
+                               struct ip_vs_iphdr *iph);
+extern int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+                            struct ip_vs_protocol *pp,
+                            struct ip_vs_iphdr *iph);
+extern int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+                               struct ip_vs_protocol *pp,
+                               struct ip_vs_iphdr *iph);
+extern int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+                           struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+                             struct ip_vs_protocol *pp, int offset,
+                             unsigned int hooknum, struct ip_vs_iphdr *iph);
 #endif
 
 #ifdef CONFIG_SYSCTL
index ddc077c51f324d74e248fada33fd152238cf5337..21947cf4fa4678f5cb301ec29ddb65b74492a6d6 100644 (file)
@@ -48,25 +48,27 @@ struct ip_tunnel_prl_entry {
        struct rcu_head                 rcu_head;
 };
 
-#define __IPTUNNEL_XMIT(stats1, stats2) do {                           \
-       int err;                                                        \
-       int pkt_len = skb->len - skb_transport_offset(skb);             \
-                                                                       \
-       skb->ip_summed = CHECKSUM_NONE;                                 \
-       ip_select_ident(iph, &rt->dst, NULL);                           \
-                                                                       \
-       err = ip_local_out(skb);                                        \
-       if (likely(net_xmit_eval(err) == 0)) {                          \
-               u64_stats_update_begin(&(stats1)->syncp);               \
-               (stats1)->tx_bytes += pkt_len;                          \
-               (stats1)->tx_packets++;                                 \
-               u64_stats_update_end(&(stats1)->syncp);                 \
-       } else {                                                        \
-               (stats2)->tx_errors++;                                  \
-               (stats2)->tx_aborted_errors++;                          \
-       }                                                               \
-} while (0)
+static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       int err;
+       struct iphdr *iph = ip_hdr(skb);
+       int pkt_len = skb->len - skb_transport_offset(skb);
+       struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
 
-#define IPTUNNEL_XMIT() __IPTUNNEL_XMIT(txq, stats)
+       nf_reset(skb);
+       skb->ip_summed = CHECKSUM_NONE;
+       ip_select_ident(iph, skb_dst(skb), NULL);
+
+       err = ip_local_out(skb);
+       if (likely(net_xmit_eval(err) == 0)) {
+               u64_stats_update_begin(&tstats->syncp);
+               tstats->tx_bytes += pkt_len;
+               tstats->tx_packets++;
+               u64_stats_update_end(&tstats->syncp);
+       } else {
+               dev->stats.tx_errors++;
+               dev->stats.tx_aborted_errors++;
+       }
+}
 
 #endif
index 979bf6c131412be9a4662d4738056feb91a26272..5af66b26ebdd6379ce34ae1a914c3c71a2ce5f32 100644 (file)
@@ -271,6 +271,15 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
 
 extern bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb);
 
+static inline bool ipv6_accept_ra(struct inet6_dev *idev)
+{
+       /* If forwarding is enabled, RA are not accepted unless the special
+        * hybrid mode (accept_ra=2) is enabled.
+        */
+       return idev->cnf.forwarding ? idev->cnf.accept_ra == 2 :
+           idev->cnf.accept_ra;
+}
+
 #if IS_ENABLED(CONFIG_IPV6)
 static inline int ip6_frag_nqueues(struct net *net)
 {
@@ -630,6 +639,16 @@ extern int                 ipv6_skip_exthdr(const struct sk_buff *, int start,
 
 extern bool                    ipv6_ext_hdr(u8 nexthdr);
 
+enum {
+       IP6_FH_F_FRAG           = (1 << 0),
+       IP6_FH_F_AUTH           = (1 << 1),
+       IP6_FH_F_SKIP_RH        = (1 << 2),
+};
+
+/* find specified header and get offset to it */
+extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+                        int target, unsigned short *fragoff, int *fragflg);
+
 extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
 
 extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
index 95e646641184a3cdd2b32255822490683ea4f819..c5a43f56b79690104c94811bfa8f83719bf1aaab 100644 (file)
@@ -23,6 +23,7 @@
 #endif
 #include <net/netns/xfrm.h>
 
+struct user_namespace;
 struct proc_dir_entry;
 struct net_device;
 struct sock;
@@ -53,6 +54,8 @@ struct net {
        struct list_head        cleanup_list;   /* namespaces on death row */
        struct list_head        exit_list;      /* Use only net_mutex */
 
+       struct user_namespace   *user_ns;       /* Owning user namespace */
+
        struct proc_dir_entry   *proc_net;
        struct proc_dir_entry   *proc_net_stat;
 
@@ -126,16 +129,21 @@ struct net {
 /* Init's network namespace */
 extern struct net init_net;
 
-#ifdef CONFIG_NET
-extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
-
-#else /* CONFIG_NET */
-static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
+#ifdef CONFIG_NET_NS
+extern struct net *copy_net_ns(unsigned long flags,
+       struct user_namespace *user_ns, struct net *old_net);
+
+#else /* CONFIG_NET_NS */
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+static inline struct net *copy_net_ns(unsigned long flags,
+       struct user_namespace *user_ns, struct net *old_net)
 {
-       /* There is nothing to copy so this is a noop */
-       return net_ns;
+       if (flags & CLONE_NEWNET)
+               return ERR_PTR(-EINVAL);
+       return old_net;
 }
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET_NS */
 
 
 extern struct list_head net_namespace_list;
index f1494feba79fa966b6924287f6cc095b893118ae..caca0c4d6b4bf4c606438df0a3de24369ffb4738 100644 (file)
@@ -182,7 +182,7 @@ __nf_conntrack_find(struct net *net, u16 zone,
 
 extern int nf_conntrack_hash_check_insert(struct nf_conn *ct);
 extern void nf_ct_delete_from_lists(struct nf_conn *ct);
-extern void nf_ct_insert_dying_list(struct nf_conn *ct);
+extern void nf_ct_dying_timeout(struct nf_conn *ct);
 
 extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report);
 
index bd8eea720f2ed0c3e0b61de6b03cb36035ff61cf..ad14a799fd2e50b153e47e80a9cd6fbc4235be7f 100644 (file)
@@ -68,4 +68,19 @@ static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
 #endif
 }
 
+static inline bool nf_nat_oif_changed(unsigned int hooknum,
+                                     enum ip_conntrack_info ctinfo,
+                                     struct nf_conn_nat *nat,
+                                     const struct net_device *out)
+{
+#if IS_ENABLED(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+    IS_ENABLED(CONFIG_IP6_NF_TARGET_MASQUERADE)
+       return nat->masq_index && hooknum == NF_INET_POST_ROUTING &&
+              CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL &&
+              nat->masq_index != out->ifindex;
+#else
+       return false;
+#endif
+}
+
 #endif
index 252fd1010b77c090766eab54ff02dd60197edc1b..fb1c0be38b6d4332b6bb5645efde17c68052342f 100644 (file)
@@ -21,14 +21,10 @@ struct nf_queue_entry {
 struct nf_queue_handler {
        int                     (*outfn)(struct nf_queue_entry *entry,
                                         unsigned int queuenum);
-       char                    *name;
 };
 
-extern int nf_register_queue_handler(u_int8_t pf,
-                                    const struct nf_queue_handler *qh);
-extern int nf_unregister_queue_handler(u_int8_t pf,
-                                      const struct nf_queue_handler *qh);
-extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
+void nf_register_queue_handler(const struct nf_queue_handler *qh);
+void nf_unregister_queue_handler(void);
 extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
 
 #endif /* _NF_QUEUE_H */
index 5e5eb1f9f14b8ca58f222c8397d6a403e3e2d8df..3573a81815ad9e0efb6ceb721eb066d3726419f0 100644 (file)
@@ -62,6 +62,9 @@ struct netns_sctp {
        /* Whether Cookie Preservative is enabled(1) or not(0) */
        int cookie_preserve_enable;
 
+       /* The namespace default hmac alg */
+       char *sctp_hmac_alg;
+
        /* Valid.Cookie.Life        - 60  seconds  */
        unsigned int valid_cookie_life;
 
index 929528c73fe8454a1dd34da7efbbc6d1fd8677fd..047c0476c0a095c2b271713ca232f7099564558b 100644 (file)
 #define _PROTOCOL_H
 
 #include <linux/in6.h>
+#include <linux/skbuff.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <linux/ipv6.h>
 #endif
+#include <linux/netdevice.h>
 
 /* This is one larger than the largest protocol value that can be
  * found in an ipv4 or ipv6 header.  Since in both cases the protocol
@@ -40,12 +42,6 @@ struct net_protocol {
        void                    (*early_demux)(struct sk_buff *skb);
        int                     (*handler)(struct sk_buff *skb);
        void                    (*err_handler)(struct sk_buff *skb, u32 info);
-       int                     (*gso_send_check)(struct sk_buff *skb);
-       struct sk_buff         *(*gso_segment)(struct sk_buff *skb,
-                                              netdev_features_t features);
-       struct sk_buff        **(*gro_receive)(struct sk_buff **head,
-                                              struct sk_buff *skb);
-       int                     (*gro_complete)(struct sk_buff *skb);
        unsigned int            no_policy:1,
                                netns_ok:1;
 };
@@ -60,23 +56,20 @@ struct inet6_protocol {
                               struct inet6_skb_parm *opt,
                               u8 type, u8 code, int offset,
                               __be32 info);
-
-       int     (*gso_send_check)(struct sk_buff *skb);
-       struct sk_buff *(*gso_segment)(struct sk_buff *skb,
-                                      netdev_features_t features);
-       struct sk_buff **(*gro_receive)(struct sk_buff **head,
-                                       struct sk_buff *skb);
-       int     (*gro_complete)(struct sk_buff *skb);
-
        unsigned int    flags;  /* INET6_PROTO_xxx */
 };
 
 #define INET6_PROTO_NOPOLICY   0x1
 #define INET6_PROTO_FINAL      0x2
-/* This should be set for any extension header which is compatible with GSO. */
-#define INET6_PROTO_GSO_EXTHDR 0x4
 #endif
 
+struct net_offload {
+       struct offload_callbacks callbacks;
+       unsigned int             flags; /* Flags used by IPv6 for now */
+};
+/* This should be set for any extension header which is compatible with GSO. */
+#define INET6_PROTO_GSO_EXTHDR 0x1
+
 /* This is used to register socket interfaces for IP protocols.  */
 struct inet_protosw {
        struct list_head list;
@@ -96,6 +89,8 @@ struct inet_protosw {
 #define INET_PROTOSW_ICSK      0x04  /* Is this an inet_connection_sock? */
 
 extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS];
 
 #if IS_ENABLED(CONFIG_IPV6)
 extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
@@ -103,6 +98,8 @@ extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
 
 extern int     inet_add_protocol(const struct net_protocol *prot, unsigned char num);
 extern int     inet_del_protocol(const struct net_protocol *prot, unsigned char num);
+extern int     inet_add_offload(const struct net_offload *prot, unsigned char num);
+extern int     inet_del_offload(const struct net_offload *prot, unsigned char num);
 extern void    inet_register_protosw(struct inet_protosw *p);
 extern void    inet_unregister_protosw(struct inet_protosw *p);
 
@@ -112,5 +109,7 @@ extern int  inet6_del_protocol(const struct inet6_protocol *prot, unsigned char n
 extern int     inet6_register_protosw(struct inet_protosw *p);
 extern void    inet6_unregister_protosw(struct inet_protosw *p);
 #endif
+extern int     inet6_add_offload(const struct net_offload *prot, unsigned char num);
+extern int     inet6_del_offload(const struct net_offload *prot, unsigned char num);
 
 #endif /* _PROTOCOL_H */
index b01d8dd9ee7ce99eb1bf702f00007ae456f28c16..a51dbd17c2de0cede7d134667e641477030519b0 100644 (file)
@@ -49,13 +49,16 @@ struct request_sock_ops {
                                           struct request_sock *req);
 };
 
+extern int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req);
+
 /* struct request_sock - mini sock to represent a connection request
  */
 struct request_sock {
        struct request_sock             *dl_next; /* Must be first member! */
        u16                             mss;
-       u8                              retrans;
-       u8                              cookie_ts; /* syncookie: encode tcpopts in timestamp */
+       u8                              num_retrans; /* number of retransmits */
+       u8                              cookie_ts:1; /* syncookie: encode tcpopts in timestamp */
+       u8                              num_timeout:7; /* number of timeouts */
        /* The following two fields can be easily recomputed I think -AK */
        u32                             window_clamp; /* window clamp at creation time */
        u32                             rcv_wnd;          /* rcv_wnd offered first time */
@@ -231,7 +234,7 @@ static inline int reqsk_queue_removed(struct request_sock_queue *queue,
 {
        struct listen_sock *lopt = queue->listen_opt;
 
-       if (req->retrans == 0)
+       if (req->num_timeout == 0)
                --lopt->qlen_young;
 
        return --lopt->qlen;
@@ -269,7 +272,8 @@ static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
        struct listen_sock *lopt = queue->listen_opt;
 
        req->expires = jiffies + timeout;
-       req->retrans = 0;
+       req->num_retrans = 0;
+       req->num_timeout = 0;
        req->sk = NULL;
        req->dl_next = lopt->syn_table[hash];
 
index bc40b633a5c4dc0e763c5c8c4ff123135160dc04..2ea40c1b5e009746dacb8f146fdcc37309aa7ff3 100644 (file)
@@ -198,10 +198,13 @@ struct in_ifaddr;
 extern void fib_add_ifaddr(struct in_ifaddr *);
 extern void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
 
-static inline void ip_rt_put(struct rtable * rt)
+static inline void ip_rt_put(struct rtable *rt)
 {
-       if (rt)
-               dst_release(&rt->dst);
+       /* dst_release() accepts a NULL parameter.
+        * We rely on dst being first structure in struct rtable
+        */
+       BUILD_BUG_ON(offsetof(struct rtable, dst) != 0);
+       dst_release(&rt->dst);
 }
 
 #define IPTOS_RT_MASK  (IPTOS_TOS_MASK & ~3)
index 6b00c4fc4291f1704e439e4a5db217b6f0a3db2d..5a15fabd6a750eb2fca1e832285a5de0179a5085 100644 (file)
@@ -125,7 +125,7 @@ extern void rtnl_af_unregister(struct rtnl_af_ops *ops);
 
 
 extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
-extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
+extern struct net_device *rtnl_create_link(struct net *net,
        char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]);
 extern int rtnl_configure_link(struct net_device *dev,
                               const struct ifinfomsg *ifm);
index 712b3bebeda78dbb2d3dbb2387fd15f3dd6b82ac..35247271e5571153110fa7759e6c24c13c1114aa 100644 (file)
@@ -130,8 +130,6 @@ typedef union {
        __be16 err;
        sctp_state_t state;
        sctp_event_timeout_t to;
-       unsigned long zero;
-       void *ptr;
        struct sctp_chunk *chunk;
        struct sctp_association *asoc;
        struct sctp_transport *transport;
@@ -154,23 +152,15 @@ typedef union {
  * which takes an __s32 and returns a sctp_arg_t containing the
  * __s32.  So, after foo = SCTP_I32(arg), foo.i32 == arg.
  */
-static inline sctp_arg_t SCTP_NULL(void)
-{
-       sctp_arg_t retval; retval.ptr = NULL; return retval;
-}
-static inline sctp_arg_t SCTP_NOFORCE(void)
-{
-       sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 0; return retval;
-}
-static inline sctp_arg_t SCTP_FORCE(void)
-{
-       sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 1; return retval;
-}
 
 #define SCTP_ARG_CONSTRUCTOR(name, type, elt) \
 static inline sctp_arg_t       \
 SCTP_## name (type arg)                \
-{ sctp_arg_t retval = {.zero = 0UL}; retval.elt = arg; return retval; }
+{ sctp_arg_t retval;\
+  memset(&retval, 0, sizeof(sctp_arg_t));\
+  retval.elt = arg;\
+  return retval;\
+}
 
 SCTP_ARG_CONSTRUCTOR(I32,      __s32, i32)
 SCTP_ARG_CONSTRUCTOR(U32,      __u32, u32)
@@ -181,7 +171,6 @@ SCTP_ARG_CONSTRUCTOR(ERROR,     int, error)
 SCTP_ARG_CONSTRUCTOR(PERR,      __be16, err)   /* protocol error */
 SCTP_ARG_CONSTRUCTOR(STATE,    sctp_state_t, state)
 SCTP_ARG_CONSTRUCTOR(TO,       sctp_event_timeout_t, to)
-SCTP_ARG_CONSTRUCTOR(PTR,      void *, ptr)
 SCTP_ARG_CONSTRUCTOR(CHUNK,    struct sctp_chunk *, chunk)
 SCTP_ARG_CONSTRUCTOR(ASOC,     struct sctp_association *, asoc)
 SCTP_ARG_CONSTRUCTOR(TRANSPORT,        struct sctp_transport *, transport)
@@ -192,6 +181,23 @@ SCTP_ARG_CONSTRUCTOR(PACKET,       struct sctp_packet *, packet)
 SCTP_ARG_CONSTRUCTOR(SACKH,    sctp_sackhdr_t *, sackh)
 SCTP_ARG_CONSTRUCTOR(DATAMSG,  struct sctp_datamsg *, msg)
 
+static inline sctp_arg_t SCTP_FORCE(void)
+{
+       return SCTP_I32(1);
+}
+
+static inline sctp_arg_t SCTP_NOFORCE(void)
+{
+       return SCTP_I32(0);
+}
+
+static inline sctp_arg_t SCTP_NULL(void)
+{
+       sctp_arg_t retval;
+       memset(&retval, 0, sizeof(sctp_arg_t));
+       return retval;
+}
+
 typedef struct {
        sctp_arg_t obj;
        sctp_verb_t verb;
index d053d2e9987613cea680ea433c3e3ae54b2906cf..c29707d654c065c3b7470166c6318e06137580e6 100644 (file)
@@ -312,14 +312,6 @@ enum { SCTP_MAX_GABS = 16 };
                                 * functions simpler to write.
                                 */
 
-#if defined (CONFIG_SCTP_HMAC_MD5)
-#define SCTP_COOKIE_HMAC_ALG "hmac(md5)"
-#elif defined (CONFIG_SCTP_HMAC_SHA1)
-#define SCTP_COOKIE_HMAC_ALG "hmac(sha1)"
-#else
-#define SCTP_COOKIE_HMAC_ALG NULL
-#endif
-
 /* These return values describe the success or failure of a number of
  * routines which form the lower interface to SCTP_outqueue.
  */
index 9c6414f553f91f2256698323ea5d8ec72db4e868..7fdf298a47efc1d18794661b652598cf960c7df2 100644 (file)
@@ -272,6 +272,18 @@ struct sctp_mib {
         unsigned long   mibs[SCTP_MIB_MAX];
 };
 
+/* helper function to track stats about max rto and related transport */
+static inline void sctp_max_rto(struct sctp_association *asoc,
+                               struct sctp_transport *trans)
+{
+       if (asoc->stats.max_obs_rto < (__u64)trans->rto) {
+               asoc->stats.max_obs_rto = trans->rto;
+               memset(&asoc->stats.obs_rto_ipaddr, 0,
+                       sizeof(struct sockaddr_storage));
+               memcpy(&asoc->stats.obs_rto_ipaddr, &trans->ipaddr,
+                       trans->af_specific->sockaddr_len);
+       }
+}
 
 /* Print debugging messages.  */
 #if SCTP_DEBUG
index b5887e1677e4e421479919399b945844133595af..2a82d1384706c61a6757db53edf8d81a53cbc7de 100644 (file)
@@ -234,6 +234,8 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
 struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *,
                                   const struct sctp_chunk *,
                                   struct sctp_paramhdr *);
+struct sctp_chunk *sctp_make_violation_max_retrans(const struct sctp_association *,
+                                                  const struct sctp_chunk *);
 struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
                                  const struct sctp_transport *);
 struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
index 64158aa1bb5f604aad0a68b172c2a1a674acca38..fdeb85a970fc846f81f53798129d12446f0318a4 100644 (file)
@@ -177,6 +177,7 @@ struct sctp_sock {
 
        /* Access to HMAC transform. */
        struct crypto_hash *hmac;
+       char *sctp_hmac_alg;
 
        /* What is our base endpointer? */
        struct sctp_endpoint *ep;
@@ -948,6 +949,8 @@ struct sctp_transport {
 
        /* 64-bit random number sent with heartbeat. */
        __u64 hb_nonce;
+
+       struct rcu_head rcu;
 };
 
 struct sctp_transport *sctp_transport_new(struct net *, const union sctp_addr *,
@@ -1311,6 +1314,40 @@ struct sctp_inithdr_host {
        __u32 initial_tsn;
 };
 
+/* SCTP_GET_ASSOC_STATS counters */
+struct sctp_priv_assoc_stats {
+       /* Maximum observed rto in the association during subsequent
+        * observations. Value is set to 0 if no RTO measurement took place
+        * The transport where the max_rto was observed is returned in
+        * obs_rto_ipaddr
+        */
+       struct sockaddr_storage obs_rto_ipaddr;
+       __u64 max_obs_rto;
+       /* Total In and Out SACKs received and sent */
+       __u64 isacks;
+       __u64 osacks;
+       /* Total In and Out packets received and sent */
+       __u64 opackets;
+       __u64 ipackets;
+       /* Total retransmitted chunks */
+       __u64 rtxchunks;
+       /* TSN received > next expected */
+       __u64 outofseqtsns;
+       /* Duplicate Chunks received */
+       __u64 idupchunks;
+       /* Gap Ack Blocks received */
+       __u64 gapcnt;
+       /* Unordered data chunks sent and received */
+       __u64 ouodchunks;
+       __u64 iuodchunks;
+       /* Ordered data chunks sent and received */
+       __u64 oodchunks;
+       __u64 iodchunks;
+       /* Control chunks sent and received */
+       __u64 octrlchunks;
+       __u64 ictrlchunks;
+};
+
 /* RFC2960
  *
  * 12. Recommended Transmission Control Block (TCB) Parameters
@@ -1829,6 +1866,8 @@ struct sctp_association {
 
        __u8 need_ecne:1,       /* Need to send an ECNE Chunk? */
             temp:1;            /* Is it a temporary association? */
+
+       struct sctp_priv_assoc_stats stats;
 };
 
 
index 2e5ee0d8458d929b284bd1b510dcfbeac1ff4aa3..ff1b8ba73ab10b5678562919e6c43db0f768821b 100644 (file)
@@ -72,7 +72,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev);
 void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
 
 /* Perform partial delivery. */
-void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
+void sctp_ulpq_partial_delivery(struct sctp_ulpq *, gfp_t);
 
 /* Abort the partial delivery. */
 void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t);
index 1b02d7ad453ba9cd0de1e566cd5220bf4333944e..9a0ae091366da42599e0a21dfc66e6fbf4e136ca 100644 (file)
@@ -107,6 +107,7 @@ typedef __s32 sctp_assoc_t;
 #define SCTP_GET_LOCAL_ADDRS   109             /* Get all local address. */
 #define SCTP_SOCKOPT_CONNECTX  110             /* CONNECTX requests. */
 #define SCTP_SOCKOPT_CONNECTX3 111     /* CONNECTX requests (updated) */
+#define SCTP_GET_ASSOC_STATS   112     /* Read only */
 
 /*
  * 5.2.1 SCTP Initiation Structure (SCTP_INIT)
@@ -719,6 +720,32 @@ struct sctp_getaddrs {
        __u8                    addrs[0]; /*output, variable size*/
 };
 
+/* A socket user request obtained via SCTP_GET_ASSOC_STATS that retrieves
+ * association stats. All stats are counts except sas_maxrto and
+ * sas_obs_rto_ipaddr. maxrto is the max observed rto + transport since
+ * the last call. Will return 0 when RTO was not update since last call
+ */
+struct sctp_assoc_stats {
+       sctp_assoc_t    sas_assoc_id;    /* Input */
+                                        /* Transport of observed max RTO */
+       struct sockaddr_storage sas_obs_rto_ipaddr;
+       __u64           sas_maxrto;      /* Maximum Observed RTO for period */
+       __u64           sas_isacks;      /* SACKs received */
+       __u64           sas_osacks;      /* SACKs sent */
+       __u64           sas_opackets;    /* Packets sent */
+       __u64           sas_ipackets;    /* Packets received */
+       __u64           sas_rtxchunks;   /* Retransmitted Chunks */
+       __u64           sas_outofseqtsns;/* TSN received > next expected */
+       __u64           sas_idupchunks;  /* Dups received (ordered+unordered) */
+       __u64           sas_gapcnt;      /* Gap Acknowledgements Received */
+       __u64           sas_ouodchunks;  /* Unordered data chunks sent */
+       __u64           sas_iuodchunks;  /* Unordered data chunks received */
+       __u64           sas_oodchunks;   /* Ordered data chunks sent */
+       __u64           sas_iodchunks;   /* Ordered data chunks received */
+       __u64           sas_octrlchunks; /* Control chunks sent */
+       __u64           sas_ictrlchunks; /* Control chunks received */
+};
+
 /* These are bit fields for msghdr->msg_flags.  See section 5.1.  */
 /* On user space Linux, these live in <bits/socket.h> as an enum.  */
 enum sctp_msg_flags {
index c945fba4f54351475ff2efb989f77b23237f60d4..0a9a01a5b0d7bf9e2f88b3614165dbdcd1920a8c 100644 (file)
@@ -126,12 +126,17 @@ struct sock;
 struct proto;
 struct net;
 
+typedef __u32 __bitwise __portpair;
+typedef __u64 __bitwise __addrpair;
+
 /**
  *     struct sock_common - minimal network layer representation of sockets
  *     @skc_daddr: Foreign IPv4 addr
  *     @skc_rcv_saddr: Bound local IPv4 addr
  *     @skc_hash: hash value used with various protocol lookup tables
  *     @skc_u16hashes: two u16 hash values used by UDP lookup tables
+ *     @skc_dport: placeholder for inet_dport/tw_dport
+ *     @skc_num: placeholder for inet_num/tw_num
  *     @skc_family: network address family
  *     @skc_state: Connection state
  *     @skc_reuse: %SO_REUSEADDR setting
@@ -149,16 +154,29 @@ struct net;
  *     for struct sock and struct inet_timewait_sock.
  */
 struct sock_common {
-       /* skc_daddr and skc_rcv_saddr must be grouped :
-        * cf INET_MATCH() and INET_TW_MATCH()
+       /* skc_daddr and skc_rcv_saddr must be grouped on a 8 bytes aligned
+        * address on 64bit arches : cf INET_MATCH() and INET_TW_MATCH()
         */
-       __be32                  skc_daddr;
-       __be32                  skc_rcv_saddr;
-
+       union {
+               __addrpair      skc_addrpair;
+               struct {
+                       __be32  skc_daddr;
+                       __be32  skc_rcv_saddr;
+               };
+       };
        union  {
                unsigned int    skc_hash;
                __u16           skc_u16hashes[2];
        };
+       /* skc_dport && skc_num must be grouped as well */
+       union {
+               __portpair      skc_portpair;
+               struct {
+                       __be16  skc_dport;
+                       __u16   skc_num;
+               };
+       };
+
        unsigned short          skc_family;
        volatile unsigned char  skc_state;
        unsigned char           skc_reuse;
index 6feeccd83dd7557abd30e32c0547f483b79bd238..3202bde2a741d22f36f369998c93420a54a0ea38 100644 (file)
@@ -369,7 +369,6 @@ extern void tcp_shutdown (struct sock *sk, int how);
 extern void tcp_v4_early_demux(struct sk_buff *skb);
 extern int tcp_v4_rcv(struct sk_buff *skb);
 
-extern struct inet_peer *tcp_v4_get_peer(struct sock *sk);
 extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
 extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                       size_t size);
index 6f0ba01afe7315d443a0aad152a9df2d5a22abf6..63445ede48bb7fd04b175c111935fb77464568b6 100644 (file)
@@ -1351,7 +1351,7 @@ struct xfrm6_tunnel {
 };
 
 extern void xfrm_init(void);
-extern void xfrm4_init(int rt_hash_size);
+extern void xfrm4_init(void);
 extern int xfrm_state_init(struct net *net);
 extern void xfrm_state_fini(struct net *net);
 extern void xfrm4_state_init(void);
index 88fae8d2015471885972da8407d0077106b527cc..55367b04dc9445e142369e98d2134d459eb5ef83 100644 (file)
@@ -135,6 +135,8 @@ struct scsi_device {
                                     * because we did a bus reset. */
        unsigned use_10_for_rw:1; /* first try 10-byte read / write */
        unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+       unsigned no_report_opcodes:1;   /* no REPORT SUPPORTED OPERATION CODES */
+       unsigned no_write_same:1;       /* no WRITE SAME command */
        unsigned skip_ms_page_8:1;      /* do not use MODE SENSE page 0x08 */
        unsigned skip_ms_page_3f:1;     /* do not use MODE SENSE page 0x3f */
        unsigned skip_vpd_pages:1;      /* do not read VPD pages */
@@ -362,6 +364,8 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
                                int retries, struct scsi_sense_hdr *sshdr);
 extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf,
                             int buf_len);
+extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+                             unsigned int len, unsigned char opcode);
 extern int scsi_device_set_state(struct scsi_device *sdev,
                                 enum scsi_device_state state);
 extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
index bc056687f647f7aa9965d5ec4b297bbe9459e557..93896ad1fcdd70164c4254bd792d9b10da992b68 100644 (file)
@@ -132,6 +132,7 @@ struct snd_card {
        int shutdown;                   /* this card is going down */
        int free_on_last_close;         /* free in context of file_release */
        wait_queue_head_t shutdown_sleep;
+       atomic_t refcount;              /* refcount for disconnection */
        struct device *dev;             /* device assigned to this card */
        struct device *card_dev;        /* cardX object for sysfs */
 
@@ -189,6 +190,7 @@ struct snd_minor {
        const struct file_operations *f_ops;    /* file operations */
        void *private_data;             /* private data for f_ops->open */
        struct device *dev;             /* device for sysfs */
+       struct snd_card *card_ptr;      /* assigned card instance */
 };
 
 /* return a device pointer linked to each sound device as a parent */
@@ -295,6 +297,7 @@ int snd_card_info_done(void);
 int snd_component_add(struct snd_card *card, const char *component);
 int snd_card_file_add(struct snd_card *card, struct file *file);
 int snd_card_file_remove(struct snd_card *card, struct file *file);
+void snd_card_unref(struct snd_card *card);
 
 #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr))
 
index 9391706e92541d2b5d865610a88525bf8215a599..d6fd8e5b14b76c41bfd532c3fa86255e4e92b0f3 100644 (file)
@@ -36,6 +36,7 @@
        {(unsigned long)__GFP_RECLAIMABLE,      "GFP_RECLAIMABLE"},     \
        {(unsigned long)__GFP_MOVABLE,          "GFP_MOVABLE"},         \
        {(unsigned long)__GFP_NOTRACK,          "GFP_NOTRACK"},         \
+       {(unsigned long)__GFP_NO_KSWAPD,        "GFP_NO_KSWAPD"},       \
        {(unsigned long)__GFP_OTHER_NODE,       "GFP_OTHER_NODE"}       \
        ) : "GFP_NOWAIT"
 
index 15ba03bdd7c69e9b4426aa3396ac772512b3e163..d06b6da5c1e3e146d500bae9b012b809d831cb25 100644 (file)
@@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd,
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);
 DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin);
 
+TRACE_EVENT(xen_mmu_flush_tlb_all,
+           TP_PROTO(int x),
+           TP_ARGS(x),
+           TP_STRUCT__entry(__array(char, x, 0)),
+           TP_fast_assign((void)x),
+           TP_printk("%s", "")
+       );
+
 TRACE_EVENT(xen_mmu_flush_tlb,
            TP_PROTO(int x),
            TP_ARGS(x),
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..486f0af73c39e05aabb8cae5650dfab9ba10ac6f 100644 (file)
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here, but the file must not be empty or patch
+ * will delete it.
+ */
index b1bea03274d5dd0ca36d31e90b361d0dc63225ec..2d32d073a6f9e4275d47c27cbd63b169a3267b9a 100644 (file)
@@ -43,6 +43,7 @@
 /* Socket filtering */
 #define SO_ATTACH_FILTER       26
 #define SO_DETACH_FILTER       27
+#define SO_GET_FILTER          SO_ATTACH_FILTER
 
 #define SO_PEERNAME            28
 #define SO_TIMESTAMP           29
index aafaa5aa54d46bb9a93a8137a22344408298223f..d40942cfc627f43b4b0da73a925d72264f778be0 100644 (file)
@@ -1 +1,9 @@
 # UAPI Header export list
+header-y += audio.h
+header-y += ca.h
+header-y += dmx.h
+header-y += frontend.h
+header-y += net.h
+header-y += osd.h
+header-y += version.h
+header-y += video.h
diff --git a/include/uapi/linux/dvb/audio.h b/include/uapi/linux/dvb/audio.h
new file mode 100644 (file)
index 0000000..d47bccd
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * audio.h
+ *
+ * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
+ *                  & Marcus Metzler <marcus@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Lesser Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVBAUDIO_H_
+#define _DVBAUDIO_H_
+
+#include <linux/types.h>
+
+typedef enum {
+       AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
+       AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */
+} audio_stream_source_t;
+
+
+typedef enum {
+       AUDIO_STOPPED,      /* Device is stopped */
+       AUDIO_PLAYING,      /* Device is currently playing */
+       AUDIO_PAUSED        /* Device is paused */
+} audio_play_state_t;
+
+
+typedef enum {
+       AUDIO_STEREO,
+       AUDIO_MONO_LEFT,
+       AUDIO_MONO_RIGHT,
+       AUDIO_MONO,
+       AUDIO_STEREO_SWAPPED
+} audio_channel_select_t;
+
+
+typedef struct audio_mixer {
+       unsigned int volume_left;
+       unsigned int volume_right;
+  // what else do we need? bass, pass-through, ...
+} audio_mixer_t;
+
+
+typedef struct audio_status {
+       int                    AV_sync_state;  /* sync audio and video? */
+       int                    mute_state;     /* audio is muted */
+       audio_play_state_t     play_state;     /* current playback state */
+       audio_stream_source_t  stream_source;  /* current stream source */
+       audio_channel_select_t channel_select; /* currently selected channel */
+       int                    bypass_mode;    /* pass on audio data to */
+       audio_mixer_t          mixer_state;    /* current mixer state */
+} audio_status_t;                              /* separate decoder hardware */
+
+
+typedef
+struct audio_karaoke {  /* if Vocal1 or Vocal2 are non-zero, they get mixed  */
+       int vocal1;    /* into left and right t at 70% each */
+       int vocal2;    /* if both, Vocal1 and Vocal2 are non-zero, Vocal1 gets*/
+       int melody;    /* mixed into the left channel and */
+                      /* Vocal2 into the right channel at 100% each. */
+                      /* if Melody is non-zero, the melody channel gets mixed*/
+} audio_karaoke_t;     /* into left and right  */
+
+
+typedef __u16 audio_attributes_t;
+/*   bits: descr. */
+/*   15-13 audio coding mode (0=ac3, 2=mpeg1, 3=mpeg2ext, 4=LPCM, 6=DTS, */
+/*   12    multichannel extension */
+/*   11-10 audio type (0=not spec, 1=language included) */
+/*    9- 8 audio application mode (0=not spec, 1=karaoke, 2=surround) */
+/*    7- 6 Quantization / DRC (mpeg audio: 1=DRC exists)(lpcm: 0=16bit,  */
+/*    5- 4 Sample frequency fs (0=48kHz, 1=96kHz) */
+/*    2- 0 number of audio channels (n+1 channels) */
+
+
+/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */
+#define AUDIO_CAP_DTS    1
+#define AUDIO_CAP_LPCM   2
+#define AUDIO_CAP_MP1    4
+#define AUDIO_CAP_MP2    8
+#define AUDIO_CAP_MP3   16
+#define AUDIO_CAP_AAC   32
+#define AUDIO_CAP_OGG   64
+#define AUDIO_CAP_SDDS 128
+#define AUDIO_CAP_AC3  256
+
+#define AUDIO_STOP                 _IO('o', 1)
+#define AUDIO_PLAY                 _IO('o', 2)
+#define AUDIO_PAUSE                _IO('o', 3)
+#define AUDIO_CONTINUE             _IO('o', 4)
+#define AUDIO_SELECT_SOURCE        _IO('o', 5)
+#define AUDIO_SET_MUTE             _IO('o', 6)
+#define AUDIO_SET_AV_SYNC          _IO('o', 7)
+#define AUDIO_SET_BYPASS_MODE      _IO('o', 8)
+#define AUDIO_CHANNEL_SELECT       _IO('o', 9)
+#define AUDIO_GET_STATUS           _IOR('o', 10, audio_status_t)
+
+#define AUDIO_GET_CAPABILITIES     _IOR('o', 11, unsigned int)
+#define AUDIO_CLEAR_BUFFER         _IO('o',  12)
+#define AUDIO_SET_ID               _IO('o', 13)
+#define AUDIO_SET_MIXER            _IOW('o', 14, audio_mixer_t)
+#define AUDIO_SET_STREAMTYPE       _IO('o', 15)
+#define AUDIO_SET_EXT_ID           _IO('o', 16)
+#define AUDIO_SET_ATTRIBUTES       _IOW('o', 17, audio_attributes_t)
+#define AUDIO_SET_KARAOKE          _IOW('o', 18, audio_karaoke_t)
+
+/**
+ * AUDIO_GET_PTS
+ *
+ * Read the 33 bit presentation time stamp as defined
+ * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+ *
+ * The PTS should belong to the currently played
+ * frame if possible, but may also be a value close to it
+ * like the PTS of the last decoded frame or the last PTS
+ * extracted by the PES parser.
+ */
+#define AUDIO_GET_PTS              _IOR('o', 19, __u64)
+#define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20)
+
+#endif /* _DVBAUDIO_H_ */
diff --git a/include/uapi/linux/dvb/ca.h b/include/uapi/linux/dvb/ca.h
new file mode 100644 (file)
index 0000000..c18537f
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * ca.h
+ *
+ * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
+ *                  & Marcus Metzler <marcus@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Lesser Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVBCA_H_
+#define _DVBCA_H_
+
+/* slot interface types and info */
+
+typedef struct ca_slot_info {
+       int num;               /* slot number */
+
+       int type;              /* CA interface this slot supports */
+#define CA_CI            1     /* CI high level interface */
+#define CA_CI_LINK       2     /* CI link layer level interface */
+#define CA_CI_PHYS       4     /* CI physical layer level interface */
+#define CA_DESCR         8     /* built-in descrambler */
+#define CA_SC          128     /* simple smart card interface */
+
+       unsigned int flags;
+#define CA_CI_MODULE_PRESENT 1 /* module (or card) inserted */
+#define CA_CI_MODULE_READY   2
+} ca_slot_info_t;
+
+
+/* descrambler types and info */
+
+typedef struct ca_descr_info {
+       unsigned int num;          /* number of available descramblers (keys) */
+       unsigned int type;         /* type of supported scrambling system */
+#define CA_ECD           1
+#define CA_NDS           2
+#define CA_DSS           4
+} ca_descr_info_t;
+
+typedef struct ca_caps {
+       unsigned int slot_num;     /* total number of CA card and module slots */
+       unsigned int slot_type;    /* OR of all supported types */
+       unsigned int descr_num;    /* total number of descrambler slots (keys) */
+       unsigned int descr_type;   /* OR of all supported types */
+} ca_caps_t;
+
+/* a message to/from a CI-CAM */
+typedef struct ca_msg {
+       unsigned int index;
+       unsigned int type;
+       unsigned int length;
+       unsigned char msg[256];
+} ca_msg_t;
+
+typedef struct ca_descr {
+       unsigned int index;
+       unsigned int parity;    /* 0 == even, 1 == odd */
+       unsigned char cw[8];
+} ca_descr_t;
+
+typedef struct ca_pid {
+       unsigned int pid;
+       int index;              /* -1 == disable*/
+} ca_pid_t;
+
+#define CA_RESET          _IO('o', 128)
+#define CA_GET_CAP        _IOR('o', 129, ca_caps_t)
+#define CA_GET_SLOT_INFO  _IOR('o', 130, ca_slot_info_t)
+#define CA_GET_DESCR_INFO _IOR('o', 131, ca_descr_info_t)
+#define CA_GET_MSG        _IOR('o', 132, ca_msg_t)
+#define CA_SEND_MSG       _IOW('o', 133, ca_msg_t)
+#define CA_SET_DESCR      _IOW('o', 134, ca_descr_t)
+#define CA_SET_PID        _IOW('o', 135, ca_pid_t)
+
+#endif
diff --git a/include/uapi/linux/dvb/dmx.h b/include/uapi/linux/dvb/dmx.h
new file mode 100644 (file)
index 0000000..b2a9ad8
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * dmx.h
+ *
+ * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
+ *                  & Ralph  Metzler <ralph@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef _UAPI_DVBDMX_H_
+#define _UAPI_DVBDMX_H_
+
+#include <linux/types.h>
+#ifndef __KERNEL__
+#include <time.h>
+#endif
+
+
+#define DMX_FILTER_SIZE 16
+
+typedef enum
+{
+       DMX_OUT_DECODER, /* Streaming directly to decoder. */
+       DMX_OUT_TAP,     /* Output going to a memory buffer */
+                        /* (to be retrieved via the read command).*/
+       DMX_OUT_TS_TAP,  /* Output multiplexed into a new TS  */
+                        /* (to be retrieved by reading from the */
+                        /* logical DVR device).                 */
+       DMX_OUT_TSDEMUX_TAP /* Like TS_TAP but retrieved from the DMX device */
+} dmx_output_t;
+
+
+typedef enum
+{
+       DMX_IN_FRONTEND, /* Input from a front-end device.  */
+       DMX_IN_DVR       /* Input from the logical DVR device.  */
+} dmx_input_t;
+
+
+typedef enum
+{
+       DMX_PES_AUDIO0,
+       DMX_PES_VIDEO0,
+       DMX_PES_TELETEXT0,
+       DMX_PES_SUBTITLE0,
+       DMX_PES_PCR0,
+
+       DMX_PES_AUDIO1,
+       DMX_PES_VIDEO1,
+       DMX_PES_TELETEXT1,
+       DMX_PES_SUBTITLE1,
+       DMX_PES_PCR1,
+
+       DMX_PES_AUDIO2,
+       DMX_PES_VIDEO2,
+       DMX_PES_TELETEXT2,
+       DMX_PES_SUBTITLE2,
+       DMX_PES_PCR2,
+
+       DMX_PES_AUDIO3,
+       DMX_PES_VIDEO3,
+       DMX_PES_TELETEXT3,
+       DMX_PES_SUBTITLE3,
+       DMX_PES_PCR3,
+
+       DMX_PES_OTHER
+} dmx_pes_type_t;
+
+#define DMX_PES_AUDIO    DMX_PES_AUDIO0
+#define DMX_PES_VIDEO    DMX_PES_VIDEO0
+#define DMX_PES_TELETEXT DMX_PES_TELETEXT0
+#define DMX_PES_SUBTITLE DMX_PES_SUBTITLE0
+#define DMX_PES_PCR      DMX_PES_PCR0
+
+
+typedef struct dmx_filter
+{
+       __u8  filter[DMX_FILTER_SIZE];
+       __u8  mask[DMX_FILTER_SIZE];
+       __u8  mode[DMX_FILTER_SIZE];
+} dmx_filter_t;
+
+
+struct dmx_sct_filter_params
+{
+       __u16          pid;
+       dmx_filter_t   filter;
+       __u32          timeout;
+       __u32          flags;
+#define DMX_CHECK_CRC       1
+#define DMX_ONESHOT         2
+#define DMX_IMMEDIATE_START 4
+#define DMX_KERNEL_CLIENT   0x8000
+};
+
+
+struct dmx_pes_filter_params
+{
+       __u16          pid;
+       dmx_input_t    input;
+       dmx_output_t   output;
+       dmx_pes_type_t pes_type;
+       __u32          flags;
+};
+
+typedef struct dmx_caps {
+       __u32 caps;
+       int num_decoders;
+} dmx_caps_t;
+
+typedef enum {
+       DMX_SOURCE_FRONT0 = 0,
+       DMX_SOURCE_FRONT1,
+       DMX_SOURCE_FRONT2,
+       DMX_SOURCE_FRONT3,
+       DMX_SOURCE_DVR0   = 16,
+       DMX_SOURCE_DVR1,
+       DMX_SOURCE_DVR2,
+       DMX_SOURCE_DVR3
+} dmx_source_t;
+
+struct dmx_stc {
+       unsigned int num;       /* input : which STC? 0..N */
+       unsigned int base;      /* output: divisor for stc to get 90 kHz clock */
+       __u64 stc;              /* output: stc in 'base'*90 kHz units */
+};
+
+
+#define DMX_START                _IO('o', 41)
+#define DMX_STOP                 _IO('o', 42)
+#define DMX_SET_FILTER           _IOW('o', 43, struct dmx_sct_filter_params)
+#define DMX_SET_PES_FILTER       _IOW('o', 44, struct dmx_pes_filter_params)
+#define DMX_SET_BUFFER_SIZE      _IO('o', 45)
+#define DMX_GET_PES_PIDS         _IOR('o', 47, __u16[5])
+#define DMX_GET_CAPS             _IOR('o', 48, dmx_caps_t)
+#define DMX_SET_SOURCE           _IOW('o', 49, dmx_source_t)
+#define DMX_GET_STC              _IOWR('o', 50, struct dmx_stc)
+#define DMX_ADD_PID              _IOW('o', 51, __u16)
+#define DMX_REMOVE_PID           _IOW('o', 52, __u16)
+
+#endif /* _UAPI_DVBDMX_H_ */
diff --git a/include/uapi/linux/dvb/frontend.h b/include/uapi/linux/dvb/frontend.h
new file mode 100644 (file)
index 0000000..c12d452
--- /dev/null
@@ -0,0 +1,516 @@
+/*
+ * frontend.h
+ *
+ * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
+ *                 Ralph  Metzler <ralph@convergence.de>
+ *                 Holger Waechtler <holger@convergence.de>
+ *                 Andre Draszik <ad@convergence.de>
+ *                 for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVBFRONTEND_H_
+#define _DVBFRONTEND_H_
+
+#include <linux/types.h>
+
+typedef enum fe_type {
+       FE_QPSK,
+       FE_QAM,
+       FE_OFDM,
+       FE_ATSC
+} fe_type_t;
+
+
+typedef enum fe_caps {
+       FE_IS_STUPID                    = 0,
+       FE_CAN_INVERSION_AUTO           = 0x1,
+       FE_CAN_FEC_1_2                  = 0x2,
+       FE_CAN_FEC_2_3                  = 0x4,
+       FE_CAN_FEC_3_4                  = 0x8,
+       FE_CAN_FEC_4_5                  = 0x10,
+       FE_CAN_FEC_5_6                  = 0x20,
+       FE_CAN_FEC_6_7                  = 0x40,
+       FE_CAN_FEC_7_8                  = 0x80,
+       FE_CAN_FEC_8_9                  = 0x100,
+       FE_CAN_FEC_AUTO                 = 0x200,
+       FE_CAN_QPSK                     = 0x400,
+       FE_CAN_QAM_16                   = 0x800,
+       FE_CAN_QAM_32                   = 0x1000,
+       FE_CAN_QAM_64                   = 0x2000,
+       FE_CAN_QAM_128                  = 0x4000,
+       FE_CAN_QAM_256                  = 0x8000,
+       FE_CAN_QAM_AUTO                 = 0x10000,
+       FE_CAN_TRANSMISSION_MODE_AUTO   = 0x20000,
+       FE_CAN_BANDWIDTH_AUTO           = 0x40000,
+       FE_CAN_GUARD_INTERVAL_AUTO      = 0x80000,
+       FE_CAN_HIERARCHY_AUTO           = 0x100000,
+       FE_CAN_8VSB                     = 0x200000,
+       FE_CAN_16VSB                    = 0x400000,
+       FE_HAS_EXTENDED_CAPS            = 0x800000,   /* We need more bitspace for newer APIs, indicate this. */
+       FE_CAN_MULTISTREAM              = 0x4000000,  /* frontend supports multistream filtering */
+       FE_CAN_TURBO_FEC                = 0x8000000,  /* frontend supports "turbo fec modulation" */
+       FE_CAN_2G_MODULATION            = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
+       FE_NEEDS_BENDING                = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
+       FE_CAN_RECOVER                  = 0x40000000, /* frontend can recover from a cable unplug automatically */
+       FE_CAN_MUTE_TS                  = 0x80000000  /* frontend can stop spurious TS data output */
+} fe_caps_t;
+
+
+struct dvb_frontend_info {
+       char       name[128];
+       fe_type_t  type;                        /* DEPRECATED. Use DTV_ENUM_DELSYS instead */
+       __u32      frequency_min;
+       __u32      frequency_max;
+       __u32      frequency_stepsize;
+       __u32      frequency_tolerance;
+       __u32      symbol_rate_min;
+       __u32      symbol_rate_max;
+       __u32      symbol_rate_tolerance;       /* ppm */
+       __u32      notifier_delay;              /* DEPRECATED */
+       fe_caps_t  caps;
+};
+
+
+/**
+ *  Check out the DiSEqC bus spec available on http://www.eutelsat.org/ for
+ *  the meaning of this struct...
+ */
+struct dvb_diseqc_master_cmd {
+       __u8 msg [6];   /*  { framing, address, command, data [3] } */
+       __u8 msg_len;   /*  valid values are 3...6  */
+};
+
+
+struct dvb_diseqc_slave_reply {
+       __u8 msg [4];   /*  { framing, data [3] } */
+       __u8 msg_len;   /*  valid values are 0...4, 0 means no msg  */
+       int  timeout;   /*  return from ioctl after timeout ms with */
+};                     /*  errorcode when no message was received  */
+
+
+typedef enum fe_sec_voltage {
+       SEC_VOLTAGE_13,
+       SEC_VOLTAGE_18,
+       SEC_VOLTAGE_OFF
+} fe_sec_voltage_t;
+
+
+typedef enum fe_sec_tone_mode {
+       SEC_TONE_ON,
+       SEC_TONE_OFF
+} fe_sec_tone_mode_t;
+
+
+typedef enum fe_sec_mini_cmd {
+       SEC_MINI_A,
+       SEC_MINI_B
+} fe_sec_mini_cmd_t;
+
+
+/**
+ * enum fe_status - enumerates the possible frontend status
+ * @FE_HAS_SIGNAL:     found something above the noise level
+ * @FE_HAS_CARRIER:    found a DVB signal
+ * @FE_HAS_VITERBI:    FEC is stable
+ * @FE_HAS_SYNC:       found sync bytes
+ * @FE_HAS_LOCK:       everything's working
+ * @FE_TIMEDOUT:       no lock within the last ~2 seconds
+ * @FE_REINIT:         frontend was reinitialized, application is recommended
+ *                     to reset DiSEqC, tone and parameters
+ */
+
+typedef enum fe_status {
+       FE_HAS_SIGNAL           = 0x01,
+       FE_HAS_CARRIER          = 0x02,
+       FE_HAS_VITERBI          = 0x04,
+       FE_HAS_SYNC             = 0x08,
+       FE_HAS_LOCK             = 0x10,
+       FE_TIMEDOUT             = 0x20,
+       FE_REINIT               = 0x40,
+} fe_status_t;
+
+typedef enum fe_spectral_inversion {
+       INVERSION_OFF,
+       INVERSION_ON,
+       INVERSION_AUTO
+} fe_spectral_inversion_t;
+
+
+typedef enum fe_code_rate {
+       FEC_NONE = 0,
+       FEC_1_2,
+       FEC_2_3,
+       FEC_3_4,
+       FEC_4_5,
+       FEC_5_6,
+       FEC_6_7,
+       FEC_7_8,
+       FEC_8_9,
+       FEC_AUTO,
+       FEC_3_5,
+       FEC_9_10,
+       FEC_2_5,
+} fe_code_rate_t;
+
+
+typedef enum fe_modulation {
+       QPSK,
+       QAM_16,
+       QAM_32,
+       QAM_64,
+       QAM_128,
+       QAM_256,
+       QAM_AUTO,
+       VSB_8,
+       VSB_16,
+       PSK_8,
+       APSK_16,
+       APSK_32,
+       DQPSK,
+       QAM_4_NR,
+} fe_modulation_t;
+
+typedef enum fe_transmit_mode {
+       TRANSMISSION_MODE_2K,
+       TRANSMISSION_MODE_8K,
+       TRANSMISSION_MODE_AUTO,
+       TRANSMISSION_MODE_4K,
+       TRANSMISSION_MODE_1K,
+       TRANSMISSION_MODE_16K,
+       TRANSMISSION_MODE_32K,
+       TRANSMISSION_MODE_C1,
+       TRANSMISSION_MODE_C3780,
+} fe_transmit_mode_t;
+
+#if defined(__DVB_CORE__) || !defined (__KERNEL__)
+typedef enum fe_bandwidth {
+       BANDWIDTH_8_MHZ,
+       BANDWIDTH_7_MHZ,
+       BANDWIDTH_6_MHZ,
+       BANDWIDTH_AUTO,
+       BANDWIDTH_5_MHZ,
+       BANDWIDTH_10_MHZ,
+       BANDWIDTH_1_712_MHZ,
+} fe_bandwidth_t;
+#endif
+
+typedef enum fe_guard_interval {
+       GUARD_INTERVAL_1_32,
+       GUARD_INTERVAL_1_16,
+       GUARD_INTERVAL_1_8,
+       GUARD_INTERVAL_1_4,
+       GUARD_INTERVAL_AUTO,
+       GUARD_INTERVAL_1_128,
+       GUARD_INTERVAL_19_128,
+       GUARD_INTERVAL_19_256,
+       GUARD_INTERVAL_PN420,
+       GUARD_INTERVAL_PN595,
+       GUARD_INTERVAL_PN945,
+} fe_guard_interval_t;
+
+
+typedef enum fe_hierarchy {
+       HIERARCHY_NONE,
+       HIERARCHY_1,
+       HIERARCHY_2,
+       HIERARCHY_4,
+       HIERARCHY_AUTO
+} fe_hierarchy_t;
+
+enum fe_interleaving {
+       INTERLEAVING_NONE,
+       INTERLEAVING_AUTO,
+       INTERLEAVING_240,
+       INTERLEAVING_720,
+};
+
+#if defined(__DVB_CORE__) || !defined (__KERNEL__)
+struct dvb_qpsk_parameters {
+       __u32           symbol_rate;  /* symbol rate in Symbols per second */
+       fe_code_rate_t  fec_inner;    /* forward error correction (see above) */
+};
+
+struct dvb_qam_parameters {
+       __u32           symbol_rate; /* symbol rate in Symbols per second */
+       fe_code_rate_t  fec_inner;   /* forward error correction (see above) */
+       fe_modulation_t modulation;  /* modulation type (see above) */
+};
+
+struct dvb_vsb_parameters {
+       fe_modulation_t modulation;  /* modulation type (see above) */
+};
+
+struct dvb_ofdm_parameters {
+       fe_bandwidth_t      bandwidth;
+       fe_code_rate_t      code_rate_HP;  /* high priority stream code rate */
+       fe_code_rate_t      code_rate_LP;  /* low priority stream code rate */
+       fe_modulation_t     constellation; /* modulation type (see above) */
+       fe_transmit_mode_t  transmission_mode;
+       fe_guard_interval_t guard_interval;
+       fe_hierarchy_t      hierarchy_information;
+};
+
+
+struct dvb_frontend_parameters {
+       __u32 frequency;     /* (absolute) frequency in Hz for QAM/OFDM/ATSC */
+                            /* intermediate frequency in kHz for QPSK */
+       fe_spectral_inversion_t inversion;
+       union {
+               struct dvb_qpsk_parameters qpsk;
+               struct dvb_qam_parameters  qam;
+               struct dvb_ofdm_parameters ofdm;
+               struct dvb_vsb_parameters vsb;
+       } u;
+};
+
+struct dvb_frontend_event {
+       fe_status_t status;
+       struct dvb_frontend_parameters parameters;
+};
+#endif
+
+/* S2API Commands */
+#define DTV_UNDEFINED          0
+#define DTV_TUNE               1
+#define DTV_CLEAR              2
+#define DTV_FREQUENCY          3
+#define DTV_MODULATION         4
+#define DTV_BANDWIDTH_HZ       5
+#define DTV_INVERSION          6
+#define DTV_DISEQC_MASTER      7
+#define DTV_SYMBOL_RATE                8
+#define DTV_INNER_FEC          9
+#define DTV_VOLTAGE            10
+#define DTV_TONE               11
+#define DTV_PILOT              12
+#define DTV_ROLLOFF            13
+#define DTV_DISEQC_SLAVE_REPLY 14
+
+/* Basic enumeration set for querying unlimited capabilities */
+#define DTV_FE_CAPABILITY_COUNT        15
+#define DTV_FE_CAPABILITY      16
+#define DTV_DELIVERY_SYSTEM    17
+
+/* ISDB-T and ISDB-Tsb */
+#define DTV_ISDBT_PARTIAL_RECEPTION    18
+#define DTV_ISDBT_SOUND_BROADCASTING   19
+
+#define DTV_ISDBT_SB_SUBCHANNEL_ID     20
+#define DTV_ISDBT_SB_SEGMENT_IDX       21
+#define DTV_ISDBT_SB_SEGMENT_COUNT     22
+
+#define DTV_ISDBT_LAYERA_FEC                   23
+#define DTV_ISDBT_LAYERA_MODULATION            24
+#define DTV_ISDBT_LAYERA_SEGMENT_COUNT         25
+#define DTV_ISDBT_LAYERA_TIME_INTERLEAVING     26
+
+#define DTV_ISDBT_LAYERB_FEC                   27
+#define DTV_ISDBT_LAYERB_MODULATION            28
+#define DTV_ISDBT_LAYERB_SEGMENT_COUNT         29
+#define DTV_ISDBT_LAYERB_TIME_INTERLEAVING     30
+
+#define DTV_ISDBT_LAYERC_FEC                   31
+#define DTV_ISDBT_LAYERC_MODULATION            32
+#define DTV_ISDBT_LAYERC_SEGMENT_COUNT         33
+#define DTV_ISDBT_LAYERC_TIME_INTERLEAVING     34
+
+#define DTV_API_VERSION                35
+
+#define DTV_CODE_RATE_HP       36
+#define DTV_CODE_RATE_LP       37
+#define DTV_GUARD_INTERVAL     38
+#define DTV_TRANSMISSION_MODE  39
+#define DTV_HIERARCHY          40
+
+#define DTV_ISDBT_LAYER_ENABLED        41
+
+#define DTV_STREAM_ID          42
+#define DTV_ISDBS_TS_ID_LEGACY DTV_STREAM_ID
+#define DTV_DVBT2_PLP_ID_LEGACY        43
+
+#define DTV_ENUM_DELSYS                44
+
+/* ATSC-MH */
+#define DTV_ATSCMH_FIC_VER             45
+#define DTV_ATSCMH_PARADE_ID           46
+#define DTV_ATSCMH_NOG                 47
+#define DTV_ATSCMH_TNOG                        48
+#define DTV_ATSCMH_SGN                 49
+#define DTV_ATSCMH_PRC                 50
+#define DTV_ATSCMH_RS_FRAME_MODE       51
+#define DTV_ATSCMH_RS_FRAME_ENSEMBLE   52
+#define DTV_ATSCMH_RS_CODE_MODE_PRI    53
+#define DTV_ATSCMH_RS_CODE_MODE_SEC    54
+#define DTV_ATSCMH_SCCC_BLOCK_MODE     55
+#define DTV_ATSCMH_SCCC_CODE_MODE_A    56
+#define DTV_ATSCMH_SCCC_CODE_MODE_B    57
+#define DTV_ATSCMH_SCCC_CODE_MODE_C    58
+#define DTV_ATSCMH_SCCC_CODE_MODE_D    59
+
+#define DTV_INTERLEAVING                       60
+#define DTV_LNA                                        61
+
+#define DTV_MAX_COMMAND                                DTV_LNA
+
+typedef enum fe_pilot {
+       PILOT_ON,
+       PILOT_OFF,
+       PILOT_AUTO,
+} fe_pilot_t;
+
+typedef enum fe_rolloff {
+       ROLLOFF_35, /* Implied value in DVB-S, default for DVB-S2 */
+       ROLLOFF_20,
+       ROLLOFF_25,
+       ROLLOFF_AUTO,
+} fe_rolloff_t;
+
+typedef enum fe_delivery_system {
+       SYS_UNDEFINED,
+       SYS_DVBC_ANNEX_A,
+       SYS_DVBC_ANNEX_B,
+       SYS_DVBT,
+       SYS_DSS,
+       SYS_DVBS,
+       SYS_DVBS2,
+       SYS_DVBH,
+       SYS_ISDBT,
+       SYS_ISDBS,
+       SYS_ISDBC,
+       SYS_ATSC,
+       SYS_ATSCMH,
+       SYS_DTMB,
+       SYS_CMMB,
+       SYS_DAB,
+       SYS_DVBT2,
+       SYS_TURBO,
+       SYS_DVBC_ANNEX_C,
+} fe_delivery_system_t;
+
+/* backward compatibility */
+#define SYS_DVBC_ANNEX_AC      SYS_DVBC_ANNEX_A
+#define SYS_DMBTH SYS_DTMB /* DMB-TH is legacy name, use DTMB instead */
+
+/* ATSC-MH */
+
+enum atscmh_sccc_block_mode {
+       ATSCMH_SCCC_BLK_SEP      = 0,
+       ATSCMH_SCCC_BLK_COMB     = 1,
+       ATSCMH_SCCC_BLK_RES      = 2,
+};
+
+enum atscmh_sccc_code_mode {
+       ATSCMH_SCCC_CODE_HLF     = 0,
+       ATSCMH_SCCC_CODE_QTR     = 1,
+       ATSCMH_SCCC_CODE_RES     = 2,
+};
+
+enum atscmh_rs_frame_ensemble {
+       ATSCMH_RSFRAME_ENS_PRI   = 0,
+       ATSCMH_RSFRAME_ENS_SEC   = 1,
+};
+
+enum atscmh_rs_frame_mode {
+       ATSCMH_RSFRAME_PRI_ONLY  = 0,
+       ATSCMH_RSFRAME_PRI_SEC   = 1,
+       ATSCMH_RSFRAME_RES       = 2,
+};
+
+enum atscmh_rs_code_mode {
+       ATSCMH_RSCODE_211_187    = 0,
+       ATSCMH_RSCODE_223_187    = 1,
+       ATSCMH_RSCODE_235_187    = 2,
+       ATSCMH_RSCODE_RES        = 3,
+};
+
+#define NO_STREAM_ID_FILTER    (~0U)
+#define LNA_AUTO                (~0U)
+
+struct dtv_cmds_h {
+       char    *name;          /* A display name for debugging purposes */
+
+       __u32   cmd;            /* A unique ID */
+
+       /* Flags */
+       __u32   set:1;          /* Either a set or get property */
+       __u32   buffer:1;       /* Does this property use the buffer? */
+       __u32   reserved:30;    /* Align */
+};
+
+struct dtv_property {
+       __u32 cmd;
+       __u32 reserved[3];
+       union {
+               __u32 data;
+               struct {
+                       __u8 data[32];
+                       __u32 len;
+                       __u32 reserved1[3];
+                       void *reserved2;
+               } buffer;
+       } u;
+       int result;
+} __attribute__ ((packed));
+
+/* num of properties cannot exceed DTV_IOCTL_MAX_MSGS per ioctl */
+#define DTV_IOCTL_MAX_MSGS 64
+
+struct dtv_properties {
+       __u32 num;
+       struct dtv_property *props;
+};
+
+#define FE_SET_PROPERTY                   _IOW('o', 82, struct dtv_properties)
+#define FE_GET_PROPERTY                   _IOR('o', 83, struct dtv_properties)
+
+
+/**
+ * When set, this flag will disable any zigzagging or other "normal" tuning
+ * behaviour. Additionally, there will be no automatic monitoring of the lock
+ * status, and hence no frontend events will be generated. If a frontend device
+ * is closed, this flag will be automatically turned off when the device is
+ * reopened read-write.
+ */
+#define FE_TUNE_MODE_ONESHOT 0x01
+
+
+#define FE_GET_INFO               _IOR('o', 61, struct dvb_frontend_info)
+
+#define FE_DISEQC_RESET_OVERLOAD   _IO('o', 62)
+#define FE_DISEQC_SEND_MASTER_CMD  _IOW('o', 63, struct dvb_diseqc_master_cmd)
+#define FE_DISEQC_RECV_SLAVE_REPLY _IOR('o', 64, struct dvb_diseqc_slave_reply)
+#define FE_DISEQC_SEND_BURST       _IO('o', 65)  /* fe_sec_mini_cmd_t */
+
+#define FE_SET_TONE               _IO('o', 66)  /* fe_sec_tone_mode_t */
+#define FE_SET_VOLTAGE            _IO('o', 67)  /* fe_sec_voltage_t */
+#define FE_ENABLE_HIGH_LNB_VOLTAGE _IO('o', 68)  /* int */
+
+#define FE_READ_STATUS            _IOR('o', 69, fe_status_t)
+#define FE_READ_BER               _IOR('o', 70, __u32)
+#define FE_READ_SIGNAL_STRENGTH    _IOR('o', 71, __u16)
+#define FE_READ_SNR               _IOR('o', 72, __u16)
+#define FE_READ_UNCORRECTED_BLOCKS _IOR('o', 73, __u32)
+
+#define FE_SET_FRONTEND                   _IOW('o', 76, struct dvb_frontend_parameters)
+#define FE_GET_FRONTEND                   _IOR('o', 77, struct dvb_frontend_parameters)
+#define FE_SET_FRONTEND_TUNE_MODE  _IO('o', 81) /* unsigned int */
+#define FE_GET_EVENT              _IOR('o', 78, struct dvb_frontend_event)
+
+#define FE_DISHNETWORK_SEND_LEGACY_CMD _IO('o', 80) /* unsigned int */
+
+#endif /*_DVBFRONTEND_H_*/
diff --git a/include/uapi/linux/dvb/net.h b/include/uapi/linux/dvb/net.h
new file mode 100644 (file)
index 0000000..f451e7e
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * net.h
+ *
+ * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
+ *                  & Ralph  Metzler <ralph@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVBNET_H_
+#define _DVBNET_H_
+
+#include <linux/types.h>
+
+struct dvb_net_if {
+       __u16 pid;
+       __u16 if_num;
+       __u8  feedtype;
+#define DVB_NET_FEEDTYPE_MPE 0 /* multi protocol encapsulation */
+#define DVB_NET_FEEDTYPE_ULE 1 /* ultra lightweight encapsulation */
+};
+
+
+#define NET_ADD_IF    _IOWR('o', 52, struct dvb_net_if)
+#define NET_REMOVE_IF _IO('o', 53)
+#define NET_GET_IF    _IOWR('o', 54, struct dvb_net_if)
+
+
+/* binary compatibility cruft: */
+struct __dvb_net_if_old {
+       __u16 pid;
+       __u16 if_num;
+};
+#define __NET_ADD_IF_OLD _IOWR('o', 52, struct __dvb_net_if_old)
+#define __NET_GET_IF_OLD _IOWR('o', 54, struct __dvb_net_if_old)
+
+
+#endif /*_DVBNET_H_*/
diff --git a/include/uapi/linux/dvb/osd.h b/include/uapi/linux/dvb/osd.h
new file mode 100644 (file)
index 0000000..880e684
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * osd.h
+ *
+ * Copyright (C) 2001 Ralph  Metzler <ralph@convergence.de>
+ *                  & Marcus Metzler <marcus@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Lesser Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVBOSD_H_
+#define _DVBOSD_H_
+
+#include <linux/compiler.h>
+
+typedef enum {
+  // All functions return -2 on "not open"
+  OSD_Close=1,    // ()
+  // Disables OSD and releases the buffers
+  // returns 0 on success
+  OSD_Open,       // (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0))
+  // Opens OSD with this size and bit depth
+  // returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
+  OSD_Show,       // ()
+  // enables OSD mode
+  // returns 0 on success
+  OSD_Hide,       // ()
+  // disables OSD mode
+  // returns 0 on success
+  OSD_Clear,      // ()
+  // Sets all pixel to color 0
+  // returns 0 on success
+  OSD_Fill,       // (color)
+  // Sets all pixel to color <col>
+  // returns 0 on success
+  OSD_SetColor,   // (color,R{x0},G{y0},B{x1},opacity{y1})
+  // set palette entry <num> to <r,g,b>, <mix> and <trans> apply
+  // R,G,B: 0..255
+  // R=Red, G=Green, B=Blue
+  // opacity=0:      pixel opacity 0% (only video pixel shows)
+  // opacity=1..254: pixel opacity as specified in header
+  // opacity=255:    pixel opacity 100% (only OSD pixel shows)
+  // returns 0 on success, -1 on error
+  OSD_SetPalette, // (firstcolor{color},lastcolor{x0},data)
+  // Set a number of entries in the palette
+  // sets the entries "firstcolor" through "lastcolor" from the array "data"
+  // data has 4 byte for each color:
+  // R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
+  OSD_SetTrans,   // (transparency{color})
+  // Sets transparency of mixed pixel (0..15)
+  // returns 0 on success
+  OSD_SetPixel,   // (x0,y0,color)
+  // sets pixel <x>,<y> to color number <col>
+  // returns 0 on success, -1 on error
+  OSD_GetPixel,   // (x0,y0)
+  // returns color number of pixel <x>,<y>,  or -1
+  OSD_SetRow,     // (x0,y0,x1,data)
+  // fills pixels x0,y through  x1,y with the content of data[]
+  // returns 0 on success, -1 on clipping all pixel (no pixel drawn)
+  OSD_SetBlock,   // (x0,y0,x1,y1,increment{color},data)
+  // fills pixels x0,y0 through  x1,y1 with the content of data[]
+  // inc contains the width of one line in the data block,
+  // inc<=0 uses blockwidth as linewidth
+  // returns 0 on success, -1 on clipping all pixel
+  OSD_FillRow,    // (x0,y0,x1,color)
+  // fills pixels x0,y through  x1,y with the color <col>
+  // returns 0 on success, -1 on clipping all pixel
+  OSD_FillBlock,  // (x0,y0,x1,y1,color)
+  // fills pixels x0,y0 through  x1,y1 with the color <col>
+  // returns 0 on success, -1 on clipping all pixel
+  OSD_Line,       // (x0,y0,x1,y1,color)
+  // draw a line from x0,y0 to x1,y1 with the color <col>
+  // returns 0 on success
+  OSD_Query,      // (x0,y0,x1,y1,xasp{color}}), yasp=11
+  // fills parameters with the picture dimensions and the pixel aspect ratio
+  // returns 0 on success
+  OSD_Test,       // ()
+  // draws a test picture. for debugging purposes only
+  // returns 0 on success
+// TODO: remove "test" in final version
+  OSD_Text,       // (x0,y0,size,color,text)
+  OSD_SetWindow, //  (x0) set window with number 0<x0<8 as current
+  OSD_MoveWindow, //  move current window to (x0, y0)
+  OSD_OpenRaw, // Open other types of OSD windows
+} OSD_Command;
+
+typedef struct osd_cmd_s {
+       OSD_Command cmd;
+       int x0;
+       int y0;
+       int x1;
+       int y1;
+       int color;
+       void __user *data;
+} osd_cmd_t;
+
+/* OSD_OpenRaw: set 'color' to desired window type */
+typedef enum {
+       OSD_BITMAP1,           /* 1 bit bitmap */
+       OSD_BITMAP2,           /* 2 bit bitmap */
+       OSD_BITMAP4,           /* 4 bit bitmap */
+       OSD_BITMAP8,           /* 8 bit bitmap */
+       OSD_BITMAP1HR,         /* 1 Bit bitmap half resolution */
+       OSD_BITMAP2HR,         /* 2 bit bitmap half resolution */
+       OSD_BITMAP4HR,         /* 4 bit bitmap half resolution */
+       OSD_BITMAP8HR,         /* 8 bit bitmap half resolution */
+       OSD_YCRCB422,          /* 4:2:2 YCRCB Graphic Display */
+       OSD_YCRCB444,          /* 4:4:4 YCRCB Graphic Display */
+       OSD_YCRCB444HR,        /* 4:4:4 YCRCB graphic half resolution */
+       OSD_VIDEOTSIZE,        /* True Size Normal MPEG Video Display */
+       OSD_VIDEOHSIZE,        /* MPEG Video Display Half Resolution */
+       OSD_VIDEOQSIZE,        /* MPEG Video Display Quarter Resolution */
+       OSD_VIDEODSIZE,        /* MPEG Video Display Double Resolution */
+       OSD_VIDEOTHSIZE,       /* True Size MPEG Video Display Half Resolution */
+       OSD_VIDEOTQSIZE,       /* True Size MPEG Video Display Quarter Resolution*/
+       OSD_VIDEOTDSIZE,       /* True Size MPEG Video Display Double Resolution */
+       OSD_VIDEONSIZE,        /* Full Size MPEG Video Display */
+       OSD_CURSOR             /* Cursor */
+} osd_raw_window_t;
+
+typedef struct osd_cap_s {
+       int  cmd;
+#define OSD_CAP_MEMSIZE         1  /* memory size */
+       long val;
+} osd_cap_t;
+
+
+#define OSD_SEND_CMD            _IOW('o', 160, osd_cmd_t)
+#define OSD_GET_CAPABILITY      _IOR('o', 161, osd_cap_t)
+
+#endif
diff --git a/include/uapi/linux/dvb/version.h b/include/uapi/linux/dvb/version.h
new file mode 100644 (file)
index 0000000..827cce7
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * version.h
+ *
+ * Copyright (C) 2000 Holger Waechtler <holger@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public 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 _DVBVERSION_H_
+#define _DVBVERSION_H_
+
+#define DVB_API_VERSION 5
+#define DVB_API_VERSION_MINOR 9
+
+#endif /*_DVBVERSION_H_*/
diff --git a/include/uapi/linux/dvb/video.h b/include/uapi/linux/dvb/video.h
new file mode 100644 (file)
index 0000000..d3d14a5
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * video.h
+ *
+ * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
+ *                  & Ralph  Metzler <ralph@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef _UAPI_DVBVIDEO_H_
+#define _UAPI_DVBVIDEO_H_
+
+#include <linux/types.h>
+#ifndef __KERNEL__
+#include <stdint.h>
+#include <time.h>
+#endif
+
+typedef enum {
+       VIDEO_FORMAT_4_3,     /* Select 4:3 format */
+       VIDEO_FORMAT_16_9,    /* Select 16:9 format. */
+       VIDEO_FORMAT_221_1    /* 2.21:1 */
+} video_format_t;
+
+
+typedef enum {
+        VIDEO_SYSTEM_PAL,
+        VIDEO_SYSTEM_NTSC,
+        VIDEO_SYSTEM_PALN,
+        VIDEO_SYSTEM_PALNc,
+        VIDEO_SYSTEM_PALM,
+        VIDEO_SYSTEM_NTSC60,
+        VIDEO_SYSTEM_PAL60,
+        VIDEO_SYSTEM_PALM60
+} video_system_t;
+
+
+typedef enum {
+       VIDEO_PAN_SCAN,       /* use pan and scan format */
+       VIDEO_LETTER_BOX,     /* use letterbox format */
+       VIDEO_CENTER_CUT_OUT  /* use center cut out format */
+} video_displayformat_t;
+
+typedef struct {
+       int w;
+       int h;
+       video_format_t aspect_ratio;
+} video_size_t;
+
+typedef enum {
+       VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
+       VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
+                              comes from the user through the write
+                              system call */
+} video_stream_source_t;
+
+
+typedef enum {
+       VIDEO_STOPPED, /* Video is stopped */
+       VIDEO_PLAYING, /* Video is currently playing */
+       VIDEO_FREEZED  /* Video is freezed */
+} video_play_state_t;
+
+
+/* Decoder commands */
+#define VIDEO_CMD_PLAY        (0)
+#define VIDEO_CMD_STOP        (1)
+#define VIDEO_CMD_FREEZE      (2)
+#define VIDEO_CMD_CONTINUE    (3)
+
+/* Flags for VIDEO_CMD_FREEZE */
+#define VIDEO_CMD_FREEZE_TO_BLACK      (1 << 0)
+
+/* Flags for VIDEO_CMD_STOP */
+#define VIDEO_CMD_STOP_TO_BLACK        (1 << 0)
+#define VIDEO_CMD_STOP_IMMEDIATELY             (1 << 1)
+
+/* Play input formats: */
+/* The decoder has no special format requirements */
+#define VIDEO_PLAY_FMT_NONE         (0)
+/* The decoder requires full GOPs */
+#define VIDEO_PLAY_FMT_GOP          (1)
+
+/* The structure must be zeroed before use by the application
+   This ensures it can be extended safely in the future. */
+struct video_command {
+       __u32 cmd;
+       __u32 flags;
+       union {
+               struct {
+                       __u64 pts;
+               } stop;
+
+               struct {
+                       /* 0 or 1000 specifies normal speed,
+                          1 specifies forward single stepping,
+                          -1 specifies backward single stepping,
+                          >1: playback at speed/1000 of the normal speed,
+                          <-1: reverse playback at (-speed/1000) of the normal speed. */
+                       __s32 speed;
+                       __u32 format;
+               } play;
+
+               struct {
+                       __u32 data[16];
+               } raw;
+       };
+};
+
+/* FIELD_UNKNOWN can be used if the hardware does not know whether
+   the Vsync is for an odd, even or progressive (i.e. non-interlaced)
+   field. */
+#define VIDEO_VSYNC_FIELD_UNKNOWN      (0)
+#define VIDEO_VSYNC_FIELD_ODD          (1)
+#define VIDEO_VSYNC_FIELD_EVEN         (2)
+#define VIDEO_VSYNC_FIELD_PROGRESSIVE  (3)
+
+struct video_event {
+       __s32 type;
+#define VIDEO_EVENT_SIZE_CHANGED       1
+#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
+#define VIDEO_EVENT_DECODER_STOPPED    3
+#define VIDEO_EVENT_VSYNC              4
+       __kernel_time_t timestamp;
+       union {
+               video_size_t size;
+               unsigned int frame_rate;        /* in frames per 1000sec */
+               unsigned char vsync_field;      /* unknown/odd/even/progressive */
+       } u;
+};
+
+
+struct video_status {
+       int                   video_blank;   /* blank video on freeze? */
+       video_play_state_t    play_state;    /* current state of playback */
+       video_stream_source_t stream_source; /* current source (demux/memory) */
+       video_format_t        video_format;  /* current aspect ratio of stream*/
+       video_displayformat_t display_format;/* selected cropping mode */
+};
+
+
+struct video_still_picture {
+       char __user *iFrame;        /* pointer to a single iframe in memory */
+       __s32 size;
+};
+
+
+typedef
+struct video_highlight {
+       int     active;      /*    1=show highlight, 0=hide highlight */
+       __u8    contrast1;   /*    7- 4  Pattern pixel contrast */
+                            /*    3- 0  Background pixel contrast */
+       __u8    contrast2;   /*    7- 4  Emphasis pixel-2 contrast */
+                            /*    3- 0  Emphasis pixel-1 contrast */
+       __u8    color1;      /*    7- 4  Pattern pixel color */
+                            /*    3- 0  Background pixel color */
+       __u8    color2;      /*    7- 4  Emphasis pixel-2 color */
+                            /*    3- 0  Emphasis pixel-1 color */
+       __u32    ypos;       /*   23-22  auto action mode */
+                            /*   21-12  start y */
+                            /*    9- 0  end y */
+       __u32    xpos;       /*   23-22  button color number */
+                            /*   21-12  start x */
+                            /*    9- 0  end x */
+} video_highlight_t;
+
+
+typedef struct video_spu {
+       int active;
+       int stream_id;
+} video_spu_t;
+
+
+typedef struct video_spu_palette {      /* SPU Palette information */
+       int length;
+       __u8 __user *palette;
+} video_spu_palette_t;
+
+
+typedef struct video_navi_pack {
+       int length;          /* 0 ... 1024 */
+       __u8 data[1024];
+} video_navi_pack_t;
+
+
+typedef __u16 video_attributes_t;
+/*   bits: descr. */
+/*   15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
+/*   13-12 TV system (0=525/60, 1=625/50) */
+/*   11-10 Aspect ratio (0=4:3, 3=16:9) */
+/*    9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */
+/*    7    line 21-1 data present in GOP (1=yes, 0=no) */
+/*    6    line 21-2 data present in GOP (1=yes, 0=no) */
+/*    5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */
+/*    2    source letterboxed (1=yes, 0=no) */
+/*    0    film/camera mode (0=camera, 1=film (625/50 only)) */
+
+
+/* bit definitions for capabilities: */
+/* can the hardware decode MPEG1 and/or MPEG2? */
+#define VIDEO_CAP_MPEG1   1
+#define VIDEO_CAP_MPEG2   2
+/* can you send a system and/or program stream to video device?
+   (you still have to open the video and the audio device but only
+    send the stream to the video device) */
+#define VIDEO_CAP_SYS     4
+#define VIDEO_CAP_PROG    8
+/* can the driver also handle SPU, NAVI and CSS encoded data?
+   (CSS API is not present yet) */
+#define VIDEO_CAP_SPU    16
+#define VIDEO_CAP_NAVI   32
+#define VIDEO_CAP_CSS    64
+
+
+#define VIDEO_STOP                 _IO('o', 21)
+#define VIDEO_PLAY                 _IO('o', 22)
+#define VIDEO_FREEZE               _IO('o', 23)
+#define VIDEO_CONTINUE             _IO('o', 24)
+#define VIDEO_SELECT_SOURCE        _IO('o', 25)
+#define VIDEO_SET_BLANK            _IO('o', 26)
+#define VIDEO_GET_STATUS           _IOR('o', 27, struct video_status)
+#define VIDEO_GET_EVENT            _IOR('o', 28, struct video_event)
+#define VIDEO_SET_DISPLAY_FORMAT   _IO('o', 29)
+#define VIDEO_STILLPICTURE         _IOW('o', 30, struct video_still_picture)
+#define VIDEO_FAST_FORWARD         _IO('o', 31)
+#define VIDEO_SLOWMOTION           _IO('o', 32)
+#define VIDEO_GET_CAPABILITIES     _IOR('o', 33, unsigned int)
+#define VIDEO_CLEAR_BUFFER         _IO('o',  34)
+#define VIDEO_SET_ID               _IO('o', 35)
+#define VIDEO_SET_STREAMTYPE       _IO('o', 36)
+#define VIDEO_SET_FORMAT           _IO('o', 37)
+#define VIDEO_SET_SYSTEM           _IO('o', 38)
+#define VIDEO_SET_HIGHLIGHT        _IOW('o', 39, video_highlight_t)
+#define VIDEO_SET_SPU              _IOW('o', 50, video_spu_t)
+#define VIDEO_SET_SPU_PALETTE      _IOW('o', 51, video_spu_palette_t)
+#define VIDEO_GET_NAVI             _IOR('o', 52, video_navi_pack_t)
+#define VIDEO_SET_ATTRIBUTES       _IO('o', 53)
+#define VIDEO_GET_SIZE             _IOR('o', 55, video_size_t)
+#define VIDEO_GET_FRAME_RATE       _IOR('o', 56, unsigned int)
+
+/**
+ * VIDEO_GET_PTS
+ *
+ * Read the 33 bit presentation time stamp as defined
+ * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+ *
+ * The PTS should belong to the currently played
+ * frame if possible, but may also be a value close to it
+ * like the PTS of the last decoded frame or the last PTS
+ * extracted by the PES parser.
+ */
+#define VIDEO_GET_PTS              _IOR('o', 57, __u64)
+
+/* Read the number of displayed frames since the decoder was started */
+#define VIDEO_GET_FRAME_COUNT             _IOR('o', 58, __u64)
+
+#define VIDEO_COMMAND             _IOWR('o', 59, struct video_command)
+#define VIDEO_TRY_COMMAND         _IOWR('o', 60, struct video_command)
+
+#endif /* _UAPI_DVBVIDEO_H_ */
index 1065078938f9f144e7c206301da7f87c24458b11..3921e33aec8e36da1775c63a6ee4e2998faa313b 100644 (file)
@@ -9,8 +9,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#ifndef _LINUX_ELF_FDPIC_H
-#define _LINUX_ELF_FDPIC_H
+#ifndef _UAPI_LINUX_ELF_FDPIC_H
+#define _UAPI_LINUX_ELF_FDPIC_H
 
 #include <linux/elf.h>
 
@@ -31,40 +31,4 @@ struct elf32_fdpic_loadmap {
 
 #define ELF32_FDPIC_LOADMAP_VERSION    0x0000
 
-#ifndef __KERNEL__
-/*
- * binfmt binary parameters structure
- */
-struct elf_fdpic_params {
-       struct elfhdr                   hdr;            /* ref copy of ELF header */
-       struct elf_phdr                 *phdrs;         /* ref copy of PT_PHDR table */
-       struct elf32_fdpic_loadmap      *loadmap;       /* loadmap to be passed to userspace */
-       unsigned long                   elfhdr_addr;    /* mapped ELF header user address */
-       unsigned long                   ph_addr;        /* mapped PT_PHDR user address */
-       unsigned long                   map_addr;       /* mapped loadmap user address */
-       unsigned long                   entry_addr;     /* mapped entry user address */
-       unsigned long                   stack_size;     /* stack size requested (PT_GNU_STACK) */
-       unsigned long                   dynamic_addr;   /* mapped PT_DYNAMIC user address */
-       unsigned long                   load_addr;      /* user address at which to map binary */
-       unsigned long                   flags;
-#define ELF_FDPIC_FLAG_ARRANGEMENT     0x0000000f      /* PT_LOAD arrangement flags */
-#define ELF_FDPIC_FLAG_INDEPENDENT     0x00000000      /* PT_LOADs can be put anywhere */
-#define ELF_FDPIC_FLAG_HONOURVADDR     0x00000001      /* PT_LOAD.vaddr must be honoured */
-#define ELF_FDPIC_FLAG_CONSTDISP       0x00000002      /* PT_LOADs require constant
-                                                        * displacement */
-#define ELF_FDPIC_FLAG_CONTIGUOUS      0x00000003      /* PT_LOADs should be contiguous */
-#define ELF_FDPIC_FLAG_EXEC_STACK      0x00000010      /* T if stack to be executable */
-#define ELF_FDPIC_FLAG_NOEXEC_STACK    0x00000020      /* T if stack not to be executable */
-#define ELF_FDPIC_FLAG_EXECUTABLE      0x00000040      /* T if this object is the executable */
-#define ELF_FDPIC_FLAG_PRESENT         0x80000000      /* T if this object is present */
-};
-
-#ifdef CONFIG_MMU
-extern void elf_fdpic_arch_lay_out_mm(struct elf_fdpic_params *exec_params,
-                                     struct elf_fdpic_params *interp_params,
-                                     unsigned long *start_stack,
-                                     unsigned long *start_brk);
-#endif
-#endif /* __KERNEL__ */
-
-#endif /* _LINUX_ELF_FDPIC_H */
+#endif /* _UAPI_LINUX_ELF_FDPIC_H */
index 8c99ce7202c53bcd93887c93dd8d8e75ebcd8aa2..2c267bcbb85c1c4e31b676127db7686d8d027e09 100644 (file)
@@ -25,7 +25,6 @@
 #define EPOLL_CTL_ADD 1
 #define EPOLL_CTL_DEL 2
 #define EPOLL_CTL_MOD 3
-#define EPOLL_CTL_DISABLE 4
 
 /*
  * Request the handling of system wakeup events so as to prevent system suspends
index 3d7922433abad7b6e3cf7985897e9536eda49037..9cfde6941099635ee567d28e240f8cbc02386f51 100644 (file)
@@ -127,7 +127,9 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
 #define SKF_AD_RXHASH  32
 #define SKF_AD_CPU     36
 #define SKF_AD_ALU_XOR_X       40
-#define SKF_AD_MAX     44
+#define SKF_AD_VLAN_TAG        44
+#define SKF_AD_VLAN_TAG_PRESENT 48
+#define SKF_AD_MAX     52
 #define SKF_NET_OFF   (-0x100000)
 #define SKF_LL_OFF    (-0x200000)
 
index 9fcc880d4be2fe7a17c5b6f64af2d41b0315c1d6..780d4c6093eb767ff7bd15ee30cd07bb76b04763 100644 (file)
@@ -57,85 +57,6 @@ struct inodes_stat_t {
 
 #define NR_FILE  8192  /* this can well be larger on a larger system */
 
-#define MAY_EXEC               0x00000001
-#define MAY_WRITE              0x00000002
-#define MAY_READ               0x00000004
-#define MAY_APPEND             0x00000008
-#define MAY_ACCESS             0x00000010
-#define MAY_OPEN               0x00000020
-#define MAY_CHDIR              0x00000040
-/* called from RCU mode, don't block */
-#define MAY_NOT_BLOCK          0x00000080
-
-/*
- * flags in file.f_mode.  Note that FMODE_READ and FMODE_WRITE must correspond
- * to O_WRONLY and O_RDWR via the strange trick in __dentry_open()
- */
-
-/* file is open for reading */
-#define FMODE_READ             ((__force fmode_t)0x1)
-/* file is open for writing */
-#define FMODE_WRITE            ((__force fmode_t)0x2)
-/* file is seekable */
-#define FMODE_LSEEK            ((__force fmode_t)0x4)
-/* file can be accessed using pread */
-#define FMODE_PREAD            ((__force fmode_t)0x8)
-/* file can be accessed using pwrite */
-#define FMODE_PWRITE           ((__force fmode_t)0x10)
-/* File is opened for execution with sys_execve / sys_uselib */
-#define FMODE_EXEC             ((__force fmode_t)0x20)
-/* File is opened with O_NDELAY (only set for block devices) */
-#define FMODE_NDELAY           ((__force fmode_t)0x40)
-/* File is opened with O_EXCL (only set for block devices) */
-#define FMODE_EXCL             ((__force fmode_t)0x80)
-/* File is opened using open(.., 3, ..) and is writeable only for ioctls
-   (specialy hack for floppy.c) */
-#define FMODE_WRITE_IOCTL      ((__force fmode_t)0x100)
-/* 32bit hashes as llseek() offset (for directories) */
-#define FMODE_32BITHASH         ((__force fmode_t)0x200)
-/* 64bit hashes as llseek() offset (for directories) */
-#define FMODE_64BITHASH         ((__force fmode_t)0x400)
-
-/*
- * Don't update ctime and mtime.
- *
- * Currently a special hack for the XFS open_by_handle ioctl, but we'll
- * hopefully graduate it to a proper O_CMTIME flag supported by open(2) soon.
- */
-#define FMODE_NOCMTIME         ((__force fmode_t)0x800)
-
-/* Expect random access pattern */
-#define FMODE_RANDOM           ((__force fmode_t)0x1000)
-
-/* File is huge (eg. /dev/kmem): treat loff_t as unsigned */
-#define FMODE_UNSIGNED_OFFSET  ((__force fmode_t)0x2000)
-
-/* File is opened with O_PATH; almost nothing can be done with it */
-#define FMODE_PATH             ((__force fmode_t)0x4000)
-
-/* File was opened by fanotify and shouldn't generate fanotify events */
-#define FMODE_NONOTIFY         ((__force fmode_t)0x1000000)
-
-/*
- * Flag for rw_copy_check_uvector and compat_rw_copy_check_uvector
- * that indicates that they should check the contents of the iovec are
- * valid, but not check the memory that the iovec elements
- * points too.
- */
-#define CHECK_IOVEC_ONLY -1
-
-#define SEL_IN         1
-#define SEL_OUT                2
-#define SEL_EX         4
-
-/* public flags for file_system_type */
-#define FS_REQUIRES_DEV 1 
-#define FS_BINARY_MOUNTDATA 2
-#define FS_HAS_SUBTYPE 4
-#define FS_REVAL_DOT   16384   /* Check the paths ".", ".." for staleness */
-#define FS_RENAME_DOES_D_MOVE  32768   /* FS will handle d_move()
-                                        * during rename() internally.
-                                        */
 
 /*
  * These are the fs-independent mount-flags: up to 32 flags are supported
@@ -181,59 +102,6 @@ struct inodes_stat_t {
 #define MS_MGC_VAL 0xC0ED0000
 #define MS_MGC_MSK 0xffff0000
 
-/* Inode flags - they have nothing to superblock flags now */
-
-#define S_SYNC         1       /* Writes are synced at once */
-#define S_NOATIME      2       /* Do not update access times */
-#define S_APPEND       4       /* Append-only file */
-#define S_IMMUTABLE    8       /* Immutable file */
-#define S_DEAD         16      /* removed, but still open directory */
-#define S_NOQUOTA      32      /* Inode is not counted to quota */
-#define S_DIRSYNC      64      /* Directory modifications are synchronous */
-#define S_NOCMTIME     128     /* Do not update file c/mtime */
-#define S_SWAPFILE     256     /* Do not truncate: swapon got its bmaps */
-#define S_PRIVATE      512     /* Inode is fs-internal */
-#define S_IMA          1024    /* Inode has an associated IMA struct */
-#define S_AUTOMOUNT    2048    /* Automount/referral quasi-directory */
-#define S_NOSEC                4096    /* no suid or xattr security attributes */
-
-/*
- * Note that nosuid etc flags are inode-specific: setting some file-system
- * flags just means all the inodes inherit those flags by default. It might be
- * possible to override it selectively if you really wanted to with some
- * ioctl() that is not currently implemented.
- *
- * Exception: MS_RDONLY is always applied to the entire file system.
- *
- * Unfortunately, it is possible to change a filesystems flags with it mounted
- * with files in use.  This means that all of the inodes will not have their
- * i_flags updated.  Hence, i_flags no longer inherit the superblock mount
- * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org
- */
-#define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg))
-
-#define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY)
-#define IS_SYNC(inode)         (__IS_FLG(inode, MS_SYNCHRONOUS) || \
-                                       ((inode)->i_flags & S_SYNC))
-#define IS_DIRSYNC(inode)      (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \
-                                       ((inode)->i_flags & (S_SYNC|S_DIRSYNC)))
-#define IS_MANDLOCK(inode)     __IS_FLG(inode, MS_MANDLOCK)
-#define IS_NOATIME(inode)   __IS_FLG(inode, MS_RDONLY|MS_NOATIME)
-#define IS_I_VERSION(inode)   __IS_FLG(inode, MS_I_VERSION)
-
-#define IS_NOQUOTA(inode)      ((inode)->i_flags & S_NOQUOTA)
-#define IS_APPEND(inode)       ((inode)->i_flags & S_APPEND)
-#define IS_IMMUTABLE(inode)    ((inode)->i_flags & S_IMMUTABLE)
-#define IS_POSIXACL(inode)     __IS_FLG(inode, MS_POSIXACL)
-
-#define IS_DEADDIR(inode)      ((inode)->i_flags & S_DEAD)
-#define IS_NOCMTIME(inode)     ((inode)->i_flags & S_NOCMTIME)
-#define IS_SWAPFILE(inode)     ((inode)->i_flags & S_SWAPFILE)
-#define IS_PRIVATE(inode)      ((inode)->i_flags & S_PRIVATE)
-#define IS_IMA(inode)          ((inode)->i_flags & S_IMA)
-#define IS_AUTOMOUNT(inode)    ((inode)->i_flags & S_AUTOMOUNT)
-#define IS_NOSEC(inode)                ((inode)->i_flags & S_NOSEC)
-
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */
 
index aafaa5aa54d46bb9a93a8137a22344408298223f..8c1d2cb75e330ae605277aa70ec44415a53f3428 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += ioctl.h
diff --git a/include/uapi/linux/hdlc/ioctl.h b/include/uapi/linux/hdlc/ioctl.h
new file mode 100644 (file)
index 0000000..04bc027
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef __HDLC_IOCTL_H__
+#define __HDLC_IOCTL_H__
+
+
+#define GENERIC_HDLC_VERSION 4 /* For synchronization with sethdlc utility */
+
+#define CLOCK_DEFAULT   0      /* Default setting */
+#define CLOCK_EXT      1       /* External TX and RX clock - DTE */
+#define CLOCK_INT      2       /* Internal TX and RX clock - DCE */
+#define CLOCK_TXINT    3       /* Internal TX and external RX clock */
+#define CLOCK_TXFROMRX 4       /* TX clock derived from external RX clock */
+
+
+#define ENCODING_DEFAULT       0 /* Default setting */
+#define ENCODING_NRZ           1
+#define ENCODING_NRZI          2
+#define ENCODING_FM_MARK       3
+#define ENCODING_FM_SPACE      4
+#define ENCODING_MANCHESTER    5
+
+
+#define PARITY_DEFAULT         0 /* Default setting */
+#define PARITY_NONE            1 /* No parity */
+#define PARITY_CRC16_PR0       2 /* CRC16, initial value 0x0000 */
+#define PARITY_CRC16_PR1       3 /* CRC16, initial value 0xFFFF */
+#define PARITY_CRC16_PR0_CCITT 4 /* CRC16, initial 0x0000, ITU-T version */
+#define PARITY_CRC16_PR1_CCITT 5 /* CRC16, initial 0xFFFF, ITU-T version */
+#define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */
+#define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */
+
+#define LMI_DEFAULT            0 /* Default setting */
+#define LMI_NONE               1 /* No LMI, all PVCs are static */
+#define LMI_ANSI               2 /* ANSI Annex D */
+#define LMI_CCITT              3 /* ITU-T Annex A */
+#define LMI_CISCO              4 /* The "original" LMI, aka Gang of Four */
+
+#ifndef __ASSEMBLY__
+
+typedef struct {
+       unsigned int clock_rate; /* bits per second */
+       unsigned int clock_type; /* internal, external, TX-internal etc. */
+       unsigned short loopback;
+} sync_serial_settings;          /* V.35, V.24, X.21 */
+
+typedef struct {
+       unsigned int clock_rate; /* bits per second */
+       unsigned int clock_type; /* internal, external, TX-internal etc. */
+       unsigned short loopback;
+       unsigned int slot_map;
+} te1_settings;                  /* T1, E1 */
+
+typedef struct {
+       unsigned short encoding;
+       unsigned short parity;
+} raw_hdlc_proto;
+
+typedef struct {
+       unsigned int t391;
+       unsigned int t392;
+       unsigned int n391;
+       unsigned int n392;
+       unsigned int n393;
+       unsigned short lmi;
+       unsigned short dce; /* 1 for DCE (network side) operation */
+} fr_proto;
+
+typedef struct {
+       unsigned int dlci;
+} fr_proto_pvc;          /* for creating/deleting FR PVCs */
+
+typedef struct {
+       unsigned int dlci;
+       char master[IFNAMSIZ];  /* Name of master FRAD device */
+}fr_proto_pvc_info;            /* for returning PVC information only */
+
+typedef struct {
+    unsigned int interval;
+    unsigned int timeout;
+} cisco_proto;
+
+/* PPP doesn't need any info now - supply length = 0 to ioctl */
+
+#endif /* __ASSEMBLY__ */
+#endif /* __HDLC_IOCTL_H__ */
index aafaa5aa54d46bb9a93a8137a22344408298223f..30ab3cd3b8a55b7f347eda392cae4578645af9e0 100644 (file)
@@ -1 +1,2 @@
 # UAPI Header export list
+header-y += hsi_char.h
diff --git a/include/uapi/linux/hsi/hsi_char.h b/include/uapi/linux/hsi/hsi_char.h
new file mode 100644 (file)
index 0000000..76160b4
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Part of the HSI character device driver.
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Andras Domokos <andras.domokos at nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+
+#ifndef __HSI_CHAR_H
+#define __HSI_CHAR_H
+
+#define HSI_CHAR_MAGIC         'k'
+#define HSC_IOW(num, dtype)    _IOW(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IOR(num, dtype)    _IOR(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IOWR(num, dtype)   _IOWR(HSI_CHAR_MAGIC, num, dtype)
+#define HSC_IO(num)            _IO(HSI_CHAR_MAGIC, num)
+
+#define HSC_RESET              HSC_IO(16)
+#define HSC_SET_PM             HSC_IO(17)
+#define HSC_SEND_BREAK         HSC_IO(18)
+#define HSC_SET_RX             HSC_IOW(19, struct hsc_rx_config)
+#define HSC_GET_RX             HSC_IOW(20, struct hsc_rx_config)
+#define HSC_SET_TX             HSC_IOW(21, struct hsc_tx_config)
+#define HSC_GET_TX             HSC_IOW(22, struct hsc_tx_config)
+
+#define HSC_PM_DISABLE         0
+#define HSC_PM_ENABLE          1
+
+#define HSC_MODE_STREAM                1
+#define HSC_MODE_FRAME         2
+#define HSC_FLOW_SYNC          0
+#define HSC_ARB_RR             0
+#define HSC_ARB_PRIO           1
+
+struct hsc_rx_config {
+       uint32_t mode;
+       uint32_t flow;
+       uint32_t channels;
+};
+
+struct hsc_tx_config {
+       uint32_t mode;
+       uint32_t channels;
+       uint32_t speed;
+       uint32_t arb_mode;
+};
+
+#endif /* __HSI_CHAR_H */
index a8fe9549ddbc65f068bcb992cc16f4a734428b27..9a0f6ff0d7e763bd3ec836328bb1377617c87afa 100644 (file)
@@ -97,5 +97,78 @@ struct __fdb_entry {
        __u16 unused;
 };
 
+/* Bridge Flags */
+#define BRIDGE_FLAGS_MASTER    1       /* Bridge command to/from master */
+#define BRIDGE_FLAGS_SELF      2       /* Bridge command to/from lowerdev */
+
+#define BRIDGE_MODE_VEB                0       /* Default loopback mode */
+#define BRIDGE_MODE_VEPA       1       /* 802.1Qbg defined VEPA mode */
+
+/* Bridge management nested attributes
+ * [IFLA_AF_SPEC] = {
+ *     [IFLA_BRIDGE_FLAGS]
+ *     [IFLA_BRIDGE_MODE]
+ * }
+ */
+enum {
+       IFLA_BRIDGE_FLAGS,
+       IFLA_BRIDGE_MODE,
+       __IFLA_BRIDGE_MAX,
+};
+#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)
+
+/* Bridge multicast database attributes
+ * [MDBA_MDB] = {
+ *     [MDBA_MDB_ENTRY] = {
+ *         [MDBA_MDB_ENTRY_INFO]
+ *     }
+ * }
+ * [MDBA_ROUTER] = {
+ *    [MDBA_ROUTER_PORT]
+ * }
+ */
+enum {
+       MDBA_UNSPEC,
+       MDBA_MDB,
+       MDBA_ROUTER,
+       __MDBA_MAX,
+};
+#define MDBA_MAX (__MDBA_MAX - 1)
+
+enum {
+       MDBA_MDB_UNSPEC,
+       MDBA_MDB_ENTRY,
+       __MDBA_MDB_MAX,
+};
+#define MDBA_MDB_MAX (__MDBA_MDB_MAX - 1)
+
+enum {
+       MDBA_MDB_ENTRY_UNSPEC,
+       MDBA_MDB_ENTRY_INFO,
+       __MDBA_MDB_ENTRY_MAX,
+};
+#define MDBA_MDB_ENTRY_MAX (__MDBA_MDB_ENTRY_MAX - 1)
+
+enum {
+       MDBA_ROUTER_UNSPEC,
+       MDBA_ROUTER_PORT,
+       __MDBA_ROUTER_MAX,
+};
+#define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1)
+
+struct br_port_msg {
+       __u32 ifindex;
+};
+
+struct br_mdb_entry {
+       __u32 ifindex;
+       struct {
+               union {
+                       __be32  ip4;
+                       struct in6_addr ip6;
+               } u;
+               __be16          proto;
+       } addr;
+};
 
 #endif /* _UAPI_LINUX_IF_BRIDGE_H */
index 0343e1f0582c01bcd54425bbb551098951d3767b..67fb87ca10945fda5711cbfe4cfc0a9c9573c6da 100644 (file)
@@ -48,6 +48,7 @@
 #define        ETH_P_BPQ       0x08FF          /* G8BPQ AX.25 Ethernet Packet  [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_IEEEPUP  0x0a00          /* Xerox IEEE802.3 PUP packet */
 #define ETH_P_IEEEPUPAT        0x0a01          /* Xerox IEEE802.3 PUP Addr Trans packet */
+#define ETH_P_BATMAN   0x4305          /* B.A.T.M.A.N.-Advanced packet [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_DEC       0x6000          /* DEC Assigned proto           */
 #define ETH_P_DNA_DL    0x6001          /* DEC DNA Dump/Load            */
 #define ETH_P_DNA_RC    0x6002          /* DEC DNA Remote Console       */
index 5c80cb11518bbe599e28c2c44ac57a03a9f18947..60f3b6b906027e086f3c5a0e6ab4ef0ffa6daaf0 100644 (file)
@@ -205,6 +205,24 @@ enum {
 
 #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
 
+enum {
+       BRIDGE_MODE_UNSPEC,
+       BRIDGE_MODE_HAIRPIN,
+};
+
+enum {
+       IFLA_BRPORT_UNSPEC,
+       IFLA_BRPORT_STATE,      /* Spanning tree state     */
+       IFLA_BRPORT_PRIORITY,   /* "             priority  */
+       IFLA_BRPORT_COST,       /* "             cost      */
+       IFLA_BRPORT_MODE,       /* mode (hairpin)          */
+       IFLA_BRPORT_GUARD,      /* bpdu guard              */
+       IFLA_BRPORT_PROTECT,    /* root port protection    */
+       IFLA_BRPORT_FAST_LEAVE, /* multicast fast leave    */
+       __IFLA_BRPORT_MAX
+};
+#define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1)
+
 struct ifla_cacheinfo {
        __u32   max_reasm_len;
        __u32   tstamp;         /* ipv6InterfaceTable updated timestamp */
@@ -285,6 +303,10 @@ enum {
        IFLA_VXLAN_AGEING,
        IFLA_VXLAN_LIMIT,
        IFLA_VXLAN_PORT_RANGE,
+       IFLA_VXLAN_PROXY,
+       IFLA_VXLAN_RSC,
+       IFLA_VXLAN_L2MISS,
+       IFLA_VXLAN_L3MISS,
        __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
index f3799295d231c7d34a114cbb75b8950e6a61da3c..f9a60375f0d0121855af7f3a157afccc909bf547 100644 (file)
@@ -50,6 +50,7 @@ struct sockaddr_ll {
 #define PACKET_TX_TIMESTAMP            16
 #define PACKET_TIMESTAMP               17
 #define PACKET_FANOUT                  18
+#define PACKET_TX_HAS_OFF              19
 
 #define PACKET_FANOUT_HASH             0
 #define PACKET_FANOUT_LB               1
index 25a585ce23e68243e1f0a1610f240624aaef6bde..2835b85fd46d85ae47ec857caa93db1ee5ba79b9 100644 (file)
 #define TUN_FASYNC     0x0010
 #define TUN_NOCHECKSUM 0x0020
 #define TUN_NO_PI      0x0040
+/* This flag has no real effect */
 #define TUN_ONE_QUEUE  0x0080
 #define TUN_PERSIST    0x0100  
 #define TUN_VNET_HDR   0x0200
+#define TUN_TAP_MQ      0x0400
 
 /* Ioctl defines */
 #define TUNSETNOCSUM  _IOW('T', 200, int) 
 #define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
 #define TUNGETVNETHDRSZ _IOR('T', 215, int)
 #define TUNSETVNETHDRSZ _IOW('T', 216, int)
+#define TUNSETQUEUE  _IOW('T', 217, int)
 
 /* TUNSETIFF ifr flags */
 #define IFF_TUN                0x0001
 #define IFF_TAP                0x0002
 #define IFF_NO_PI      0x1000
+/* This flag has no real effect */
 #define IFF_ONE_QUEUE  0x2000
 #define IFF_VNET_HDR   0x4000
 #define IFF_TUN_EXCL   0x8000
+#define IFF_MULTI_QUEUE 0x0100
+#define IFF_ATTACH_QUEUE 0x0200
+#define IFF_DETACH_QUEUE 0x0400
 
 /* Features for GSO (TUNSETOFFLOAD). */
 #define TUN_F_CSUM     0x01    /* You can hand me unchecksummed packets. */
index 5db5942575fe9781f4e06bdb89f6f1e86e1dfb5f..aee73d0611fb9bbb72f3ab52a0b91c09ba861c12 100644 (file)
@@ -37,6 +37,26 @@ struct ip_tunnel_parm {
        struct iphdr            iph;
 };
 
+enum {
+       IFLA_IPTUN_UNSPEC,
+       IFLA_IPTUN_LINK,
+       IFLA_IPTUN_LOCAL,
+       IFLA_IPTUN_REMOTE,
+       IFLA_IPTUN_TTL,
+       IFLA_IPTUN_TOS,
+       IFLA_IPTUN_ENCAP_LIMIT,
+       IFLA_IPTUN_FLOWINFO,
+       IFLA_IPTUN_FLAGS,
+       IFLA_IPTUN_PROTO,
+       IFLA_IPTUN_PMTUDISC,
+       IFLA_IPTUN_6RD_PREFIX,
+       IFLA_IPTUN_6RD_RELAY_PREFIX,
+       IFLA_IPTUN_6RD_PREFIXLEN,
+       IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+       __IFLA_IPTUN_MAX,
+};
+#define IFLA_IPTUN_MAX (__IFLA_IPTUN_MAX - 1)
+
 /* SIT-mode i_flags */
 #define        SIT_ISATAP      0x0001
 
index 1e3159989958efb006f607a5a3755ccf24e2308a..f79c3721da6e772991779c4ee55eddce00f3bab0 100644 (file)
@@ -240,6 +240,7 @@ struct in6_flowlabel_req {
  *
  * IP6T_SO_GET_REVISION_MATCH  68
  * IP6T_SO_GET_REVISION_TARGET 69
+ * IP6T_SO_ORIGINAL_DST                80
  */
 
 /* RFC5014: Source address selection */
index 8c469af939aab33a2117d7361e247371c6303750..bbde90fa58380bb6d6940d9ec7454af7a4d55608 100644 (file)
@@ -109,9 +109,10 @@ enum {
        INET_DIAG_TOS,
        INET_DIAG_TCLASS,
        INET_DIAG_SKMEMINFO,
+       INET_DIAG_SHUTDOWN,
 };
 
-#define INET_DIAG_MAX INET_DIAG_SKMEMINFO
+#define INET_DIAG_MAX INET_DIAG_SHUTDOWN
 
 
 /* INET_DIAG_MEM */
index a6d7d1c536c33708b84b88661184d4256299450d..5a2991cf0251d558c15d108d9ea88155240425e7 100644 (file)
@@ -157,6 +157,7 @@ enum {
        DEVCONF_DISABLE_IPV6,
        DEVCONF_ACCEPT_DAD,
        DEVCONF_FORCE_TLLAO,
+       DEVCONF_NDISC_NOTIFY,
        DEVCONF_MAX
 };
 
index 0459664c263690a5f4ed7f6e77fd97faf543eafe..2be7bd174751ae393e3c15f702e07308afbcbe16 100644 (file)
@@ -55,4 +55,7 @@ struct in6_rtmsg {
 #define RTMSG_NEWROUTE         0x21
 #define RTMSG_DELROUTE         0x22
 
+#define IP6_RT_PRIO_USER       1024
+#define IP6_RT_PRIO_ADDRCONF   256
+
 #endif /* _UAPI_LINUX_IPV6_ROUTE_H */
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ae5704fa77ad6d15e8de4623ca6465f24f2341b9 100644 (file)
@@ -0,0 +1,4 @@
+/*
+ * There isn't anything here anymore, but the file must not be empty or patch
+ * will delete it.
+ */
diff --git a/include/uapi/linux/netconf.h b/include/uapi/linux/netconf.h
new file mode 100644 (file)
index 0000000..64804a7
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef _UAPI_LINUX_NETCONF_H_
+#define _UAPI_LINUX_NETCONF_H_
+
+#include <linux/types.h>
+#include <linux/netlink.h>
+
+struct netconfmsg {
+       __u8    ncm_family;
+};
+
+enum {
+       NETCONFA_UNSPEC,
+       NETCONFA_IFINDEX,
+       NETCONFA_FORWARDING,
+       NETCONFA_RP_FILTER,
+       NETCONFA_MC_FORWARDING,
+       __NETCONFA_MAX
+};
+#define NETCONFA_MAX   (__NETCONFA_MAX - 1)
+
+#define NETCONFA_IFINDEX_ALL           -1
+#define NETCONFA_IFINDEX_DEFAULT       -2
+
+#endif /* _UAPI_LINUX_NETCONF_H_ */
index 43bfe3e1685b21d7dcf5bbb254a269ec941e5523..86e930cf3dfba3f472046e8cded054a1159a83d8 100644 (file)
@@ -9,6 +9,8 @@ enum cntl_msg_types {
        IPCTNL_MSG_CT_GET_CTRZERO,
        IPCTNL_MSG_CT_GET_STATS_CPU,
        IPCTNL_MSG_CT_GET_STATS,
+       IPCTNL_MSG_CT_GET_DYING,
+       IPCTNL_MSG_CT_GET_UNCONFIRMED,
 
        IPCTNL_MSG_MAX
 };
index bf1ef65cc58248033c2ea6aedb27385bdd6955e3..649c68062dcaf822741b926ad14664841a3e84d2 100644 (file)
@@ -178,6 +178,9 @@ struct ip6t_error {
 #define IP6T_SO_GET_REVISION_TARGET    (IP6T_BASE_CTL + 5)
 #define IP6T_SO_GET_MAX                        IP6T_SO_GET_REVISION_TARGET
 
+/* obtain original address if REDIRECT'd connection */
+#define IP6T_SO_ORIGINAL_DST            80
+
 /* ICMP matching stuff */
 struct ip6t_icmp {
        __u8 type;                              /* type to match */
index a49c4afc70600d22ff904586cd41098a9e360e2d..b29272d621ce21162dc148217e4b6e89f72304b1 100644 (file)
@@ -8,4 +8,13 @@
 #define OOM_SCORE_ADJ_MIN      (-1000)
 #define OOM_SCORE_ADJ_MAX      1000
 
+/*
+ * /proc/<pid>/oom_adj set to -17 protects from the oom killer for legacy
+ * purposes.
+ */
+#define OOM_DISABLE (-17)
+/* inclusive */
+#define OOM_ADJUST_MIN (-16)
+#define OOM_ADJUST_MAX 15
+
 #endif /* _UAPI__INCLUDE_LINUX_OOM_H */
index 94e981f810a21d938e863797f9fad25652ef5068..b65c834f83e903c6dd00c062362a93bfd9a51aea 100644 (file)
@@ -67,12 +67,26 @@ struct ptp_perout_request {
        unsigned int rsv[4];          /* Reserved for future use. */
 };
 
+#define PTP_MAX_SAMPLES 25 /* Maximum allowed offset measurement samples. */
+
+struct ptp_sys_offset {
+       unsigned int n_samples; /* Desired number of measurements. */
+       unsigned int rsv[3];    /* Reserved for future use. */
+       /*
+        * Array of interleaved system/phc time stamps. The kernel
+        * will provide 2*n_samples + 1 time stamps, with the last
+        * one as a system time stamp.
+        */
+       struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
+};
+
 #define PTP_CLK_MAGIC '='
 
 #define PTP_CLOCK_GETCAPS  _IOR(PTP_CLK_MAGIC, 1, struct ptp_clock_caps)
 #define PTP_EXTTS_REQUEST  _IOW(PTP_CLK_MAGIC, 2, struct ptp_extts_request)
 #define PTP_PEROUT_REQUEST _IOW(PTP_CLK_MAGIC, 3, struct ptp_perout_request)
 #define PTP_ENABLE_PPS     _IOW(PTP_CLK_MAGIC, 4, int)
+#define PTP_SYS_OFFSET     _IOW(PTP_CLK_MAGIC, 5, struct ptp_sys_offset)
 
 struct ptp_extts_event {
        struct ptp_clock_time t; /* Time event occured. */
index aafaa5aa54d46bb9a93a8137a22344408298223f..e2c3d25405d7e20de2dc708088b0399350bd861f 100644 (file)
@@ -1 +1,3 @@
 # UAPI Header export list
+header-y += md_p.h
+header-y += md_u.h
diff --git a/include/uapi/linux/raid/md_p.h b/include/uapi/linux/raid/md_p.h
new file mode 100644 (file)
index 0000000..ee75353
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+   md_p.h : physical layout of Linux RAID devices
+          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
+         
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _MD_P_H
+#define _MD_P_H
+
+#include <linux/types.h>
+
+/*
+ * RAID superblock.
+ *
+ * The RAID superblock maintains some statistics on each RAID configuration.
+ * Each real device in the RAID set contains it near the end of the device.
+ * Some of the ideas are copied from the ext2fs implementation.
+ *
+ * We currently use 4096 bytes as follows:
+ *
+ *     word offset     function
+ *
+ *        0  -    31   Constant generic RAID device information.
+ *        32  -    63   Generic state information.
+ *       64  -   127   Personality specific information.
+ *      128  -   511   12 32-words descriptors of the disks in the raid set.
+ *      512  -   911   Reserved.
+ *      912  -  1023   Disk specific descriptor.
+ */
+
+/*
+ * If x is the real device size in bytes, we return an apparent size of:
+ *
+ *     y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
+ *
+ * and place the 4kB superblock at offset y.
+ */
+#define MD_RESERVED_BYTES              (64 * 1024)
+#define MD_RESERVED_SECTORS            (MD_RESERVED_BYTES / 512)
+
+#define MD_NEW_SIZE_SECTORS(x)         ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
+
+#define MD_SB_BYTES                    4096
+#define MD_SB_WORDS                    (MD_SB_BYTES / 4)
+#define MD_SB_SECTORS                  (MD_SB_BYTES / 512)
+
+/*
+ * The following are counted in 32-bit words
+ */
+#define        MD_SB_GENERIC_OFFSET            0
+#define MD_SB_PERSONALITY_OFFSET       64
+#define MD_SB_DISKS_OFFSET             128
+#define MD_SB_DESCRIPTOR_OFFSET                992
+
+#define MD_SB_GENERIC_CONSTANT_WORDS   32
+#define MD_SB_GENERIC_STATE_WORDS      32
+#define MD_SB_GENERIC_WORDS            (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
+#define MD_SB_PERSONALITY_WORDS                64
+#define MD_SB_DESCRIPTOR_WORDS         32
+#define MD_SB_DISKS                    27
+#define MD_SB_DISKS_WORDS              (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
+#define MD_SB_RESERVED_WORDS           (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
+#define MD_SB_EQUAL_WORDS              (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
+
+/*
+ * Device "operational" state bits
+ */
+#define MD_DISK_FAULTY         0 /* disk is faulty / operational */
+#define MD_DISK_ACTIVE         1 /* disk is running or spare disk */
+#define MD_DISK_SYNC           2 /* disk is in sync with the raid set */
+#define MD_DISK_REMOVED                3 /* disk is in sync with the raid set */
+
+#define        MD_DISK_WRITEMOSTLY     9 /* disk is "write-mostly" is RAID1 config.
+                                  * read requests will only be sent here in
+                                  * dire need
+                                  */
+
+typedef struct mdp_device_descriptor_s {
+       __u32 number;           /* 0 Device number in the entire set          */
+       __u32 major;            /* 1 Device major number                      */
+       __u32 minor;            /* 2 Device minor number                      */
+       __u32 raid_disk;        /* 3 The role of the device in the raid set   */
+       __u32 state;            /* 4 Operational state                        */
+       __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
+} mdp_disk_t;
+
+#define MD_SB_MAGIC            0xa92b4efc
+
+/*
+ * Superblock state bits
+ */
+#define MD_SB_CLEAN            0
+#define MD_SB_ERRORS           1
+
+#define        MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
+
+/*
+ * Notes:
+ * - if an array is being reshaped (restriped) in order to change the
+ *   the number of active devices in the array, 'raid_disks' will be
+ *   the larger of the old and new numbers.  'delta_disks' will
+ *   be the "new - old".  So if +ve, raid_disks is the new value, and
+ *   "raid_disks-delta_disks" is the old.  If -ve, raid_disks is the
+ *   old value and "raid_disks+delta_disks" is the new (smaller) value.
+ */
+
+
+typedef struct mdp_superblock_s {
+       /*
+        * Constant generic information
+        */
+       __u32 md_magic;         /*  0 MD identifier                           */
+       __u32 major_version;    /*  1 major version to which the set conforms */
+       __u32 minor_version;    /*  2 minor version ...                       */
+       __u32 patch_version;    /*  3 patchlevel version ...                  */
+       __u32 gvalid_words;     /*  4 Number of used words in this section    */
+       __u32 set_uuid0;        /*  5 Raid set identifier                     */
+       __u32 ctime;            /*  6 Creation time                           */
+       __u32 level;            /*  7 Raid personality                        */
+       __u32 size;             /*  8 Apparent size of each individual disk   */
+       __u32 nr_disks;         /*  9 total disks in the raid set             */
+       __u32 raid_disks;       /* 10 disks in a fully functional raid set    */
+       __u32 md_minor;         /* 11 preferred MD minor device number        */
+       __u32 not_persistent;   /* 12 does it have a persistent superblock    */
+       __u32 set_uuid1;        /* 13 Raid set identifier #2                  */
+       __u32 set_uuid2;        /* 14 Raid set identifier #3                  */
+       __u32 set_uuid3;        /* 15 Raid set identifier #4                  */
+       __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
+
+       /*
+        * Generic state information
+        */
+       __u32 utime;            /*  0 Superblock update time                  */
+       __u32 state;            /*  1 State bits (clean, ...)                 */
+       __u32 active_disks;     /*  2 Number of currently active disks        */
+       __u32 working_disks;    /*  3 Number of working disks                 */
+       __u32 failed_disks;     /*  4 Number of failed disks                  */
+       __u32 spare_disks;      /*  5 Number of spare disks                   */
+       __u32 sb_csum;          /*  6 checksum of the whole superblock        */
+#ifdef __BIG_ENDIAN
+       __u32 events_hi;        /*  7 high-order of superblock update count   */
+       __u32 events_lo;        /*  8 low-order of superblock update count    */
+       __u32 cp_events_hi;     /*  9 high-order of checkpoint update count   */
+       __u32 cp_events_lo;     /* 10 low-order of checkpoint update count    */
+#else
+       __u32 events_lo;        /*  7 low-order of superblock update count    */
+       __u32 events_hi;        /*  8 high-order of superblock update count   */
+       __u32 cp_events_lo;     /*  9 low-order of checkpoint update count    */
+       __u32 cp_events_hi;     /* 10 high-order of checkpoint update count   */
+#endif
+       __u32 recovery_cp;      /* 11 recovery checkpoint sector count        */
+       /* There are only valid for minor_version > 90 */
+       __u64 reshape_position; /* 12,13 next address in array-space for reshape */
+       __u32 new_level;        /* 14 new level we are reshaping to           */
+       __u32 delta_disks;      /* 15 change in number of raid_disks          */
+       __u32 new_layout;       /* 16 new layout                              */
+       __u32 new_chunk;        /* 17 new chunk size (bytes)                  */
+       __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
+
+       /*
+        * Personality information
+        */
+       __u32 layout;           /*  0 the array's physical layout             */
+       __u32 chunk_size;       /*  1 chunk size in bytes                     */
+       __u32 root_pv;          /*  2 LV root PV */
+       __u32 root_block;       /*  3 LV root block */
+       __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
+
+       /*
+        * Disks information
+        */
+       mdp_disk_t disks[MD_SB_DISKS];
+
+       /*
+        * Reserved
+        */
+       __u32 reserved[MD_SB_RESERVED_WORDS];
+
+       /*
+        * Active descriptor
+        */
+       mdp_disk_t this_disk;
+
+} mdp_super_t;
+
+static inline __u64 md_event(mdp_super_t *sb) {
+       __u64 ev = sb->events_hi;
+       return (ev<<32)| sb->events_lo;
+}
+
+#define MD_SUPERBLOCK_1_TIME_SEC_MASK ((1ULL<<40) - 1)
+
+/*
+ * The version-1 superblock :
+ * All numeric fields are little-endian.
+ *
+ * total size: 256 bytes plus 2 per device.
+ *  1K allows 384 devices.
+ */
+struct mdp_superblock_1 {
+       /* constant array information - 128 bytes */
+       __le32  magic;          /* MD_SB_MAGIC: 0xa92b4efc - little endian */
+       __le32  major_version;  /* 1 */
+       __le32  feature_map;    /* bit 0 set if 'bitmap_offset' is meaningful */
+       __le32  pad0;           /* always set to 0 when writing */
+
+       __u8    set_uuid[16];   /* user-space generated. */
+       char    set_name[32];   /* set and interpreted by user-space */
+
+       __le64  ctime;          /* lo 40 bits are seconds, top 24 are microseconds or 0*/
+       __le32  level;          /* -4 (multipath), -1 (linear), 0,1,4,5 */
+       __le32  layout;         /* only for raid5 and raid10 currently */
+       __le64  size;           /* used size of component devices, in 512byte sectors */
+
+       __le32  chunksize;      /* in 512byte sectors */
+       __le32  raid_disks;
+       __le32  bitmap_offset;  /* sectors after start of superblock that bitmap starts
+                                * NOTE: signed, so bitmap can be before superblock
+                                * only meaningful of feature_map[0] is set.
+                                */
+
+       /* These are only valid with feature bit '4' */
+       __le32  new_level;      /* new level we are reshaping to                */
+       __le64  reshape_position;       /* next address in array-space for reshape */
+       __le32  delta_disks;    /* change in number of raid_disks               */
+       __le32  new_layout;     /* new layout                                   */
+       __le32  new_chunk;      /* new chunk size (512byte sectors)             */
+       __le32  new_offset;     /* signed number to add to data_offset in new
+                                * layout.  0 == no-change.  This can be
+                                * different on each device in the array.
+                                */
+
+       /* constant this-device information - 64 bytes */
+       __le64  data_offset;    /* sector start of data, often 0 */
+       __le64  data_size;      /* sectors in this device that can be used for data */
+       __le64  super_offset;   /* sector start of this superblock */
+       __le64  recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
+       __le32  dev_number;     /* permanent identifier of this  device - not role in raid */
+       __le32  cnt_corrected_read; /* number of read errors that were corrected by re-writing */
+       __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
+       __u8    devflags;       /* per-device flags.  Only one defined...*/
+#define        WriteMostly1    1       /* mask for writemostly flag in above */
+       /* Bad block log.  If there are any bad blocks the feature flag is set.
+        * If offset and size are non-zero, that space is reserved and available
+        */
+       __u8    bblog_shift;    /* shift from sectors to block size */
+       __le16  bblog_size;     /* number of sectors reserved for list */
+       __le32  bblog_offset;   /* sector offset from superblock to bblog,
+                                * signed - not unsigned */
+
+       /* array state information - 64 bytes */
+       __le64  utime;          /* 40 bits second, 24 bits microseconds */
+       __le64  events;         /* incremented when superblock updated */
+       __le64  resync_offset;  /* data before this offset (from data_offset) known to be in sync */
+       __le32  sb_csum;        /* checksum up to devs[max_dev] */
+       __le32  max_dev;        /* size of devs[] array to consider */
+       __u8    pad3[64-32];    /* set to 0 when writing */
+
+       /* device state information. Indexed by dev_number.
+        * 2 bytes per device
+        * Note there are no per-device state flags. State information is rolled
+        * into the 'roles' value.  If a device is spare or faulty, then it doesn't
+        * have a meaningful role.
+        */
+       __le16  dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
+};
+
+/* feature_map bits */
+#define MD_FEATURE_BITMAP_OFFSET       1
+#define        MD_FEATURE_RECOVERY_OFFSET      2 /* recovery_offset is present and
+                                          * must be honoured
+                                          */
+#define        MD_FEATURE_RESHAPE_ACTIVE       4
+#define        MD_FEATURE_BAD_BLOCKS           8 /* badblock list is not empty */
+#define        MD_FEATURE_REPLACEMENT          16 /* This device is replacing an
+                                           * active device with same 'role'.
+                                           * 'recovery_offset' is also set.
+                                           */
+#define        MD_FEATURE_RESHAPE_BACKWARDS    32 /* Reshape doesn't change number
+                                           * of devices, but is going
+                                           * backwards anyway.
+                                           */
+#define        MD_FEATURE_NEW_OFFSET           64 /* new_offset must be honoured */
+#define        MD_FEATURE_ALL                  (MD_FEATURE_BITMAP_OFFSET       \
+                                       |MD_FEATURE_RECOVERY_OFFSET     \
+                                       |MD_FEATURE_RESHAPE_ACTIVE      \
+                                       |MD_FEATURE_BAD_BLOCKS          \
+                                       |MD_FEATURE_REPLACEMENT         \
+                                       |MD_FEATURE_RESHAPE_BACKWARDS   \
+                                       |MD_FEATURE_NEW_OFFSET          \
+                                       )
+
+#endif 
diff --git a/include/uapi/linux/raid/md_u.h b/include/uapi/linux/raid/md_u.h
new file mode 100644 (file)
index 0000000..4133e74
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
+          Copyright (C) 1998 Ingo Molnar
+         
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+   
+   You should have received a copy of the GNU General Public License
+   (for example /usr/src/linux/COPYING); if not, write to the Free
+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
+*/
+
+#ifndef _UAPI_MD_U_H
+#define _UAPI_MD_U_H
+
+/*
+ * Different major versions are not compatible.
+ * Different minor versions are only downward compatible.
+ * Different patchlevel versions are downward and upward compatible.
+ */
+#define MD_MAJOR_VERSION                0
+#define MD_MINOR_VERSION                90
+/*
+ * MD_PATCHLEVEL_VERSION indicates kernel functionality.
+ * >=1 means different superblock formats are selectable using SET_ARRAY_INFO
+ *     and major_version/minor_version accordingly
+ * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT
+ *     in the super status byte
+ * >=3 means that bitmap superblock version 4 is supported, which uses
+ *     little-ending representation rather than host-endian
+ */
+#define MD_PATCHLEVEL_VERSION           3
+
+/* ioctls */
+
+/* status */
+#define RAID_VERSION           _IOR (MD_MAJOR, 0x10, mdu_version_t)
+#define GET_ARRAY_INFO         _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
+#define GET_DISK_INFO          _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
+#define PRINT_RAID_DEBUG       _IO (MD_MAJOR, 0x13)
+#define RAID_AUTORUN           _IO (MD_MAJOR, 0x14)
+#define GET_BITMAP_FILE                _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
+
+/* configuration */
+#define CLEAR_ARRAY            _IO (MD_MAJOR, 0x20)
+#define ADD_NEW_DISK           _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
+#define HOT_REMOVE_DISK                _IO (MD_MAJOR, 0x22)
+#define SET_ARRAY_INFO         _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
+#define SET_DISK_INFO          _IO (MD_MAJOR, 0x24)
+#define WRITE_RAID_INFO                _IO (MD_MAJOR, 0x25)
+#define UNPROTECT_ARRAY                _IO (MD_MAJOR, 0x26)
+#define PROTECT_ARRAY          _IO (MD_MAJOR, 0x27)
+#define HOT_ADD_DISK           _IO (MD_MAJOR, 0x28)
+#define SET_DISK_FAULTY                _IO (MD_MAJOR, 0x29)
+#define HOT_GENERATE_ERROR     _IO (MD_MAJOR, 0x2a)
+#define SET_BITMAP_FILE                _IOW (MD_MAJOR, 0x2b, int)
+
+/* usage */
+#define RUN_ARRAY              _IOW (MD_MAJOR, 0x30, mdu_param_t)
+/*  0x31 was START_ARRAY  */
+#define STOP_ARRAY             _IO (MD_MAJOR, 0x32)
+#define STOP_ARRAY_RO          _IO (MD_MAJOR, 0x33)
+#define RESTART_ARRAY_RW       _IO (MD_MAJOR, 0x34)
+
+/* 63 partitions with the alternate major number (mdp) */
+#define MdpMinorShift 6
+
+typedef struct mdu_version_s {
+       int major;
+       int minor;
+       int patchlevel;
+} mdu_version_t;
+
+typedef struct mdu_array_info_s {
+       /*
+        * Generic constant information
+        */
+       int major_version;
+       int minor_version;
+       int patch_version;
+       int ctime;
+       int level;
+       int size;
+       int nr_disks;
+       int raid_disks;
+       int md_minor;
+       int not_persistent;
+
+       /*
+        * Generic state information
+        */
+       int utime;              /*  0 Superblock update time                  */
+       int state;              /*  1 State bits (clean, ...)                 */
+       int active_disks;       /*  2 Number of currently active disks        */
+       int working_disks;      /*  3 Number of working disks                 */
+       int failed_disks;       /*  4 Number of failed disks                  */
+       int spare_disks;        /*  5 Number of spare disks                   */
+
+       /*
+        * Personality information
+        */
+       int layout;             /*  0 the array's physical layout             */
+       int chunk_size; /*  1 chunk size in bytes                     */
+
+} mdu_array_info_t;
+
+/* non-obvious values for 'level' */
+#define        LEVEL_MULTIPATH         (-4)
+#define        LEVEL_LINEAR            (-1)
+#define        LEVEL_FAULTY            (-5)
+
+/* we need a value for 'no level specified' and 0
+ * means 'raid0', so we need something else.  This is
+ * for internal use only
+ */
+#define        LEVEL_NONE              (-1000000)
+
+typedef struct mdu_disk_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       int number;
+       int major;
+       int minor;
+       int raid_disk;
+       int state;
+
+} mdu_disk_info_t;
+
+typedef struct mdu_start_info_s {
+       /*
+        * configuration/status of one particular disk
+        */
+       int major;
+       int minor;
+       int raid_disk;
+       int state;
+
+} mdu_start_info_t;
+
+typedef struct mdu_bitmap_file_s
+{
+       char pathname[4096];
+} mdu_bitmap_file_t;
+
+typedef struct mdu_param_s
+{
+       int                     personality;    /* 1,2,3,4 */
+       int                     chunk_size;     /* in bytes */
+       int                     max_fault;      /* unused for now */
+} mdu_param_t;
+
+#endif /* _UAPI_MD_U_H */
index fcd768b09f6e898fdccc64dda92d4ac289d58fdd..354a1e7d32a3f7845da80dc3775738438b6b8edd 100644 (file)
@@ -120,6 +120,14 @@ enum {
        RTM_SETDCB,
 #define RTM_SETDCB RTM_SETDCB
 
+       RTM_NEWNETCONF = 80,
+#define RTM_NEWNETCONF RTM_NEWNETCONF
+       RTM_GETNETCONF = 82,
+#define RTM_GETNETCONF RTM_GETNETCONF
+
+       RTM_GETMDB = 86,
+#define RTM_GETMDB RTM_GETMDB
+
        __RTM_MAX,
 #define RTM_MAX                (((__RTM_MAX + 3) & ~3) - 1)
 };
@@ -222,6 +230,7 @@ enum {
 #define RTPROT_XORP    14      /* XORP */
 #define RTPROT_NTK     15      /* Netsukuku */
 #define RTPROT_DHCP    16      /* DHCP client */
+#define RTPROT_MROUTED 17      /* Multicast daemon */
 
 /* rtm_scope
 
@@ -283,6 +292,7 @@ enum rtattr_type_t {
        RTA_MP_ALGO, /* no longer used */
        RTA_TABLE,
        RTA_MARK,
+       RTA_MFC_STATS,
        __RTA_MAX
 };
 
@@ -403,6 +413,12 @@ struct rta_session {
        } u;
 };
 
+struct rta_mfc_stats {
+       __u64   mfcs_packets;
+       __u64   mfcs_bytes;
+       __u64   mfcs_wrong_if;
+};
+
 /****
  *             General form of address family dependent message.
  ****/
@@ -587,6 +603,10 @@ enum rtnetlink_groups {
 #define RTNLGRP_PHONET_ROUTE   RTNLGRP_PHONET_ROUTE
        RTNLGRP_DCB,
 #define RTNLGRP_DCB            RTNLGRP_DCB
+       RTNLGRP_IPV4_NETCONF,
+#define RTNLGRP_IPV4_NETCONF   RTNLGRP_IPV4_NETCONF
+       RTNLGRP_IPV6_NETCONF,
+#define RTNLGRP_IPV6_NETCONF   RTNLGRP_IPV6_NETCONF
        __RTNLGRP_MAX
 };
 #define RTNLGRP_MAX    (__RTNLGRP_MAX - 1)
index c4b89a5cb7df4ffa3f93a0206e1f03bf19829d31..e962faa5ab0dcf9d58909b0256a78f51029e290b 100644 (file)
@@ -130,6 +130,7 @@ enum {
 #define TCPI_OPT_WSCALE                4
 #define TCPI_OPT_ECN           8 /* ECN was negociated at TCP session init */
 #define TCPI_OPT_ECN_SEEN      16 /* we received at least one packet with ECT */
+#define TCPI_OPT_SYN_DATA      32 /* SYN-ACK acked data in SYN sent or rcvd */
 
 enum tcp_ca_state {
        TCP_CA_Open = 0,
index b1d2bf16b33c92fe4f5e27aafe5d34fe87d5fede..b8a24941db21e82b11d80d0912c057a54bcf7742 100644 (file)
@@ -37,6 +37,7 @@ enum {
        UNIX_DIAG_ICONS,
        UNIX_DIAG_RQLEN,
        UNIX_DIAG_MEMINFO,
+       UNIX_DIAG_SHUTDOWN,
 
        UNIX_DIAG_MAX,
 };
index aafaa5aa54d46bb9a93a8137a22344408298223f..6cb4ea8268349b44864c93d94960a6670059f4ed 100644 (file)
@@ -1 +1,11 @@
 # UAPI Header export list
+header-y += audio.h
+header-y += cdc.h
+header-y += ch11.h
+header-y += ch9.h
+header-y += functionfs.h
+header-y += g_printer.h
+header-y += gadgetfs.h
+header-y += midi.h
+header-y += tmc.h
+header-y += video.h
diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h
new file mode 100644 (file)
index 0000000..ac90037
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+ * <linux/usb/audio.h> -- USB Audio definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for Audio Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/audio10.pdf
+ *
+ * Types and defines in this file are either specific to version 1.0 of
+ * this standard or common for newer versions.
+ */
+
+#ifndef _UAPI__LINUX_USB_AUDIO_H
+#define _UAPI__LINUX_USB_AUDIO_H
+
+#include <linux/types.h>
+
+/* bInterfaceProtocol values to denote the version of the standard used */
+#define UAC_VERSION_1                  0x00
+#define UAC_VERSION_2                  0x20
+
+/* A.2 Audio Interface Subclass Codes */
+#define USB_SUBCLASS_AUDIOCONTROL      0x01
+#define USB_SUBCLASS_AUDIOSTREAMING    0x02
+#define USB_SUBCLASS_MIDISTREAMING     0x03
+
+/* A.5 Audio Class-Specific AC Interface Descriptor Subtypes */
+#define UAC_HEADER                     0x01
+#define UAC_INPUT_TERMINAL             0x02
+#define UAC_OUTPUT_TERMINAL            0x03
+#define UAC_MIXER_UNIT                 0x04
+#define UAC_SELECTOR_UNIT              0x05
+#define UAC_FEATURE_UNIT               0x06
+#define UAC1_PROCESSING_UNIT           0x07
+#define UAC1_EXTENSION_UNIT            0x08
+
+/* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */
+#define UAC_AS_GENERAL                 0x01
+#define UAC_FORMAT_TYPE                        0x02
+#define UAC_FORMAT_SPECIFIC            0x03
+
+/* A.7 Processing Unit Process Types */
+#define UAC_PROCESS_UNDEFINED          0x00
+#define UAC_PROCESS_UP_DOWNMIX         0x01
+#define UAC_PROCESS_DOLBY_PROLOGIC     0x02
+#define UAC_PROCESS_STEREO_EXTENDER    0x03
+#define UAC_PROCESS_REVERB             0x04
+#define UAC_PROCESS_CHORUS             0x05
+#define UAC_PROCESS_DYN_RANGE_COMP     0x06
+
+/* A.8 Audio Class-Specific Endpoint Descriptor Subtypes */
+#define UAC_EP_GENERAL                 0x01
+
+/* A.9 Audio Class-Specific Request Codes */
+#define UAC_SET_                       0x00
+#define UAC_GET_                       0x80
+
+#define UAC__CUR                       0x1
+#define UAC__MIN                       0x2
+#define UAC__MAX                       0x3
+#define UAC__RES                       0x4
+#define UAC__MEM                       0x5
+
+#define UAC_SET_CUR                    (UAC_SET_ | UAC__CUR)
+#define UAC_GET_CUR                    (UAC_GET_ | UAC__CUR)
+#define UAC_SET_MIN                    (UAC_SET_ | UAC__MIN)
+#define UAC_GET_MIN                    (UAC_GET_ | UAC__MIN)
+#define UAC_SET_MAX                    (UAC_SET_ | UAC__MAX)
+#define UAC_GET_MAX                    (UAC_GET_ | UAC__MAX)
+#define UAC_SET_RES                    (UAC_SET_ | UAC__RES)
+#define UAC_GET_RES                    (UAC_GET_ | UAC__RES)
+#define UAC_SET_MEM                    (UAC_SET_ | UAC__MEM)
+#define UAC_GET_MEM                    (UAC_GET_ | UAC__MEM)
+
+#define UAC_GET_STAT                   0xff
+
+/* A.10 Control Selector Codes */
+
+/* A.10.1 Terminal Control Selectors */
+#define UAC_TERM_COPY_PROTECT          0x01
+
+/* A.10.2 Feature Unit Control Selectors */
+#define UAC_FU_MUTE                    0x01
+#define UAC_FU_VOLUME                  0x02
+#define UAC_FU_BASS                    0x03
+#define UAC_FU_MID                     0x04
+#define UAC_FU_TREBLE                  0x05
+#define UAC_FU_GRAPHIC_EQUALIZER       0x06
+#define UAC_FU_AUTOMATIC_GAIN          0x07
+#define UAC_FU_DELAY                   0x08
+#define UAC_FU_BASS_BOOST              0x09
+#define UAC_FU_LOUDNESS                        0x0a
+
+#define UAC_CONTROL_BIT(CS)    (1 << ((CS) - 1))
+
+/* A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */
+#define UAC_UD_ENABLE                  0x01
+#define UAC_UD_MODE_SELECT             0x02
+
+/* A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */
+#define UAC_DP_ENABLE                  0x01
+#define UAC_DP_MODE_SELECT             0x02
+
+/* A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */
+#define UAC_3D_ENABLE                  0x01
+#define UAC_3D_SPACE                   0x02
+
+/* A.10.3.4 Reverberation Processing Unit Control Selectors */
+#define UAC_REVERB_ENABLE              0x01
+#define UAC_REVERB_LEVEL               0x02
+#define UAC_REVERB_TIME                        0x03
+#define UAC_REVERB_FEEDBACK            0x04
+
+/* A.10.3.5 Chorus Processing Unit Control Selectors */
+#define UAC_CHORUS_ENABLE              0x01
+#define UAC_CHORUS_LEVEL               0x02
+#define UAC_CHORUS_RATE                        0x03
+#define UAC_CHORUS_DEPTH               0x04
+
+/* A.10.3.6 Dynamic Range Compressor Unit Control Selectors */
+#define UAC_DCR_ENABLE                 0x01
+#define UAC_DCR_RATE                   0x02
+#define UAC_DCR_MAXAMPL                        0x03
+#define UAC_DCR_THRESHOLD              0x04
+#define UAC_DCR_ATTACK_TIME            0x05
+#define UAC_DCR_RELEASE_TIME           0x06
+
+/* A.10.4 Extension Unit Control Selectors */
+#define UAC_XU_ENABLE                  0x01
+
+/* MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */
+#define UAC_MS_HEADER                  0x01
+#define UAC_MIDI_IN_JACK               0x02
+#define UAC_MIDI_OUT_JACK              0x03
+
+/* MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */
+#define UAC_MS_GENERAL                 0x01
+
+/* Terminals - 2.1 USB Terminal Types */
+#define UAC_TERMINAL_UNDEFINED         0x100
+#define UAC_TERMINAL_STREAMING         0x101
+#define UAC_TERMINAL_VENDOR_SPEC       0x1FF
+
+/* Terminal Control Selectors */
+/* 4.3.2  Class-Specific AC Interface Descriptor */
+struct uac1_ac_header_descriptor {
+       __u8  bLength;                  /* 8 + n */
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* UAC_MS_HEADER */
+       __le16 bcdADC;                  /* 0x0100 */
+       __le16 wTotalLength;            /* includes Unit and Terminal desc. */
+       __u8  bInCollection;            /* n */
+       __u8  baInterfaceNr[];          /* [n] */
+} __attribute__ ((packed));
+
+#define UAC_DT_AC_HEADER_SIZE(n)       (8 + (n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n)                    \
+struct uac1_ac_header_descriptor_##n {                 \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __le16 bcdADC;                                          \
+       __le16 wTotalLength;                                    \
+       __u8  bInCollection;                                    \
+       __u8  baInterfaceNr[n];                                 \
+} __attribute__ ((packed))
+
+/* 4.3.2.1 Input Terminal Descriptor */
+struct uac_input_terminal_descriptor {
+       __u8  bLength;                  /* in bytes: 12 */
+       __u8  bDescriptorType;          /* CS_INTERFACE descriptor type */
+       __u8  bDescriptorSubtype;       /* INPUT_TERMINAL descriptor subtype */
+       __u8  bTerminalID;              /* Constant uniquely terminal ID */
+       __le16 wTerminalType;           /* USB Audio Terminal Types */
+       __u8  bAssocTerminal;           /* ID of the Output Terminal associated */
+       __u8  bNrChannels;              /* Number of logical output channels */
+       __le16 wChannelConfig;
+       __u8  iChannelNames;
+       __u8  iTerminal;
+} __attribute__ ((packed));
+
+#define UAC_DT_INPUT_TERMINAL_SIZE                     12
+
+/* Terminals - 2.2 Input Terminal Types */
+#define UAC_INPUT_TERMINAL_UNDEFINED                   0x200
+#define UAC_INPUT_TERMINAL_MICROPHONE                  0x201
+#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE          0x202
+#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE         0x203
+#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE         0x204
+#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY            0x205
+#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY       0x206
+
+/* Terminals - control selectors */
+
+#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL           0x01
+
+/* 4.3.2.2 Output Terminal Descriptor */
+struct uac1_output_terminal_descriptor {
+       __u8  bLength;                  /* in bytes: 9 */
+       __u8  bDescriptorType;          /* CS_INTERFACE descriptor type */
+       __u8  bDescriptorSubtype;       /* OUTPUT_TERMINAL descriptor subtype */
+       __u8  bTerminalID;              /* Constant uniquely terminal ID */
+       __le16 wTerminalType;           /* USB Audio Terminal Types */
+       __u8  bAssocTerminal;           /* ID of the Input Terminal associated */
+       __u8  bSourceID;                /* ID of the connected Unit or Terminal*/
+       __u8  iTerminal;
+} __attribute__ ((packed));
+
+#define UAC_DT_OUTPUT_TERMINAL_SIZE                    9
+
+/* Terminals - 2.3 Output Terminal Types */
+#define UAC_OUTPUT_TERMINAL_UNDEFINED                  0x300
+#define UAC_OUTPUT_TERMINAL_SPEAKER                    0x301
+#define UAC_OUTPUT_TERMINAL_HEADPHONES                 0x302
+#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303
+#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER            0x304
+#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER               0x305
+#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER      0x306
+#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER   0x307
+
+/* Set bControlSize = 2 as default setting */
+#define UAC_DT_FEATURE_UNIT_SIZE(ch)           (7 + ((ch) + 1) * 2)
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch)                        \
+struct uac_feature_unit_descriptor_##ch {                      \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bUnitID;                                          \
+       __u8  bSourceID;                                        \
+       __u8  bControlSize;                                     \
+       __le16 bmaControls[ch + 1];                             \
+       __u8  iFeature;                                         \
+} __attribute__ ((packed))
+
+/* 4.3.2.3 Mixer Unit Descriptor */
+struct uac_mixer_unit_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bUnitID;
+       __u8 bNrInPins;
+       __u8 baSourceID[];
+} __attribute__ ((packed));
+
+static inline __u8 uac_mixer_unit_bNrChannels(struct uac_mixer_unit_descriptor *desc)
+{
+       return desc->baSourceID[desc->bNrInPins];
+}
+
+static inline __u32 uac_mixer_unit_wChannelConfig(struct uac_mixer_unit_descriptor *desc,
+                                                 int protocol)
+{
+       if (protocol == UAC_VERSION_1)
+               return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
+                       desc->baSourceID[desc->bNrInPins + 1];
+       else
+               return  (desc->baSourceID[desc->bNrInPins + 4] << 24) |
+                       (desc->baSourceID[desc->bNrInPins + 3] << 16) |
+                       (desc->baSourceID[desc->bNrInPins + 2] << 8)  |
+                       (desc->baSourceID[desc->bNrInPins + 1]);
+}
+
+static inline __u8 uac_mixer_unit_iChannelNames(struct uac_mixer_unit_descriptor *desc,
+                                               int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               desc->baSourceID[desc->bNrInPins + 3] :
+               desc->baSourceID[desc->bNrInPins + 5];
+}
+
+static inline __u8 *uac_mixer_unit_bmControls(struct uac_mixer_unit_descriptor *desc,
+                                             int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               &desc->baSourceID[desc->bNrInPins + 4] :
+               &desc->baSourceID[desc->bNrInPins + 6];
+}
+
+static inline __u8 uac_mixer_unit_iMixer(struct uac_mixer_unit_descriptor *desc)
+{
+       __u8 *raw = (__u8 *) desc;
+       return raw[desc->bLength - 1];
+}
+
+/* 4.3.2.4 Selector Unit Descriptor */
+struct uac_selector_unit_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bUintID;
+       __u8 bNrInPins;
+       __u8 baSourceID[];
+} __attribute__ ((packed));
+
+static inline __u8 uac_selector_unit_iSelector(struct uac_selector_unit_descriptor *desc)
+{
+       __u8 *raw = (__u8 *) desc;
+       return raw[desc->bLength - 1];
+}
+
+/* 4.3.2.5 Feature Unit Descriptor */
+struct uac_feature_unit_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bUnitID;
+       __u8 bSourceID;
+       __u8 bControlSize;
+       __u8 bmaControls[0]; /* variable length */
+} __attribute__((packed));
+
+static inline __u8 uac_feature_unit_iFeature(struct uac_feature_unit_descriptor *desc)
+{
+       __u8 *raw = (__u8 *) desc;
+       return raw[desc->bLength - 1];
+}
+
+/* 4.3.2.6 Processing Unit Descriptors */
+struct uac_processing_unit_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bUnitID;
+       __u16 wProcessType;
+       __u8 bNrInPins;
+       __u8 baSourceID[];
+} __attribute__ ((packed));
+
+static inline __u8 uac_processing_unit_bNrChannels(struct uac_processing_unit_descriptor *desc)
+{
+       return desc->baSourceID[desc->bNrInPins];
+}
+
+static inline __u32 uac_processing_unit_wChannelConfig(struct uac_processing_unit_descriptor *desc,
+                                                      int protocol)
+{
+       if (protocol == UAC_VERSION_1)
+               return (desc->baSourceID[desc->bNrInPins + 2] << 8) |
+                       desc->baSourceID[desc->bNrInPins + 1];
+       else
+               return  (desc->baSourceID[desc->bNrInPins + 4] << 24) |
+                       (desc->baSourceID[desc->bNrInPins + 3] << 16) |
+                       (desc->baSourceID[desc->bNrInPins + 2] << 8)  |
+                       (desc->baSourceID[desc->bNrInPins + 1]);
+}
+
+static inline __u8 uac_processing_unit_iChannelNames(struct uac_processing_unit_descriptor *desc,
+                                                    int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               desc->baSourceID[desc->bNrInPins + 3] :
+               desc->baSourceID[desc->bNrInPins + 5];
+}
+
+static inline __u8 uac_processing_unit_bControlSize(struct uac_processing_unit_descriptor *desc,
+                                                   int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               desc->baSourceID[desc->bNrInPins + 4] :
+               desc->baSourceID[desc->bNrInPins + 6];
+}
+
+static inline __u8 *uac_processing_unit_bmControls(struct uac_processing_unit_descriptor *desc,
+                                                  int protocol)
+{
+       return (protocol == UAC_VERSION_1) ?
+               &desc->baSourceID[desc->bNrInPins + 5] :
+               &desc->baSourceID[desc->bNrInPins + 7];
+}
+
+static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_descriptor *desc,
+                                                  int protocol)
+{
+       __u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
+       return desc->baSourceID[desc->bNrInPins + control_size];
+}
+
+static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc,
+                                                int protocol)
+{
+       __u8 control_size = uac_processing_unit_bControlSize(desc, protocol);
+       return &desc->baSourceID[desc->bNrInPins + control_size + 1];
+}
+
+/* 4.5.2 Class-Specific AS Interface Descriptor */
+struct uac1_as_header_descriptor {
+       __u8  bLength;                  /* in bytes: 7 */
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* AS_GENERAL */
+       __u8  bTerminalLink;            /* Terminal ID of connected Terminal */
+       __u8  bDelay;                   /* Delay introduced by the data path */
+       __le16 wFormatTag;              /* The Audio Data Format */
+} __attribute__ ((packed));
+
+#define UAC_DT_AS_HEADER_SIZE          7
+
+/* Formats - A.1.1 Audio Data Format Type I Codes */
+#define UAC_FORMAT_TYPE_I_UNDEFINED    0x0
+#define UAC_FORMAT_TYPE_I_PCM          0x1
+#define UAC_FORMAT_TYPE_I_PCM8         0x2
+#define UAC_FORMAT_TYPE_I_IEEE_FLOAT   0x3
+#define UAC_FORMAT_TYPE_I_ALAW         0x4
+#define UAC_FORMAT_TYPE_I_MULAW                0x5
+
+struct uac_format_type_i_continuous_descriptor {
+       __u8  bLength;                  /* in bytes: 8 + (ns * 3) */
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* FORMAT_TYPE */
+       __u8  bFormatType;              /* FORMAT_TYPE_1 */
+       __u8  bNrChannels;              /* physical channels in the stream */
+       __u8  bSubframeSize;            /* */
+       __u8  bBitResolution;
+       __u8  bSamFreqType;
+       __u8  tLowerSamFreq[3];
+       __u8  tUpperSamFreq[3];
+} __attribute__ ((packed));
+
+#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14
+
+struct uac_format_type_i_discrete_descriptor {
+       __u8  bLength;                  /* in bytes: 8 + (ns * 3) */
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* FORMAT_TYPE */
+       __u8  bFormatType;              /* FORMAT_TYPE_1 */
+       __u8  bNrChannels;              /* physical channels in the stream */
+       __u8  bSubframeSize;            /* */
+       __u8  bBitResolution;
+       __u8  bSamFreqType;
+       __u8  tSamFreq[][3];
+} __attribute__ ((packed));
+
+#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n)             \
+struct uac_format_type_i_discrete_descriptor_##n {             \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bFormatType;                                      \
+       __u8  bNrChannels;                                      \
+       __u8  bSubframeSize;                                    \
+       __u8  bBitResolution;                                   \
+       __u8  bSamFreqType;                                     \
+       __u8  tSamFreq[n][3];                                   \
+} __attribute__ ((packed))
+
+#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n)        (8 + (n * 3))
+
+struct uac_format_type_i_ext_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bFormatType;
+       __u8 bSubslotSize;
+       __u8 bBitResolution;
+       __u8 bHeaderLength;
+       __u8 bControlSize;
+       __u8 bSideBandProtocol;
+} __attribute__((packed));
+
+/* Formats - Audio Data Format Type I Codes */
+
+#define UAC_FORMAT_TYPE_II_MPEG        0x1001
+#define UAC_FORMAT_TYPE_II_AC3 0x1002
+
+struct uac_format_type_ii_discrete_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bFormatType;
+       __le16 wMaxBitRate;
+       __le16 wSamplesPerFrame;
+       __u8 bSamFreqType;
+       __u8 tSamFreq[][3];
+} __attribute__((packed));
+
+struct uac_format_type_ii_ext_descriptor {
+       __u8 bLength;
+       __u8 bDescriptorType;
+       __u8 bDescriptorSubtype;
+       __u8 bFormatType;
+       __u16 wMaxBitRate;
+       __u16 wSamplesPerFrame;
+       __u8 bHeaderLength;
+       __u8 bSideBandProtocol;
+} __attribute__((packed));
+
+/* type III */
+#define UAC_FORMAT_TYPE_III_IEC1937_AC3        0x2001
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1       0x2002
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT        0x2003
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT  0x2004
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS    0x2005
+#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS   0x2006
+
+/* Formats - A.2 Format Type Codes */
+#define UAC_FORMAT_TYPE_UNDEFINED      0x0
+#define UAC_FORMAT_TYPE_I              0x1
+#define UAC_FORMAT_TYPE_II             0x2
+#define UAC_FORMAT_TYPE_III            0x3
+#define UAC_EXT_FORMAT_TYPE_I          0x81
+#define UAC_EXT_FORMAT_TYPE_II         0x82
+#define UAC_EXT_FORMAT_TYPE_III                0x83
+
+struct uac_iso_endpoint_descriptor {
+       __u8  bLength;                  /* in bytes: 7 */
+       __u8  bDescriptorType;          /* USB_DT_CS_ENDPOINT */
+       __u8  bDescriptorSubtype;       /* EP_GENERAL */
+       __u8  bmAttributes;
+       __u8  bLockDelayUnits;
+       __le16 wLockDelay;
+} __attribute__((packed));
+#define UAC_ISO_ENDPOINT_DESC_SIZE     7
+
+#define UAC_EP_CS_ATTR_SAMPLE_RATE     0x01
+#define UAC_EP_CS_ATTR_PITCH_CONTROL   0x02
+#define UAC_EP_CS_ATTR_FILL_MAX                0x80
+
+/* status word format (3.7.1.1) */
+
+#define UAC1_STATUS_TYPE_ORIG_MASK             0x0f
+#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0
+#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF  0x1
+#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP  0x2
+
+#define UAC1_STATUS_TYPE_IRQ_PENDING           (1 << 7)
+#define UAC1_STATUS_TYPE_MEM_CHANGED           (1 << 6)
+
+struct uac1_status_word {
+       __u8 bStatusType;
+       __u8 bOriginator;
+} __attribute__((packed));
+
+
+#endif /* _UAPI__LINUX_USB_AUDIO_H */
diff --git a/include/uapi/linux/usb/cdc.h b/include/uapi/linux/usb/cdc.h
new file mode 100644 (file)
index 0000000..f35aa0a
--- /dev/null
@@ -0,0 +1,435 @@
+/*
+ * USB Communications Device Class (CDC) definitions
+ *
+ * CDC says how to talk to lots of different types of network adapters,
+ * notably ethernet adapters and various modems.  It's used mostly with
+ * firmware based USB peripherals.
+ */
+
+#ifndef __LINUX_USB_CDC_H
+#define __LINUX_USB_CDC_H
+
+#include <linux/types.h>
+
+#define USB_CDC_SUBCLASS_ACM                   0x02
+#define USB_CDC_SUBCLASS_ETHERNET              0x06
+#define USB_CDC_SUBCLASS_WHCM                  0x08
+#define USB_CDC_SUBCLASS_DMM                   0x09
+#define USB_CDC_SUBCLASS_MDLM                  0x0a
+#define USB_CDC_SUBCLASS_OBEX                  0x0b
+#define USB_CDC_SUBCLASS_EEM                   0x0c
+#define USB_CDC_SUBCLASS_NCM                   0x0d
+#define USB_CDC_SUBCLASS_MBIM                  0x0e
+
+#define USB_CDC_PROTO_NONE                     0
+
+#define USB_CDC_ACM_PROTO_AT_V25TER            1
+#define USB_CDC_ACM_PROTO_AT_PCCA101           2
+#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE      3
+#define USB_CDC_ACM_PROTO_AT_GSM               4
+#define USB_CDC_ACM_PROTO_AT_3G                        5
+#define USB_CDC_ACM_PROTO_AT_CDMA              6
+#define USB_CDC_ACM_PROTO_VENDOR               0xff
+
+#define USB_CDC_PROTO_EEM                      7
+
+#define USB_CDC_NCM_PROTO_NTB                  1
+#define USB_CDC_MBIM_PROTO_NTB                 2
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific descriptors ... there are a couple dozen of them
+ */
+
+#define USB_CDC_HEADER_TYPE            0x00    /* header_desc */
+#define USB_CDC_CALL_MANAGEMENT_TYPE   0x01    /* call_mgmt_descriptor */
+#define USB_CDC_ACM_TYPE               0x02    /* acm_descriptor */
+#define USB_CDC_UNION_TYPE             0x06    /* union_desc */
+#define USB_CDC_COUNTRY_TYPE           0x07
+#define USB_CDC_NETWORK_TERMINAL_TYPE  0x0a    /* network_terminal_desc */
+#define USB_CDC_ETHERNET_TYPE          0x0f    /* ether_desc */
+#define USB_CDC_WHCM_TYPE              0x11
+#define USB_CDC_MDLM_TYPE              0x12    /* mdlm_desc */
+#define USB_CDC_MDLM_DETAIL_TYPE       0x13    /* mdlm_detail_desc */
+#define USB_CDC_DMM_TYPE               0x14
+#define USB_CDC_OBEX_TYPE              0x15
+#define USB_CDC_NCM_TYPE               0x1a
+#define USB_CDC_MBIM_TYPE              0x1b
+
+/* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
+struct usb_cdc_header_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __le16  bcdCDC;
+} __attribute__ ((packed));
+
+/* "Call Management Descriptor" from CDC spec  5.2.3.2 */
+struct usb_cdc_call_mgmt_descriptor {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    bmCapabilities;
+#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT                0x01
+#define USB_CDC_CALL_MGMT_CAP_DATA_INTF                0x02
+
+       __u8    bDataInterface;
+} __attribute__ ((packed));
+
+/* "Abstract Control Management Descriptor" from CDC spec  5.2.3.3 */
+struct usb_cdc_acm_descriptor {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    bmCapabilities;
+} __attribute__ ((packed));
+
+/* capabilities from 5.2.3.3 */
+
+#define USB_CDC_COMM_FEATURE   0x01
+#define USB_CDC_CAP_LINE       0x02
+#define USB_CDC_CAP_BRK                0x04
+#define USB_CDC_CAP_NOTIFY     0x08
+
+/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
+struct usb_cdc_union_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    bMasterInterface0;
+       __u8    bSlaveInterface0;
+       /* ... and there could be other slave interfaces */
+} __attribute__ ((packed));
+
+/* "Country Selection Functional Descriptor" from CDC spec 5.2.3.9 */
+struct usb_cdc_country_functional_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    iCountryCodeRelDate;
+       __le16  wCountyCode0;
+       /* ... and there can be a lot of country codes */
+} __attribute__ ((packed));
+
+/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */
+struct usb_cdc_network_terminal_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    bEntityId;
+       __u8    iName;
+       __u8    bChannelIndex;
+       __u8    bPhysicalInterface;
+} __attribute__ ((packed));
+
+/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
+struct usb_cdc_ether_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __u8    iMACAddress;
+       __le32  bmEthernetStatistics;
+       __le16  wMaxSegmentSize;
+       __le16  wNumberMCFilters;
+       __u8    bNumberPowerFilters;
+} __attribute__ ((packed));
+
+/* "Telephone Control Model Functional Descriptor" from CDC WMC spec 6.3..3 */
+struct usb_cdc_dmm_desc {
+       __u8    bFunctionLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubtype;
+       __u16   bcdVersion;
+       __le16  wMaxCommand;
+} __attribute__ ((packed));
+
+/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */
+struct usb_cdc_mdlm_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __le16  bcdVersion;
+       __u8    bGUID[16];
+} __attribute__ ((packed));
+
+/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */
+struct usb_cdc_mdlm_detail_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       /* type is associated with mdlm_desc.bGUID */
+       __u8    bGuidDescriptorType;
+       __u8    bDetailData[0];
+} __attribute__ ((packed));
+
+/* "OBEX Control Model Functional Descriptor" */
+struct usb_cdc_obex_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __le16  bcdVersion;
+} __attribute__ ((packed));
+
+/* "NCM Control Model Functional Descriptor" */
+struct usb_cdc_ncm_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __le16  bcdNcmVersion;
+       __u8    bmNetworkCapabilities;
+} __attribute__ ((packed));
+
+/* "MBIM Control Model Functional Descriptor" */
+struct usb_cdc_mbim_desc {
+       __u8    bLength;
+       __u8    bDescriptorType;
+       __u8    bDescriptorSubType;
+
+       __le16  bcdMBIMVersion;
+       __le16  wMaxControlMessage;
+       __u8    bNumberFilters;
+       __u8    bMaxFilterSize;
+       __le16  wMaxSegmentSize;
+       __u8    bmNetworkCapabilities;
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific Control Requests (6.2)
+ *
+ * section 3.6.2.1 table 4 has the ACM profile, for modems.
+ * section 3.8.2 table 10 has the ethernet profile.
+ *
+ * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant,
+ * heavily dependent on the encapsulated (proprietary) command mechanism.
+ */
+
+#define USB_CDC_SEND_ENCAPSULATED_COMMAND      0x00
+#define USB_CDC_GET_ENCAPSULATED_RESPONSE      0x01
+#define USB_CDC_REQ_SET_LINE_CODING            0x20
+#define USB_CDC_REQ_GET_LINE_CODING            0x21
+#define USB_CDC_REQ_SET_CONTROL_LINE_STATE     0x22
+#define USB_CDC_REQ_SEND_BREAK                 0x23
+#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40
+#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41
+#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42
+#define USB_CDC_SET_ETHERNET_PACKET_FILTER     0x43
+#define USB_CDC_GET_ETHERNET_STATISTIC         0x44
+#define USB_CDC_GET_NTB_PARAMETERS             0x80
+#define USB_CDC_GET_NET_ADDRESS                        0x81
+#define USB_CDC_SET_NET_ADDRESS                        0x82
+#define USB_CDC_GET_NTB_FORMAT                 0x83
+#define USB_CDC_SET_NTB_FORMAT                 0x84
+#define USB_CDC_GET_NTB_INPUT_SIZE             0x85
+#define USB_CDC_SET_NTB_INPUT_SIZE             0x86
+#define USB_CDC_GET_MAX_DATAGRAM_SIZE          0x87
+#define USB_CDC_SET_MAX_DATAGRAM_SIZE          0x88
+#define USB_CDC_GET_CRC_MODE                   0x89
+#define USB_CDC_SET_CRC_MODE                   0x8a
+
+/* Line Coding Structure from CDC spec 6.2.13 */
+struct usb_cdc_line_coding {
+       __le32  dwDTERate;
+       __u8    bCharFormat;
+#define USB_CDC_1_STOP_BITS                    0
+#define USB_CDC_1_5_STOP_BITS                  1
+#define USB_CDC_2_STOP_BITS                    2
+
+       __u8    bParityType;
+#define USB_CDC_NO_PARITY                      0
+#define USB_CDC_ODD_PARITY                     1
+#define USB_CDC_EVEN_PARITY                    2
+#define USB_CDC_MARK_PARITY                    3
+#define USB_CDC_SPACE_PARITY                   4
+
+       __u8    bDataBits;
+} __attribute__ ((packed));
+
+/* table 62; bits in multicast filter */
+#define        USB_CDC_PACKET_TYPE_PROMISCUOUS         (1 << 0)
+#define        USB_CDC_PACKET_TYPE_ALL_MULTICAST       (1 << 1) /* no filter */
+#define        USB_CDC_PACKET_TYPE_DIRECTED            (1 << 2)
+#define        USB_CDC_PACKET_TYPE_BROADCAST           (1 << 3)
+#define        USB_CDC_PACKET_TYPE_MULTICAST           (1 << 4) /* filtered */
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific Notifications (6.3) sent by interrupt transfers
+ *
+ * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications
+ * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS
+ * RNDIS also defines its own bit-incompatible notifications
+ */
+
+#define USB_CDC_NOTIFY_NETWORK_CONNECTION      0x00
+#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE      0x01
+#define USB_CDC_NOTIFY_SERIAL_STATE            0x20
+#define USB_CDC_NOTIFY_SPEED_CHANGE            0x2a
+
+struct usb_cdc_notification {
+       __u8    bmRequestType;
+       __u8    bNotificationType;
+       __le16  wValue;
+       __le16  wIndex;
+       __le16  wLength;
+} __attribute__ ((packed));
+
+struct usb_cdc_speed_change {
+       __le32  DLBitRRate;     /* contains the downlink bit rate (IN pipe) */
+       __le32  ULBitRate;      /* contains the uplink bit rate (OUT pipe) */
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class Specific structures and constants
+ *
+ * CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1
+ *
+ */
+
+struct usb_cdc_ncm_ntb_parameters {
+       __le16  wLength;
+       __le16  bmNtbFormatsSupported;
+       __le32  dwNtbInMaxSize;
+       __le16  wNdpInDivisor;
+       __le16  wNdpInPayloadRemainder;
+       __le16  wNdpInAlignment;
+       __le16  wPadding1;
+       __le32  dwNtbOutMaxSize;
+       __le16  wNdpOutDivisor;
+       __le16  wNdpOutPayloadRemainder;
+       __le16  wNdpOutAlignment;
+       __le16  wNtbOutMaxDatagrams;
+} __attribute__ ((packed));
+
+/*
+ * CDC NCM transfer headers, CDC NCM subclass 3.2
+ */
+
+#define USB_CDC_NCM_NTH16_SIGN         0x484D434E /* NCMH */
+#define USB_CDC_NCM_NTH32_SIGN         0x686D636E /* ncmh */
+
+struct usb_cdc_ncm_nth16 {
+       __le32  dwSignature;
+       __le16  wHeaderLength;
+       __le16  wSequence;
+       __le16  wBlockLength;
+       __le16  wNdpIndex;
+} __attribute__ ((packed));
+
+struct usb_cdc_ncm_nth32 {
+       __le32  dwSignature;
+       __le16  wHeaderLength;
+       __le16  wSequence;
+       __le32  dwBlockLength;
+       __le32  dwNdpIndex;
+} __attribute__ ((packed));
+
+/*
+ * CDC NCM datagram pointers, CDC NCM subclass 3.3
+ */
+
+#define USB_CDC_NCM_NDP16_CRC_SIGN     0x314D434E /* NCM1 */
+#define USB_CDC_NCM_NDP16_NOCRC_SIGN   0x304D434E /* NCM0 */
+#define USB_CDC_NCM_NDP32_CRC_SIGN     0x316D636E /* ncm1 */
+#define USB_CDC_NCM_NDP32_NOCRC_SIGN   0x306D636E /* ncm0 */
+
+#define USB_CDC_MBIM_NDP16_IPS_SIGN     0x00535049 /* IPS<sessionID> : IPS0 for now */
+#define USB_CDC_MBIM_NDP32_IPS_SIGN     0x00737069 /* ips<sessionID> : ips0 for now */
+#define USB_CDC_MBIM_NDP16_DSS_SIGN     0x00535344 /* DSS<sessionID> */
+#define USB_CDC_MBIM_NDP32_DSS_SIGN     0x00737364 /* dss<sessionID> */
+
+/* 16-bit NCM Datagram Pointer Entry */
+struct usb_cdc_ncm_dpe16 {
+       __le16  wDatagramIndex;
+       __le16  wDatagramLength;
+} __attribute__((__packed__));
+
+/* 16-bit NCM Datagram Pointer Table */
+struct usb_cdc_ncm_ndp16 {
+       __le32  dwSignature;
+       __le16  wLength;
+       __le16  wNextNdpIndex;
+       struct  usb_cdc_ncm_dpe16 dpe16[0];
+} __attribute__ ((packed));
+
+/* 32-bit NCM Datagram Pointer Entry */
+struct usb_cdc_ncm_dpe32 {
+       __le32  dwDatagramIndex;
+       __le32  dwDatagramLength;
+} __attribute__((__packed__));
+
+/* 32-bit NCM Datagram Pointer Table */
+struct usb_cdc_ncm_ndp32 {
+       __le32  dwSignature;
+       __le16  wLength;
+       __le16  wReserved6;
+       __le32  dwNextNdpIndex;
+       __le32  dwReserved12;
+       struct  usb_cdc_ncm_dpe32 dpe32[0];
+} __attribute__ ((packed));
+
+/* CDC NCM subclass 3.2.1 and 3.2.2 */
+#define USB_CDC_NCM_NDP16_INDEX_MIN                    0x000C
+#define USB_CDC_NCM_NDP32_INDEX_MIN                    0x0010
+
+/* CDC NCM subclass 3.3.3 Datagram Formatting */
+#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC                        0x30
+#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC              0X31
+
+/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */
+#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS       0x00
+#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO            0xFE
+
+/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */
+#define USB_CDC_NCM_NCAP_ETH_FILTER                    (1 << 0)
+#define USB_CDC_NCM_NCAP_NET_ADDRESS                   (1 << 1)
+#define USB_CDC_NCM_NCAP_ENCAP_COMMAND                 (1 << 2)
+#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE             (1 << 3)
+#define USB_CDC_NCM_NCAP_CRC_MODE                      (1 << 4)
+#define        USB_CDC_NCM_NCAP_NTB_INPUT_SIZE                 (1 << 5)
+
+/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
+#define USB_CDC_NCM_NTB16_SUPPORTED                    (1 << 0)
+#define USB_CDC_NCM_NTB32_SUPPORTED                    (1 << 1)
+
+/* CDC NCM subclass Table 6-3: NTB Parameter Structure */
+#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE                 0x04
+#define USB_CDC_NCM_NTB_MAX_LENGTH                     0x1C
+
+/* CDC NCM subclass 6.2.5 SetNtbFormat */
+#define USB_CDC_NCM_NTB16_FORMAT                       0x00
+#define USB_CDC_NCM_NTB32_FORMAT                       0x01
+
+/* CDC NCM subclass 6.2.7 SetNtbInputSize */
+#define USB_CDC_NCM_NTB_MIN_IN_SIZE                    2048
+#define USB_CDC_NCM_NTB_MIN_OUT_SIZE                   2048
+
+/* NTB Input Size Structure */
+struct usb_cdc_ncm_ndp_input_size {
+       __le32  dwNtbInMaxSize;
+       __le16  wNtbInMaxDatagrams;
+       __le16  wReserved;
+} __attribute__ ((packed));
+
+/* CDC NCM subclass 6.2.11 SetCrcMode */
+#define USB_CDC_NCM_CRC_NOT_APPENDED                   0x00
+#define USB_CDC_NCM_CRC_APPENDED                       0x01
+
+#endif /* __LINUX_USB_CDC_H */
diff --git a/include/uapi/linux/usb/ch11.h b/include/uapi/linux/usb/ch11.h
new file mode 100644 (file)
index 0000000..7692dc6
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * This file holds Hub protocol constants and data structures that are
+ * defined in chapter 11 (Hub Specification) of the USB 2.0 specification.
+ *
+ * It is used/shared between the USB core, the HCDs and couple of other USB
+ * drivers.
+ */
+
+#ifndef __LINUX_CH11_H
+#define __LINUX_CH11_H
+
+#include <linux/types.h>       /* __u8 etc */
+
+/*
+ * Hub request types
+ */
+
+#define USB_RT_HUB     (USB_TYPE_CLASS | USB_RECIP_DEVICE)
+#define USB_RT_PORT    (USB_TYPE_CLASS | USB_RECIP_OTHER)
+
+/*
+ * Hub class requests
+ * See USB 2.0 spec Table 11-16
+ */
+#define HUB_CLEAR_TT_BUFFER    8
+#define HUB_RESET_TT           9
+#define HUB_GET_TT_STATE       10
+#define HUB_STOP_TT            11
+
+/*
+ * Hub class additional requests defined by USB 3.0 spec
+ * See USB 3.0 spec Table 10-6
+ */
+#define HUB_SET_DEPTH          12
+#define HUB_GET_PORT_ERR_COUNT 13
+
+/*
+ * Hub Class feature numbers
+ * See USB 2.0 spec Table 11-17
+ */
+#define C_HUB_LOCAL_POWER      0
+#define C_HUB_OVER_CURRENT     1
+
+/*
+ * Port feature numbers
+ * See USB 2.0 spec Table 11-17
+ */
+#define USB_PORT_FEAT_CONNECTION       0
+#define USB_PORT_FEAT_ENABLE           1
+#define USB_PORT_FEAT_SUSPEND          2       /* L2 suspend */
+#define USB_PORT_FEAT_OVER_CURRENT     3
+#define USB_PORT_FEAT_RESET            4
+#define USB_PORT_FEAT_L1               5       /* L1 suspend */
+#define USB_PORT_FEAT_POWER            8
+#define USB_PORT_FEAT_LOWSPEED         9       /* Should never be used */
+#define USB_PORT_FEAT_C_CONNECTION     16
+#define USB_PORT_FEAT_C_ENABLE         17
+#define USB_PORT_FEAT_C_SUSPEND                18
+#define USB_PORT_FEAT_C_OVER_CURRENT   19
+#define USB_PORT_FEAT_C_RESET          20
+#define USB_PORT_FEAT_TEST              21
+#define USB_PORT_FEAT_INDICATOR         22
+#define USB_PORT_FEAT_C_PORT_L1         23
+
+/*
+ * Port feature selectors added by USB 3.0 spec.
+ * See USB 3.0 spec Table 10-7
+ */
+#define USB_PORT_FEAT_LINK_STATE               5
+#define USB_PORT_FEAT_U1_TIMEOUT               23
+#define USB_PORT_FEAT_U2_TIMEOUT               24
+#define USB_PORT_FEAT_C_PORT_LINK_STATE                25
+#define USB_PORT_FEAT_C_PORT_CONFIG_ERROR      26
+#define USB_PORT_FEAT_REMOTE_WAKE_MASK         27
+#define USB_PORT_FEAT_BH_PORT_RESET            28
+#define USB_PORT_FEAT_C_BH_PORT_RESET          29
+#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT      30
+
+#define USB_PORT_LPM_TIMEOUT(p)                        (((p) & 0xff) << 8)
+
+/* USB 3.0 hub remote wake mask bits, see table 10-14 */
+#define USB_PORT_FEAT_REMOTE_WAKE_CONNECT      (1 << 8)
+#define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT   (1 << 9)
+#define USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT (1 << 10)
+
+/*
+ * Hub Status and Hub Change results
+ * See USB 2.0 spec Table 11-19 and Table 11-20
+ */
+struct usb_port_status {
+       __le16 wPortStatus;
+       __le16 wPortChange;
+} __attribute__ ((packed));
+
+/*
+ * wPortStatus bit field
+ * See USB 2.0 spec Table 11-21
+ */
+#define USB_PORT_STAT_CONNECTION       0x0001
+#define USB_PORT_STAT_ENABLE           0x0002
+#define USB_PORT_STAT_SUSPEND          0x0004
+#define USB_PORT_STAT_OVERCURRENT      0x0008
+#define USB_PORT_STAT_RESET            0x0010
+#define USB_PORT_STAT_L1               0x0020
+/* bits 6 to 7 are reserved */
+#define USB_PORT_STAT_POWER            0x0100
+#define USB_PORT_STAT_LOW_SPEED                0x0200
+#define USB_PORT_STAT_HIGH_SPEED        0x0400
+#define USB_PORT_STAT_TEST              0x0800
+#define USB_PORT_STAT_INDICATOR         0x1000
+/* bits 13 to 15 are reserved */
+
+/*
+ * Additions to wPortStatus bit field from USB 3.0
+ * See USB 3.0 spec Table 10-10
+ */
+#define USB_PORT_STAT_LINK_STATE       0x01e0
+#define USB_SS_PORT_STAT_POWER         0x0200
+#define USB_SS_PORT_STAT_SPEED         0x1c00
+#define USB_PORT_STAT_SPEED_5GBPS      0x0000
+/* Valid only if port is enabled */
+/* Bits that are the same from USB 2.0 */
+#define USB_SS_PORT_STAT_MASK (USB_PORT_STAT_CONNECTION |          \
+                               USB_PORT_STAT_ENABLE |      \
+                               USB_PORT_STAT_OVERCURRENT | \
+                               USB_PORT_STAT_RESET)
+
+/*
+ * Definitions for PORT_LINK_STATE values
+ * (bits 5-8) in wPortStatus
+ */
+#define USB_SS_PORT_LS_U0              0x0000
+#define USB_SS_PORT_LS_U1              0x0020
+#define USB_SS_PORT_LS_U2              0x0040
+#define USB_SS_PORT_LS_U3              0x0060
+#define USB_SS_PORT_LS_SS_DISABLED     0x0080
+#define USB_SS_PORT_LS_RX_DETECT       0x00a0
+#define USB_SS_PORT_LS_SS_INACTIVE     0x00c0
+#define USB_SS_PORT_LS_POLLING         0x00e0
+#define USB_SS_PORT_LS_RECOVERY                0x0100
+#define USB_SS_PORT_LS_HOT_RESET       0x0120
+#define USB_SS_PORT_LS_COMP_MOD                0x0140
+#define USB_SS_PORT_LS_LOOPBACK                0x0160
+
+/*
+ * wPortChange bit field
+ * See USB 2.0 spec Table 11-22 and USB 2.0 LPM ECN Table-4.10
+ * Bits 0 to 5 shown, bits 6 to 15 are reserved
+ */
+#define USB_PORT_STAT_C_CONNECTION     0x0001
+#define USB_PORT_STAT_C_ENABLE         0x0002
+#define USB_PORT_STAT_C_SUSPEND                0x0004
+#define USB_PORT_STAT_C_OVERCURRENT    0x0008
+#define USB_PORT_STAT_C_RESET          0x0010
+#define USB_PORT_STAT_C_L1             0x0020
+/*
+ * USB 3.0 wPortChange bit fields
+ * See USB 3.0 spec Table 10-11
+ */
+#define USB_PORT_STAT_C_BH_RESET       0x0020
+#define USB_PORT_STAT_C_LINK_STATE     0x0040
+#define USB_PORT_STAT_C_CONFIG_ERROR   0x0080
+
+/*
+ * wHubCharacteristics (masks)
+ * See USB 2.0 spec Table 11-13, offset 3
+ */
+#define HUB_CHAR_LPSM          0x0003 /* Logical Power Switching Mode mask */
+#define HUB_CHAR_COMMON_LPSM   0x0000 /* All ports power control at once */
+#define HUB_CHAR_INDV_PORT_LPSM        0x0001 /* per-port power control */
+#define HUB_CHAR_NO_LPSM       0x0002 /* no power switching */
+
+#define HUB_CHAR_COMPOUND      0x0004 /* hub is part of a compound device */
+
+#define HUB_CHAR_OCPM          0x0018 /* Over-Current Protection Mode mask */
+#define HUB_CHAR_COMMON_OCPM   0x0000 /* All ports Over-Current reporting */
+#define HUB_CHAR_INDV_PORT_OCPM        0x0008 /* per-port Over-current reporting */
+#define HUB_CHAR_NO_OCPM       0x0010 /* No Over-current Protection support */
+
+#define HUB_CHAR_TTTT          0x0060 /* TT Think Time mask */
+#define HUB_CHAR_PORTIND       0x0080 /* per-port indicators (LEDs) */
+
+struct usb_hub_status {
+       __le16 wHubStatus;
+       __le16 wHubChange;
+} __attribute__ ((packed));
+
+/*
+ * Hub Status & Hub Change bit masks
+ * See USB 2.0 spec Table 11-19 and Table 11-20
+ * Bits 0 and 1 for wHubStatus and wHubChange
+ * Bits 2 to 15 are reserved for both
+ */
+#define HUB_STATUS_LOCAL_POWER 0x0001
+#define HUB_STATUS_OVERCURRENT 0x0002
+#define HUB_CHANGE_LOCAL_POWER 0x0001
+#define HUB_CHANGE_OVERCURRENT 0x0002
+
+
+/*
+ * Hub descriptor
+ * See USB 2.0 spec Table 11-13
+ */
+
+#define USB_DT_HUB                     (USB_TYPE_CLASS | 0x09)
+#define USB_DT_SS_HUB                  (USB_TYPE_CLASS | 0x0a)
+#define USB_DT_HUB_NONVAR_SIZE         7
+#define USB_DT_SS_HUB_SIZE              12
+
+/*
+ * Hub Device descriptor
+ * USB Hub class device protocols
+ */
+
+#define USB_HUB_PR_FS          0 /* Full speed hub */
+#define USB_HUB_PR_HS_NO_TT    0 /* Hi-speed hub without TT */
+#define USB_HUB_PR_HS_SINGLE_TT        1 /* Hi-speed hub with single TT */
+#define USB_HUB_PR_HS_MULTI_TT 2 /* Hi-speed hub with multiple TT */
+#define USB_HUB_PR_SS          3 /* Super speed hub */
+
+struct usb_hub_descriptor {
+       __u8  bDescLength;
+       __u8  bDescriptorType;
+       __u8  bNbrPorts;
+       __le16 wHubCharacteristics;
+       __u8  bPwrOn2PwrGood;
+       __u8  bHubContrCurrent;
+
+       /* 2.0 and 3.0 hubs differ here */
+       union {
+               struct {
+                       /* add 1 bit for hub status change; round to bytes */
+                       __u8  DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8];
+                       __u8  PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8];
+               }  __attribute__ ((packed)) hs;
+
+               struct {
+                       __u8 bHubHdrDecLat;
+                       __le16 wHubDelay;
+                       __le16 DeviceRemovable;
+               }  __attribute__ ((packed)) ss;
+       } u;
+} __attribute__ ((packed));
+
+/* port indicator status selectors, tables 11-7 and 11-25 */
+#define HUB_LED_AUTO   0
+#define HUB_LED_AMBER  1
+#define HUB_LED_GREEN  2
+#define HUB_LED_OFF    3
+
+enum hub_led_mode {
+       INDICATOR_AUTO = 0,
+       INDICATOR_CYCLE,
+       /* software blinks for attention:  software, hardware, reserved */
+       INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF,
+       INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF,
+       INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF
+} __attribute__ ((packed));
+
+/* Transaction Translator Think Times, in bits */
+#define HUB_TTTT_8_BITS                0x00
+#define HUB_TTTT_16_BITS       0x20
+#define HUB_TTTT_24_BITS       0x40
+#define HUB_TTTT_32_BITS       0x60
+
+#endif /* __LINUX_CH11_H */
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
new file mode 100644 (file)
index 0000000..5059847
--- /dev/null
@@ -0,0 +1,993 @@
+/*
+ * This file holds USB constants and structures that are needed for
+ * USB device APIs.  These are used by the USB device model, which is
+ * defined in chapter 9 of the USB 2.0 specification and in the
+ * Wireless USB 1.0 (spread around).  Linux has several APIs in C that
+ * need these:
+ *
+ * - the master/host side Linux-USB kernel driver API;
+ * - the "usbfs" user space API; and
+ * - the Linux "gadget" slave/device/peripheral side driver API.
+ *
+ * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems
+ * act either as a USB master/host or as a USB slave/device.  That means
+ * the master and slave side APIs benefit from working well together.
+ *
+ * There's also "Wireless USB", using low power short range radios for
+ * peripheral interconnection but otherwise building on the USB framework.
+ *
+ * Note all descriptors are declared '__attribute__((packed))' so that:
+ *
+ * [a] they never get padded, either internally (USB spec writers
+ *     probably handled that) or externally;
+ *
+ * [b] so that accessing bigger-than-a-bytes fields will never
+ *     generate bus errors on any platform, even when the location of
+ *     its descriptor inside a bundle isn't "naturally aligned", and
+ *
+ * [c] for consistency, removing all doubt even when it appears to
+ *     someone that the two other points are non-issues for that
+ *     particular descriptor type.
+ */
+
+#ifndef _UAPI__LINUX_USB_CH9_H
+#define _UAPI__LINUX_USB_CH9_H
+
+#include <linux/types.h>       /* __u8 etc */
+#include <asm/byteorder.h>     /* le16_to_cpu */
+
+/*-------------------------------------------------------------------------*/
+
+/* CONTROL REQUEST SUPPORT */
+
+/*
+ * USB directions
+ *
+ * This bit flag is used in endpoint descriptors' bEndpointAddress field.
+ * It's also one of three fields in control requests bRequestType.
+ */
+#define USB_DIR_OUT                    0               /* to device */
+#define USB_DIR_IN                     0x80            /* to host */
+
+/*
+ * USB types, the second of three bRequestType fields
+ */
+#define USB_TYPE_MASK                  (0x03 << 5)
+#define USB_TYPE_STANDARD              (0x00 << 5)
+#define USB_TYPE_CLASS                 (0x01 << 5)
+#define USB_TYPE_VENDOR                        (0x02 << 5)
+#define USB_TYPE_RESERVED              (0x03 << 5)
+
+/*
+ * USB recipients, the third of three bRequestType fields
+ */
+#define USB_RECIP_MASK                 0x1f
+#define USB_RECIP_DEVICE               0x00
+#define USB_RECIP_INTERFACE            0x01
+#define USB_RECIP_ENDPOINT             0x02
+#define USB_RECIP_OTHER                        0x03
+/* From Wireless USB 1.0 */
+#define USB_RECIP_PORT                 0x04
+#define USB_RECIP_RPIPE                0x05
+
+/*
+ * Standard requests, for the bRequest field of a SETUP packet.
+ *
+ * These are qualified by the bRequestType field, so that for example
+ * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved
+ * by a GET_STATUS request.
+ */
+#define USB_REQ_GET_STATUS             0x00
+#define USB_REQ_CLEAR_FEATURE          0x01
+#define USB_REQ_SET_FEATURE            0x03
+#define USB_REQ_SET_ADDRESS            0x05
+#define USB_REQ_GET_DESCRIPTOR         0x06
+#define USB_REQ_SET_DESCRIPTOR         0x07
+#define USB_REQ_GET_CONFIGURATION      0x08
+#define USB_REQ_SET_CONFIGURATION      0x09
+#define USB_REQ_GET_INTERFACE          0x0A
+#define USB_REQ_SET_INTERFACE          0x0B
+#define USB_REQ_SYNCH_FRAME            0x0C
+#define USB_REQ_SET_SEL                        0x30
+#define USB_REQ_SET_ISOCH_DELAY                0x31
+
+#define USB_REQ_SET_ENCRYPTION         0x0D    /* Wireless USB */
+#define USB_REQ_GET_ENCRYPTION         0x0E
+#define USB_REQ_RPIPE_ABORT            0x0E
+#define USB_REQ_SET_HANDSHAKE          0x0F
+#define USB_REQ_RPIPE_RESET            0x0F
+#define USB_REQ_GET_HANDSHAKE          0x10
+#define USB_REQ_SET_CONNECTION         0x11
+#define USB_REQ_SET_SECURITY_DATA      0x12
+#define USB_REQ_GET_SECURITY_DATA      0x13
+#define USB_REQ_SET_WUSB_DATA          0x14
+#define USB_REQ_LOOPBACK_DATA_WRITE    0x15
+#define USB_REQ_LOOPBACK_DATA_READ     0x16
+#define USB_REQ_SET_INTERFACE_DS       0x17
+
+/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command,
+ * used by hubs to put ports into a new L1 suspend state, except that it
+ * forgot to define its number ...
+ */
+
+/*
+ * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and
+ * are read as a bit array returned by USB_REQ_GET_STATUS.  (So there
+ * are at most sixteen features of each type.)  Hubs may also support a
+ * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend.
+ */
+#define USB_DEVICE_SELF_POWERED                0       /* (read only) */
+#define USB_DEVICE_REMOTE_WAKEUP       1       /* dev may initiate wakeup */
+#define USB_DEVICE_TEST_MODE           2       /* (wired high speed only) */
+#define USB_DEVICE_BATTERY             2       /* (wireless) */
+#define USB_DEVICE_B_HNP_ENABLE                3       /* (otg) dev may initiate HNP */
+#define USB_DEVICE_WUSB_DEVICE         3       /* (wireless)*/
+#define USB_DEVICE_A_HNP_SUPPORT       4       /* (otg) RH port supports HNP */
+#define USB_DEVICE_A_ALT_HNP_SUPPORT   5       /* (otg) other RH port does */
+#define USB_DEVICE_DEBUG_MODE          6       /* (special devices only) */
+
+/*
+ * Test Mode Selectors
+ * See USB 2.0 spec Table 9-7
+ */
+#define        TEST_J          1
+#define        TEST_K          2
+#define        TEST_SE0_NAK    3
+#define        TEST_PACKET     4
+#define        TEST_FORCE_EN   5
+
+/*
+ * New Feature Selectors as added by USB 3.0
+ * See USB 3.0 spec Table 9-6
+ */
+#define USB_DEVICE_U1_ENABLE   48      /* dev may initiate U1 transition */
+#define USB_DEVICE_U2_ENABLE   49      /* dev may initiate U2 transition */
+#define USB_DEVICE_LTM_ENABLE  50      /* dev may send LTM */
+#define USB_INTRF_FUNC_SUSPEND 0       /* function suspend */
+
+#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00
+/*
+ * Suspend Options, Table 9-7 USB 3.0 spec
+ */
+#define USB_INTRF_FUNC_SUSPEND_LP      (1 << (8 + 0))
+#define USB_INTRF_FUNC_SUSPEND_RW      (1 << (8 + 1))
+
+#define USB_ENDPOINT_HALT              0       /* IN/OUT will STALL */
+
+/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */
+#define USB_DEV_STAT_U1_ENABLED                2       /* transition into U1 state */
+#define USB_DEV_STAT_U2_ENABLED                3       /* transition into U2 state */
+#define USB_DEV_STAT_LTM_ENABLED       4       /* Latency tolerance messages */
+
+/**
+ * struct usb_ctrlrequest - SETUP data for a USB device control request
+ * @bRequestType: matches the USB bmRequestType field
+ * @bRequest: matches the USB bRequest field
+ * @wValue: matches the USB wValue field (le16 byte order)
+ * @wIndex: matches the USB wIndex field (le16 byte order)
+ * @wLength: matches the USB wLength field (le16 byte order)
+ *
+ * This structure is used to send control requests to a USB device.  It matches
+ * the different fields of the USB 2.0 Spec section 9.3, table 9-2.  See the
+ * USB spec for a fuller description of the different fields, and what they are
+ * used for.
+ *
+ * Note that the driver for any interface can issue control requests.
+ * For most devices, interfaces don't coordinate with each other, so
+ * such requests may be made at any time.
+ */
+struct usb_ctrlrequest {
+       __u8 bRequestType;
+       __u8 bRequest;
+       __le16 wValue;
+       __le16 wIndex;
+       __le16 wLength;
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or
+ * (rarely) accepted by SET_DESCRIPTOR.
+ *
+ * Note that all multi-byte values here are encoded in little endian
+ * byte order "on the wire".  Within the kernel and when exposed
+ * through the Linux-USB APIs, they are not converted to cpu byte
+ * order; it is the responsibility of the client code to do this.
+ * The single exception is when device and configuration descriptors (but
+ * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD);
+ * in this case the fields are converted to host endianness by the kernel.
+ */
+
+/*
+ * Descriptor types ... USB 2.0 spec table 9.5
+ */
+#define USB_DT_DEVICE                  0x01
+#define USB_DT_CONFIG                  0x02
+#define USB_DT_STRING                  0x03
+#define USB_DT_INTERFACE               0x04
+#define USB_DT_ENDPOINT                        0x05
+#define USB_DT_DEVICE_QUALIFIER                0x06
+#define USB_DT_OTHER_SPEED_CONFIG      0x07
+#define USB_DT_INTERFACE_POWER         0x08
+/* these are from a minor usb 2.0 revision (ECN) */
+#define USB_DT_OTG                     0x09
+#define USB_DT_DEBUG                   0x0a
+#define USB_DT_INTERFACE_ASSOCIATION   0x0b
+/* these are from the Wireless USB spec */
+#define USB_DT_SECURITY                        0x0c
+#define USB_DT_KEY                     0x0d
+#define USB_DT_ENCRYPTION_TYPE         0x0e
+#define USB_DT_BOS                     0x0f
+#define USB_DT_DEVICE_CAPABILITY       0x10
+#define USB_DT_WIRELESS_ENDPOINT_COMP  0x11
+#define USB_DT_WIRE_ADAPTER            0x21
+#define USB_DT_RPIPE                   0x22
+#define USB_DT_CS_RADIO_CONTROL                0x23
+/* From the T10 UAS specification */
+#define USB_DT_PIPE_USAGE              0x24
+/* From the USB 3.0 spec */
+#define        USB_DT_SS_ENDPOINT_COMP         0x30
+
+/* Conventional codes for class-specific descriptors.  The convention is
+ * defined in the USB "Common Class" Spec (3.11).  Individual class specs
+ * are authoritative for their usage, not the "common class" writeup.
+ */
+#define USB_DT_CS_DEVICE               (USB_TYPE_CLASS | USB_DT_DEVICE)
+#define USB_DT_CS_CONFIG               (USB_TYPE_CLASS | USB_DT_CONFIG)
+#define USB_DT_CS_STRING               (USB_TYPE_CLASS | USB_DT_STRING)
+#define USB_DT_CS_INTERFACE            (USB_TYPE_CLASS | USB_DT_INTERFACE)
+#define USB_DT_CS_ENDPOINT             (USB_TYPE_CLASS | USB_DT_ENDPOINT)
+
+/* All standard descriptors have these 2 fields at the beginning */
+struct usb_descriptor_header {
+       __u8  bLength;
+       __u8  bDescriptorType;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE: Device descriptor */
+struct usb_device_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 bcdUSB;
+       __u8  bDeviceClass;
+       __u8  bDeviceSubClass;
+       __u8  bDeviceProtocol;
+       __u8  bMaxPacketSize0;
+       __le16 idVendor;
+       __le16 idProduct;
+       __le16 bcdDevice;
+       __u8  iManufacturer;
+       __u8  iProduct;
+       __u8  iSerialNumber;
+       __u8  bNumConfigurations;
+} __attribute__ ((packed));
+
+#define USB_DT_DEVICE_SIZE             18
+
+
+/*
+ * Device and/or Interface Class codes
+ * as found in bDeviceClass or bInterfaceClass
+ * and defined by www.usb.org documents
+ */
+#define USB_CLASS_PER_INTERFACE                0       /* for DeviceClass */
+#define USB_CLASS_AUDIO                        1
+#define USB_CLASS_COMM                 2
+#define USB_CLASS_HID                  3
+#define USB_CLASS_PHYSICAL             5
+#define USB_CLASS_STILL_IMAGE          6
+#define USB_CLASS_PRINTER              7
+#define USB_CLASS_MASS_STORAGE         8
+#define USB_CLASS_HUB                  9
+#define USB_CLASS_CDC_DATA             0x0a
+#define USB_CLASS_CSCID                        0x0b    /* chip+ smart card */
+#define USB_CLASS_CONTENT_SEC          0x0d    /* content security */
+#define USB_CLASS_VIDEO                        0x0e
+#define USB_CLASS_WIRELESS_CONTROLLER  0xe0
+#define USB_CLASS_MISC                 0xef
+#define USB_CLASS_APP_SPEC             0xfe
+#define USB_CLASS_VENDOR_SPEC          0xff
+
+#define USB_SUBCLASS_VENDOR_SPEC       0xff
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_CONFIG: Configuration descriptor information.
+ *
+ * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
+ * descriptor type is different.  Highspeed-capable devices can look
+ * different depending on what speed they're currently running.  Only
+ * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG
+ * descriptors.
+ */
+struct usb_config_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 wTotalLength;
+       __u8  bNumInterfaces;
+       __u8  bConfigurationValue;
+       __u8  iConfiguration;
+       __u8  bmAttributes;
+       __u8  bMaxPower;
+} __attribute__ ((packed));
+
+#define USB_DT_CONFIG_SIZE             9
+
+/* from config descriptor bmAttributes */
+#define USB_CONFIG_ATT_ONE             (1 << 7)        /* must be set */
+#define USB_CONFIG_ATT_SELFPOWER       (1 << 6)        /* self powered */
+#define USB_CONFIG_ATT_WAKEUP          (1 << 5)        /* can wakeup */
+#define USB_CONFIG_ATT_BATTERY         (1 << 4)        /* battery powered */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_STRING: String descriptor */
+struct usb_string_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 wData[1];                /* UTF-16LE encoded */
+} __attribute__ ((packed));
+
+/* note that "string" zero is special, it holds language codes that
+ * the device supports, not Unicode characters.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_INTERFACE: Interface descriptor */
+struct usb_interface_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bInterfaceNumber;
+       __u8  bAlternateSetting;
+       __u8  bNumEndpoints;
+       __u8  bInterfaceClass;
+       __u8  bInterfaceSubClass;
+       __u8  bInterfaceProtocol;
+       __u8  iInterface;
+} __attribute__ ((packed));
+
+#define USB_DT_INTERFACE_SIZE          9
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_ENDPOINT: Endpoint descriptor */
+struct usb_endpoint_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bEndpointAddress;
+       __u8  bmAttributes;
+       __le16 wMaxPacketSize;
+       __u8  bInterval;
+
+       /* NOTE:  these two are _only_ in audio endpoints. */
+       /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */
+       __u8  bRefresh;
+       __u8  bSynchAddress;
+} __attribute__ ((packed));
+
+#define USB_DT_ENDPOINT_SIZE           7
+#define USB_DT_ENDPOINT_AUDIO_SIZE     9       /* Audio extension */
+
+
+/*
+ * Endpoints
+ */
+#define USB_ENDPOINT_NUMBER_MASK       0x0f    /* in bEndpointAddress */
+#define USB_ENDPOINT_DIR_MASK          0x80
+
+#define USB_ENDPOINT_XFERTYPE_MASK     0x03    /* in bmAttributes */
+#define USB_ENDPOINT_XFER_CONTROL      0
+#define USB_ENDPOINT_XFER_ISOC         1
+#define USB_ENDPOINT_XFER_BULK         2
+#define USB_ENDPOINT_XFER_INT          3
+#define USB_ENDPOINT_MAX_ADJUSTABLE    0x80
+
+/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */
+#define USB_ENDPOINT_INTRTYPE          0x30
+#define USB_ENDPOINT_INTR_PERIODIC     (0 << 4)
+#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4)
+
+#define USB_ENDPOINT_SYNCTYPE          0x0c
+#define USB_ENDPOINT_SYNC_NONE         (0 << 2)
+#define USB_ENDPOINT_SYNC_ASYNC                (1 << 2)
+#define USB_ENDPOINT_SYNC_ADAPTIVE     (2 << 2)
+#define USB_ENDPOINT_SYNC_SYNC         (3 << 2)
+
+#define USB_ENDPOINT_USAGE_MASK                0x30
+#define USB_ENDPOINT_USAGE_DATA                0x00
+#define USB_ENDPOINT_USAGE_FEEDBACK    0x10
+#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20    /* Implicit feedback Data endpoint */
+
+/*-------------------------------------------------------------------------*/
+
+/**
+ * usb_endpoint_num - get the endpoint's number
+ * @epd: endpoint to be checked
+ *
+ * Returns @epd's number: 0 to 15.
+ */
+static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd)
+{
+       return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+}
+
+/**
+ * usb_endpoint_type - get the endpoint's transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according
+ * to @epd's transfer type.
+ */
+static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd)
+{
+       return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
+}
+
+/**
+ * usb_endpoint_dir_in - check if the endpoint has IN direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type IN, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
+}
+
+/**
+ * usb_endpoint_dir_out - check if the endpoint has OUT direction
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type OUT, otherwise it returns false.
+ */
+static inline int usb_endpoint_dir_out(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
+}
+
+/**
+ * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type bulk, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_bulk(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_BULK);
+}
+
+/**
+ * usb_endpoint_xfer_control - check if the endpoint has control transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type control, otherwise it returns false.
+ */
+static inline int usb_endpoint_xfer_control(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_CONTROL);
+}
+
+/**
+ * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type interrupt, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_int(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_INT);
+}
+
+/**
+ * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint is of type isochronous, otherwise it returns
+ * false.
+ */
+static inline int usb_endpoint_xfer_isoc(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+               USB_ENDPOINT_XFER_ISOC);
+}
+
+/**
+ * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_in(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has bulk transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_bulk_out(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_is_int_in - check if the endpoint is interrupt IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_in(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has interrupt transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_int_out(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and IN direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_in(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd);
+}
+
+/**
+ * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
+ * @epd: endpoint to be checked
+ *
+ * Returns true if the endpoint has isochronous transfer type and OUT direction,
+ * otherwise it returns false.
+ */
+static inline int usb_endpoint_is_isoc_out(
+                               const struct usb_endpoint_descriptor *epd)
+{
+       return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd);
+}
+
+/**
+ * usb_endpoint_maxp - get endpoint's max packet size
+ * @epd: endpoint to be checked
+ *
+ * Returns @epd's max packet
+ */
+static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd)
+{
+       return __le16_to_cpu(epd->wMaxPacketSize);
+}
+
+static inline int usb_endpoint_interrupt_type(
+               const struct usb_endpoint_descriptor *epd)
+{
+       return epd->bmAttributes & USB_ENDPOINT_INTRTYPE;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */
+struct usb_ss_ep_comp_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bMaxBurst;
+       __u8  bmAttributes;
+       __le16 wBytesPerInterval;
+} __attribute__ ((packed));
+
+#define USB_DT_SS_EP_COMP_SIZE         6
+
+/* Bits 4:0 of bmAttributes if this is a bulk endpoint */
+static inline int
+usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp)
+{
+       int             max_streams;
+
+       if (!comp)
+               return 0;
+
+       max_streams = comp->bmAttributes & 0x1f;
+
+       if (!max_streams)
+               return 0;
+
+       max_streams = 1 << max_streams;
+
+       return max_streams;
+}
+
+/* Bits 1:0 of bmAttributes if this is an isoc endpoint */
+#define USB_SS_MULT(p)                 (1 + ((p) & 0x3))
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */
+struct usb_qualifier_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 bcdUSB;
+       __u8  bDeviceClass;
+       __u8  bDeviceSubClass;
+       __u8  bDeviceProtocol;
+       __u8  bMaxPacketSize0;
+       __u8  bNumConfigurations;
+       __u8  bRESERVED;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_OTG (from OTG 1.0a supplement) */
+struct usb_otg_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bmAttributes;     /* support for HNP, SRP, etc */
+} __attribute__ ((packed));
+
+/* from usb_otg_descriptor.bmAttributes */
+#define USB_OTG_SRP            (1 << 0)
+#define USB_OTG_HNP            (1 << 1)        /* swap host/device roles */
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEBUG:  for special highspeed devices, replacing serial console */
+struct usb_debug_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       /* bulk endpoints with 8 byte maxpacket */
+       __u8  bDebugInEndpoint;
+       __u8  bDebugOutEndpoint;
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */
+struct usb_interface_assoc_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bFirstInterface;
+       __u8  bInterfaceCount;
+       __u8  bFunctionClass;
+       __u8  bFunctionSubClass;
+       __u8  bFunctionProtocol;
+       __u8  iFunction;
+} __attribute__ ((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_SECURITY:  group of wireless security descriptors, including
+ * encryption types available for setting up a CC/association.
+ */
+struct usb_security_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 wTotalLength;
+       __u8  bNumEncryptionTypes;
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_KEY:  used with {GET,SET}_SECURITY_DATA; only public keys
+ * may be retrieved.
+ */
+struct usb_key_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  tTKID[3];
+       __u8  bReserved;
+       __u8  bKeyData[0];
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_ENCRYPTION_TYPE:  bundled in DT_SECURITY groups */
+struct usb_encryption_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bEncryptionType;
+#define        USB_ENC_TYPE_UNSECURE           0
+#define        USB_ENC_TYPE_WIRED              1       /* non-wireless mode */
+#define        USB_ENC_TYPE_CCM_1              2       /* aes128/cbc session */
+#define        USB_ENC_TYPE_RSA_1              3       /* rsa3072/sha1 auth */
+       __u8  bEncryptionValue;         /* use in SET_ENCRYPTION */
+       __u8  bAuthKeyIndex;
+} __attribute__((packed));
+
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_BOS:  group of device-level capabilities */
+struct usb_bos_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __le16 wTotalLength;
+       __u8  bNumDeviceCaps;
+} __attribute__((packed));
+
+#define USB_DT_BOS_SIZE                5
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_DEVICE_CAPABILITY:  grouped with BOS */
+struct usb_dev_cap_header {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+} __attribute__((packed));
+
+#define        USB_CAP_TYPE_WIRELESS_USB       1
+
+struct usb_wireless_cap_descriptor {   /* Ultra Wide Band */
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+
+       __u8  bmAttributes;
+#define        USB_WIRELESS_P2P_DRD            (1 << 1)
+#define        USB_WIRELESS_BEACON_MASK        (3 << 2)
+#define        USB_WIRELESS_BEACON_SELF        (1 << 2)
+#define        USB_WIRELESS_BEACON_DIRECTED    (2 << 2)
+#define        USB_WIRELESS_BEACON_NONE        (3 << 2)
+       __le16 wPHYRates;       /* bit rates, Mbps */
+#define        USB_WIRELESS_PHY_53             (1 << 0)        /* always set */
+#define        USB_WIRELESS_PHY_80             (1 << 1)
+#define        USB_WIRELESS_PHY_107            (1 << 2)        /* always set */
+#define        USB_WIRELESS_PHY_160            (1 << 3)
+#define        USB_WIRELESS_PHY_200            (1 << 4)        /* always set */
+#define        USB_WIRELESS_PHY_320            (1 << 5)
+#define        USB_WIRELESS_PHY_400            (1 << 6)
+#define        USB_WIRELESS_PHY_480            (1 << 7)
+       __u8  bmTFITXPowerInfo; /* TFI power levels */
+       __u8  bmFFITXPowerInfo; /* FFI power levels */
+       __le16 bmBandGroup;
+       __u8  bReserved;
+} __attribute__((packed));
+
+/* USB 2.0 Extension descriptor */
+#define        USB_CAP_TYPE_EXT                2
+
+struct usb_ext_cap_descriptor {                /* Link Power Management */
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+       __le32 bmAttributes;
+#define USB_LPM_SUPPORT                        (1 << 1)        /* supports LPM */
+#define USB_BESL_SUPPORT               (1 << 2)        /* supports BESL */
+#define USB_BESL_BASELINE_VALID                (1 << 3)        /* Baseline BESL valid*/
+#define USB_BESL_DEEP_VALID            (1 << 4)        /* Deep BESL valid */
+#define USB_GET_BESL_BASELINE(p)       (((p) & (0xf << 8)) >> 8)
+#define USB_GET_BESL_DEEP(p)           (((p) & (0xf << 12)) >> 12)
+} __attribute__((packed));
+
+#define USB_DT_USB_EXT_CAP_SIZE        7
+
+/*
+ * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB
+ * specific device level capabilities
+ */
+#define                USB_SS_CAP_TYPE         3
+struct usb_ss_cap_descriptor {         /* Link Power Management */
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+       __u8  bmAttributes;
+#define USB_LTM_SUPPORT                        (1 << 1) /* supports LTM */
+       __le16 wSpeedSupported;
+#define USB_LOW_SPEED_OPERATION                (1)      /* Low speed operation */
+#define USB_FULL_SPEED_OPERATION       (1 << 1) /* Full speed operation */
+#define USB_HIGH_SPEED_OPERATION       (1 << 2) /* High speed operation */
+#define USB_5GBPS_OPERATION            (1 << 3) /* Operation at 5Gbps */
+       __u8  bFunctionalitySupport;
+       __u8  bU1devExitLat;
+       __le16 bU2DevExitLat;
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CAP_SIZE 10
+
+/*
+ * Container ID Capability descriptor: Defines the instance unique ID used to
+ * identify the instance across all operating modes
+ */
+#define        CONTAINER_ID_TYPE       4
+struct usb_ss_container_id_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDevCapabilityType;
+       __u8  bReserved;
+       __u8  ContainerID[16]; /* 128-bit number */
+} __attribute__((packed));
+
+#define USB_DT_USB_SS_CONTN_ID_SIZE    20
+/*-------------------------------------------------------------------------*/
+
+/* USB_DT_WIRELESS_ENDPOINT_COMP:  companion descriptor associated with
+ * each endpoint descriptor for a wireless device
+ */
+struct usb_wireless_ep_comp_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bMaxBurst;
+       __u8  bMaxSequence;
+       __le16 wMaxStreamDelay;
+       __le16 wOverTheAirPacketSize;
+       __u8  bOverTheAirInterval;
+       __u8  bmCompAttributes;
+#define USB_ENDPOINT_SWITCH_MASK       0x03    /* in bmCompAttributes */
+#define USB_ENDPOINT_SWITCH_NO         0
+#define USB_ENDPOINT_SWITCH_SWITCH     1
+#define USB_ENDPOINT_SWITCH_SCALE      2
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless
+ * host and a device for connection set up, mutual authentication, and
+ * exchanging short lived session keys.  The handshake depends on a CC.
+ */
+struct usb_handshake {
+       __u8 bMessageNumber;
+       __u8 bStatus;
+       __u8 tTKID[3];
+       __u8 bReserved;
+       __u8 CDID[16];
+       __u8 nonce[16];
+       __u8 MIC[8];
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC).
+ * A CC may also be set up using non-wireless secure channels (including
+ * wired USB!), and some devices may support CCs with multiple hosts.
+ */
+struct usb_connection_context {
+       __u8 CHID[16];          /* persistent host id */
+       __u8 CDID[16];          /* device id (unique w/in host context) */
+       __u8 CK[16];            /* connection key */
+} __attribute__((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/* USB 2.0 defines three speeds, here's how Linux identifies them */
+
+enum usb_device_speed {
+       USB_SPEED_UNKNOWN = 0,                  /* enumerating */
+       USB_SPEED_LOW, USB_SPEED_FULL,          /* usb 1.1 */
+       USB_SPEED_HIGH,                         /* usb 2.0 */
+       USB_SPEED_WIRELESS,                     /* wireless (usb 2.5) */
+       USB_SPEED_SUPER,                        /* usb 3.0 */
+};
+
+
+enum usb_device_state {
+       /* NOTATTACHED isn't in the USB spec, and this state acts
+        * the same as ATTACHED ... but it's clearer this way.
+        */
+       USB_STATE_NOTATTACHED = 0,
+
+       /* chapter 9 and authentication (wireless) device states */
+       USB_STATE_ATTACHED,
+       USB_STATE_POWERED,                      /* wired */
+       USB_STATE_RECONNECTING,                 /* auth */
+       USB_STATE_UNAUTHENTICATED,              /* auth */
+       USB_STATE_DEFAULT,                      /* limited function */
+       USB_STATE_ADDRESS,
+       USB_STATE_CONFIGURED,                   /* most functions */
+
+       USB_STATE_SUSPENDED
+
+       /* NOTE:  there are actually four different SUSPENDED
+        * states, returning to POWERED, DEFAULT, ADDRESS, or
+        * CONFIGURED respectively when SOF tokens flow again.
+        * At this level there's no difference between L1 and L2
+        * suspend states.  (L2 being original USB 1.1 suspend.)
+        */
+};
+
+enum usb3_link_state {
+       USB3_LPM_U0 = 0,
+       USB3_LPM_U1,
+       USB3_LPM_U2,
+       USB3_LPM_U3
+};
+
+/*
+ * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1.
+ * 0xff means the parent hub will accept transitions to U1, but will not
+ * initiate a transition.
+ *
+ * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to
+ * U1 after that many microseconds.  Timeouts of 0x80 to 0xFE are reserved
+ * values.
+ *
+ * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2.
+ * 0xff means the parent hub will accept transitions to U2, but will not
+ * initiate a transition.
+ *
+ * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to
+ * U2 after N*256 microseconds.  Therefore a U2 timeout value of 0x1 means a U2
+ * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means
+ * 65.024ms.
+ */
+#define USB3_LPM_DISABLED              0x0
+#define USB3_LPM_U1_MAX_TIMEOUT                0x7F
+#define USB3_LPM_U2_MAX_TIMEOUT                0xFE
+#define USB3_LPM_DEVICE_INITIATED      0xFF
+
+struct usb_set_sel_req {
+       __u8    u1_sel;
+       __u8    u1_pel;
+       __le16  u2_sel;
+       __le16  u2_pel;
+} __attribute__ ((packed));
+
+/*
+ * The Set System Exit Latency control transfer provides one byte each for
+ * U1 SEL and U1 PEL, so the max exit latency is 0xFF.  U2 SEL and U2 PEL each
+ * are two bytes long.
+ */
+#define USB3_LPM_MAX_U1_SEL_PEL                0xFF
+#define USB3_LPM_MAX_U2_SEL_PEL                0xFFFF
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * As per USB compliance update, a device that is actively drawing
+ * more than 100mA from USB must report itself as bus-powered in
+ * the GetStatus(DEVICE) call.
+ * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34
+ */
+#define USB_SELF_POWER_VBUS_MAX_DRAW           100
+
+#endif /* _UAPI__LINUX_USB_CH9_H */
diff --git a/include/uapi/linux/usb/functionfs.h b/include/uapi/linux/usb/functionfs.h
new file mode 100644 (file)
index 0000000..d6b0128
--- /dev/null
@@ -0,0 +1,169 @@
+#ifndef _UAPI__LINUX_FUNCTIONFS_H__
+#define _UAPI__LINUX_FUNCTIONFS_H__
+
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include <linux/usb/ch9.h>
+
+
+enum {
+       FUNCTIONFS_DESCRIPTORS_MAGIC = 1,
+       FUNCTIONFS_STRINGS_MAGIC     = 2
+};
+
+
+#ifndef __KERNEL__
+
+/* Descriptor of an non-audio endpoint */
+struct usb_endpoint_descriptor_no_audio {
+       __u8  bLength;
+       __u8  bDescriptorType;
+
+       __u8  bEndpointAddress;
+       __u8  bmAttributes;
+       __le16 wMaxPacketSize;
+       __u8  bInterval;
+} __attribute__((packed));
+
+
+/*
+ * All numbers must be in little endian order.
+ */
+
+struct usb_functionfs_descs_head {
+       __le32 magic;
+       __le32 length;
+       __le32 fs_count;
+       __le32 hs_count;
+} __attribute__((packed));
+
+/*
+ * Descriptors format:
+ *
+ * | off | name      | type         | description                          |
+ * |-----+-----------+--------------+--------------------------------------|
+ * |   0 | magic     | LE32         | FUNCTIONFS_{FS,HS}_DESCRIPTORS_MAGIC |
+ * |   4 | length    | LE32         | length of the whole data chunk       |
+ * |   8 | fs_count  | LE32         | number of full-speed descriptors     |
+ * |  12 | hs_count  | LE32         | number of high-speed descriptors     |
+ * |  16 | fs_descrs | Descriptor[] | list of full-speed descriptors       |
+ * |     | hs_descrs | Descriptor[] | list of high-speed descriptors       |
+ *
+ * descs are just valid USB descriptors and have the following format:
+ *
+ * | off | name            | type | description              |
+ * |-----+-----------------+------+--------------------------|
+ * |   0 | bLength         | U8   | length of the descriptor |
+ * |   1 | bDescriptorType | U8   | descriptor type          |
+ * |   2 | payload         |      | descriptor's payload     |
+ */
+
+struct usb_functionfs_strings_head {
+       __le32 magic;
+       __le32 length;
+       __le32 str_count;
+       __le32 lang_count;
+} __attribute__((packed));
+
+/*
+ * Strings format:
+ *
+ * | off | name       | type                  | description                |
+ * |-----+------------+-----------------------+----------------------------|
+ * |   0 | magic      | LE32                  | FUNCTIONFS_STRINGS_MAGIC   |
+ * |   4 | length     | LE32                  | length of the data chunk   |
+ * |   8 | str_count  | LE32                  | number of strings          |
+ * |  12 | lang_count | LE32                  | number of languages        |
+ * |  16 | stringtab  | StringTab[lang_count] | table of strings per lang  |
+ *
+ * For each language there is one stringtab entry (ie. there are lang_count
+ * stringtab entires).  Each StringTab has following format:
+ *
+ * | off | name    | type              | description                        |
+ * |-----+---------+-------------------+------------------------------------|
+ * |   0 | lang    | LE16              | language code                      |
+ * |   2 | strings | String[str_count] | array of strings in given language |
+ *
+ * For each string there is one strings entry (ie. there are str_count
+ * string entries).  Each String is a NUL terminated string encoded in
+ * UTF-8.
+ */
+
+#endif
+
+
+/*
+ * Events are delivered on the ep0 file descriptor, when the user mode driver
+ * reads from this file descriptor after writing the descriptors.  Don't
+ * stop polling this descriptor.
+ */
+
+enum usb_functionfs_event_type {
+       FUNCTIONFS_BIND,
+       FUNCTIONFS_UNBIND,
+
+       FUNCTIONFS_ENABLE,
+       FUNCTIONFS_DISABLE,
+
+       FUNCTIONFS_SETUP,
+
+       FUNCTIONFS_SUSPEND,
+       FUNCTIONFS_RESUME
+};
+
+/* NOTE:  this structure must stay the same size and layout on
+ * both 32-bit and 64-bit kernels.
+ */
+struct usb_functionfs_event {
+       union {
+               /* SETUP: packet; DATA phase i/o precedes next event
+                *(setup.bmRequestType & USB_DIR_IN) flags direction */
+               struct usb_ctrlrequest  setup;
+       } __attribute__((packed)) u;
+
+       /* enum usb_functionfs_event_type */
+       __u8                            type;
+       __u8                            _pad[3];
+} __attribute__((packed));
+
+
+/* Endpoint ioctls */
+/* The same as in gadgetfs */
+
+/* IN transfers may be reported to the gadget driver as complete
+ *     when the fifo is loaded, before the host reads the data;
+ * OUT transfers may be reported to the host's "client" driver as
+ *     complete when they're sitting in the FIFO unread.
+ * THIS returns how many bytes are "unclaimed" in the endpoint fifo
+ * (needed for precise fault handling, when the hardware allows it)
+ */
+#define        FUNCTIONFS_FIFO_STATUS  _IO('g', 1)
+
+/* discards any unclaimed data in the fifo. */
+#define        FUNCTIONFS_FIFO_FLUSH   _IO('g', 2)
+
+/* resets endpoint halt+toggle; used to implement set_interface.
+ * some hardware (like pxa2xx) can't support this.
+ */
+#define        FUNCTIONFS_CLEAR_HALT   _IO('g', 3)
+
+/* Specific for functionfs */
+
+/*
+ * Returns reverse mapping of an interface.  Called on EP0.  If there
+ * is no such interface returns -EDOM.  If function is not active
+ * returns -ENODEV.
+ */
+#define        FUNCTIONFS_INTERFACE_REVMAP     _IO('g', 128)
+
+/*
+ * Returns real bEndpointAddress of an endpoint.  If function is not
+ * active returns -ENODEV.
+ */
+#define        FUNCTIONFS_ENDPOINT_REVMAP      _IO('g', 129)
+
+
+
+#endif /* _UAPI__LINUX_FUNCTIONFS_H__ */
diff --git a/include/uapi/linux/usb/g_printer.h b/include/uapi/linux/usb/g_printer.h
new file mode 100644 (file)
index 0000000..6178fde
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * g_printer.h -- Header file for USB Printer gadget driver
+ *
+ * Copyright (C) 2007 Craig W. Nadler
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __LINUX_USB_G_PRINTER_H
+#define __LINUX_USB_G_PRINTER_H
+
+#define PRINTER_NOT_ERROR      0x08
+#define PRINTER_SELECTED       0x10
+#define PRINTER_PAPER_EMPTY    0x20
+
+/* The 'g' code is also used by gadgetfs ioctl requests.
+ * Don't add any colliding codes to either driver, and keep
+ * them in unique ranges (size 0x20 for now).
+ */
+#define GADGET_GET_PRINTER_STATUS      _IOR('g', 0x21, unsigned char)
+#define GADGET_SET_PRINTER_STATUS      _IOWR('g', 0x22, unsigned char)
+
+#endif /* __LINUX_USB_G_PRINTER_H */
diff --git a/include/uapi/linux/usb/gadgetfs.h b/include/uapi/linux/usb/gadgetfs.h
new file mode 100644 (file)
index 0000000..0bb12e0
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Filesystem based user-mode API to USB Gadget controller hardware
+ *
+ * Other than ep0 operations, most things are done by read() and write()
+ * on endpoint files found in one directory.  They are configured by
+ * writing descriptors, and then may be used for normal stream style
+ * i/o requests.  When ep0 is configured, the device can enumerate;
+ * when it's closed, the device disconnects from usb.  Operations on
+ * ep0 require ioctl() operations.
+ *
+ * Configuration and device descriptors get written to /dev/gadget/$CHIP,
+ * which may then be used to read usb_gadgetfs_event structs.  The driver
+ * may activate endpoints as it handles SET_CONFIGURATION setup events,
+ * or earlier; writing endpoint descriptors to /dev/gadget/$ENDPOINT
+ * then performing data transfers by reading or writing.
+ */
+
+#ifndef __LINUX_USB_GADGETFS_H
+#define __LINUX_USB_GADGETFS_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#include <linux/usb/ch9.h>
+
+/*
+ * Events are delivered on the ep0 file descriptor, when the user mode driver
+ * reads from this file descriptor after writing the descriptors.  Don't
+ * stop polling this descriptor.
+ */
+
+enum usb_gadgetfs_event_type {
+       GADGETFS_NOP = 0,
+
+       GADGETFS_CONNECT,
+       GADGETFS_DISCONNECT,
+       GADGETFS_SETUP,
+       GADGETFS_SUSPEND,
+       /* and likely more ! */
+};
+
+/* NOTE:  this structure must stay the same size and layout on
+ * both 32-bit and 64-bit kernels.
+ */
+struct usb_gadgetfs_event {
+       union {
+               /* NOP, DISCONNECT, SUSPEND: nothing
+                * ... some hardware can't report disconnection
+                */
+
+               /* CONNECT: just the speed */
+               enum usb_device_speed   speed;
+
+               /* SETUP: packet; DATA phase i/o precedes next event
+                *(setup.bmRequestType & USB_DIR_IN) flags direction
+                * ... includes SET_CONFIGURATION, SET_INTERFACE
+                */
+               struct usb_ctrlrequest  setup;
+       } u;
+       enum usb_gadgetfs_event_type    type;
+};
+
+
+/* The 'g' code is also used by printer gadget ioctl requests.
+ * Don't add any colliding codes to either driver, and keep
+ * them in unique ranges (size 0x20 for now).
+ */
+
+/* endpoint ioctls */
+
+/* IN transfers may be reported to the gadget driver as complete
+ *     when the fifo is loaded, before the host reads the data;
+ * OUT transfers may be reported to the host's "client" driver as
+ *     complete when they're sitting in the FIFO unread.
+ * THIS returns how many bytes are "unclaimed" in the endpoint fifo
+ * (needed for precise fault handling, when the hardware allows it)
+ */
+#define        GADGETFS_FIFO_STATUS    _IO('g', 1)
+
+/* discards any unclaimed data in the fifo. */
+#define        GADGETFS_FIFO_FLUSH     _IO('g', 2)
+
+/* resets endpoint halt+toggle; used to implement set_interface.
+ * some hardware (like pxa2xx) can't support this.
+ */
+#define        GADGETFS_CLEAR_HALT     _IO('g', 3)
+
+#endif /* __LINUX_USB_GADGETFS_H */
diff --git a/include/uapi/linux/usb/midi.h b/include/uapi/linux/usb/midi.h
new file mode 100644 (file)
index 0000000..c8c52e3
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * <linux/usb/midi.h> -- USB MIDI definitions.
+ *
+ * Copyright (C) 2006 Thumtronics Pty Ltd.
+ * Developed for Thumtronics by Grey Innovation
+ * Ben Williamson <ben.williamson@greyinnovation.com>
+ *
+ * This software is distributed under the terms of the GNU General Public
+ * License ("GPL") version 2, as published by the Free Software Foundation.
+ *
+ * This file holds USB constants and structures defined
+ * by the USB Device Class Definition for MIDI Devices.
+ * Comments below reference relevant sections of that document:
+ *
+ * http://www.usb.org/developers/devclass_docs/midi10.pdf
+ */
+
+#ifndef __LINUX_USB_MIDI_H
+#define __LINUX_USB_MIDI_H
+
+#include <linux/types.h>
+
+/* A.1  MS Class-Specific Interface Descriptor Subtypes */
+#define USB_MS_HEADER          0x01
+#define USB_MS_MIDI_IN_JACK    0x02
+#define USB_MS_MIDI_OUT_JACK   0x03
+#define USB_MS_ELEMENT         0x04
+
+/* A.2  MS Class-Specific Endpoint Descriptor Subtypes */
+#define USB_MS_GENERAL         0x01
+
+/* A.3  MS MIDI IN and OUT Jack Types */
+#define USB_MS_EMBEDDED                0x01
+#define USB_MS_EXTERNAL                0x02
+
+/* 6.1.2.1  Class-Specific MS Interface Header Descriptor */
+struct usb_ms_header_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubtype;
+       __le16 bcdMSC;
+       __le16 wTotalLength;
+} __attribute__ ((packed));
+
+#define USB_DT_MS_HEADER_SIZE  7
+
+/* 6.1.2.2  MIDI IN Jack Descriptor */
+struct usb_midi_in_jack_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* USB_MS_MIDI_IN_JACK */
+       __u8  bJackType;                /* USB_MS_EMBEDDED/EXTERNAL */
+       __u8  bJackID;
+       __u8  iJack;
+} __attribute__ ((packed));
+
+#define USB_DT_MIDI_IN_SIZE    6
+
+struct usb_midi_source_pin {
+       __u8  baSourceID;
+       __u8  baSourcePin;
+} __attribute__ ((packed));
+
+/* 6.1.2.3  MIDI OUT Jack Descriptor */
+struct usb_midi_out_jack_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;          /* USB_DT_CS_INTERFACE */
+       __u8  bDescriptorSubtype;       /* USB_MS_MIDI_OUT_JACK */
+       __u8  bJackType;                /* USB_MS_EMBEDDED/EXTERNAL */
+       __u8  bJackID;
+       __u8  bNrInputPins;             /* p */
+       struct usb_midi_source_pin pins[]; /* [p] */
+       /*__u8  iJack;  -- omitted due to variable-sized pins[] */
+} __attribute__ ((packed));
+
+#define USB_DT_MIDI_OUT_SIZE(p)        (7 + 2 * (p))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(p)                        \
+struct usb_midi_out_jack_descriptor_##p {                      \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bJackType;                                        \
+       __u8  bJackID;                                          \
+       __u8  bNrInputPins;                                     \
+       struct usb_midi_source_pin pins[p];                     \
+       __u8  iJack;                                            \
+} __attribute__ ((packed))
+
+/* 6.2.2  Class-Specific MS Bulk Data Endpoint Descriptor */
+struct usb_ms_endpoint_descriptor {
+       __u8  bLength;                  /* 4+n */
+       __u8  bDescriptorType;          /* USB_DT_CS_ENDPOINT */
+       __u8  bDescriptorSubtype;       /* USB_MS_GENERAL */
+       __u8  bNumEmbMIDIJack;          /* n */
+       __u8  baAssocJackID[];          /* [n] */
+} __attribute__ ((packed));
+
+#define USB_DT_MS_ENDPOINT_SIZE(n)     (4 + (n))
+
+/* As above, but more useful for defining your own descriptors: */
+#define DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(n)                  \
+struct usb_ms_endpoint_descriptor_##n {                                \
+       __u8  bLength;                                          \
+       __u8  bDescriptorType;                                  \
+       __u8  bDescriptorSubtype;                               \
+       __u8  bNumEmbMIDIJack;                                  \
+       __u8  baAssocJackID[n];                                 \
+} __attribute__ ((packed))
+
+#endif /* __LINUX_USB_MIDI_H */
diff --git a/include/uapi/linux/usb/tmc.h b/include/uapi/linux/usb/tmc.h
new file mode 100644 (file)
index 0000000..c045ae1
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2007 Stefan Kopp, Gechingen, Germany
+ * Copyright (C) 2008 Novell, Inc.
+ * Copyright (C) 2008 Greg Kroah-Hartman <gregkh@suse.de>
+ *
+ * This file holds USB constants defined by the USB Device Class
+ * Definition for Test and Measurement devices published by the USB-IF.
+ *
+ * It also has the ioctl definitions for the usbtmc kernel driver that
+ * userspace needs to know about.
+ */
+
+#ifndef __LINUX_USB_TMC_H
+#define __LINUX_USB_TMC_H
+
+/* USB TMC status values */
+#define USBTMC_STATUS_SUCCESS                          0x01
+#define USBTMC_STATUS_PENDING                          0x02
+#define USBTMC_STATUS_FAILED                           0x80
+#define USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS         0x81
+#define USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS            0x82
+#define USBTMC_STATUS_SPLIT_IN_PROGRESS                        0x83
+
+/* USB TMC requests values */
+#define USBTMC_REQUEST_INITIATE_ABORT_BULK_OUT         1
+#define USBTMC_REQUEST_CHECK_ABORT_BULK_OUT_STATUS     2
+#define USBTMC_REQUEST_INITIATE_ABORT_BULK_IN          3
+#define USBTMC_REQUEST_CHECK_ABORT_BULK_IN_STATUS      4
+#define USBTMC_REQUEST_INITIATE_CLEAR                  5
+#define USBTMC_REQUEST_CHECK_CLEAR_STATUS              6
+#define USBTMC_REQUEST_GET_CAPABILITIES                        7
+#define USBTMC_REQUEST_INDICATOR_PULSE                 64
+
+/* Request values for USBTMC driver's ioctl entry point */
+#define USBTMC_IOC_NR                  91
+#define USBTMC_IOCTL_INDICATOR_PULSE   _IO(USBTMC_IOC_NR, 1)
+#define USBTMC_IOCTL_CLEAR             _IO(USBTMC_IOC_NR, 2)
+#define USBTMC_IOCTL_ABORT_BULK_OUT    _IO(USBTMC_IOC_NR, 3)
+#define USBTMC_IOCTL_ABORT_BULK_IN     _IO(USBTMC_IOC_NR, 4)
+#define USBTMC_IOCTL_CLEAR_OUT_HALT    _IO(USBTMC_IOC_NR, 6)
+#define USBTMC_IOCTL_CLEAR_IN_HALT     _IO(USBTMC_IOC_NR, 7)
+
+#endif
diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h
new file mode 100644 (file)
index 0000000..3b3b95e
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * USB Video Class definitions.
+ *
+ * Copyright (C) 2009 Laurent Pinchart <laurent.pinchart@skynet.be>
+ *
+ * This file holds USB constants and structures defined by the USB Device
+ * Class Definition for Video Devices. Unless otherwise stated, comments
+ * below reference relevant sections of the USB Video Class 1.1 specification
+ * available at
+ *
+ * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip
+ */
+
+#ifndef __LINUX_USB_VIDEO_H
+#define __LINUX_USB_VIDEO_H
+
+#include <linux/types.h>
+
+/* --------------------------------------------------------------------------
+ * UVC constants
+ */
+
+/* A.2. Video Interface Subclass Codes */
+#define UVC_SC_UNDEFINED                               0x00
+#define UVC_SC_VIDEOCONTROL                            0x01
+#define UVC_SC_VIDEOSTREAMING                          0x02
+#define UVC_SC_VIDEO_INTERFACE_COLLECTION              0x03
+
+/* A.3. Video Interface Protocol Codes */
+#define UVC_PC_PROTOCOL_UNDEFINED                      0x00
+
+/* A.5. Video Class-Specific VC Interface Descriptor Subtypes */
+#define UVC_VC_DESCRIPTOR_UNDEFINED                    0x00
+#define UVC_VC_HEADER                                  0x01
+#define UVC_VC_INPUT_TERMINAL                          0x02
+#define UVC_VC_OUTPUT_TERMINAL                         0x03
+#define UVC_VC_SELECTOR_UNIT                           0x04
+#define UVC_VC_PROCESSING_UNIT                         0x05
+#define UVC_VC_EXTENSION_UNIT                          0x06
+
+/* A.6. Video Class-Specific VS Interface Descriptor Subtypes */
+#define UVC_VS_UNDEFINED                               0x00
+#define UVC_VS_INPUT_HEADER                            0x01
+#define UVC_VS_OUTPUT_HEADER                           0x02
+#define UVC_VS_STILL_IMAGE_FRAME                       0x03
+#define UVC_VS_FORMAT_UNCOMPRESSED                     0x04
+#define UVC_VS_FRAME_UNCOMPRESSED                      0x05
+#define UVC_VS_FORMAT_MJPEG                            0x06
+#define UVC_VS_FRAME_MJPEG                             0x07
+#define UVC_VS_FORMAT_MPEG2TS                          0x0a
+#define UVC_VS_FORMAT_DV                               0x0c
+#define UVC_VS_COLORFORMAT                             0x0d
+#define UVC_VS_FORMAT_FRAME_BASED                      0x10
+#define UVC_VS_FRAME_FRAME_BASED                       0x11
+#define UVC_VS_FORMAT_STREAM_BASED                     0x12
+
+/* A.7. Video Class-Specific Endpoint Descriptor Subtypes */
+#define UVC_EP_UNDEFINED                               0x00
+#define UVC_EP_GENERAL                                 0x01
+#define UVC_EP_ENDPOINT                                        0x02
+#define UVC_EP_INTERRUPT                               0x03
+
+/* A.8. Video Class-Specific Request Codes */
+#define UVC_RC_UNDEFINED                               0x00
+#define UVC_SET_CUR                                    0x01
+#define UVC_GET_CUR                                    0x81
+#define UVC_GET_MIN                                    0x82
+#define UVC_GET_MAX                                    0x83
+#define UVC_GET_RES                                    0x84
+#define UVC_GET_LEN                                    0x85
+#define UVC_GET_INFO                                   0x86
+#define UVC_GET_DEF                                    0x87
+
+/* A.9.1. VideoControl Interface Control Selectors */
+#define UVC_VC_CONTROL_UNDEFINED                       0x00
+#define UVC_VC_VIDEO_POWER_MODE_CONTROL                        0x01
+#define UVC_VC_REQUEST_ERROR_CODE_CONTROL              0x02
+
+/* A.9.2. Terminal Control Selectors */
+#define UVC_TE_CONTROL_UNDEFINED                       0x00
+
+/* A.9.3. Selector Unit Control Selectors */
+#define UVC_SU_CONTROL_UNDEFINED                       0x00
+#define UVC_SU_INPUT_SELECT_CONTROL                    0x01
+
+/* A.9.4. Camera Terminal Control Selectors */
+#define UVC_CT_CONTROL_UNDEFINED                       0x00
+#define UVC_CT_SCANNING_MODE_CONTROL                   0x01
+#define UVC_CT_AE_MODE_CONTROL                         0x02
+#define UVC_CT_AE_PRIORITY_CONTROL                     0x03
+#define UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL          0x04
+#define UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL          0x05
+#define UVC_CT_FOCUS_ABSOLUTE_CONTROL                  0x06
+#define UVC_CT_FOCUS_RELATIVE_CONTROL                  0x07
+#define UVC_CT_FOCUS_AUTO_CONTROL                      0x08
+#define UVC_CT_IRIS_ABSOLUTE_CONTROL                   0x09
+#define UVC_CT_IRIS_RELATIVE_CONTROL                   0x0a
+#define UVC_CT_ZOOM_ABSOLUTE_CONTROL                   0x0b
+#define UVC_CT_ZOOM_RELATIVE_CONTROL                   0x0c
+#define UVC_CT_PANTILT_ABSOLUTE_CONTROL                        0x0d
+#define UVC_CT_PANTILT_RELATIVE_CONTROL                        0x0e
+#define UVC_CT_ROLL_ABSOLUTE_CONTROL                   0x0f
+#define UVC_CT_ROLL_RELATIVE_CONTROL                   0x10
+#define UVC_CT_PRIVACY_CONTROL                         0x11
+
+/* A.9.5. Processing Unit Control Selectors */
+#define UVC_PU_CONTROL_UNDEFINED                       0x00
+#define UVC_PU_BACKLIGHT_COMPENSATION_CONTROL          0x01
+#define UVC_PU_BRIGHTNESS_CONTROL                      0x02
+#define UVC_PU_CONTRAST_CONTROL                                0x03
+#define UVC_PU_GAIN_CONTROL                            0x04
+#define UVC_PU_POWER_LINE_FREQUENCY_CONTROL            0x05
+#define UVC_PU_HUE_CONTROL                             0x06
+#define UVC_PU_SATURATION_CONTROL                      0x07
+#define UVC_PU_SHARPNESS_CONTROL                       0x08
+#define UVC_PU_GAMMA_CONTROL                           0x09
+#define UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL       0x0a
+#define UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL  0x0b
+#define UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL         0x0c
+#define UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL    0x0d
+#define UVC_PU_DIGITAL_MULTIPLIER_CONTROL              0x0e
+#define UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL                0x0f
+#define UVC_PU_HUE_AUTO_CONTROL                                0x10
+#define UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL           0x11
+#define UVC_PU_ANALOG_LOCK_STATUS_CONTROL              0x12
+
+/* A.9.7. VideoStreaming Interface Control Selectors */
+#define UVC_VS_CONTROL_UNDEFINED                       0x00
+#define UVC_VS_PROBE_CONTROL                           0x01
+#define UVC_VS_COMMIT_CONTROL                          0x02
+#define UVC_VS_STILL_PROBE_CONTROL                     0x03
+#define UVC_VS_STILL_COMMIT_CONTROL                    0x04
+#define UVC_VS_STILL_IMAGE_TRIGGER_CONTROL             0x05
+#define UVC_VS_STREAM_ERROR_CODE_CONTROL               0x06
+#define UVC_VS_GENERATE_KEY_FRAME_CONTROL              0x07
+#define UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL            0x08
+#define UVC_VS_SYNC_DELAY_CONTROL                      0x09
+
+/* B.1. USB Terminal Types */
+#define UVC_TT_VENDOR_SPECIFIC                         0x0100
+#define UVC_TT_STREAMING                               0x0101
+
+/* B.2. Input Terminal Types */
+#define UVC_ITT_VENDOR_SPECIFIC                                0x0200
+#define UVC_ITT_CAMERA                                 0x0201
+#define UVC_ITT_MEDIA_TRANSPORT_INPUT                  0x0202
+
+/* B.3. Output Terminal Types */
+#define UVC_OTT_VENDOR_SPECIFIC                                0x0300
+#define UVC_OTT_DISPLAY                                        0x0301
+#define UVC_OTT_MEDIA_TRANSPORT_OUTPUT                 0x0302
+
+/* B.4. External Terminal Types */
+#define UVC_EXTERNAL_VENDOR_SPECIFIC                   0x0400
+#define UVC_COMPOSITE_CONNECTOR                                0x0401
+#define UVC_SVIDEO_CONNECTOR                           0x0402
+#define UVC_COMPONENT_CONNECTOR                                0x0403
+
+/* 2.4.2.2. Status Packet Type */
+#define UVC_STATUS_TYPE_CONTROL                                1
+#define UVC_STATUS_TYPE_STREAMING                      2
+
+/* 2.4.3.3. Payload Header Information */
+#define UVC_STREAM_EOH                                 (1 << 7)
+#define UVC_STREAM_ERR                                 (1 << 6)
+#define UVC_STREAM_STI                                 (1 << 5)
+#define UVC_STREAM_RES                                 (1 << 4)
+#define UVC_STREAM_SCR                                 (1 << 3)
+#define UVC_STREAM_PTS                                 (1 << 2)
+#define UVC_STREAM_EOF                                 (1 << 1)
+#define UVC_STREAM_FID                                 (1 << 0)
+
+/* 4.1.2. Control Capabilities */
+#define UVC_CONTROL_CAP_GET                            (1 << 0)
+#define UVC_CONTROL_CAP_SET                            (1 << 1)
+#define UVC_CONTROL_CAP_DISABLED                       (1 << 2)
+#define UVC_CONTROL_CAP_AUTOUPDATE                     (1 << 3)
+#define UVC_CONTROL_CAP_ASYNCHRONOUS                   (1 << 4)
+
+/* ------------------------------------------------------------------------
+ * UVC structures
+ */
+
+/* All UVC descriptors have these 3 fields at the beginning */
+struct uvc_descriptor_header {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+} __attribute__((packed));
+
+/* 3.7.2. Video Control Interface Header Descriptor */
+struct uvc_header_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u16 bcdUVC;
+       __u16 wTotalLength;
+       __u32 dwClockFrequency;
+       __u8  bInCollection;
+       __u8  baInterfaceNr[];
+} __attribute__((__packed__));
+
+#define UVC_DT_HEADER_SIZE(n)                          (12+(n))
+
+#define UVC_HEADER_DESCRIPTOR(n) \
+       uvc_header_descriptor_##n
+
+#define DECLARE_UVC_HEADER_DESCRIPTOR(n)               \
+struct UVC_HEADER_DESCRIPTOR(n) {                      \
+       __u8  bLength;                                  \
+       __u8  bDescriptorType;                          \
+       __u8  bDescriptorSubType;                       \
+       __u16 bcdUVC;                                   \
+       __u16 wTotalLength;                             \
+       __u32 dwClockFrequency;                         \
+       __u8  bInCollection;                            \
+       __u8  baInterfaceNr[n];                         \
+} __attribute__ ((packed))
+
+/* 3.7.2.1. Input Terminal Descriptor */
+struct uvc_input_terminal_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bTerminalID;
+       __u16 wTerminalType;
+       __u8  bAssocTerminal;
+       __u8  iTerminal;
+} __attribute__((__packed__));
+
+#define UVC_DT_INPUT_TERMINAL_SIZE                     8
+
+/* 3.7.2.2. Output Terminal Descriptor */
+struct uvc_output_terminal_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bTerminalID;
+       __u16 wTerminalType;
+       __u8  bAssocTerminal;
+       __u8  bSourceID;
+       __u8  iTerminal;
+} __attribute__((__packed__));
+
+#define UVC_DT_OUTPUT_TERMINAL_SIZE                    9
+
+/* 3.7.2.3. Camera Terminal Descriptor */
+struct uvc_camera_terminal_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bTerminalID;
+       __u16 wTerminalType;
+       __u8  bAssocTerminal;
+       __u8  iTerminal;
+       __u16 wObjectiveFocalLengthMin;
+       __u16 wObjectiveFocalLengthMax;
+       __u16 wOcularFocalLength;
+       __u8  bControlSize;
+       __u8  bmControls[3];
+} __attribute__((__packed__));
+
+#define UVC_DT_CAMERA_TERMINAL_SIZE(n)                 (15+(n))
+
+/* 3.7.2.4. Selector Unit Descriptor */
+struct uvc_selector_unit_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bUnitID;
+       __u8  bNrInPins;
+       __u8  baSourceID[0];
+       __u8  iSelector;
+} __attribute__((__packed__));
+
+#define UVC_DT_SELECTOR_UNIT_SIZE(n)                   (6+(n))
+
+#define UVC_SELECTOR_UNIT_DESCRIPTOR(n)        \
+       uvc_selector_unit_descriptor_##n
+
+#define DECLARE_UVC_SELECTOR_UNIT_DESCRIPTOR(n)        \
+struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) {               \
+       __u8  bLength;                                  \
+       __u8  bDescriptorType;                          \
+       __u8  bDescriptorSubType;                       \
+       __u8  bUnitID;                                  \
+       __u8  bNrInPins;                                \
+       __u8  baSourceID[n];                            \
+       __u8  iSelector;                                \
+} __attribute__ ((packed))
+
+/* 3.7.2.5. Processing Unit Descriptor */
+struct uvc_processing_unit_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bUnitID;
+       __u8  bSourceID;
+       __u16 wMaxMultiplier;
+       __u8  bControlSize;
+       __u8  bmControls[2];
+       __u8  iProcessing;
+} __attribute__((__packed__));
+
+#define UVC_DT_PROCESSING_UNIT_SIZE(n)                 (9+(n))
+
+/* 3.7.2.6. Extension Unit Descriptor */
+struct uvc_extension_unit_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bUnitID;
+       __u8  guidExtensionCode[16];
+       __u8  bNumControls;
+       __u8  bNrInPins;
+       __u8  baSourceID[0];
+       __u8  bControlSize;
+       __u8  bmControls[0];
+       __u8  iExtension;
+} __attribute__((__packed__));
+
+#define UVC_DT_EXTENSION_UNIT_SIZE(p, n)               (24+(p)+(n))
+
+#define UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \
+       uvc_extension_unit_descriptor_##p_##n
+
+#define DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(p, n)    \
+struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) {           \
+       __u8  bLength;                                  \
+       __u8  bDescriptorType;                          \
+       __u8  bDescriptorSubType;                       \
+       __u8  bUnitID;                                  \
+       __u8  guidExtensionCode[16];                    \
+       __u8  bNumControls;                             \
+       __u8  bNrInPins;                                \
+       __u8  baSourceID[p];                            \
+       __u8  bControlSize;                             \
+       __u8  bmControls[n];                            \
+       __u8  iExtension;                               \
+} __attribute__ ((packed))
+
+/* 3.8.2.2. Video Control Interrupt Endpoint Descriptor */
+struct uvc_control_endpoint_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u16 wMaxTransferSize;
+} __attribute__((__packed__));
+
+#define UVC_DT_CONTROL_ENDPOINT_SIZE                   5
+
+/* 3.9.2.1. Input Header Descriptor */
+struct uvc_input_header_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bNumFormats;
+       __u16 wTotalLength;
+       __u8  bEndpointAddress;
+       __u8  bmInfo;
+       __u8  bTerminalLink;
+       __u8  bStillCaptureMethod;
+       __u8  bTriggerSupport;
+       __u8  bTriggerUsage;
+       __u8  bControlSize;
+       __u8  bmaControls[];
+} __attribute__((__packed__));
+
+#define UVC_DT_INPUT_HEADER_SIZE(n, p)                 (13+(n*p))
+
+#define UVC_INPUT_HEADER_DESCRIPTOR(n, p) \
+       uvc_input_header_descriptor_##n_##p
+
+#define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p)      \
+struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) {             \
+       __u8  bLength;                                  \
+       __u8  bDescriptorType;                          \
+       __u8  bDescriptorSubType;                       \
+       __u8  bNumFormats;                              \
+       __u16 wTotalLength;                             \
+       __u8  bEndpointAddress;                         \
+       __u8  bmInfo;                                   \
+       __u8  bTerminalLink;                            \
+       __u8  bStillCaptureMethod;                      \
+       __u8  bTriggerSupport;                          \
+       __u8  bTriggerUsage;                            \
+       __u8  bControlSize;                             \
+       __u8  bmaControls[p][n];                        \
+} __attribute__ ((packed))
+
+/* 3.9.2.2. Output Header Descriptor */
+struct uvc_output_header_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bNumFormats;
+       __u16 wTotalLength;
+       __u8  bEndpointAddress;
+       __u8  bTerminalLink;
+       __u8  bControlSize;
+       __u8  bmaControls[];
+} __attribute__((__packed__));
+
+#define UVC_DT_OUTPUT_HEADER_SIZE(n, p)                        (9+(n*p))
+
+#define UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \
+       uvc_output_header_descriptor_##n_##p
+
+#define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p)     \
+struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) {            \
+       __u8  bLength;                                  \
+       __u8  bDescriptorType;                          \
+       __u8  bDescriptorSubType;                       \
+       __u8  bNumFormats;                              \
+       __u16 wTotalLength;                             \
+       __u8  bEndpointAddress;                         \
+       __u8  bTerminalLink;                            \
+       __u8  bControlSize;                             \
+       __u8  bmaControls[p][n];                        \
+} __attribute__ ((packed))
+
+/* 3.9.2.6. Color matching descriptor */
+struct uvc_color_matching_descriptor {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bColorPrimaries;
+       __u8  bTransferCharacteristics;
+       __u8  bMatrixCoefficients;
+} __attribute__((__packed__));
+
+#define UVC_DT_COLOR_MATCHING_SIZE                     6
+
+/* 4.3.1.1. Video Probe and Commit Controls */
+struct uvc_streaming_control {
+       __u16 bmHint;
+       __u8  bFormatIndex;
+       __u8  bFrameIndex;
+       __u32 dwFrameInterval;
+       __u16 wKeyFrameRate;
+       __u16 wPFrameRate;
+       __u16 wCompQuality;
+       __u16 wCompWindowSize;
+       __u16 wDelay;
+       __u32 dwMaxVideoFrameSize;
+       __u32 dwMaxPayloadTransferSize;
+       __u32 dwClockFrequency;
+       __u8  bmFramingInfo;
+       __u8  bPreferedVersion;
+       __u8  bMinVersion;
+       __u8  bMaxVersion;
+} __attribute__((__packed__));
+
+/* Uncompressed Payload - 3.1.1. Uncompressed Video Format Descriptor */
+struct uvc_format_uncompressed {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bFormatIndex;
+       __u8  bNumFrameDescriptors;
+       __u8  guidFormat[16];
+       __u8  bBitsPerPixel;
+       __u8  bDefaultFrameIndex;
+       __u8  bAspectRatioX;
+       __u8  bAspectRatioY;
+       __u8  bmInterfaceFlags;
+       __u8  bCopyProtect;
+} __attribute__((__packed__));
+
+#define UVC_DT_FORMAT_UNCOMPRESSED_SIZE                        27
+
+/* Uncompressed Payload - 3.1.2. Uncompressed Video Frame Descriptor */
+struct uvc_frame_uncompressed {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bFrameIndex;
+       __u8  bmCapabilities;
+       __u16 wWidth;
+       __u16 wHeight;
+       __u32 dwMinBitRate;
+       __u32 dwMaxBitRate;
+       __u32 dwMaxVideoFrameBufferSize;
+       __u32 dwDefaultFrameInterval;
+       __u8  bFrameIntervalType;
+       __u32 dwFrameInterval[];
+} __attribute__((__packed__));
+
+#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n)              (26+4*(n))
+
+#define UVC_FRAME_UNCOMPRESSED(n) \
+       uvc_frame_uncompressed_##n
+
+#define DECLARE_UVC_FRAME_UNCOMPRESSED(n)              \
+struct UVC_FRAME_UNCOMPRESSED(n) {                     \
+       __u8  bLength;                                  \
+       __u8  bDescriptorType;                          \
+       __u8  bDescriptorSubType;                       \
+       __u8  bFrameIndex;                              \
+       __u8  bmCapabilities;                           \
+       __u16 wWidth;                                   \
+       __u16 wHeight;                                  \
+       __u32 dwMinBitRate;                             \
+       __u32 dwMaxBitRate;                             \
+       __u32 dwMaxVideoFrameBufferSize;                \
+       __u32 dwDefaultFrameInterval;                   \
+       __u8  bFrameIntervalType;                       \
+       __u32 dwFrameInterval[n];                       \
+} __attribute__ ((packed))
+
+/* MJPEG Payload - 3.1.1. MJPEG Video Format Descriptor */
+struct uvc_format_mjpeg {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bFormatIndex;
+       __u8  bNumFrameDescriptors;
+       __u8  bmFlags;
+       __u8  bDefaultFrameIndex;
+       __u8  bAspectRatioX;
+       __u8  bAspectRatioY;
+       __u8  bmInterfaceFlags;
+       __u8  bCopyProtect;
+} __attribute__((__packed__));
+
+#define UVC_DT_FORMAT_MJPEG_SIZE                       11
+
+/* MJPEG Payload - 3.1.2. MJPEG Video Frame Descriptor */
+struct uvc_frame_mjpeg {
+       __u8  bLength;
+       __u8  bDescriptorType;
+       __u8  bDescriptorSubType;
+       __u8  bFrameIndex;
+       __u8  bmCapabilities;
+       __u16 wWidth;
+       __u16 wHeight;
+       __u32 dwMinBitRate;
+       __u32 dwMaxBitRate;
+       __u32 dwMaxVideoFrameBufferSize;
+       __u32 dwDefaultFrameInterval;
+       __u8  bFrameIntervalType;
+       __u32 dwFrameInterval[];
+} __attribute__((__packed__));
+
+#define UVC_DT_FRAME_MJPEG_SIZE(n)                     (26+4*(n))
+
+#define UVC_FRAME_MJPEG(n) \
+       uvc_frame_mjpeg_##n
+
+#define DECLARE_UVC_FRAME_MJPEG(n)                     \
+struct UVC_FRAME_MJPEG(n) {                            \
+       __u8  bLength;                                  \
+       __u8  bDescriptorType;                          \
+       __u8  bDescriptorSubType;                       \
+       __u8  bFrameIndex;                              \
+       __u8  bmCapabilities;                           \
+       __u16 wWidth;                                   \
+       __u16 wHeight;                                  \
+       __u32 dwMinBitRate;                             \
+       __u32 dwMaxBitRate;                             \
+       __u32 dwMaxVideoFrameBufferSize;                \
+       __u32 dwDefaultFrameInterval;                   \
+       __u8  bFrameIntervalType;                       \
+       __u32 dwFrameInterval[n];                       \
+} __attribute__ ((packed))
+
+#endif /* __LINUX_USB_VIDEO_H */
+
index 2470f541af5078c6841a8fd329d0c470b0770b31..848e3584d7c8063759548eb4f440e7b2bf262126 100644 (file)
@@ -51,6 +51,8 @@
 #define VIRTIO_NET_F_CTRL_RX_EXTRA 20  /* Extra RX mode control support */
 #define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the
                                         * network */
+#define VIRTIO_NET_F_MQ        22      /* Device supports Receive Flow
+                                        * Steering */
 
 #define VIRTIO_NET_S_LINK_UP   1       /* Link is up */
 #define VIRTIO_NET_S_ANNOUNCE  2       /* Announcement is needed */
@@ -60,6 +62,11 @@ struct virtio_net_config {
        __u8 mac[6];
        /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
        __u16 status;
+       /* Maximum number of each of transmit and receive queues;
+        * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ.
+        * Legal values are between 1 and 0x8000
+        */
+       __u16 max_virtqueue_pairs;
 } __attribute__((packed));
 
 /* This is the first element of the scatter-gather list.  If you don't
@@ -166,4 +173,24 @@ struct virtio_net_ctrl_mac {
 #define VIRTIO_NET_CTRL_ANNOUNCE       3
  #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
 
+/*
+ * Control Receive Flow Steering
+ *
+ * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET
+ * enables Receive Flow Steering, specifying the number of the transmit and
+ * receive queues that will be used. After the command is consumed and acked by
+ * the device, the device will not steer new packets on receive virtqueues
+ * other than specified nor read from transmit virtqueues other than specified.
+ * Accordingly, driver should not transmit new packets  on virtqueues other than
+ * specified.
+ */
+struct virtio_net_ctrl_mq {
+       u16 virtqueue_pairs;
+};
+
+#define VIRTIO_NET_CTRL_MQ   4
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET        0
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN        1
+ #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000
+
 #endif /* _LINUX_VIRTIO_NET_H */
diff --git a/include/xen/Kbuild b/include/xen/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index aecee9d112cbe6aea2532652c8c3f768bb829cce..694dcaf266e635335dfdaf22994624d3d5e3d9d4 100644 (file)
@@ -170,7 +170,7 @@ gnttab_set_unmap_op(struct gnttab_unmap_grant_ref *unmap, phys_addr_t addr,
        unmap->dev_bus_addr = 0;
 }
 
-int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
+int arch_gnttab_map_shared(xen_pfn_t *frames, unsigned long nr_gframes,
                           unsigned long max_nr_gframes,
                           void **__shared);
 int arch_gnttab_map_status(uint64_t *frames, unsigned long nr_gframes,
index b193fa2f9fddb2ef6670a7e1aa7f27ef4b60edbe..13e43e41637dad471aa9c7033474c57596260371 100644 (file)
@@ -5,6 +5,36 @@
 #include <xen/interface/hvm/params.h>
 #include <asm/xen/hypercall.h>
 
+static const char *param_name(int op)
+{
+#define PARAM(x) [HVM_PARAM_##x] = #x
+       static const char *const names[] = {
+               PARAM(CALLBACK_IRQ),
+               PARAM(STORE_PFN),
+               PARAM(STORE_EVTCHN),
+               PARAM(PAE_ENABLED),
+               PARAM(IOREQ_PFN),
+               PARAM(BUFIOREQ_PFN),
+               PARAM(TIMER_MODE),
+               PARAM(HPET_ENABLED),
+               PARAM(IDENT_PT),
+               PARAM(DM_DOMAIN),
+               PARAM(ACPI_S_STATE),
+               PARAM(VM86_TSS),
+               PARAM(VPT_ALIGN),
+               PARAM(CONSOLE_PFN),
+               PARAM(CONSOLE_EVTCHN),
+       };
+#undef PARAM
+
+       if (op >= ARRAY_SIZE(names))
+               return "unknown";
+
+       if (!names[op])
+               return "reserved";
+
+       return names[op];
+}
 static inline int hvm_get_parameter(int idx, uint64_t *value)
 {
        struct xen_hvm_param xhv;
@@ -14,8 +44,8 @@ static inline int hvm_get_parameter(int idx, uint64_t *value)
        xhv.index = idx;
        r = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
        if (r < 0) {
-               printk(KERN_ERR "Cannot get hvm parameter %d: %d!\n",
-                       idx, r);
+               printk(KERN_ERR "Cannot get hvm parameter %s (%d): %d!\n",
+                       param_name(idx), idx, r);
                return r;
        }
        *value = xhv.value;
index f9f8b975ae7448bfdae47100ad7da63a34fbe39b..e40fae9bf11acd67b64ece81bae1d04efefc44fd 100644 (file)
@@ -310,7 +310,7 @@ struct gnttab_setup_table {
     uint32_t nr_frames;
     /* OUT parameters. */
     int16_t  status;              /* GNTST_* */
-    GUEST_HANDLE(ulong) frame_list;
+    GUEST_HANDLE(xen_pfn_t) frame_list;
 };
 DEFINE_GUEST_HANDLE_STRUCT(gnttab_setup_table);
 
index b66d04ce6957549a1097c532bc483e5ee6ab38d8..90712e2072d57ba6c6154549352266d253ab3615 100644 (file)
@@ -179,28 +179,8 @@ struct xen_add_to_physmap {
 };
 DEFINE_GUEST_HANDLE_STRUCT(xen_add_to_physmap);
 
-/*
- * Translates a list of domain-specific GPFNs into MFNs. Returns a -ve error
- * code on failure. This call only works for auto-translated guests.
- */
-#define XENMEM_translate_gpfn_list  8
-struct xen_translate_gpfn_list {
-    /* Which domain to translate for? */
-    domid_t domid;
-
-    /* Length of list. */
-    xen_ulong_t nr_gpfns;
-
-    /* List of GPFNs to translate. */
-    GUEST_HANDLE(ulong) gpfn_list;
-
-    /*
-     * Output list to contain MFN translations. May be the same as the input
-     * list (in which case each input GPFN is overwritten with the output MFN).
-     */
-    GUEST_HANDLE(ulong) mfn_list;
-};
-DEFINE_GUEST_HANDLE_STRUCT(xen_translate_gpfn_list);
+/*** REMOVED ***/
+/*#define XENMEM_translate_gpfn_list  8*/
 
 /*
  * Returns the pseudo-physical memory map as it was when the domain
index 9cf77ab138a68738bb6926b8b31aaf6ba8cd4f6e..e33e09df3cbc61ad11736776ef4138010df1de8e 100644 (file)
@@ -442,9 +442,11 @@ void __init __weak smp_setup_processor_id(void)
 {
 }
 
+# if THREAD_SIZE >= PAGE_SIZE
 void __init __weak thread_info_cache_init(void)
 {
 }
+#endif
 
 /*
  * Set up kernel memory allocators
index 0dfeca4324ee06dbb6566db568b9874758344232..86e3285ae7e5b48fd9b123291da2d8dbfe0d7460 100644 (file)
@@ -174,10 +174,8 @@ signing_key.priv signing_key.x509: x509.genkey
        @echo "###"
        @echo "### If this takes a long time, you might wish to run rngd in the"
        @echo "### background to keep the supply of entropy topped up.  It"
-       @echo "### needs to be run as root, and should use a hardware random"
-       @echo "### number generator if one is available, eg:"
-       @echo "###"
-       @echo "###     rngd -r /dev/hwrandom"
+       @echo "### needs to be run as root, and uses a hardware random"
+       @echo "### number generator if one is available."
        @echo "###"
        openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \
                -x509 -config x509.genkey \
index 13774b3b39aac9b73e25ba34a366d5402b70df00..f24f724620dd8489fc2e3cb9781433df84096c96 100644 (file)
@@ -1962,9 +1962,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp,
         * trading it for newcg is protected by cgroup_mutex, we're safe to drop
         * it here; it will be freed under RCU.
         */
-       put_css_set(oldcg);
-
        set_bit(CGRP_RELEASABLE, &oldcgrp->flags);
+       put_css_set(oldcg);
 }
 
 /**
@@ -4815,31 +4814,20 @@ static const struct file_operations proc_cgroupstats_operations = {
  *
  * A pointer to the shared css_set was automatically copied in
  * fork.c by dup_task_struct().  However, we ignore that copy, since
- * it was not made under the protection of RCU, cgroup_mutex or
- * threadgroup_change_begin(), so it might no longer be a valid
- * cgroup pointer.  cgroup_attach_task() might have already changed
- * current->cgroups, allowing the previously referenced cgroup
- * group to be removed and freed.
- *
- * Outside the pointer validity we also need to process the css_set
- * inheritance between threadgoup_change_begin() and
- * threadgoup_change_end(), this way there is no leak in any process
- * wide migration performed by cgroup_attach_proc() that could otherwise
- * miss a thread because it is too early or too late in the fork stage.
+ * it was not made under the protection of RCU or cgroup_mutex, so
+ * might no longer be a valid cgroup pointer.  cgroup_attach_task() might
+ * have already changed current->cgroups, allowing the previously
+ * referenced cgroup group to be removed and freed.
  *
  * At the point that cgroup_fork() is called, 'current' is the parent
  * task, and the passed argument 'child' points to the child task.
  */
 void cgroup_fork(struct task_struct *child)
 {
-       /*
-        * We don't need to task_lock() current because current->cgroups
-        * can't be changed concurrently here. The parent obviously hasn't
-        * exited and called cgroup_exit(), and we are synchronized against
-        * cgroup migration through threadgroup_change_begin().
-        */
+       task_lock(current);
        child->cgroups = current->cgroups;
        get_css_set(child->cgroups);
+       task_unlock(current);
        INIT_LIST_HEAD(&child->cg_list);
 }
 
@@ -4895,19 +4883,10 @@ void cgroup_post_fork(struct task_struct *child)
         */
        if (use_task_css_set_links) {
                write_lock(&css_set_lock);
-               if (list_empty(&child->cg_list)) {
-                       /*
-                        * It's safe to use child->cgroups without task_lock()
-                        * here because we are protected through
-                        * threadgroup_change_begin() against concurrent
-                        * css_set change in cgroup_task_migrate(). Also
-                        * the task can't exit at that point until
-                        * wake_up_new_task() is called, so we are protected
-                        * against cgroup_exit() setting child->cgroup to
-                        * init_css_set.
-                        */
+               task_lock(child);
+               if (list_empty(&child->cg_list))
                        list_add(&child->cg_list, &child->cgroups->tasks);
-               }
+               task_unlock(child);
                write_unlock(&css_set_lock);
        }
 }
index 98256bc71ee136915b126b81dd1e61b8990a8ce3..5cc4e7e42e689a7076ece7eb252f5a1f3a1eb5b6 100644 (file)
@@ -78,15 +78,23 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
  */
 static atomic_t uprobe_events = ATOMIC_INIT(0);
 
+/* Have a copy of original instruction */
+#define UPROBE_COPY_INSN       0
+/* Dont run handlers when first register/ last unregister in progress*/
+#define UPROBE_RUN_HANDLER     1
+/* Can skip singlestep */
+#define UPROBE_SKIP_SSTEP      2
+
 struct uprobe {
        struct rb_node          rb_node;        /* node in the rb tree */
        atomic_t                ref;
        struct rw_semaphore     consumer_rwsem;
+       struct mutex            copy_mutex;     /* TODO: kill me and UPROBE_COPY_INSN */
        struct list_head        pending_list;
        struct uprobe_consumer  *consumers;
        struct inode            *inode;         /* Also hold a ref to inode */
        loff_t                  offset;
-       int                     flags;
+       unsigned long           flags;
        struct arch_uprobe      arch;
 };
 
@@ -100,17 +108,12 @@ struct uprobe {
  */
 static bool valid_vma(struct vm_area_struct *vma, bool is_register)
 {
-       if (!vma->vm_file)
-               return false;
-
-       if (!is_register)
-               return true;
+       vm_flags_t flags = VM_HUGETLB | VM_MAYEXEC | VM_SHARED;
 
-       if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED))
-                               == (VM_READ|VM_EXEC))
-               return true;
+       if (is_register)
+               flags |= VM_WRITE;
 
-       return false;
+       return vma->vm_file && (vma->vm_flags & flags) == VM_MAYEXEC;
 }
 
 static unsigned long offset_to_vaddr(struct vm_area_struct *vma, loff_t offset)
@@ -193,19 +196,44 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
        return *insn == UPROBE_SWBP_INSN;
 }
 
+static void copy_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *opcode)
+{
+       void *kaddr = kmap_atomic(page);
+       memcpy(opcode, kaddr + (vaddr & ~PAGE_MASK), UPROBE_SWBP_INSN_SIZE);
+       kunmap_atomic(kaddr);
+}
+
+static int verify_opcode(struct page *page, unsigned long vaddr, uprobe_opcode_t *new_opcode)
+{
+       uprobe_opcode_t old_opcode;
+       bool is_swbp;
+
+       copy_opcode(page, vaddr, &old_opcode);
+       is_swbp = is_swbp_insn(&old_opcode);
+
+       if (is_swbp_insn(new_opcode)) {
+               if (is_swbp)            /* register: already installed? */
+                       return 0;
+       } else {
+               if (!is_swbp)           /* unregister: was it changed by us? */
+                       return 0;
+       }
+
+       return 1;
+}
+
 /*
  * NOTE:
  * Expect the breakpoint instruction to be the smallest size instruction for
  * the architecture. If an arch has variable length instruction and the
  * breakpoint instruction is not of the smallest length instruction
- * supported by that architecture then we need to modify read_opcode /
+ * supported by that architecture then we need to modify is_swbp_at_addr and
  * write_opcode accordingly. This would never be a problem for archs that
  * have fixed length instructions.
  */
 
 /*
  * write_opcode - write the opcode at a given virtual address.
- * @auprobe: arch breakpointing information.
  * @mm: the probed process address space.
  * @vaddr: the virtual address to store the opcode.
  * @opcode: opcode to be written at @vaddr.
@@ -216,8 +244,8 @@ bool __weak is_swbp_insn(uprobe_opcode_t *insn)
  * For mm @mm, write the opcode at @vaddr.
  * Return 0 (success) or a negative errno.
  */
-static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
-                       unsigned long vaddr, uprobe_opcode_t opcode)
+static int write_opcode(struct mm_struct *mm, unsigned long vaddr,
+                       uprobe_opcode_t opcode)
 {
        struct page *old_page, *new_page;
        void *vaddr_old, *vaddr_new;
@@ -226,10 +254,14 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 
 retry:
        /* Read the page with vaddr into memory */
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma);
+       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &old_page, &vma);
        if (ret <= 0)
                return ret;
 
+       ret = verify_opcode(old_page, vaddr, &opcode);
+       if (ret <= 0)
+               goto put_old;
+
        ret = -ENOMEM;
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
        if (!new_page)
@@ -263,63 +295,6 @@ put_old:
        return ret;
 }
 
-/**
- * read_opcode - read the opcode at a given virtual address.
- * @mm: the probed process address space.
- * @vaddr: the virtual address to read the opcode.
- * @opcode: location to store the read opcode.
- *
- * Called with mm->mmap_sem held (for read and with a reference to
- * mm.
- *
- * For mm @mm, read the opcode at @vaddr and store it in @opcode.
- * Return 0 (success) or a negative errno.
- */
-static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_t *opcode)
-{
-       struct page *page;
-       void *vaddr_new;
-       int ret;
-
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
-       if (ret <= 0)
-               return ret;
-
-       vaddr_new = kmap_atomic(page);
-       vaddr &= ~PAGE_MASK;
-       memcpy(opcode, vaddr_new + vaddr, UPROBE_SWBP_INSN_SIZE);
-       kunmap_atomic(vaddr_new);
-
-       put_page(page);
-
-       return 0;
-}
-
-static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
-{
-       uprobe_opcode_t opcode;
-       int result;
-
-       if (current->mm == mm) {
-               pagefault_disable();
-               result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
-                                                               sizeof(opcode));
-               pagefault_enable();
-
-               if (likely(result == 0))
-                       goto out;
-       }
-
-       result = read_opcode(mm, vaddr, &opcode);
-       if (result)
-               return result;
-out:
-       if (is_swbp_insn(&opcode))
-               return 1;
-
-       return 0;
-}
-
 /**
  * set_swbp - store breakpoint at a given address.
  * @auprobe: arch specific probepoint information.
@@ -331,18 +306,7 @@ out:
  */
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       int result;
-       /*
-        * See the comment near uprobes_hash().
-        */
-       result = is_swbp_at_addr(mm, vaddr);
-       if (result == 1)
-               return 0;
-
-       if (result)
-               return result;
-
-       return write_opcode(auprobe, mm, vaddr, UPROBE_SWBP_INSN);
+       return write_opcode(mm, vaddr, UPROBE_SWBP_INSN);
 }
 
 /**
@@ -357,16 +321,7 @@ int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned
 int __weak
 set_orig_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       int result;
-
-       result = is_swbp_at_addr(mm, vaddr);
-       if (!result)
-               return -EINVAL;
-
-       if (result != 1)
-               return result;
-
-       return write_opcode(auprobe, mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
+       return write_opcode(mm, vaddr, *(uprobe_opcode_t *)auprobe->insn);
 }
 
 static int match_uprobe(struct uprobe *l, struct uprobe *r)
@@ -473,7 +428,7 @@ static struct uprobe *insert_uprobe(struct uprobe *uprobe)
        spin_unlock(&uprobes_treelock);
 
        /* For now assume that the instruction need not be single-stepped */
-       uprobe->flags |= UPROBE_SKIP_SSTEP;
+       __set_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
 
        return u;
 }
@@ -495,6 +450,7 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
        uprobe->inode = igrab(inode);
        uprobe->offset = offset;
        init_rwsem(&uprobe->consumer_rwsem);
+       mutex_init(&uprobe->copy_mutex);
 
        /* add to uprobes_tree, sorted on inode:offset */
        cur_uprobe = insert_uprobe(uprobe);
@@ -515,7 +471,7 @@ static void handler_chain(struct uprobe *uprobe, struct pt_regs *regs)
 {
        struct uprobe_consumer *uc;
 
-       if (!(uprobe->flags & UPROBE_RUN_HANDLER))
+       if (!test_bit(UPROBE_RUN_HANDLER, &uprobe->flags))
                return;
 
        down_read(&uprobe->consumer_rwsem);
@@ -621,29 +577,43 @@ static int copy_insn(struct uprobe *uprobe, struct file *filp)
        return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
 }
 
-/*
- * How mm->uprobes_state.count gets updated
- * uprobe_mmap() increments the count if
- *     - it successfully adds a breakpoint.
- *     - it cannot add a breakpoint, but sees that there is a underlying
- *       breakpoint (via a is_swbp_at_addr()).
- *
- * uprobe_munmap() decrements the count if
- *     - it sees a underlying breakpoint, (via is_swbp_at_addr)
- *       (Subsequent uprobe_unregister wouldnt find the breakpoint
- *       unless a uprobe_mmap kicks in, since the old vma would be
- *       dropped just after uprobe_munmap.)
- *
- * uprobe_register increments the count if:
- *     - it successfully adds a breakpoint.
- *
- * uprobe_unregister decrements the count if:
- *     - it sees a underlying breakpoint and removes successfully.
- *       (via is_swbp_at_addr)
- *       (Subsequent uprobe_munmap wouldnt find the breakpoint
- *       since there is no underlying breakpoint after the
- *       breakpoint removal.)
- */
+static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
+                               struct mm_struct *mm, unsigned long vaddr)
+{
+       int ret = 0;
+
+       if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
+               return ret;
+
+       mutex_lock(&uprobe->copy_mutex);
+       if (test_bit(UPROBE_COPY_INSN, &uprobe->flags))
+               goto out;
+
+       ret = copy_insn(uprobe, file);
+       if (ret)
+               goto out;
+
+       ret = -ENOTSUPP;
+       if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
+               goto out;
+
+       ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
+       if (ret)
+               goto out;
+
+       /* write_opcode() assumes we don't cross page boundary */
+       BUG_ON((uprobe->offset & ~PAGE_MASK) +
+                       UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
+
+       smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
+       set_bit(UPROBE_COPY_INSN, &uprobe->flags);
+
+ out:
+       mutex_unlock(&uprobe->copy_mutex);
+
+       return ret;
+}
+
 static int
 install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
                        struct vm_area_struct *vma, unsigned long vaddr)
@@ -661,24 +631,9 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        if (!uprobe->consumers)
                return 0;
 
-       if (!(uprobe->flags & UPROBE_COPY_INSN)) {
-               ret = copy_insn(uprobe, vma->vm_file);
-               if (ret)
-                       return ret;
-
-               if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
-                       return -ENOTSUPP;
-
-               ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
-               if (ret)
-                       return ret;
-
-               /* write_opcode() assumes we don't cross page boundary */
-               BUG_ON((uprobe->offset & ~PAGE_MASK) +
-                               UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
-
-               uprobe->flags |= UPROBE_COPY_INSN;
-       }
+       ret = prepare_uprobe(uprobe, vma->vm_file, mm, vaddr);
+       if (ret)
+               return ret;
 
        /*
         * set MMF_HAS_UPROBES in advance for uprobe_pre_sstep_notifier(),
@@ -697,15 +652,15 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        return ret;
 }
 
-static void
+static int
 remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
 {
        /* can happen if uprobe_register() fails */
        if (!test_bit(MMF_HAS_UPROBES, &mm->flags))
-               return;
+               return 0;
 
        set_bit(MMF_RECALC_UPROBES, &mm->flags);
-       set_orig_insn(&uprobe->arch, mm, vaddr);
+       return set_orig_insn(&uprobe->arch, mm, vaddr);
 }
 
 /*
@@ -820,7 +775,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                struct mm_struct *mm = info->mm;
                struct vm_area_struct *vma;
 
-               if (err)
+               if (err && is_register)
                        goto free;
 
                down_write(&mm->mmap_sem);
@@ -836,7 +791,7 @@ static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
                if (is_register)
                        err = install_breakpoint(uprobe, mm, vma, info->vaddr);
                else
-                       remove_breakpoint(uprobe, mm, info->vaddr);
+                       err |= remove_breakpoint(uprobe, mm, info->vaddr);
 
  unlock:
                up_write(&mm->mmap_sem);
@@ -893,13 +848,15 @@ int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *
        mutex_lock(uprobes_hash(inode));
        uprobe = alloc_uprobe(inode, offset);
 
-       if (uprobe && !consumer_add(uprobe, uc)) {
+       if (!uprobe) {
+               ret = -ENOMEM;
+       } else if (!consumer_add(uprobe, uc)) {
                ret = __uprobe_register(uprobe);
                if (ret) {
                        uprobe->consumers = NULL;
                        __uprobe_unregister(uprobe);
                } else {
-                       uprobe->flags |= UPROBE_RUN_HANDLER;
+                       set_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
                }
        }
 
@@ -932,7 +889,7 @@ void uprobe_unregister(struct inode *inode, loff_t offset, struct uprobe_consume
        if (consumer_del(uprobe, uc)) {
                if (!uprobe->consumers) {
                        __uprobe_unregister(uprobe);
-                       uprobe->flags &= ~UPROBE_RUN_HANDLER;
+                       clear_bit(UPROBE_RUN_HANDLER, &uprobe->flags);
                }
        }
 
@@ -1393,10 +1350,11 @@ bool uprobe_deny_signal(void)
  */
 static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
 {
-       if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
-               return true;
-
-       uprobe->flags &= ~UPROBE_SKIP_SSTEP;
+       if (test_bit(UPROBE_SKIP_SSTEP, &uprobe->flags)) {
+               if (arch_uprobe_skip_sstep(&uprobe->arch, regs))
+                       return true;
+               clear_bit(UPROBE_SKIP_SSTEP, &uprobe->flags);
+       }
        return false;
 }
 
@@ -1419,6 +1377,30 @@ static void mmf_recalc_uprobes(struct mm_struct *mm)
        clear_bit(MMF_HAS_UPROBES, &mm->flags);
 }
 
+static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
+{
+       struct page *page;
+       uprobe_opcode_t opcode;
+       int result;
+
+       pagefault_disable();
+       result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+                                                       sizeof(opcode));
+       pagefault_enable();
+
+       if (likely(result == 0))
+               goto out;
+
+       result = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
+       if (result < 0)
+               return result;
+
+       copy_opcode(page, vaddr, &opcode);
+       put_page(page);
+ out:
+       return is_swbp_insn(&opcode);
+}
+
 static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
 {
        struct mm_struct *mm = current->mm;
@@ -1489,38 +1471,41 @@ static void handle_swbp(struct pt_regs *regs)
                }
                return;
        }
+       /*
+        * TODO: move copy_insn/etc into _register and remove this hack.
+        * After we hit the bp, _unregister + _register can install the
+        * new and not-yet-analyzed uprobe at the same address, restart.
+        */
+       smp_rmb(); /* pairs with wmb() in install_breakpoint() */
+       if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
+               goto restart;
 
        utask = current->utask;
        if (!utask) {
                utask = add_utask();
                /* Cannot allocate; re-execute the instruction. */
                if (!utask)
-                       goto cleanup_ret;
+                       goto restart;
        }
-       utask->active_uprobe = uprobe;
+
        handler_chain(uprobe, regs);
-       if (uprobe->flags & UPROBE_SKIP_SSTEP && can_skip_sstep(uprobe, regs))
-               goto cleanup_ret;
+       if (can_skip_sstep(uprobe, regs))
+               goto out;
 
-       utask->state = UTASK_SSTEP;
        if (!pre_ssout(uprobe, regs, bp_vaddr)) {
                arch_uprobe_enable_step(&uprobe->arch);
+               utask->active_uprobe = uprobe;
+               utask->state = UTASK_SSTEP;
                return;
        }
 
-cleanup_ret:
-       if (utask) {
-               utask->active_uprobe = NULL;
-               utask->state = UTASK_RUNNING;
-       }
-       if (!(uprobe->flags & UPROBE_SKIP_SSTEP))
-
-               /*
-                * cannot singlestep; cannot skip instruction;
-                * re-execute the instruction.
-                */
-               instruction_pointer_set(regs, bp_vaddr);
-
+restart:
+       /*
+        * cannot singlestep; cannot skip instruction;
+        * re-execute the instruction.
+        */
+       instruction_pointer_set(regs, bp_vaddr);
+out:
        put_uprobe(uprobe);
 }
 
@@ -1552,13 +1537,12 @@ static void handle_singlestep(struct uprobe_task *utask, struct pt_regs *regs)
 }
 
 /*
- * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag.  (and on
- * subsequent probe hits on the thread sets the state to UTASK_BP_HIT) and
- * allows the thread to return from interrupt.
+ * On breakpoint hit, breakpoint notifier sets the TIF_UPROBE flag and
+ * allows the thread to return from interrupt. After that handle_swbp()
+ * sets utask->active_uprobe.
  *
- * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag and
- * also sets the state to UTASK_SSTEP_ACK and allows the thread to return from
- * interrupt.
+ * On singlestep exception, singlestep notifier sets the TIF_UPROBE flag
+ * and allows the thread to return from interrupt.
  *
  * While returning to userspace, thread notices the TIF_UPROBE flag and calls
  * uprobe_notify_resume().
@@ -1567,11 +1551,13 @@ void uprobe_notify_resume(struct pt_regs *regs)
 {
        struct uprobe_task *utask;
 
+       clear_thread_flag(TIF_UPROBE);
+
        utask = current->utask;
-       if (!utask || utask->state == UTASK_BP_HIT)
-               handle_swbp(regs);
-       else
+       if (utask && utask->active_uprobe)
                handle_singlestep(utask, regs);
+       else
+               handle_swbp(regs);
 }
 
 /*
@@ -1580,17 +1566,10 @@ void uprobe_notify_resume(struct pt_regs *regs)
  */
 int uprobe_pre_sstep_notifier(struct pt_regs *regs)
 {
-       struct uprobe_task *utask;
-
        if (!current->mm || !test_bit(MMF_HAS_UPROBES, &current->mm->flags))
                return 0;
 
-       utask = current->utask;
-       if (utask)
-               utask->state = UTASK_BP_HIT;
-
        set_thread_flag(TIF_UPROBE);
-
        return 1;
 }
 
index 3717e7b306e08c0e8c2d3a66219c3cae13176d99..19eb089ca003a7f7a09347eb393d5241cc93342e 100644 (file)
@@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
                                struct futex_pi_state **ps,
                                struct task_struct *task, int set_waiters)
 {
-       int lock_taken, ret, ownerdied = 0;
+       int lock_taken, ret, force_take = 0;
        u32 uval, newval, curval, vpid = task_pid_vnr(task);
 
 retry:
@@ -755,17 +755,15 @@ retry:
        newval = curval | FUTEX_WAITERS;
 
        /*
-        * There are two cases, where a futex might have no owner (the
-        * owner TID is 0): OWNER_DIED. We take over the futex in this
-        * case. We also do an unconditional take over, when the owner
-        * of the futex died.
-        *
-        * This is safe as we are protected by the hash bucket lock !
+        * Should we force take the futex? See below.
         */
-       if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
-               /* Keep the OWNER_DIED bit */
+       if (unlikely(force_take)) {
+               /*
+                * Keep the OWNER_DIED and the WAITERS bit and set the
+                * new TID value.
+                */
                newval = (curval & ~FUTEX_TID_MASK) | vpid;
-               ownerdied = 0;
+               force_take = 0;
                lock_taken = 1;
        }
 
@@ -775,7 +773,7 @@ retry:
                goto retry;
 
        /*
-        * We took the lock due to owner died take over.
+        * We took the lock due to forced take over.
         */
        if (unlikely(lock_taken))
                return 1;
@@ -790,20 +788,25 @@ retry:
                switch (ret) {
                case -ESRCH:
                        /*
-                        * No owner found for this futex. Check if the
-                        * OWNER_DIED bit is set to figure out whether
-                        * this is a robust futex or not.
+                        * We failed to find an owner for this
+                        * futex. So we have no pi_state to block
+                        * on. This can happen in two cases:
+                        *
+                        * 1) The owner died
+                        * 2) A stale FUTEX_WAITERS bit
+                        *
+                        * Re-read the futex value.
                         */
                        if (get_futex_value_locked(&curval, uaddr))
                                return -EFAULT;
 
                        /*
-                        * We simply start over in case of a robust
-                        * futex. The code above will take the futex
-                        * and return happy.
+                        * If the owner died or we have a stale
+                        * WAITERS bit the owner TID in the user space
+                        * futex is 0.
                         */
-                       if (curval & FUTEX_OWNER_DIED) {
-                               ownerdied = 1;
+                       if (!(curval & FUTEX_TID_MASK)) {
+                               force_take = 1;
                                goto retry;
                        }
                default:
@@ -840,6 +843,9 @@ static void wake_futex(struct futex_q *q)
 {
        struct task_struct *p = q->task;
 
+       if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
+               return;
+
        /*
         * We set q->lock_ptr = NULL _before_ we wake up the task. If
         * a non-futex wake up happens on another CPU then the task
@@ -1075,6 +1081,10 @@ retry_private:
 
        plist_for_each_entry_safe(this, next, head, list) {
                if (match_futex (&this->key, &key1)) {
+                       if (this->pi_state || this->rt_waiter) {
+                               ret = -EINVAL;
+                               goto out_unlock;
+                       }
                        wake_futex(this);
                        if (++ret >= nr_wake)
                                break;
@@ -1087,6 +1097,10 @@ retry_private:
                op_ret = 0;
                plist_for_each_entry_safe(this, next, head, list) {
                        if (match_futex (&this->key, &key2)) {
+                               if (this->pi_state || this->rt_waiter) {
+                                       ret = -EINVAL;
+                                       goto out_unlock;
+                               }
                                wake_futex(this);
                                if (++op_ret >= nr_wake2)
                                        break;
@@ -1095,6 +1109,7 @@ retry_private:
                ret += op_ret;
        }
 
+out_unlock:
        double_unlock_hb(hb1, hb2);
 out_put_keys:
        put_futex_key(&key2);
@@ -1384,9 +1399,13 @@ retry_private:
                /*
                 * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always
                 * be paired with each other and no other futex ops.
+                *
+                * We should never be requeueing a futex_q with a pi_state,
+                * which is awaiting a futex_unlock_pi().
                 */
                if ((requeue_pi && !this->rt_waiter) ||
-                   (!requeue_pi && this->rt_waiter)) {
+                   (!requeue_pi && this->rt_waiter) ||
+                   this->pi_state) {
                        ret = -EINVAL;
                        break;
                }
index 6114a13419bdc3e7424e82db981131c580f6349c..24f9247b7d0214d4b3755bb4396f14d9ef712753 100644 (file)
@@ -11,5 +11,4 @@
 
 extern struct key *modsign_keyring;
 
-extern int mod_verify_sig(const void *mod, unsigned long modlen,
-                         const void *sig, unsigned long siglen);
+extern int mod_verify_sig(const void *mod, unsigned long *_modlen);
index 0e2da8695f8ed2d80b4b498eed883e49936fc59f..6e48c3a43599b6f5d5ce074ec2fbbf8778680ee4 100644 (file)
@@ -2293,12 +2293,17 @@ static void layout_symtab(struct module *mod, struct load_info *info)
        src = (void *)info->hdr + symsect->sh_offset;
        nsrc = symsect->sh_size / sizeof(*src);
 
+       /* strtab always starts with a nul, so offset 0 is the empty string. */
+       strtab_size = 1;
+
        /* Compute total space required for the core symbols' strtab. */
-       for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src)
-               if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) {
-                       strtab_size += strlen(&info->strtab[src->st_name]) + 1;
+       for (ndst = i = 0; i < nsrc; i++) {
+               if (i == 0 ||
+                   is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+                       strtab_size += strlen(&info->strtab[src[i].st_name])+1;
                        ndst++;
                }
+       }
 
        /* Append room for core symbols at end of core part. */
        info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
@@ -2332,15 +2337,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info)
        mod->core_symtab = dst = mod->module_core + info->symoffs;
        mod->core_strtab = s = mod->module_core + info->stroffs;
        src = mod->symtab;
-       *dst = *src;
        *s++ = 0;
-       for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
-               if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum))
-                       continue;
-
-               dst[ndst] = *src;
-               dst[ndst++].st_name = s - mod->core_strtab;
-               s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1;
+       for (ndst = i = 0; i < mod->num_symtab; i++) {
+               if (i == 0 ||
+                   is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) {
+                       dst[ndst] = src[i];
+                       dst[ndst++].st_name = s - mod->core_strtab;
+                       s += strlcpy(s, &mod->strtab[src[i].st_name],
+                                    KSYM_NAME_LEN) + 1;
+               }
        }
        mod->core_num_syms = ndst;
 }
@@ -2421,25 +2426,17 @@ static inline void kmemleak_load_module(const struct module *mod,
 
 #ifdef CONFIG_MODULE_SIG
 static int module_sig_check(struct load_info *info,
-                           const void *mod, unsigned long *len)
+                           const void *mod, unsigned long *_len)
 {
        int err = -ENOKEY;
-       const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
-       const void *p = mod, *end = mod + *len;
-
-       /* Poor man's memmem. */
-       while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) {
-               if (p + markerlen > end)
-                       break;
-
-               if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) {
-                       const void *sig = p + markerlen;
-                       /* Truncate module up to signature. */
-                       *len = p - mod;
-                       err = mod_verify_sig(mod, *len, sig, end - sig);
-                       break;
-               }
-               p++;
+       unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
+       unsigned long len = *_len;
+
+       if (len > markerlen &&
+           memcmp(mod + len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
+               /* We truncate the module to discard the signature */
+               *_len -= markerlen;
+               err = mod_verify_sig(mod, _len);
        }
 
        if (!err) {
index 6b09f6983ac0d75ef35828ebacccb74db57a1817..ea1b1df5dbb0077a167caaf8e013b8baf765e902 100644 (file)
@@ -183,27 +183,33 @@ static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
 /*
  * Verify the signature on a module.
  */
-int mod_verify_sig(const void *mod, unsigned long modlen,
-                  const void *sig, unsigned long siglen)
+int mod_verify_sig(const void *mod, unsigned long *_modlen)
 {
        struct public_key_signature *pks;
        struct module_signature ms;
        struct key *key;
-       size_t sig_len;
+       const void *sig;
+       size_t modlen = *_modlen, sig_len;
        int ret;
 
-       pr_devel("==>%s(,%lu,,%lu,)\n", __func__, modlen, siglen);
+       pr_devel("==>%s(,%zu)\n", __func__, modlen);
 
-       if (siglen <= sizeof(ms))
+       if (modlen <= sizeof(ms))
                return -EBADMSG;
 
-       memcpy(&ms, sig + (siglen - sizeof(ms)), sizeof(ms));
-       siglen -= sizeof(ms);
+       memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
+       modlen -= sizeof(ms);
 
        sig_len = be32_to_cpu(ms.sig_len);
-       if (sig_len >= siglen ||
-           siglen - sig_len != (size_t)ms.signer_len + ms.key_id_len)
+       if (sig_len >= modlen)
                return -EBADMSG;
+       modlen -= sig_len;
+       if ((size_t)ms.signer_len + ms.key_id_len >= modlen)
+               return -EBADMSG;
+       modlen -= (size_t)ms.signer_len + ms.key_id_len;
+
+       *_modlen = modlen;
+       sig = mod + modlen;
 
        /* For the moment, only support RSA and X.509 identifiers */
        if (ms.algo != PKEY_ALGO_RSA ||
index b576f7f14bc6957fdf04ba0324f7416f78995c6a..7e1c3de1ce45f1520fc9b1ef71507b43c2f08697 100644 (file)
@@ -90,7 +90,7 @@ static struct nsproxy *create_new_namespaces(unsigned long flags,
                goto out_pid;
        }
 
-       new_nsp->net_ns = copy_net_ns(flags, tsk->nsproxy->net_ns);
+       new_nsp->net_ns = copy_net_ns(flags, task_cred_xxx(tsk, user_ns), tsk->nsproxy->net_ns);
        if (IS_ERR(new_nsp->net_ns)) {
                err = PTR_ERR(new_nsp->net_ns);
                goto out_net;
index 478bad2745e3a8357fcc2f9a56059d167bf67e49..7b07cc0dfb75fb6b2f2f802178abf82565d9c1a4 100644 (file)
@@ -71,12 +71,22 @@ err_alloc:
        return NULL;
 }
 
+/* MAX_PID_NS_LEVEL is needed for limiting size of 'struct pid' */
+#define MAX_PID_NS_LEVEL 32
+
 static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
 {
        struct pid_namespace *ns;
        unsigned int level = parent_pid_ns->level + 1;
-       int i, err = -ENOMEM;
+       int i;
+       int err;
+
+       if (level > MAX_PID_NS_LEVEL) {
+               err = -EINVAL;
+               goto out;
+       }
 
+       err = -ENOMEM;
        ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
        if (ns == NULL)
                goto out;
@@ -133,19 +143,26 @@ struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old
        return create_pid_namespace(old_ns);
 }
 
-void free_pid_ns(struct kref *kref)
+static void free_pid_ns(struct kref *kref)
 {
-       struct pid_namespace *ns, *parent;
+       struct pid_namespace *ns;
 
        ns = container_of(kref, struct pid_namespace, kref);
-
-       parent = ns->parent;
        destroy_pid_namespace(ns);
+}
+
+void put_pid_ns(struct pid_namespace *ns)
+{
+       struct pid_namespace *parent;
 
-       if (parent != NULL)
-               put_pid_ns(parent);
+       while (ns != &init_pid_ns) {
+               parent = ns->parent;
+               if (!kref_put(&ns->kref, free_pid_ns))
+                       break;
+               ns = parent;
+       }
 }
-EXPORT_SYMBOL_GPL(free_pid_ns);
+EXPORT_SYMBOL_GPL(put_pid_ns);
 
 void zap_pid_ns_processes(struct pid_namespace *pid_ns)
 {
index 66a2ea37b5763b450929a5f955e3bc81ad130a1c..2d607f4d1797cb02e0e4fb60453312a8d3491975 100644 (file)
@@ -1890,7 +1890,6 @@ static int __cpuinit console_cpu_notify(struct notifier_block *self,
        switch (action) {
        case CPU_ONLINE:
        case CPU_DEAD:
-       case CPU_DYING:
        case CPU_DOWN_FAILED:
        case CPU_UP_CANCELED:
                console_lock();
index c5cb5b99cb8152808f569f6b993010a33e646bce..e6e0ece5f6a04401506d62fb602d7034d4273fe1 100644 (file)
@@ -1265,15 +1265,16 @@ DECLARE_RWSEM(uts_sem);
  * Work around broken programs that cannot handle "Linux 3.0".
  * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
  */
-static int override_release(char __user *release, int len)
+static int override_release(char __user *release, size_t len)
 {
        int ret = 0;
-       char buf[65];
 
        if (current->personality & UNAME26) {
-               char *rest = UTS_RELEASE;
+               const char *rest = UTS_RELEASE;
+               char buf[65] = { 0 };
                int ndots = 0;
                unsigned v;
+               size_t copy;
 
                while (*rest) {
                        if (*rest == '.' && ++ndots >= 3)
@@ -1283,8 +1284,9 @@ static int override_release(char __user *release, int len)
                        rest++;
                }
                v = ((LINUX_VERSION_CODE >> 8) & 0xff) + 40;
-               snprintf(buf, len, "2.6.%u%s", v, rest);
-               ret = copy_to_user(release, buf, len);
+               copy = clamp_t(size_t, len, 1, sizeof(buf));
+               copy = scnprintf(buf, copy, "2.6.%u%s", v, rest);
+               ret = copy_to_user(release, buf, copy + 1);
        }
        return ret;
 }
index e2fd74b8e8c250cb9de5ec5650eb32f5d4dcd93d..ff7d9d2ab504ec69da98156f3df39a9b5a868478 100644 (file)
@@ -1,4 +1,4 @@
-obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o timecompare.o
+obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
 obj-y += timeconv.o posix-clock.o alarmtimer.o
 
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BUILD)                += clockevents.o
diff --git a/kernel/time/timecompare.c b/kernel/time/timecompare.c
deleted file mode 100644 (file)
index a9ae369..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2009 Intel Corporation.
- * Author: Patrick Ohly <patrick.ohly@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/timecompare.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/math64.h>
-#include <linux/kernel.h>
-
-/*
- * fixed point arithmetic scale factor for skew
- *
- * Usually one would measure skew in ppb (parts per billion, 1e9), but
- * using a factor of 2 simplifies the math.
- */
-#define TIMECOMPARE_SKEW_RESOLUTION (((s64)1)<<30)
-
-ktime_t timecompare_transform(struct timecompare *sync,
-                             u64 source_tstamp)
-{
-       u64 nsec;
-
-       nsec = source_tstamp + sync->offset;
-       nsec += (s64)(source_tstamp - sync->last_update) * sync->skew /
-               TIMECOMPARE_SKEW_RESOLUTION;
-
-       return ns_to_ktime(nsec);
-}
-EXPORT_SYMBOL_GPL(timecompare_transform);
-
-int timecompare_offset(struct timecompare *sync,
-                      s64 *offset,
-                      u64 *source_tstamp)
-{
-       u64 start_source = 0, end_source = 0;
-       struct {
-               s64 offset;
-               s64 duration_target;
-       } buffer[10], sample, *samples;
-       int counter = 0, i;
-       int used;
-       int index;
-       int num_samples = sync->num_samples;
-
-       if (num_samples > ARRAY_SIZE(buffer)) {
-               samples = kmalloc(sizeof(*samples) * num_samples, GFP_ATOMIC);
-               if (!samples) {
-                       samples = buffer;
-                       num_samples = ARRAY_SIZE(buffer);
-               }
-       } else {
-               samples = buffer;
-       }
-
-       /* run until we have enough valid samples, but do not try forever */
-       i = 0;
-       counter = 0;
-       while (1) {
-               u64 ts;
-               ktime_t start, end;
-
-               start = sync->target();
-               ts = timecounter_read(sync->source);
-               end = sync->target();
-
-               if (!i)
-                       start_source = ts;
-
-               /* ignore negative durations */
-               sample.duration_target = ktime_to_ns(ktime_sub(end, start));
-               if (sample.duration_target >= 0) {
-                       /*
-                        * assume symetric delay to and from source:
-                        * average target time corresponds to measured
-                        * source time
-                        */
-                       sample.offset =
-                               (ktime_to_ns(end) + ktime_to_ns(start)) / 2 -
-                               ts;
-
-                       /* simple insertion sort based on duration */
-                       index = counter - 1;
-                       while (index >= 0) {
-                               if (samples[index].duration_target <
-                                   sample.duration_target)
-                                       break;
-                               samples[index + 1] = samples[index];
-                               index--;
-                       }
-                       samples[index + 1] = sample;
-                       counter++;
-               }
-
-               i++;
-               if (counter >= num_samples || i >= 100000) {
-                       end_source = ts;
-                       break;
-               }
-       }
-
-       *source_tstamp = (end_source + start_source) / 2;
-
-       /* remove outliers by only using 75% of the samples */
-       used = counter * 3 / 4;
-       if (!used)
-               used = counter;
-       if (used) {
-               /* calculate average */
-               s64 off = 0;
-               for (index = 0; index < used; index++)
-                       off += samples[index].offset;
-               *offset = div_s64(off, used);
-       }
-
-       if (samples && samples != buffer)
-               kfree(samples);
-
-       return used;
-}
-EXPORT_SYMBOL_GPL(timecompare_offset);
-
-void __timecompare_update(struct timecompare *sync,
-                         u64 source_tstamp)
-{
-       s64 offset;
-       u64 average_time;
-
-       if (!timecompare_offset(sync, &offset, &average_time))
-               return;
-
-       if (!sync->last_update) {
-               sync->last_update = average_time;
-               sync->offset = offset;
-               sync->skew = 0;
-       } else {
-               s64 delta_nsec = average_time - sync->last_update;
-
-               /* avoid division by negative or small deltas */
-               if (delta_nsec >= 10000) {
-                       s64 delta_offset_nsec = offset - sync->offset;
-                       s64 skew; /* delta_offset_nsec *
-                                    TIMECOMPARE_SKEW_RESOLUTION /
-                                    delta_nsec */
-                       u64 divisor;
-
-                       /* div_s64() is limited to 32 bit divisor */
-                       skew = delta_offset_nsec * TIMECOMPARE_SKEW_RESOLUTION;
-                       divisor = delta_nsec;
-                       while (unlikely(divisor >= ((s64)1) << 32)) {
-                               /* divide both by 2; beware, right shift
-                                  of negative value has undefined
-                                  behavior and can only be used for
-                                  the positive divisor */
-                               skew = div_s64(skew, 2);
-                               divisor >>= 1;
-                       }
-                       skew = div_s64(skew, divisor);
-
-                       /*
-                        * Calculate new overall skew as 4/16 the
-                        * old value and 12/16 the new one. This is
-                        * a rather arbitrary tradeoff between
-                        * only using the latest measurement (0/16 and
-                        * 16/16) and even more weight on past measurements.
-                        */
-#define TIMECOMPARE_NEW_SKEW_PER_16 12
-                       sync->skew =
-                               div_s64((16 - TIMECOMPARE_NEW_SKEW_PER_16) *
-                                       sync->skew +
-                                       TIMECOMPARE_NEW_SKEW_PER_16 * skew,
-                                       16);
-                       sync->last_update = average_time;
-                       sync->offset = offset;
-               }
-       }
-}
-EXPORT_SYMBOL_GPL(__timecompare_update);
index b32ed0e385a59b40b971bd04e0e374d333992749..b979426d16c6efc48e743b6a9df48a78bcaa9f4b 100644 (file)
@@ -1567,6 +1567,10 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
 
                put_online_cpus();
        } else {
+               /* Make sure this CPU has been intitialized */
+               if (!cpumask_test_cpu(cpu_id, buffer->cpumask))
+                       goto out;
+
                cpu_buffer = buffer->buffers[cpu_id];
 
                if (nr_pages == cpu_buffer->nr_pages)
index 9d4c8d5a1f538b25b6698483ed37080ecb7652fc..dd4b80a9f1a986ff35b192655064db6db3b85883 100644 (file)
@@ -116,7 +116,7 @@ static unsigned long get_timestamp(int this_cpu)
        return cpu_clock(this_cpu) >> 30LL;  /* 2^30 ~= 10^9 */
 }
 
-static unsigned long get_sample_period(void)
+static u64 get_sample_period(void)
 {
        /*
         * convert watchdog_thresh from seconds to ns
@@ -125,7 +125,7 @@ static unsigned long get_sample_period(void)
         * and hard thresholds) to increment before the
         * hardlockup detector generates a warning
         */
-       return get_softlockup_thresh() * (NSEC_PER_SEC / 5);
+       return get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5);
 }
 
 /* Commands for resetting the watchdog */
index d951daa0ca9a81b21f6b1387b140f537b53c27c1..042d221d33cc1675fadf7ee291e86717f2c8f6c9 100644 (file)
@@ -2982,7 +2982,7 @@ bool cancel_delayed_work(struct delayed_work *dwork)
 
        set_work_cpu_and_clear_pending(&dwork->work, work_cpu(&dwork->work));
        local_irq_restore(flags);
-       return true;
+       return ret;
 }
 EXPORT_SYMBOL(cancel_delayed_work);
 
index b9087bff008be9ef4b4eb2ebb7acea898b69be8d..d84beb994f36f1c0b6d7e82fa02fc558a13f88c9 100644 (file)
@@ -264,7 +264,7 @@ static struct dma_debug_entry *__hash_bucket_find(struct hash_bucket *bucket,
                                                  match_fn match)
 {
        struct dma_debug_entry *entry, *ret = NULL;
-       int matches = 0, match_lvl, last_lvl = 0;
+       int matches = 0, match_lvl, last_lvl = -1;
 
        list_for_each_entry(entry, &bucket->list, list) {
                if (!match(ref, entry))
@@ -293,7 +293,7 @@ static struct dma_debug_entry *__hash_bucket_find(struct hash_bucket *bucket,
                } else if (match_lvl > last_lvl) {
                        /*
                         * We found an entry that fits better then the
-                        * previous one
+                        * previous one or it is the 1st match.
                         */
                        last_lvl = match_lvl;
                        ret      = entry;
index ca208a92628c1b49a6f5c1fece1a81592a65ecaa..54920433705adbff385b319574a9f04b50d8ca77 100644 (file)
@@ -178,7 +178,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy
        struct gen_pool_chunk *chunk;
        int nbits = size >> pool->min_alloc_order;
        int nbytes = sizeof(struct gen_pool_chunk) +
-                               (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE;
+                               BITS_TO_LONGS(nbits) * sizeof(long);
 
        chunk = kmalloc_node(nbytes, GFP_KERNEL | __GFP_ZERO, nid);
        if (unlikely(chunk == NULL))
index 678ce4f1e124b4be4c255f297cef1e29477e7ce0..095ab157a5215a800d01585bbb50b0d6b6a88a17 100644 (file)
@@ -641,7 +641,14 @@ do { \
        **************  MIPS  *****************
        ***************************************/
 #if defined(__mips__) && W_TYPE_SIZE == 32
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v)                        \
+do {                                           \
+       UDItype __ll = (UDItype)(u) * (v);      \
+       w1 = __ll >> 32;                        \
+       w0 = __ll;                              \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #define umul_ppmm(w1, w0, u, v) \
        __asm__ ("multu %2,%3" \
        : "=l" ((USItype)(w0)), \
@@ -666,7 +673,15 @@ do { \
        **************  MIPS/64  **************
        ***************************************/
 #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v) \
+do {                                                                   \
+       typedef unsigned int __ll_UTItype __attribute__((mode(TI)));    \
+       __ll_UTItype __ll = (__ll_UTItype)(u) * (v);                    \
+       w1 = __ll >> 64;                                                \
+       w0 = __ll;                                                      \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #define umul_ppmm(w1, w0, u, v) \
        __asm__ ("dmultu %2,%3" \
        : "=l" ((UDItype)(w0)), \
index 434be4ae7a0495817267e5e100c68f47c2006415..f468185b3b28a517aaceb79b80e7f799df0dfc6f 100644 (file)
@@ -198,8 +198,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                        int order = ilog2(BITS_PER_LONG);
 
                        __free_pages_bootmem(pfn_to_page(start), order);
-                       fixup_zone_present_pages(page_to_nid(pfn_to_page(start)),
-                                       start, start + BITS_PER_LONG);
                        count += BITS_PER_LONG;
                        start += BITS_PER_LONG;
                } else {
@@ -210,9 +208,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                                if (vec & 1) {
                                        page = pfn_to_page(start + off);
                                        __free_pages_bootmem(page, 0);
-                                       fixup_zone_present_pages(
-                                               page_to_nid(page),
-                                               start + off, start + off + 1);
                                        count++;
                                }
                                vec >>= 1;
@@ -226,11 +221,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
        pages = bdata->node_low_pfn - bdata->node_min_pfn;
        pages = bootmem_bootmap_pages(pages);
        count += pages;
-       while (pages--) {
-               fixup_zone_present_pages(page_to_nid(page),
-                               page_to_pfn(page), page_to_pfn(page) + 1);
+       while (pages--)
                __free_pages_bootmem(page++, 0);
-       }
 
        bdebug("nid=%td released=%lx\n", bdata - bootmem_node_data, count);
 
index 2c4ce17651d825c97c7d89ecea52bf53f17ce0aa..9eef55838fca5ff99580982e85ea0c0fa6dea839 100644 (file)
@@ -346,7 +346,7 @@ static unsigned long isolate_freepages_block(struct compact_control *cc,
         * pages requested were isolated. If there were any failures, 0 is
         * returned and CMA will fail.
         */
-       if (strict && nr_strict_required != total_isolated)
+       if (strict && nr_strict_required > total_isolated)
                total_isolated = 0;
 
        if (locked)
index 3899a86851ceb6bf021e51c014fef16e0893a7f0..a0aaf0e56800394be8b9ae0d0da47712b6e0bb53 100644 (file)
@@ -169,7 +169,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
        if (vma->vm_private_data && !(vma->vm_flags & VM_NONLINEAR))
                goto out;
 
-       if (!vma->vm_ops->remap_pages)
+       if (!vma->vm_ops || !vma->vm_ops->remap_pages)
                goto out;
 
        if (start < vma->vm_start || start + size > vma->vm_end)
index d517cd16a6eb91e8df18f3cbd79cd67621b27d3f..2da13a5c50e2b48e8fe8dea34d4bd4835c127da9 100644 (file)
@@ -98,7 +98,7 @@ struct page *kmap_to_page(void *vaddr)
 {
        unsigned long addr = (unsigned long)vaddr;
 
-       if (addr >= PKMAP_ADDR(0) && addr <= PKMAP_ADDR(LAST_PKMAP)) {
+       if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) {
                int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT;
                return pte_page(pkmap_page_table[i]);
        }
index a863af26c79c0190f378c36ac4e680add06f700a..40f17c34b4153fab93b4f1a2685dee0b8cac4da8 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/khugepaged.h>
 #include <linux/freezer.h>
 #include <linux/mman.h>
+#include <linux/pagemap.h>
 #include <asm/tlb.h>
 #include <asm/pgalloc.h>
 #include "internal.h"
index 931eef145af5eed370ed6f2b0c9dc577295be6ff..625905523c2a1592f539c46f6721723d62376648 100644 (file)
@@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si
        return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
 }
 
+void __init_memblock memblock_trim_memory(phys_addr_t align)
+{
+       int i;
+       phys_addr_t start, end, orig_start, orig_end;
+       struct memblock_type *mem = &memblock.memory;
+
+       for (i = 0; i < mem->cnt; i++) {
+               orig_start = mem->regions[i].base;
+               orig_end = mem->regions[i].base + mem->regions[i].size;
+               start = round_up(orig_start, align);
+               end = round_down(orig_end, align);
+
+               if (start == orig_start && end == orig_end)
+                       continue;
+
+               if (start < end) {
+                       mem->regions[i].base = start;
+                       mem->regions[i].size = end - start;
+               } else {
+                       memblock_remove_region(mem, i);
+                       i--;
+               }
+       }
+}
 
 void __init_memblock memblock_set_current_limit(phys_addr_t limit)
 {
index 7acf43bf04a270cf2bf90f342c66142d1c5cf675..dd39ba000b31f98730c6fd6d22bdf695ced3bedf 100644 (file)
@@ -1055,12 +1055,24 @@ struct lruvec *mem_cgroup_zone_lruvec(struct zone *zone,
                                      struct mem_cgroup *memcg)
 {
        struct mem_cgroup_per_zone *mz;
+       struct lruvec *lruvec;
 
-       if (mem_cgroup_disabled())
-               return &zone->lruvec;
+       if (mem_cgroup_disabled()) {
+               lruvec = &zone->lruvec;
+               goto out;
+       }
 
        mz = mem_cgroup_zoneinfo(memcg, zone_to_nid(zone), zone_idx(zone));
-       return &mz->lruvec;
+       lruvec = &mz->lruvec;
+out:
+       /*
+        * Since a node can be onlined after the mem_cgroup was created,
+        * we have to be prepared to initialize lruvec->zone here;
+        * and if offlined then reonlined, we need to reinitialize it.
+        */
+       if (unlikely(lruvec->zone != zone))
+               lruvec->zone = zone;
+       return lruvec;
 }
 
 /*
@@ -1087,9 +1099,12 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone)
        struct mem_cgroup_per_zone *mz;
        struct mem_cgroup *memcg;
        struct page_cgroup *pc;
+       struct lruvec *lruvec;
 
-       if (mem_cgroup_disabled())
-               return &zone->lruvec;
+       if (mem_cgroup_disabled()) {
+               lruvec = &zone->lruvec;
+               goto out;
+       }
 
        pc = lookup_page_cgroup(page);
        memcg = pc->mem_cgroup;
@@ -1107,7 +1122,16 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone)
                pc->mem_cgroup = memcg = root_mem_cgroup;
 
        mz = page_cgroup_zoneinfo(memcg, page);
-       return &mz->lruvec;
+       lruvec = &mz->lruvec;
+out:
+       /*
+        * Since a node can be onlined after the mem_cgroup was created,
+        * we have to be prepared to initialize lruvec->zone here;
+        * and if offlined then reonlined, we need to reinitialize it.
+        */
+       if (unlikely(lruvec->zone != zone))
+               lruvec->zone = zone;
+       return lruvec;
 }
 
 /**
@@ -1452,17 +1476,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg)
 static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
 {
        u64 limit;
-       u64 memsw;
 
        limit = res_counter_read_u64(&memcg->res, RES_LIMIT);
-       limit += total_swap_pages << PAGE_SHIFT;
 
-       memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
        /*
-        * If memsw is finite and limits the amount of swap space available
-        * to this memcg, return that limit.
+        * Do not consider swap space if we cannot swap due to swappiness
         */
-       return min(limit, memsw);
+       if (mem_cgroup_swappiness(memcg)) {
+               u64 memsw;
+
+               limit += total_swap_pages << PAGE_SHIFT;
+               memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
+
+               /*
+                * If memsw is finite and limits the amount of swap space
+                * available to this memcg, return that limit.
+                */
+               limit = min(limit, memsw);
+       }
+
+       return limit;
 }
 
 void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
@@ -3688,17 +3721,17 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
                                int node, int zid, enum lru_list lru)
 {
-       struct mem_cgroup_per_zone *mz;
+       struct lruvec *lruvec;
        unsigned long flags, loop;
        struct list_head *list;
        struct page *busy;
        struct zone *zone;
 
        zone = &NODE_DATA(node)->node_zones[zid];
-       mz = mem_cgroup_zoneinfo(memcg, node, zid);
-       list = &mz->lruvec.lists[lru];
+       lruvec = mem_cgroup_zone_lruvec(zone, memcg);
+       list = &lruvec->lists[lru];
 
-       loop = mz->lru_size[lru];
+       loop = mem_cgroup_get_lru_size(lruvec, lru);
        /* give some margin against EBUSY etc...*/
        loop += 256;
        busy = NULL;
@@ -4736,7 +4769,7 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 
        for (zone = 0; zone < MAX_NR_ZONES; zone++) {
                mz = &pn->zoneinfo[zone];
-               lruvec_init(&mz->lruvec, &NODE_DATA(node)->node_zones[zone]);
+               lruvec_init(&mz->lruvec);
                mz->usage_in_excess = 0;
                mz->on_tree = false;
                mz->memcg = memcg;
index fb135ba4aba90349e58c79d49838860cb7db8105..221fc9ffcab1da33eb15947776975730b5058b67 100644 (file)
@@ -2527,9 +2527,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        int ret = 0;
        int page_mkwrite = 0;
        struct page *dirty_page = NULL;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
-       bool mmun_called = false;       /* For mmu_notifiers */
+       unsigned long mmun_start = 0;   /* For mmu_notifiers */
+       unsigned long mmun_end = 0;     /* For mmu_notifiers */
 
        old_page = vm_normal_page(vma, address, orig_pte);
        if (!old_page) {
@@ -2708,8 +2707,7 @@ gotten:
                goto oom_free_new;
 
        mmun_start  = address & PAGE_MASK;
-       mmun_end    = (address & PAGE_MASK) + PAGE_SIZE;
-       mmun_called = true;
+       mmun_end    = mmun_start + PAGE_SIZE;
        mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 
        /*
@@ -2778,7 +2776,7 @@ gotten:
                page_cache_release(new_page);
 unlock:
        pte_unmap_unlock(page_table, ptl);
-       if (mmun_called)
+       if (mmun_end > mmun_start)
                mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
        if (old_page) {
                /*
index 56b758ae57d2eeb2230bbcaf3f8e8d4538a15a9d..e4eeacae2b91199142776390bdaef73241416b47 100644 (file)
@@ -106,7 +106,6 @@ static void get_page_bootmem(unsigned long info,  struct page *page,
 void __ref put_page_bootmem(struct page *page)
 {
        unsigned long type;
-       struct zone *zone;
 
        type = (unsigned long) page->lru.next;
        BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
@@ -117,12 +116,6 @@ void __ref put_page_bootmem(struct page *page)
                set_page_private(page, 0);
                INIT_LIST_HEAD(&page->lru);
                __free_pages_bootmem(page, 0);
-
-               zone = page_zone(page);
-               zone_span_writelock(zone);
-               zone->present_pages++;
-               zone_span_writeunlock(zone);
-               totalram_pages++;
        }
 
 }
index 0b78fb9ea65b60afa08287f0eff1d797d75c9a7e..d04a8a54c294f852f55e624e3c41d1b03b7a56e9 100644 (file)
@@ -1536,9 +1536,8 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
  *
  * Returns effective policy for a VMA at specified address.
  * Falls back to @task or system default policy, as necessary.
- * Current or other task's task mempolicy and non-shared vma policies
- * are protected by the task's mmap_sem, which must be held for read by
- * the caller.
+ * Current or other task's task mempolicy and non-shared vma policies must be
+ * protected by task_lock(task) by the caller.
  * Shared policies [those marked as MPOL_F_SHARED] require an extra reference
  * count--added by the get_policy() vm_op, as appropriate--to protect against
  * freeing by another task.  It is the caller's responsibility to free the
index 2d942353d681a8b4f08155eebdcfb20b088093e7..9a796c41e7d9ecf8d474089df2d1b2235451ce3c 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -334,8 +334,10 @@ void validate_mm(struct mm_struct *mm)
        struct vm_area_struct *vma = mm->mmap;
        while (vma) {
                struct anon_vma_chain *avc;
+               vma_lock_anon_vma(vma);
                list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
                        anon_vma_interval_tree_verify(avc);
+               vma_unlock_anon_vma(vma);
                vma = vma->vm_next;
                i++;
        }
index 479a1e751a73fb4781e1b856db60b2381909c9e6..8a5ac8c686b03480fae7d5b193a5c714c7c2397b 100644 (file)
@@ -196,28 +196,28 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
 
        /*
-       * Verify that mmu_notifier_init() already run and the global srcu is
-       * initialized.
-       */
+        * Verify that mmu_notifier_init() already run and the global srcu is
+        * initialized.
+        */
        BUG_ON(!srcu.per_cpu_ref);
 
+       ret = -ENOMEM;
+       mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL);
+       if (unlikely(!mmu_notifier_mm))
+               goto out;
+
        if (take_mmap_sem)
                down_write(&mm->mmap_sem);
        ret = mm_take_all_locks(mm);
        if (unlikely(ret))
-               goto out;
+               goto out_clean;
 
        if (!mm_has_notifiers(mm)) {
-               mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm),
-                                       GFP_KERNEL);
-               if (unlikely(!mmu_notifier_mm)) {
-                       ret = -ENOMEM;
-                       goto out_of_mem;
-               }
                INIT_HLIST_HEAD(&mmu_notifier_mm->list);
                spin_lock_init(&mmu_notifier_mm->lock);
 
                mm->mmu_notifier_mm = mmu_notifier_mm;
+               mmu_notifier_mm = NULL;
        }
        atomic_inc(&mm->mm_count);
 
@@ -233,12 +233,12 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
        hlist_add_head(&mn->hlist, &mm->mmu_notifier_mm->list);
        spin_unlock(&mm->mmu_notifier_mm->lock);
 
-out_of_mem:
        mm_drop_all_locks(mm);
-out:
+out_clean:
        if (take_mmap_sem)
                up_write(&mm->mmap_sem);
-
+       kfree(mmu_notifier_mm);
+out:
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
        return ret;
 }
index 3cef80f6ac79ff2e8b5fef7bcd373679e91df2c1..4596d81b89b16280b4768e83df3290d674aaf005 100644 (file)
@@ -87,7 +87,7 @@ int memmap_valid_within(unsigned long pfn,
 }
 #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
 
-void lruvec_init(struct lruvec *lruvec, struct zone *zone)
+void lruvec_init(struct lruvec *lruvec)
 {
        enum lru_list lru;
 
@@ -95,8 +95,4 @@ void lruvec_init(struct lruvec *lruvec, struct zone *zone)
 
        for_each_lru(lru)
                INIT_LIST_HEAD(&lruvec->lists[lru]);
-
-#ifdef CONFIG_MEMCG
-       lruvec->zone = zone;
-#endif
 }
index 714d5d6504708c83c64365618749a84b1da4cd66..bd82f6b314114dc937bea707a70072b299860a08 100644 (file)
@@ -116,8 +116,6 @@ static unsigned long __init __free_memory_core(phys_addr_t start,
                return 0;
 
        __free_pages_memory(start_pfn, end_pfn);
-       fixup_zone_present_pages(pfn_to_nid(start >> PAGE_SHIFT),
-                       start_pfn, end_pfn);
 
        return end_pfn - start_pfn;
 }
@@ -128,7 +126,6 @@ unsigned long __init free_low_memory_core_early(int nodeid)
        phys_addr_t start, end, size;
        u64 i;
 
-       reset_zone_present_pages();
        for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL)
                count += __free_memory_core(start, end);
 
index bb90971182bd8c833e40f508e3c8b8677d6913c8..92871579cbee3b8feb12376df03ad2969f942c48 100644 (file)
@@ -1405,7 +1405,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
 
        mt = get_pageblock_migratetype(page);
        if (unlikely(mt != MIGRATE_ISOLATE))
-               __mod_zone_freepage_state(zone, -(1UL << order), mt);
+               __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
 
        if (alloc_order != order)
                expand(zone, page, alloc_order, order,
@@ -1809,10 +1809,10 @@ static void __paginginit init_zone_allows_reclaim(int nid)
        int i;
 
        for_each_online_node(i)
-               if (node_distance(nid, i) <= RECLAIM_DISTANCE) {
+               if (node_distance(nid, i) <= RECLAIM_DISTANCE)
                        node_set(i, NODE_DATA(nid)->reclaim_nodes);
+               else
                        zone_reclaim_mode = 1;
-               }
 }
 
 #else  /* CONFIG_NUMA */
@@ -2416,8 +2416,9 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
                goto nopage;
 
 restart:
-       wake_all_kswapd(order, zonelist, high_zoneidx,
-                                       zone_idx(preferred_zone));
+       if (!(gfp_mask & __GFP_NO_KSWAPD))
+               wake_all_kswapd(order, zonelist, high_zoneidx,
+                                               zone_idx(preferred_zone));
 
        /*
         * OK, we're below the kswapd watermark and have kicked background
@@ -2494,7 +2495,7 @@ rebalance:
         * system then fail the allocation instead of entering direct reclaim.
         */
        if ((deferred_compaction || contended_compaction) &&
-           (gfp_mask & (__GFP_MOVABLE|__GFP_REPEAT)) == __GFP_MOVABLE)
+                                               (gfp_mask & __GFP_NO_KSWAPD))
                goto nopage;
 
        /* Try direct reclaim and then allocating */
@@ -4505,7 +4506,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                zone->zone_pgdat = pgdat;
 
                zone_pcp_init(zone);
-               lruvec_init(&zone->lruvec, zone);
+               lruvec_init(&zone->lruvec);
                if (!size)
                        continue;
 
@@ -5825,7 +5826,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
        ret = start_isolate_page_range(pfn_max_align_down(start),
                                       pfn_max_align_up(end), migratetype);
        if (ret)
-               goto done;
+               return ret;
 
        ret = __alloc_contig_migrate_range(&cc, start, end);
        if (ret)
@@ -6098,37 +6099,3 @@ void dump_page(struct page *page)
        dump_page_flags(page->flags);
        mem_cgroup_print_bad_page(page);
 }
-
-/* reset zone->present_pages */
-void reset_zone_present_pages(void)
-{
-       struct zone *z;
-       int i, nid;
-
-       for_each_node_state(nid, N_HIGH_MEMORY) {
-               for (i = 0; i < MAX_NR_ZONES; i++) {
-                       z = NODE_DATA(nid)->node_zones + i;
-                       z->present_pages = 0;
-               }
-       }
-}
-
-/* calculate zone's present pages in buddy system */
-void fixup_zone_present_pages(int nid, unsigned long start_pfn,
-                               unsigned long end_pfn)
-{
-       struct zone *z;
-       unsigned long zone_start_pfn, zone_end_pfn;
-       int i;
-
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               z = NODE_DATA(nid)->node_zones + i;
-               zone_start_pfn = z->zone_start_pfn;
-               zone_end_pfn = zone_start_pfn + z->spanned_pages;
-
-               /* if the two regions intersect */
-               if (!(zone_start_pfn >= end_pfn || zone_end_pfn <= start_pfn))
-                       z->present_pages += min(end_pfn, zone_end_pfn) -
-                                           max(start_pfn, zone_start_pfn);
-       }
-}
index 7df7984d476c8661b900725c0e2c3f33c883a32d..2ee1ef0f317b7487bfb21b7a6717b1e12d1f7ef4 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -56,6 +56,7 @@
 #include <linux/mmu_notifier.h>
 #include <linux/migrate.h>
 #include <linux/hugetlb.h>
+#include <linux/backing-dev.h>
 
 #include <asm/tlbflush.h>
 
@@ -926,11 +927,8 @@ int page_mkclean(struct page *page)
 
        if (page_mapped(page)) {
                struct address_space *mapping = page_mapping(page);
-               if (mapping) {
+               if (mapping)
                        ret = page_mkclean_file(mapping, page);
-                       if (page_test_and_clear_dirty(page_to_pfn(page), 1))
-                               ret = 1;
-               }
        }
 
        return ret;
@@ -1116,6 +1114,7 @@ void page_add_file_rmap(struct page *page)
  */
 void page_remove_rmap(struct page *page)
 {
+       struct address_space *mapping = page_mapping(page);
        bool anon = PageAnon(page);
        bool locked;
        unsigned long flags;
@@ -1138,8 +1137,19 @@ void page_remove_rmap(struct page *page)
         * this if the page is anon, so about to be freed; but perhaps
         * not if it's in swapcache - there might be another pte slot
         * containing the swap entry, but page not yet written to swap.
+        *
+        * And we can skip it on file pages, so long as the filesystem
+        * participates in dirty tracking; but need to catch shm and tmpfs
+        * and ramfs pages which have been modified since creation by read
+        * fault.
+        *
+        * Note that mapping must be decided above, before decrementing
+        * mapcount (which luckily provides a barrier): once page is unmapped,
+        * it could be truncated and page->mapping reset to NULL at any moment.
+        * Note also that we are relying on page_mapping(page) to set mapping
+        * to &swapper_space when PageSwapCache(page).
         */
-       if ((!anon || PageSwapCache(page)) &&
+       if (mapping && !mapping_cap_account_dirty(mapping) &&
            page_test_and_clear_dirty(page_to_pfn(page), 1))
                set_page_dirty(page);
        /*
index 67afba5117f2ebe80ef54e487d068fdf99e986bb..89341b658bd06b05d908f8becfef7fe0d904b808 100644 (file)
@@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode)
                kfree(info->symlink);
 
        simple_xattrs_free(&info->xattrs);
-       BUG_ON(inode->i_blocks);
+       WARN_ON(inode->i_blocks);
        shmem_free_inode(inode->i_sb);
        clear_inode(inode);
 }
@@ -1145,8 +1145,20 @@ repeat:
                if (!error) {
                        error = shmem_add_to_page_cache(page, mapping, index,
                                                gfp, swp_to_radix_entry(swap));
-                       /* We already confirmed swap, and make no allocation */
-                       VM_BUG_ON(error);
+                       /*
+                        * We already confirmed swap under page lock, and make
+                        * no memory allocation here, so usually no possibility
+                        * of error; but free_swap_and_cache() only trylocks a
+                        * page, so it is just possible that the entry has been
+                        * truncated or holepunched since swap was confirmed.
+                        * shmem_undo_range() will have done some of the
+                        * unaccounting, now delete_from_swap_cache() will do
+                        * the rest (including mem_cgroup_uncharge_swapcache).
+                        * Reset swap.val? No, leave it so "failed" goes back to
+                        * "repeat": reading a hole and writing should succeed.
+                        */
+                       if (error)
+                               delete_from_swap_cache(page);
                }
                if (error)
                        goto failed;
index a08e4681fd0d630ff212e299f5b657f71e48c4b0..1e921c5e9576b6db64cc07fb4f4c90a8f4e2729e 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -429,7 +429,7 @@ static __always_inline void *
 __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
 {
        unsigned int *m;
-       int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+       int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
        void *ret;
 
        gfp &= gfp_allowed_mask;
@@ -502,7 +502,7 @@ void kfree(const void *block)
 
        sp = virt_to_page(block);
        if (PageSlab(sp)) {
-               int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+               int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
                unsigned int *m = (unsigned int *)(block - align);
                slob_free(m, *m + align);
        } else
@@ -521,7 +521,7 @@ size_t ksize(const void *block)
 
        sp = virt_to_page(block);
        if (PageSlab(sp)) {
-               int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
+               int align = max_t(size_t, ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN);
                unsigned int *m = (unsigned int *)(block - align);
                return SLOB_UNITS(*m) * SLOB_UNIT;
        } else
index 71cd288b200179d4962222337f3947342fcebe57..f91a25547ffe1f2febdfb0a526ee296996da171b 100644 (file)
@@ -1494,9 +1494,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        BUG_ON(!current->mm);
 
        pathname = getname(specialfile);
-       err = PTR_ERR(pathname);
        if (IS_ERR(pathname))
-               goto out;
+               return PTR_ERR(pathname);
 
        victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
        err = PTR_ERR(victim);
@@ -1608,6 +1607,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 out_dput:
        filp_close(victim, NULL);
 out:
+       putname(pathname);
        return err;
 }
 
index 2624edcfb42095d6e91ae79c7ca30e0e4838a0fd..cbf84e152f043c82b15d754a9f8c2c4c50866488 100644 (file)
@@ -1760,28 +1760,6 @@ static bool in_reclaim_compaction(struct scan_control *sc)
        return false;
 }
 
-#ifdef CONFIG_COMPACTION
-/*
- * If compaction is deferred for sc->order then scale the number of pages
- * reclaimed based on the number of consecutive allocation failures
- */
-static unsigned long scale_for_compaction(unsigned long pages_for_compaction,
-                       struct lruvec *lruvec, struct scan_control *sc)
-{
-       struct zone *zone = lruvec_zone(lruvec);
-
-       if (zone->compact_order_failed <= sc->order)
-               pages_for_compaction <<= zone->compact_defer_shift;
-       return pages_for_compaction;
-}
-#else
-static unsigned long scale_for_compaction(unsigned long pages_for_compaction,
-                       struct lruvec *lruvec, struct scan_control *sc)
-{
-       return pages_for_compaction;
-}
-#endif
-
 /*
  * Reclaim/compaction is used for high-order allocation requests. It reclaims
  * order-0 pages before compacting the zone. should_continue_reclaim() returns
@@ -1829,9 +1807,6 @@ static inline bool should_continue_reclaim(struct lruvec *lruvec,
         * inactive lists are large enough, continue reclaiming
         */
        pages_for_compaction = (2UL << sc->order);
-
-       pages_for_compaction = scale_for_compaction(pages_for_compaction,
-                                                   lruvec, sc);
        inactive_lru_pages = get_lru_size(lruvec, LRU_INACTIVE_FILE);
        if (nr_swap_pages > 0)
                inactive_lru_pages += get_lru_size(lruvec, LRU_INACTIVE_ANON);
@@ -2232,9 +2207,12 @@ static bool pfmemalloc_watermark_ok(pg_data_t *pgdat)
  * Throttle direct reclaimers if backing storage is backed by the network
  * and the PFMEMALLOC reserve for the preferred node is getting dangerously
  * depleted. kswapd will continue to make progress and wake the processes
- * when the low watermark is reached
+ * when the low watermark is reached.
+ *
+ * Returns true if a fatal signal was delivered during throttling. If this
+ * happens, the page allocator should not consider triggering the OOM killer.
  */
-static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
+static bool throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
                                        nodemask_t *nodemask)
 {
        struct zone *zone;
@@ -2249,13 +2227,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
         * processes to block on log_wait_commit().
         */
        if (current->flags & PF_KTHREAD)
-               return;
+               goto out;
+
+       /*
+        * If a fatal signal is pending, this process should not throttle.
+        * It should return quickly so it can exit and free its memory
+        */
+       if (fatal_signal_pending(current))
+               goto out;
 
        /* Check if the pfmemalloc reserves are ok */
        first_zones_zonelist(zonelist, high_zoneidx, NULL, &zone);
        pgdat = zone->zone_pgdat;
        if (pfmemalloc_watermark_ok(pgdat))
-               return;
+               goto out;
 
        /* Account for the throttling */
        count_vm_event(PGSCAN_DIRECT_THROTTLE);
@@ -2271,12 +2256,20 @@ static void throttle_direct_reclaim(gfp_t gfp_mask, struct zonelist *zonelist,
        if (!(gfp_mask & __GFP_FS)) {
                wait_event_interruptible_timeout(pgdat->pfmemalloc_wait,
                        pfmemalloc_watermark_ok(pgdat), HZ);
-               return;
+
+               goto check_pending;
        }
 
        /* Throttle until kswapd wakes the process */
        wait_event_killable(zone->zone_pgdat->pfmemalloc_wait,
                pfmemalloc_watermark_ok(pgdat));
+
+check_pending:
+       if (fatal_signal_pending(current))
+               return true;
+
+out:
+       return false;
 }
 
 unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
@@ -2298,13 +2291,12 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
                .gfp_mask = sc.gfp_mask,
        };
 
-       throttle_direct_reclaim(gfp_mask, zonelist, nodemask);
-
        /*
-        * Do not enter reclaim if fatal signal is pending. 1 is returned so
-        * that the page allocator does not consider triggering OOM
+        * Do not enter reclaim if fatal signal was delivered while throttled.
+        * 1 is returned so that the page allocator does not OOM kill at this
+        * point.
         */
-       if (fatal_signal_pending(current))
+       if (throttle_direct_reclaim(gfp_mask, zonelist, nodemask))
                return 1;
 
        trace_mm_vmscan_direct_reclaim_begin(order,
@@ -3017,6 +3009,8 @@ static int kswapd(void *p)
                                                &balanced_classzone_idx);
                }
        }
+
+       current->reclaim_state = NULL;
        return 0;
 }
 
index 9096bcb081326c92bb64b6dedb11033073998ca5..a292e8050ef234029611090004f1b46f889610d3 100644 (file)
@@ -242,6 +242,7 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id)
         * hope the underlying device can handle it.
         */
        new_dev->mtu = real_dev->mtu;
+       new_dev->priv_flags |= (real_dev->priv_flags & IFF_UNICAST_FLT);
 
        vlan_dev_priv(new_dev)->vlan_id = vlan_id;
        vlan_dev_priv(new_dev)->real_dev = real_dev;
@@ -294,7 +295,7 @@ static void vlan_transfer_features(struct net_device *dev,
        else
                vlandev->hard_header_len = dev->hard_header_len + VLAN_HLEN;
 
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
        vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid;
 #endif
 
@@ -463,7 +464,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 
        case NETDEV_PRE_TYPE_CHANGE:
                /* Forbid underlaying device to change its type. */
-               return NOTIFY_BAD;
+               if (vlan_uses_dev(dev))
+                       return NOTIFY_BAD;
+               break;
 
        case NETDEV_NOTIFY_PEERS:
        case NETDEV_BONDING_FAILOVER:
@@ -527,7 +530,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
        switch (args.cmd) {
        case SET_VLAN_INGRESS_PRIORITY_CMD:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
                vlan_dev_set_ingress_priority(dev,
                                              args.u.skb_priority,
@@ -537,7 +540,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 
        case SET_VLAN_EGRESS_PRIORITY_CMD:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
                err = vlan_dev_set_egress_priority(dev,
                                                   args.u.skb_priority,
@@ -546,7 +549,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 
        case SET_VLAN_FLAG_CMD:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
                err = vlan_dev_change_flags(dev,
                                            args.vlan_qos ? args.u.flag : 0,
@@ -555,7 +558,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 
        case SET_VLAN_NAME_TYPE_CMD:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
                if ((args.u.name_type >= 0) &&
                    (args.u.name_type < VLAN_NAME_TYPE_HIGHEST)) {
@@ -571,14 +574,14 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 
        case ADD_VLAN_CMD:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
                err = register_vlan_device(dev, args.u.VID);
                break;
 
        case DEL_VLAN_CMD:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
                unregister_vlan_dev(dev, NULL);
                err = 0;
index fbbf1fa00940e2c843f1706ea1a6bcfff349c555..65e06abe023f7fba92f468120937d84fd5911d43 100644 (file)
@@ -366,6 +366,13 @@ EXPORT_SYMBOL(vlan_vids_del_by_dev);
 
 bool vlan_uses_dev(const struct net_device *dev)
 {
-       return rtnl_dereference(dev->vlan_info) ? true : false;
+       struct vlan_info *vlan_info;
+
+       ASSERT_RTNL();
+
+       vlan_info = rtnl_dereference(dev->vlan_info);
+       if (!vlan_info)
+               return false;
+       return vlan_info->grp.nr_vlan_devs ? true : false;
 }
 EXPORT_SYMBOL(vlan_uses_dev);
index 402442402af710d5acedf500347cca48f89a6be4..4a6d31a082b9e534eadc3fa2873313fa07cc7869 100644 (file)
@@ -409,7 +409,7 @@ static int vlan_dev_neigh_setup(struct net_device *dev, struct neigh_parms *pa)
        return err;
 }
 
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
 static int vlan_dev_fcoe_ddp_setup(struct net_device *dev, u16 xid,
                                   struct scatterlist *sgl, unsigned int sgc)
 {
@@ -531,6 +531,10 @@ static const struct header_ops vlan_header_ops = {
        .parse   = eth_header_parse,
 };
 
+static struct device_type vlan_type = {
+       .name   = "vlan",
+};
+
 static const struct net_device_ops vlan_netdev_ops;
 
 static int vlan_dev_init(struct net_device *dev)
@@ -564,7 +568,7 @@ static int vlan_dev_init(struct net_device *dev)
        if (is_zero_ether_addr(dev->broadcast))
                memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
 
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
        dev->fcoe_ddp_xid = real_dev->fcoe_ddp_xid;
 #endif
 
@@ -579,6 +583,8 @@ static int vlan_dev_init(struct net_device *dev)
 
        dev->netdev_ops = &vlan_netdev_ops;
 
+       SET_NETDEV_DEVTYPE(dev, &vlan_type);
+
        if (is_vlan_dev(real_dev))
                subclass = 1;
 
@@ -741,7 +747,7 @@ static const struct net_device_ops vlan_netdev_ops = {
        .ndo_do_ioctl           = vlan_dev_ioctl,
        .ndo_neigh_setup        = vlan_dev_neigh_setup,
        .ndo_get_stats64        = vlan_dev_get_stats64,
-#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
+#if IS_ENABLED(CONFIG_FCOE)
        .ndo_fcoe_ddp_setup     = vlan_dev_fcoe_ddp_setup,
        .ndo_fcoe_ddp_done      = vlan_dev_fcoe_ddp_done,
        .ndo_fcoe_enable        = vlan_dev_fcoe_enable,
index 4819d31533e0e1ffc17e501318b41a66d580d1a6..403e71fa88feb900a7d194f3f3c83f4f6e1cb0d4 100644 (file)
@@ -68,12 +68,15 @@ struct br2684_vcc {
        /* keep old push, pop functions for chaining */
        void (*old_push)(struct atm_vcc *vcc, struct sk_buff *skb);
        void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
+       void (*old_release_cb)(struct atm_vcc *vcc);
+       struct module *old_owner;
        enum br2684_encaps encaps;
        struct list_head brvccs;
 #ifdef CONFIG_ATM_BR2684_IPFILTER
        struct br2684_filter filter;
 #endif /* CONFIG_ATM_BR2684_IPFILTER */
        unsigned int copies_needed, copies_failed;
+       atomic_t qspace;
 };
 
 struct br2684_dev {
@@ -181,18 +184,15 @@ static struct notifier_block atm_dev_notifier = {
 static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
 {
        struct br2684_vcc *brvcc = BR2684_VCC(vcc);
-       struct net_device *net_dev = skb->dev;
 
-       pr_debug("(vcc %p ; net_dev %p )\n", vcc, net_dev);
+       pr_debug("(vcc %p ; net_dev %p )\n", vcc, brvcc->device);
        brvcc->old_pop(vcc, skb);
 
-       if (!net_dev)
-               return;
-
-       if (atm_may_send(vcc, 0))
-               netif_wake_queue(net_dev);
-
+       /* If the queue space just went up from zero, wake */
+       if (atomic_inc_return(&brvcc->qspace) == 1)
+               netif_wake_queue(brvcc->device);
 }
+
 /*
  * Send a packet out a particular vcc.  Not to useful right now, but paves
  * the way for multiple vcc's per itf.  Returns true if we can send,
@@ -256,16 +256,30 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
        ATM_SKB(skb)->atm_options = atmvcc->atm_options;
        dev->stats.tx_packets++;
        dev->stats.tx_bytes += skb->len;
-       atmvcc->send(atmvcc, skb);
 
-       if (!atm_may_send(atmvcc, 0)) {
+       if (atomic_dec_return(&brvcc->qspace) < 1) {
+               /* No more please! */
                netif_stop_queue(brvcc->device);
-               /*check for race with br2684_pop*/
-               if (atm_may_send(atmvcc, 0))
-                       netif_start_queue(brvcc->device);
+               /* We might have raced with br2684_pop() */
+               if (unlikely(atomic_read(&brvcc->qspace) > 0))
+                       netif_wake_queue(brvcc->device);
        }
 
-       return 1;
+       /* If this fails immediately, the skb will be freed and br2684_pop()
+          will wake the queue if appropriate. Just return an error so that
+          the stats are updated correctly */
+       return !atmvcc->send(atmvcc, skb);
+}
+
+static void br2684_release_cb(struct atm_vcc *atmvcc)
+{
+       struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
+
+       if (atomic_read(&brvcc->qspace) > 0)
+               netif_wake_queue(brvcc->device);
+
+       if (brvcc->old_release_cb)
+               brvcc->old_release_cb(atmvcc);
 }
 
 static inline struct br2684_vcc *pick_outgoing_vcc(const struct sk_buff *skb,
@@ -279,6 +293,8 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
 {
        struct br2684_dev *brdev = BRPRIV(dev);
        struct br2684_vcc *brvcc;
+       struct atm_vcc *atmvcc;
+       netdev_tx_t ret = NETDEV_TX_OK;
 
        pr_debug("skb_dst(skb)=%p\n", skb_dst(skb));
        read_lock(&devs_lock);
@@ -289,9 +305,26 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
                dev->stats.tx_carrier_errors++;
                /* netif_stop_queue(dev); */
                dev_kfree_skb(skb);
-               read_unlock(&devs_lock);
-               return NETDEV_TX_OK;
+               goto out_devs;
        }
+       atmvcc = brvcc->atmvcc;
+
+       bh_lock_sock(sk_atm(atmvcc));
+
+       if (test_bit(ATM_VF_RELEASED, &atmvcc->flags) ||
+           test_bit(ATM_VF_CLOSE, &atmvcc->flags) ||
+           !test_bit(ATM_VF_READY, &atmvcc->flags)) {
+               dev->stats.tx_dropped++;
+               dev_kfree_skb(skb);
+               goto out;
+       }
+
+       if (sock_owned_by_user(sk_atm(atmvcc))) {
+               netif_stop_queue(brvcc->device);
+               ret = NETDEV_TX_BUSY;
+               goto out;
+       }
+
        if (!br2684_xmit_vcc(skb, dev, brvcc)) {
                /*
                 * We should probably use netif_*_queue() here, but that
@@ -303,8 +336,11 @@ static netdev_tx_t br2684_start_xmit(struct sk_buff *skb,
                dev->stats.tx_errors++;
                dev->stats.tx_fifo_errors++;
        }
+ out:
+       bh_unlock_sock(sk_atm(atmvcc));
+ out_devs:
        read_unlock(&devs_lock);
-       return NETDEV_TX_OK;
+       return ret;
 }
 
 /*
@@ -377,9 +413,10 @@ static void br2684_close_vcc(struct br2684_vcc *brvcc)
        list_del(&brvcc->brvccs);
        write_unlock_irq(&devs_lock);
        brvcc->atmvcc->user_back = NULL;        /* what about vcc->recvq ??? */
+       brvcc->atmvcc->release_cb = brvcc->old_release_cb;
        brvcc->old_push(brvcc->atmvcc, NULL);   /* pass on the bad news */
+       module_put(brvcc->old_owner);
        kfree(brvcc);
-       module_put(THIS_MODULE);
 }
 
 /* when AAL5 PDU comes in: */
@@ -504,6 +541,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
        brvcc = kzalloc(sizeof(struct br2684_vcc), GFP_KERNEL);
        if (!brvcc)
                return -ENOMEM;
+       /*
+        * Allow two packets in the ATM queue. One actually being sent, and one
+        * for the ATM 'TX done' handler to send. It shouldn't take long to get
+        * the next one from the netdev queue, when we need it. More than that
+        * would be bufferbloat.
+        */
+       atomic_set(&brvcc->qspace, 2);
        write_lock_irq(&devs_lock);
        net_dev = br2684_find_dev(&be.ifspec);
        if (net_dev == NULL) {
@@ -546,9 +590,13 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
        brvcc->encaps = (enum br2684_encaps)be.encaps;
        brvcc->old_push = atmvcc->push;
        brvcc->old_pop = atmvcc->pop;
+       brvcc->old_release_cb = atmvcc->release_cb;
+       brvcc->old_owner = atmvcc->owner;
        barrier();
        atmvcc->push = br2684_push;
        atmvcc->pop = br2684_pop;
+       atmvcc->release_cb = br2684_release_cb;
+       atmvcc->owner = THIS_MODULE;
 
        /* initialize netdev carrier state */
        if (atmvcc->dev->signal == ATM_PHY_SIG_LOST)
@@ -687,10 +735,13 @@ static int br2684_ioctl(struct socket *sock, unsigned int cmd,
                        return -ENOIOCTLCMD;
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
-               if (cmd == ATM_SETBACKEND)
+               if (cmd == ATM_SETBACKEND) {
+                       if (sock->state != SS_CONNECTED)
+                               return -EINVAL;
                        return br2684_regvcc(atmvcc, argp);
-               else
+               } else {
                        return br2684_create(argp);
+               }
 #ifdef CONFIG_ATM_BR2684_IPFILTER
        case BR2684_SETFILT:
                if (atmvcc->push != br2684_push)
index 0c0ad930a632f23e4c0661a20684c5d572e3dc15..806fc0a400514b677ca1d74abf1c55a055097822 100644 (file)
@@ -126,10 +126,19 @@ static void vcc_write_space(struct sock *sk)
        rcu_read_unlock();
 }
 
+static void vcc_release_cb(struct sock *sk)
+{
+       struct atm_vcc *vcc = atm_sk(sk);
+
+       if (vcc->release_cb)
+               vcc->release_cb(vcc);
+}
+
 static struct proto vcc_proto = {
        .name     = "VCC",
        .owner    = THIS_MODULE,
        .obj_size = sizeof(struct atm_vcc),
+       .release_cb = vcc_release_cb,
 };
 
 int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
@@ -156,7 +165,9 @@ int vcc_create(struct net *net, struct socket *sock, int protocol, int family)
        atomic_set(&sk->sk_rmem_alloc, 0);
        vcc->push = NULL;
        vcc->pop = NULL;
+       vcc->owner = NULL;
        vcc->push_oam = NULL;
+       vcc->release_cb = NULL;
        vcc->vpi = vcc->vci = 0; /* no VCI/VPI yet */
        vcc->atm_options = vcc->aal_options = 0;
        sk->sk_destruct = vcc_sock_destruct;
@@ -175,6 +186,7 @@ static void vcc_destroy_socket(struct sock *sk)
                        vcc->dev->ops->close(vcc);
                if (vcc->push)
                        vcc->push(vcc, NULL); /* atmarpd has no push */
+               module_put(vcc->owner);
 
                while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
                        atm_return(vcc, skb->truesize);
index 226dca9894487fd7fc1b391e827acef905a44d90..8c93267ce96910a48f9eb9e5bb8e295470656edf 100644 (file)
@@ -60,6 +60,8 @@ struct pppoatm_vcc {
        struct atm_vcc  *atmvcc;        /* VCC descriptor */
        void (*old_push)(struct atm_vcc *, struct sk_buff *);
        void (*old_pop)(struct atm_vcc *, struct sk_buff *);
+       void (*old_release_cb)(struct atm_vcc *);
+       struct module *old_owner;
                                        /* keep old push/pop for detaching */
        enum pppoatm_encaps encaps;
        atomic_t inflight;
@@ -107,6 +109,24 @@ static void pppoatm_wakeup_sender(unsigned long arg)
        ppp_output_wakeup((struct ppp_channel *) arg);
 }
 
+static void pppoatm_release_cb(struct atm_vcc *atmvcc)
+{
+       struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
+
+       /*
+        * As in pppoatm_pop(), it's safe to clear the BLOCKED bit here because
+        * the wakeup *can't* race with pppoatm_send(). They both hold the PPP
+        * channel's ->downl lock. And the potential race with *setting* it,
+        * which leads to the double-check dance in pppoatm_may_send(), doesn't
+        * exist here. In the sock_owned_by_user() case in pppoatm_send(), we
+        * set the BLOCKED bit while the socket is still locked. We know that
+        * ->release_cb() can't be called until that's done.
+        */
+       if (test_and_clear_bit(BLOCKED, &pvcc->blocked))
+               tasklet_schedule(&pvcc->wakeup_tasklet);
+       if (pvcc->old_release_cb)
+               pvcc->old_release_cb(atmvcc);
+}
 /*
  * This gets called every time the ATM card has finished sending our
  * skb.  The ->old_pop will take care up normal atm flow control,
@@ -151,12 +171,11 @@ static void pppoatm_unassign_vcc(struct atm_vcc *atmvcc)
        pvcc = atmvcc_to_pvcc(atmvcc);
        atmvcc->push = pvcc->old_push;
        atmvcc->pop = pvcc->old_pop;
+       atmvcc->release_cb = pvcc->old_release_cb;
        tasklet_kill(&pvcc->wakeup_tasklet);
        ppp_unregister_channel(&pvcc->chan);
        atmvcc->user_back = NULL;
        kfree(pvcc);
-       /* Gee, I hope we have the big kernel lock here... */
-       module_put(THIS_MODULE);
 }
 
 /* Called when an AAL5 PDU comes in */
@@ -165,9 +184,13 @@ static void pppoatm_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
        struct pppoatm_vcc *pvcc = atmvcc_to_pvcc(atmvcc);
        pr_debug("\n");
        if (skb == NULL) {                      /* VCC was closed */
+               struct module *module;
+
                pr_debug("removing ATMPPP VCC %p\n", pvcc);
+               module = pvcc->old_owner;
                pppoatm_unassign_vcc(atmvcc);
                atmvcc->push(atmvcc, NULL);     /* Pass along bad news */
+               module_put(module);
                return;
        }
        atm_return(atmvcc, skb->truesize);
@@ -211,7 +234,7 @@ error:
        ppp_input_error(&pvcc->chan, 0);
 }
 
-static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
+static int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
 {
        /*
         * It's not clear that we need to bother with using atm_may_send()
@@ -269,10 +292,33 @@ static inline int pppoatm_may_send(struct pppoatm_vcc *pvcc, int size)
 static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
 {
        struct pppoatm_vcc *pvcc = chan_to_pvcc(chan);
+       struct atm_vcc *vcc;
+       int ret;
+
        ATM_SKB(skb)->vcc = pvcc->atmvcc;
        pr_debug("(skb=0x%p, vcc=0x%p)\n", skb, pvcc->atmvcc);
        if (skb->data[0] == '\0' && (pvcc->flags & SC_COMP_PROT))
                (void) skb_pull(skb, 1);
+
+       vcc = ATM_SKB(skb)->vcc;
+       bh_lock_sock(sk_atm(vcc));
+       if (sock_owned_by_user(sk_atm(vcc))) {
+               /*
+                * Needs to happen (and be flushed, hence test_and_) before we unlock
+                * the socket. It needs to be seen by the time our ->release_cb gets
+                * called.
+                */
+               test_and_set_bit(BLOCKED, &pvcc->blocked);
+               goto nospace;
+       }
+       if (test_bit(ATM_VF_RELEASED, &vcc->flags) ||
+           test_bit(ATM_VF_CLOSE, &vcc->flags) ||
+           !test_bit(ATM_VF_READY, &vcc->flags)) {
+               bh_unlock_sock(sk_atm(vcc));
+               kfree_skb(skb);
+               return DROP_PACKET;
+       }
+
        switch (pvcc->encaps) {         /* LLC encapsulation needed */
        case e_llc:
                if (skb_headroom(skb) < LLC_LEN) {
@@ -285,8 +331,10 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
                        }
                        consume_skb(skb);
                        skb = n;
-                       if (skb == NULL)
+                       if (skb == NULL) {
+                               bh_unlock_sock(sk_atm(vcc));
                                return DROP_PACKET;
+                       }
                } else if (!pppoatm_may_send(pvcc, skb->truesize))
                        goto nospace;
                memcpy(skb_push(skb, LLC_LEN), pppllc, LLC_LEN);
@@ -296,6 +344,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
                        goto nospace;
                break;
        case e_autodetect:
+               bh_unlock_sock(sk_atm(vcc));
                pr_debug("Trying to send without setting encaps!\n");
                kfree_skb(skb);
                return 1;
@@ -305,9 +354,12 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
        ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
        pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
                 skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
-       return ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
+       ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
            ? DROP_PACKET : 1;
+       bh_unlock_sock(sk_atm(vcc));
+       return ret;
 nospace:
+       bh_unlock_sock(sk_atm(vcc));
        /*
         * We don't have space to send this SKB now, but we might have
         * already applied SC_COMP_PROT compression, so may need to undo
@@ -362,6 +414,8 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
        atomic_set(&pvcc->inflight, NONE_INFLIGHT);
        pvcc->old_push = atmvcc->push;
        pvcc->old_pop = atmvcc->pop;
+       pvcc->old_owner = atmvcc->owner;
+       pvcc->old_release_cb = atmvcc->release_cb;
        pvcc->encaps = (enum pppoatm_encaps) be.encaps;
        pvcc->chan.private = pvcc;
        pvcc->chan.ops = &pppoatm_ops;
@@ -377,7 +431,9 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void __user *arg)
        atmvcc->user_back = pvcc;
        atmvcc->push = pppoatm_push;
        atmvcc->pop = pppoatm_pop;
+       atmvcc->release_cb = pppoatm_release_cb;
        __module_get(THIS_MODULE);
+       atmvcc->owner = THIS_MODULE;
 
        /* re-process everything received between connection setup and
           backend setup */
@@ -406,6 +462,8 @@ static int pppoatm_ioctl(struct socket *sock, unsigned int cmd,
                        return -ENOIOCTLCMD;
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
+               if (sock->state != SS_CONNECTED)
+                       return -EINVAL;
                return pppoatm_assign_vcc(atmvcc, argp);
                }
        case PPPIOCGCHAN:
index 53f5244e28f809a83b3cc3abca10ae5b61f0324e..8d8afb134b3ac016799be9ab43d6fe45f40962bb 100644 (file)
@@ -6,6 +6,7 @@ config BATMAN_ADV
        tristate "B.A.T.M.A.N. Advanced Meshing Protocol"
        depends on NET
        select CRC16
+       select LIBCRC32C
         default n
        help
           B.A.T.M.A.N. (better approach to mobile ad-hoc networking) is
@@ -25,6 +26,16 @@ config BATMAN_ADV_BLA
          more than one mesh node in the same LAN, you can safely remove
          this feature and save some space.
 
+config BATMAN_ADV_DAT
+       bool "Distributed ARP Table"
+       depends on BATMAN_ADV && INET
+       default n
+       help
+         This option enables DAT (Distributed ARP Table), a DHT based
+         mechanism that increases ARP reliability on sparse wireless
+         mesh networks. If you think that your network does not need
+         this option you can safely remove it and save some space.
+
 config BATMAN_ADV_DEBUG
        bool "B.A.T.M.A.N. debugging"
        depends on BATMAN_ADV
index 8676d2b1d57438d94ba90cef20e63c345880cdd3..e45e3b4e32e3f480b2b65d5900ff0838391bc2ec 100644 (file)
@@ -23,6 +23,7 @@ batman-adv-y += bat_iv_ogm.o
 batman-adv-y += bitarray.o
 batman-adv-$(CONFIG_BATMAN_ADV_BLA) += bridge_loop_avoidance.o
 batman-adv-y += debugfs.o
+batman-adv-$(CONFIG_BATMAN_ADV_DAT) += distributed-arp-table.o
 batman-adv-y += gateway_client.o
 batman-adv-y += gateway_common.o
 batman-adv-y += hard-interface.o
index b02b75dae3a8a5dfeb015838ba5eca2ecb5d6109..9f3925a85aab07e8eae11a1ac7b40e85f64fc480 100644 (file)
@@ -57,20 +57,22 @@ out:
 static int batadv_iv_ogm_iface_enable(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_ogm_packet *batadv_ogm_packet;
+       unsigned char *ogm_buff;
        uint32_t random_seqno;
        int res = -ENOMEM;
 
        /* randomize initial seqno to avoid collision */
        get_random_bytes(&random_seqno, sizeof(random_seqno));
-       atomic_set(&hard_iface->seqno, random_seqno);
+       atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
 
-       hard_iface->packet_len = BATADV_OGM_HLEN;
-       hard_iface->packet_buff = kmalloc(hard_iface->packet_len, GFP_ATOMIC);
-
-       if (!hard_iface->packet_buff)
+       hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
+       ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
+       if (!ogm_buff)
                goto out;
 
-       batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+       hard_iface->bat_iv.ogm_buff = ogm_buff;
+
+       batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
        batadv_ogm_packet->header.packet_type = BATADV_IV_OGM;
        batadv_ogm_packet->header.version = BATADV_COMPAT_VERSION;
        batadv_ogm_packet->header.ttl = 2;
@@ -87,15 +89,16 @@ out:
 
 static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
 {
-       kfree(hard_iface->packet_buff);
-       hard_iface->packet_buff = NULL;
+       kfree(hard_iface->bat_iv.ogm_buff);
+       hard_iface->bat_iv.ogm_buff = NULL;
 }
 
 static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_ogm_packet *batadv_ogm_packet;
+       unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
 
-       batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+       batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
        memcpy(batadv_ogm_packet->orig,
               hard_iface->net_dev->dev_addr, ETH_ALEN);
        memcpy(batadv_ogm_packet->prev_sender,
@@ -106,8 +109,9 @@ static void
 batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_ogm_packet *batadv_ogm_packet;
+       unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
 
-       batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+       batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
        batadv_ogm_packet->flags = BATADV_PRIMARIES_FIRST_HOP;
        batadv_ogm_packet->header.ttl = BATADV_TTL;
 }
@@ -407,9 +411,11 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
 
        if ((atomic_read(&bat_priv->aggregated_ogms)) &&
            (packet_len < BATADV_MAX_AGGREGATION_BYTES))
-               skb_size = BATADV_MAX_AGGREGATION_BYTES + ETH_HLEN;
+               skb_size = BATADV_MAX_AGGREGATION_BYTES;
        else
-               skb_size = packet_len + ETH_HLEN;
+               skb_size = packet_len;
+
+       skb_size += ETH_HLEN + NET_IP_ALIGN;
 
        forw_packet_aggr->skb = dev_alloc_skb(skb_size);
        if (!forw_packet_aggr->skb) {
@@ -418,7 +424,7 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff,
                kfree(forw_packet_aggr);
                goto out;
        }
-       skb_reserve(forw_packet_aggr->skb, ETH_HLEN);
+       skb_reserve(forw_packet_aggr->skb, ETH_HLEN + NET_IP_ALIGN);
 
        INIT_HLIST_NODE(&forw_packet_aggr->list);
 
@@ -590,8 +596,10 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node,
 static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+       unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
        struct batadv_ogm_packet *batadv_ogm_packet;
        struct batadv_hard_iface *primary_if;
+       int *ogm_buff_len = &hard_iface->bat_iv.ogm_buff_len;
        int vis_server, tt_num_changes = 0;
        uint32_t seqno;
        uint8_t bandwidth;
@@ -600,17 +608,16 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
        primary_if = batadv_primary_if_get_selected(bat_priv);
 
        if (hard_iface == primary_if)
-               tt_num_changes = batadv_tt_append_diff(bat_priv,
-                                                      &hard_iface->packet_buff,
-                                                      &hard_iface->packet_len,
+               tt_num_changes = batadv_tt_append_diff(bat_priv, ogm_buff,
+                                                      ogm_buff_len,
                                                       BATADV_OGM_HLEN);
 
-       batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff;
+       batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
 
        /* change sequence number to network order */
-       seqno = (uint32_t)atomic_read(&hard_iface->seqno);
+       seqno = (uint32_t)atomic_read(&hard_iface->bat_iv.ogm_seqno);
        batadv_ogm_packet->seqno = htonl(seqno);
-       atomic_inc(&hard_iface->seqno);
+       atomic_inc(&hard_iface->bat_iv.ogm_seqno);
 
        batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn);
        batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc);
@@ -631,8 +638,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
        }
 
        batadv_slide_own_bcast_window(hard_iface);
-       batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff,
-                               hard_iface->packet_len, hard_iface, 1,
+       batadv_iv_ogm_queue_add(bat_priv, hard_iface->bat_iv.ogm_buff,
+                               hard_iface->bat_iv.ogm_buff_len, hard_iface, 1,
                                batadv_iv_ogm_emit_send_time(bat_priv));
 
        if (primary_if)
@@ -1015,7 +1022,7 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr,
                return;
 
        /* could be changed by schedule_own_packet() */
-       if_incoming_seqno = atomic_read(&if_incoming->seqno);
+       if_incoming_seqno = atomic_read(&if_incoming->bat_iv.ogm_seqno);
 
        if (batadv_ogm_packet->flags & BATADV_DIRECTLINK)
                has_directlink_flag = 1;
index aea174cdbfbd4689b6ee989dfa9ab710a7f5cc11..5453b17d8df20249c6647bcc5c2485edfec4c1e5 100644 (file)
@@ -79,20 +79,17 @@ int batadv_bit_get_packet(void *priv, unsigned long *seq_bits,
         * or the old packet got delayed somewhere in the network. The
         * packet should be dropped without calling this function if the
         * seqno window is protected.
+        *
+        * seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE
+        * or
+        * seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE
         */
-       if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE ||
-           seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
+       batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                  "Other host probably restarted!\n");
 
-               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
-                          "Other host probably restarted!\n");
-
-               bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
-               if (set_mark)
-                       batadv_set_bit(seq_bits, 0);
-
-               return 1;
-       }
+       bitmap_zero(seq_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
+       if (set_mark)
+               batadv_set_bit(seq_bits, 0);
 
-       /* never reached */
-       return 0;
+       return 1;
 }
index 0a9084ad19a60f71a2f9f70a8879e7ada24ccf6c..5aebe9327d68c8fd691243f78880c12d69951611 100644 (file)
@@ -40,15 +40,11 @@ static void batadv_bla_send_announce(struct batadv_priv *bat_priv,
 /* return the index of the claim */
 static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
 {
-       const unsigned char *key = data;
+       struct batadv_claim *claim = (struct batadv_claim *)data;
        uint32_t hash = 0;
-       size_t i;
 
-       for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
-               hash += key[i];
-               hash += (hash << 10);
-               hash ^= (hash >> 6);
-       }
+       hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
+       hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
 
        hash += (hash << 3);
        hash ^= (hash >> 11);
@@ -61,15 +57,11 @@ static inline uint32_t batadv_choose_claim(const void *data, uint32_t size)
 static inline uint32_t batadv_choose_backbone_gw(const void *data,
                                                 uint32_t size)
 {
-       const unsigned char *key = data;
+       struct batadv_claim *claim = (struct batadv_claim *)data;
        uint32_t hash = 0;
-       size_t i;
 
-       for (i = 0; i < ETH_ALEN + sizeof(short); i++) {
-               hash += key[i];
-               hash += (hash << 10);
-               hash ^= (hash >> 6);
-       }
+       hash = batadv_hash_bytes(hash, &claim->addr, sizeof(claim->addr));
+       hash = batadv_hash_bytes(hash, &claim->vid, sizeof(claim->vid));
 
        hash += (hash << 3);
        hash ^= (hash >> 11);
@@ -85,8 +77,15 @@ static int batadv_compare_backbone_gw(const struct hlist_node *node,
 {
        const void *data1 = container_of(node, struct batadv_backbone_gw,
                                         hash_entry);
+       const struct batadv_backbone_gw *gw1 = data1, *gw2 = data2;
+
+       if (!batadv_compare_eth(gw1->orig, gw2->orig))
+               return 0;
 
-       return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
+       if (gw1->vid != gw2->vid)
+               return 0;
+
+       return 1;
 }
 
 /* compares address and vid of two claims */
@@ -95,8 +94,15 @@ static int batadv_compare_claim(const struct hlist_node *node,
 {
        const void *data1 = container_of(node, struct batadv_claim,
                                         hash_entry);
+       const struct batadv_claim *cl1 = data1, *cl2 = data2;
 
-       return (memcmp(data1, data2, ETH_ALEN + sizeof(short)) == 0 ? 1 : 0);
+       if (!batadv_compare_eth(cl1->addr, cl2->addr))
+               return 0;
+
+       if (cl1->vid != cl2->vid)
+               return 0;
+
+       return 1;
 }
 
 /* free a backbone gw */
@@ -362,7 +368,7 @@ out:
  */
 static struct batadv_backbone_gw *
 batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
-                          short vid)
+                          short vid, bool own_backbone)
 {
        struct batadv_backbone_gw *entry;
        struct batadv_orig_node *orig_node;
@@ -386,6 +392,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
        entry->crc = BATADV_BLA_CRC_INIT;
        entry->bat_priv = bat_priv;
        atomic_set(&entry->request_sent, 0);
+       atomic_set(&entry->wait_periods, 0);
        memcpy(entry->orig, orig, ETH_ALEN);
 
        /* one for the hash, one for returning */
@@ -409,6 +416,16 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig,
                                          "became a backbone gateway");
                batadv_orig_node_free_ref(orig_node);
        }
+
+       if (own_backbone) {
+               batadv_bla_send_announce(bat_priv, entry);
+
+               /* this will be decreased in the worker thread */
+               atomic_inc(&entry->request_sent);
+               atomic_set(&entry->wait_periods, BATADV_BLA_WAIT_PERIODS);
+               atomic_inc(&bat_priv->bla.num_requests);
+       }
+
        return entry;
 }
 
@@ -424,7 +441,7 @@ batadv_bla_update_own_backbone_gw(struct batadv_priv *bat_priv,
 
        backbone_gw = batadv_bla_get_backbone_gw(bat_priv,
                                                 primary_if->net_dev->dev_addr,
-                                                vid);
+                                                vid, true);
        if (unlikely(!backbone_gw))
                return;
 
@@ -632,7 +649,8 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv,
        if (memcmp(an_addr, batadv_announce_mac, 4) != 0)
                return 0;
 
-       backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
+       backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
+                                                false);
 
        if (unlikely(!backbone_gw))
                return 1;
@@ -730,7 +748,8 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv,
 
        /* register the gateway if not yet available, and add the claim. */
 
-       backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid);
+       backbone_gw = batadv_bla_get_backbone_gw(bat_priv, backbone_addr, vid,
+                                                false);
 
        if (unlikely(!backbone_gw))
                return 1;
@@ -1140,6 +1159,24 @@ static void batadv_bla_periodic_work(struct work_struct *work)
                        backbone_gw->lasttime = jiffies;
 
                        batadv_bla_send_announce(bat_priv, backbone_gw);
+
+                       /* request_sent is only set after creation to avoid
+                        * problems when we are not yet known as backbone gw
+                        * in the backbone.
+                        *
+                        * We can reset this now after we waited some periods
+                        * to give bridge forward delays and bla group forming
+                        * some grace time.
+                        */
+
+                       if (atomic_read(&backbone_gw->request_sent) == 0)
+                               continue;
+
+                       if (!atomic_dec_and_test(&backbone_gw->wait_periods))
+                               continue;
+
+                       atomic_dec(&backbone_gw->bat_priv->bla.num_requests);
+                       atomic_set(&backbone_gw->request_sent, 0);
                }
                rcu_read_unlock();
        }
@@ -1167,6 +1204,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
        uint16_t crc;
        unsigned long entrytime;
 
+       spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
+
        batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");
 
        /* setting claim destination address */
@@ -1210,8 +1249,7 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
 /**
  * batadv_bla_check_bcast_duplist
  * @bat_priv: the bat priv with all the soft interface information
- * @bcast_packet: originator mac address
- * @hdr_size: maximum length of the frame
+ * @skb: contains the bcast_packet to be checked
  *
  * check if it is on our broadcast list. Another gateway might
  * have sent the same packet because it is connected to the same backbone,
@@ -1223,20 +1261,19 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
  * the same host however as this might be intended.
  */
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-                                  struct batadv_bcast_packet *bcast_packet,
-                                  int hdr_size)
+                                  struct sk_buff *skb)
 {
-       int i, length, curr;
-       uint8_t *content;
-       uint16_t crc;
+       int i, curr, ret = 0;
+       __be32 crc;
+       struct batadv_bcast_packet *bcast_packet;
        struct batadv_bcast_duplist_entry *entry;
 
-       length = hdr_size - sizeof(*bcast_packet);
-       content = (uint8_t *)bcast_packet;
-       content += sizeof(*bcast_packet);
+       bcast_packet = (struct batadv_bcast_packet *)skb->data;
 
        /* calculate the crc ... */
-       crc = crc16(0, content, length);
+       crc = batadv_skb_crc32(skb, (u8 *)(bcast_packet + 1));
+
+       spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
 
        for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
                curr = (bat_priv->bla.bcast_duplist_curr + i);
@@ -1259,9 +1296,12 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
                /* this entry seems to match: same crc, not too old,
                 * and from another gw. therefore return 1 to forbid it.
                 */
-               return 1;
+               ret = 1;
+               goto out;
        }
-       /* not found, add a new entry (overwrite the oldest entry) */
+       /* not found, add a new entry (overwrite the oldest entry)
+        * and allow it, its the first occurence.
+        */
        curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
        curr %= BATADV_DUPLIST_SIZE;
        entry = &bat_priv->bla.bcast_duplist[curr];
@@ -1270,8 +1310,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
        memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
        bat_priv->bla.bcast_duplist_curr = curr;
 
-       /* allow it, its the first occurence. */
-       return 0;
+out:
+       spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);
+
+       return ret;
 }
 
 
@@ -1576,23 +1618,11 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
        struct hlist_head *head;
        uint32_t i;
        bool is_own;
-       int ret = 0;
        uint8_t *primary_addr;
 
-       primary_if = batadv_primary_if_get_selected(bat_priv);
-       if (!primary_if) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-                                net_dev->name);
-               goto out;
-       }
-
-       if (primary_if->if_status != BATADV_IF_ACTIVE) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - primary interface not active\n",
-                                net_dev->name);
+       primary_if = batadv_seq_print_text_primary_if_get(seq);
+       if (!primary_if)
                goto out;
-       }
 
        primary_addr = primary_if->net_dev->dev_addr;
        seq_printf(seq,
@@ -1619,7 +1649,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset)
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       return ret;
+       return 0;
 }
 
 int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
@@ -1634,23 +1664,11 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
        int secs, msecs;
        uint32_t i;
        bool is_own;
-       int ret = 0;
        uint8_t *primary_addr;
 
-       primary_if = batadv_primary_if_get_selected(bat_priv);
-       if (!primary_if) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-                                net_dev->name);
-               goto out;
-       }
-
-       if (primary_if->if_status != BATADV_IF_ACTIVE) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - primary interface not active\n",
-                                net_dev->name);
+       primary_if = batadv_seq_print_text_primary_if_get(seq);
+       if (!primary_if)
                goto out;
-       }
 
        primary_addr = primary_if->net_dev->dev_addr;
        seq_printf(seq,
@@ -1684,5 +1702,5 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset)
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       return ret;
+       return 0;
 }
index 789cb73bde67acf8f19375d67e8c0ec2322f509f..196d9a0254bcbc6820c5f60f3c53a63638b683c9 100644 (file)
@@ -31,8 +31,7 @@ int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq,
                                             void *offset);
 int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig);
 int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-                                  struct batadv_bcast_packet *bcast_packet,
-                                  int hdr_size);
+                                  struct sk_buff *skb);
 void batadv_bla_update_orig_address(struct batadv_priv *bat_priv,
                                    struct batadv_hard_iface *primary_if,
                                    struct batadv_hard_iface *oldif);
@@ -81,8 +80,7 @@ static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv,
 
 static inline int
 batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
-                              struct batadv_bcast_packet *bcast_packet,
-                              int hdr_size)
+                              struct sk_buff *skb)
 {
        return 0;
 }
index 391d4fb2026f9acf7ce1b1f85a0c2f5366152c35..6f58ddd53bff8d2752c7a59dda1c20e40ec428e0 100644 (file)
@@ -31,6 +31,7 @@
 #include "vis.h"
 #include "icmp_socket.h"
 #include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
 
 static struct dentry *batadv_debugfs;
 
@@ -99,15 +100,17 @@ int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...)
 
 static int batadv_log_open(struct inode *inode, struct file *file)
 {
+       if (!try_module_get(THIS_MODULE))
+               return -EBUSY;
+
        nonseekable_open(inode, file);
        file->private_data = inode->i_private;
-       batadv_inc_module_count();
        return 0;
 }
 
 static int batadv_log_release(struct inode *inode, struct file *file)
 {
-       batadv_dec_module_count();
+       module_put(THIS_MODULE);
        return 0;
 }
 
@@ -278,6 +281,19 @@ static int batadv_bla_backbone_table_open(struct inode *inode,
 
 #endif
 
+#ifdef CONFIG_BATMAN_ADV_DAT
+/**
+ * batadv_dat_cache_open - Prepare file handler for reads from dat_chache
+ * @inode: inode which was opened
+ * @file: file handle to be initialized
+ */
+static int batadv_dat_cache_open(struct inode *inode, struct file *file)
+{
+       struct net_device *net_dev = (struct net_device *)inode->i_private;
+       return single_open(file, batadv_dat_cache_seq_print_text, net_dev);
+}
+#endif
+
 static int batadv_transtable_local_open(struct inode *inode, struct file *file)
 {
        struct net_device *net_dev = (struct net_device *)inode->i_private;
@@ -307,7 +323,17 @@ struct batadv_debuginfo batadv_debuginfo_##_name = {       \
                }                                       \
 };
 
+/* the following attributes are general and therefore they will be directly
+ * placed in the BATADV_DEBUGFS_SUBDIR subdirectory of debugfs
+ */
 static BATADV_DEBUGINFO(routing_algos, S_IRUGO, batadv_algorithms_open);
+
+static struct batadv_debuginfo *batadv_general_debuginfos[] = {
+       &batadv_debuginfo_routing_algos,
+       NULL,
+};
+
+/* The following attributes are per soft interface */
 static BATADV_DEBUGINFO(originators, S_IRUGO, batadv_originators_open);
 static BATADV_DEBUGINFO(gateways, S_IRUGO, batadv_gateways_open);
 static BATADV_DEBUGINFO(transtable_global, S_IRUGO,
@@ -317,6 +343,9 @@ static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open);
 static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO,
                        batadv_bla_backbone_table_open);
 #endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+static BATADV_DEBUGINFO(dat_cache, S_IRUGO, batadv_dat_cache_open);
+#endif
 static BATADV_DEBUGINFO(transtable_local, S_IRUGO,
                        batadv_transtable_local_open);
 static BATADV_DEBUGINFO(vis_data, S_IRUGO, batadv_vis_data_open);
@@ -328,6 +357,9 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 #ifdef CONFIG_BATMAN_ADV_BLA
        &batadv_debuginfo_bla_claim_table,
        &batadv_debuginfo_bla_backbone_table,
+#endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+       &batadv_debuginfo_dat_cache,
 #endif
        &batadv_debuginfo_transtable_local,
        &batadv_debuginfo_vis_data,
@@ -336,7 +368,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = {
 
 void batadv_debugfs_init(void)
 {
-       struct batadv_debuginfo *bat_debug;
+       struct batadv_debuginfo **bat_debug;
        struct dentry *file;
 
        batadv_debugfs = debugfs_create_dir(BATADV_DEBUGFS_SUBDIR, NULL);
@@ -344,17 +376,23 @@ void batadv_debugfs_init(void)
                batadv_debugfs = NULL;
 
        if (!batadv_debugfs)
-               goto out;
+               goto err;
 
-       bat_debug = &batadv_debuginfo_routing_algos;
-       file = debugfs_create_file(bat_debug->attr.name,
-                                  S_IFREG | bat_debug->attr.mode,
-                                  batadv_debugfs, NULL, &bat_debug->fops);
-       if (!file)
-               pr_err("Can't add debugfs file: %s\n", bat_debug->attr.name);
+       for (bat_debug = batadv_general_debuginfos; *bat_debug; ++bat_debug) {
+               file = debugfs_create_file(((*bat_debug)->attr).name,
+                                          S_IFREG | ((*bat_debug)->attr).mode,
+                                          batadv_debugfs, NULL,
+                                          &(*bat_debug)->fops);
+               if (!file) {
+                       pr_err("Can't add general debugfs file: %s\n",
+                              ((*bat_debug)->attr).name);
+                       goto err;
+               }
+       }
 
-out:
        return;
+err:
+       debugfs_remove_recursive(batadv_debugfs);
 }
 
 void batadv_debugfs_destroy(void)
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
new file mode 100644 (file)
index 0000000..8e1d89d
--- /dev/null
@@ -0,0 +1,1066 @@
+/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
+ *
+ * Antonio Quartulli
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+
+#include "main.h"
+#include "hash.h"
+#include "distributed-arp-table.h"
+#include "hard-interface.h"
+#include "originator.h"
+#include "send.h"
+#include "types.h"
+#include "translation-table.h"
+#include "unicast.h"
+
+static void batadv_dat_purge(struct work_struct *work);
+
+/**
+ * batadv_dat_start_timer - initialise the DAT periodic worker
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_dat_start_timer(struct batadv_priv *bat_priv)
+{
+       INIT_DELAYED_WORK(&bat_priv->dat.work, batadv_dat_purge);
+       queue_delayed_work(batadv_event_workqueue, &bat_priv->dat.work,
+                          msecs_to_jiffies(10000));
+}
+
+/**
+ * batadv_dat_entry_free_ref - decrements the dat_entry refcounter and possibly
+ * free it
+ * @dat_entry: the oentry to free
+ */
+static void batadv_dat_entry_free_ref(struct batadv_dat_entry *dat_entry)
+{
+       if (atomic_dec_and_test(&dat_entry->refcount))
+               kfree_rcu(dat_entry, rcu);
+}
+
+/**
+ * batadv_dat_to_purge - checks whether a dat_entry has to be purged or not
+ * @dat_entry: the entry to check
+ *
+ * Returns true if the entry has to be purged now, false otherwise
+ */
+static bool batadv_dat_to_purge(struct batadv_dat_entry *dat_entry)
+{
+       return batadv_has_timed_out(dat_entry->last_update,
+                                   BATADV_DAT_ENTRY_TIMEOUT);
+}
+
+/**
+ * __batadv_dat_purge - delete entries from the DAT local storage
+ * @bat_priv: the bat priv with all the soft interface information
+ * @to_purge: function in charge to decide whether an entry has to be purged or
+ *           not. This function takes the dat_entry as argument and has to
+ *           returns a boolean value: true is the entry has to be deleted,
+ *           false otherwise
+ *
+ * Loops over each entry in the DAT local storage and delete it if and only if
+ * the to_purge function passed as argument returns true
+ */
+static void __batadv_dat_purge(struct batadv_priv *bat_priv,
+                              bool (*to_purge)(struct batadv_dat_entry *))
+{
+       spinlock_t *list_lock; /* protects write access to the hash lists */
+       struct batadv_dat_entry *dat_entry;
+       struct hlist_node *node, *node_tmp;
+       struct hlist_head *head;
+       uint32_t i;
+
+       if (!bat_priv->dat.hash)
+               return;
+
+       for (i = 0; i < bat_priv->dat.hash->size; i++) {
+               head = &bat_priv->dat.hash->table[i];
+               list_lock = &bat_priv->dat.hash->list_locks[i];
+
+               spin_lock_bh(list_lock);
+               hlist_for_each_entry_safe(dat_entry, node, node_tmp, head,
+                                         hash_entry) {
+                       /* if an helper function has been passed as parameter,
+                        * ask it if the entry has to be purged or not
+                        */
+                       if (to_purge && !to_purge(dat_entry))
+                               continue;
+
+                       hlist_del_rcu(node);
+                       batadv_dat_entry_free_ref(dat_entry);
+               }
+               spin_unlock_bh(list_lock);
+       }
+}
+
+/**
+ * batadv_dat_purge - periodic task that deletes old entries from the local DAT
+ * hash table
+ * @work: kernel work struct
+ */
+static void batadv_dat_purge(struct work_struct *work)
+{
+       struct delayed_work *delayed_work;
+       struct batadv_priv_dat *priv_dat;
+       struct batadv_priv *bat_priv;
+
+       delayed_work = container_of(work, struct delayed_work, work);
+       priv_dat = container_of(delayed_work, struct batadv_priv_dat, work);
+       bat_priv = container_of(priv_dat, struct batadv_priv, dat);
+
+       __batadv_dat_purge(bat_priv, batadv_dat_to_purge);
+       batadv_dat_start_timer(bat_priv);
+}
+
+/**
+ * batadv_compare_dat - comparing function used in the local DAT hash table
+ * @node: node in the local table
+ * @data2: second object to compare the node to
+ *
+ * Returns 1 if the two entry are the same, 0 otherwise
+ */
+static int batadv_compare_dat(const struct hlist_node *node, const void *data2)
+{
+       const void *data1 = container_of(node, struct batadv_dat_entry,
+                                        hash_entry);
+
+       return (memcmp(data1, data2, sizeof(__be32)) == 0 ? 1 : 0);
+}
+
+/**
+ * batadv_arp_hw_src - extract the hw_src field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the hw_src field in the ARP packet
+ */
+static uint8_t *batadv_arp_hw_src(struct sk_buff *skb, int hdr_size)
+{
+       uint8_t *addr;
+
+       addr = (uint8_t *)(skb->data + hdr_size);
+       addr += ETH_HLEN + sizeof(struct arphdr);
+
+       return addr;
+}
+
+/**
+ * batadv_arp_ip_src - extract the ip_src field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the ip_src field in the ARP packet
+ */
+static __be32 batadv_arp_ip_src(struct sk_buff *skb, int hdr_size)
+{
+       return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN);
+}
+
+/**
+ * batadv_arp_hw_dst - extract the hw_dst field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the hw_dst field in the ARP packet
+ */
+static uint8_t *batadv_arp_hw_dst(struct sk_buff *skb, int hdr_size)
+{
+       return batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN + 4;
+}
+
+/**
+ * batadv_arp_ip_dst - extract the ip_dst field from an ARP packet
+ * @skb: ARP packet
+ * @hdr_size: size of the possible header before the ARP packet
+ *
+ * Returns the value of the ip_dst field in the ARP packet
+ */
+static __be32 batadv_arp_ip_dst(struct sk_buff *skb, int hdr_size)
+{
+       return *(__be32 *)(batadv_arp_hw_src(skb, hdr_size) + ETH_ALEN * 2 + 4);
+}
+
+/**
+ * batadv_hash_dat - compute the hash value for an IP address
+ * @data: data to hash
+ * @size: size of the hash table
+ *
+ * Returns the selected index in the hash table for the given data
+ */
+static uint32_t batadv_hash_dat(const void *data, uint32_t size)
+{
+       const unsigned char *key = data;
+       uint32_t hash = 0;
+       size_t i;
+
+       for (i = 0; i < 4; i++) {
+               hash += key[i];
+               hash += (hash << 10);
+               hash ^= (hash >> 6);
+       }
+
+       hash += (hash << 3);
+       hash ^= (hash >> 11);
+       hash += (hash << 15);
+
+       return hash % size;
+}
+
+/**
+ * batadv_dat_entry_hash_find - looks for a given dat_entry in the local hash
+ * table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip: search key
+ *
+ * Returns the dat_entry if found, NULL otherwise
+ */
+static struct batadv_dat_entry *
+batadv_dat_entry_hash_find(struct batadv_priv *bat_priv, __be32 ip)
+{
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct batadv_dat_entry *dat_entry, *dat_entry_tmp = NULL;
+       struct batadv_hashtable *hash = bat_priv->dat.hash;
+       uint32_t index;
+
+       if (!hash)
+               return NULL;
+
+       index = batadv_hash_dat(&ip, hash->size);
+       head = &hash->table[index];
+
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) {
+               if (dat_entry->ip != ip)
+                       continue;
+
+               if (!atomic_inc_not_zero(&dat_entry->refcount))
+                       continue;
+
+               dat_entry_tmp = dat_entry;
+               break;
+       }
+       rcu_read_unlock();
+
+       return dat_entry_tmp;
+}
+
+/**
+ * batadv_dat_entry_add - add a new dat entry or update it if already exists
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip: ipv4 to add/edit
+ * @mac_addr: mac address to assign to the given ipv4
+ */
+static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip,
+                                uint8_t *mac_addr)
+{
+       struct batadv_dat_entry *dat_entry;
+       int hash_added;
+
+       dat_entry = batadv_dat_entry_hash_find(bat_priv, ip);
+       /* if this entry is already known, just update it */
+       if (dat_entry) {
+               if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
+                       memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
+               dat_entry->last_update = jiffies;
+               batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                          "Entry updated: %pI4 %pM\n", &dat_entry->ip,
+                          dat_entry->mac_addr);
+               goto out;
+       }
+
+       dat_entry = kmalloc(sizeof(*dat_entry), GFP_ATOMIC);
+       if (!dat_entry)
+               goto out;
+
+       dat_entry->ip = ip;
+       memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN);
+       dat_entry->last_update = jiffies;
+       atomic_set(&dat_entry->refcount, 2);
+
+       hash_added = batadv_hash_add(bat_priv->dat.hash, batadv_compare_dat,
+                                    batadv_hash_dat, &dat_entry->ip,
+                                    &dat_entry->hash_entry);
+
+       if (unlikely(hash_added != 0)) {
+               /* remove the reference for the hash */
+               batadv_dat_entry_free_ref(dat_entry);
+               goto out;
+       }
+
+       batadv_dbg(BATADV_DBG_DAT, bat_priv, "New entry added: %pI4 %pM\n",
+                  &dat_entry->ip, dat_entry->mac_addr);
+
+out:
+       if (dat_entry)
+               batadv_dat_entry_free_ref(dat_entry);
+}
+
+#ifdef CONFIG_BATMAN_ADV_DEBUG
+
+/**
+ * batadv_dbg_arp - print a debug message containing all the ARP packet details
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: ARP packet
+ * @type: ARP type
+ * @hdr_size: size of the possible header before the ARP packet
+ * @msg: message to print together with the debugging information
+ */
+static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
+                          uint16_t type, int hdr_size, char *msg)
+{
+       struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+       struct batadv_bcast_packet *bcast_pkt;
+       uint8_t *orig_addr;
+       __be32 ip_src, ip_dst;
+
+       if (msg)
+               batadv_dbg(BATADV_DBG_DAT, bat_priv, "%s\n", msg);
+
+       ip_src = batadv_arp_ip_src(skb, hdr_size);
+       ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+       batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                  "ARP MSG = [src: %pM-%pI4 dst: %pM-%pI4]\n",
+                  batadv_arp_hw_src(skb, hdr_size), &ip_src,
+                  batadv_arp_hw_dst(skb, hdr_size), &ip_dst);
+
+       if (hdr_size == 0)
+               return;
+
+       /* if the ARP packet is encapsulated in a batman packet, let's print
+        * some debug messages
+        */
+       unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+
+       switch (unicast_4addr_packet->u.header.packet_type) {
+       case BATADV_UNICAST:
+               batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                          "* encapsulated within a UNICAST packet\n");
+               break;
+       case BATADV_UNICAST_4ADDR:
+               batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                          "* encapsulated within a UNICAST_4ADDR packet (src: %pM)\n",
+                          unicast_4addr_packet->src);
+               switch (unicast_4addr_packet->subtype) {
+               case BATADV_P_DAT_DHT_PUT:
+                       batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_PUT\n");
+                       break;
+               case BATADV_P_DAT_DHT_GET:
+                       batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DAT_DHT_GET\n");
+                       break;
+               case BATADV_P_DAT_CACHE_REPLY:
+                       batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                                  "* type: DAT_CACHE_REPLY\n");
+                       break;
+               case BATADV_P_DATA:
+                       batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: DATA\n");
+                       break;
+               default:
+                       batadv_dbg(BATADV_DBG_DAT, bat_priv, "* type: Unknown (%u)!\n",
+                                  unicast_4addr_packet->u.header.packet_type);
+               }
+               break;
+       case BATADV_BCAST:
+               bcast_pkt = (struct batadv_bcast_packet *)unicast_4addr_packet;
+               orig_addr = bcast_pkt->orig;
+               batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                          "* encapsulated within a BCAST packet (src: %pM)\n",
+                          orig_addr);
+               break;
+       default:
+               batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                          "* encapsulated within an unknown packet type (0x%x)\n",
+                          unicast_4addr_packet->u.header.packet_type);
+       }
+}
+
+#else
+
+static void batadv_dbg_arp(struct batadv_priv *bat_priv, struct sk_buff *skb,
+                          uint16_t type, int hdr_size, char *msg)
+{
+}
+
+#endif /* CONFIG_BATMAN_ADV_DEBUG */
+
+/**
+ * batadv_is_orig_node_eligible - check whether a node can be a DHT candidate
+ * @res: the array with the already selected candidates
+ * @select: number of already selected candidates
+ * @tmp_max: address of the currently evaluated node
+ * @max: current round max address
+ * @last_max: address of the last selected candidate
+ * @candidate: orig_node under evaluation
+ * @max_orig_node: last selected candidate
+ *
+ * Returns true if the node has been elected as next candidate or false othrwise
+ */
+static bool batadv_is_orig_node_eligible(struct batadv_dat_candidate *res,
+                                        int select, batadv_dat_addr_t tmp_max,
+                                        batadv_dat_addr_t max,
+                                        batadv_dat_addr_t last_max,
+                                        struct batadv_orig_node *candidate,
+                                        struct batadv_orig_node *max_orig_node)
+{
+       bool ret = false;
+       int j;
+
+       /* Check if this node has already been selected... */
+       for (j = 0; j < select; j++)
+               if (res[j].orig_node == candidate)
+                       break;
+       /* ..and possibly skip it */
+       if (j < select)
+               goto out;
+       /* sanity check: has it already been selected? This should not happen */
+       if (tmp_max > last_max)
+               goto out;
+       /* check if during this iteration an originator with a closer dht
+        * address has already been found
+        */
+       if (tmp_max < max)
+               goto out;
+       /* this is an hash collision with the temporary selected node. Choose
+        * the one with the lowest address
+        */
+       if ((tmp_max == max) &&
+           (batadv_compare_eth(candidate->orig, max_orig_node->orig) > 0))
+               goto out;
+
+       ret = true;
+out:
+       return ret;
+}
+
+/**
+ * batadv_choose_next_candidate - select the next DHT candidate
+ * @bat_priv: the bat priv with all the soft interface information
+ * @cands: candidates array
+ * @select: number of candidates already present in the array
+ * @ip_key: key to look up in the DHT
+ * @last_max: pointer where the address of the selected candidate will be saved
+ */
+static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
+                                        struct batadv_dat_candidate *cands,
+                                        int select, batadv_dat_addr_t ip_key,
+                                        batadv_dat_addr_t *last_max)
+{
+       batadv_dat_addr_t max = 0, tmp_max = 0;
+       struct batadv_orig_node *orig_node, *max_orig_node = NULL;
+       struct batadv_hashtable *hash = bat_priv->orig_hash;
+       struct hlist_node *node;
+       struct hlist_head *head;
+       int i;
+
+       /* if no node is eligible as candidate, leave the candidate type as
+        * NOT_FOUND
+        */
+       cands[select].type = BATADV_DAT_CANDIDATE_NOT_FOUND;
+
+       /* iterate over the originator list and find the node with closest
+        * dat_address which has not been selected yet
+        */
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
+
+               rcu_read_lock();
+               hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
+                       /* the dht space is a ring and addresses are unsigned */
+                       tmp_max = BATADV_DAT_ADDR_MAX - orig_node->dat_addr +
+                                 ip_key;
+
+                       if (!batadv_is_orig_node_eligible(cands, select,
+                                                         tmp_max, max,
+                                                         *last_max, orig_node,
+                                                         max_orig_node))
+                               continue;
+
+                       if (!atomic_inc_not_zero(&orig_node->refcount))
+                               continue;
+
+                       max = tmp_max;
+                       if (max_orig_node)
+                               batadv_orig_node_free_ref(max_orig_node);
+                       max_orig_node = orig_node;
+               }
+               rcu_read_unlock();
+       }
+       if (max_orig_node) {
+               cands[select].type = BATADV_DAT_CANDIDATE_ORIG;
+               cands[select].orig_node = max_orig_node;
+               batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                          "dat_select_candidates() %d: selected %pM addr=%u dist=%u\n",
+                          select, max_orig_node->orig, max_orig_node->dat_addr,
+                          max);
+       }
+       *last_max = max;
+}
+
+/**
+ * batadv_dat_select_candidates - selects the nodes which the DHT message has to
+ * be sent to
+ * @bat_priv: the bat priv with all the soft interface information
+ * @ip_dst: ipv4 to look up in the DHT
+ *
+ * An originator O is selected if and only if its DHT_ID value is one of three
+ * closest values (from the LEFT, with wrap around if needed) then the hash
+ * value of the key. ip_dst is the key.
+ *
+ * Returns the candidate array of size BATADV_DAT_CANDIDATE_NUM
+ */
+static struct batadv_dat_candidate *
+batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
+{
+       int select;
+       batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
+       struct batadv_dat_candidate *res;
+
+       if (!bat_priv->orig_hash)
+               return NULL;
+
+       res = kmalloc(BATADV_DAT_CANDIDATES_NUM * sizeof(*res), GFP_ATOMIC);
+       if (!res)
+               return NULL;
+
+       ip_key = (batadv_dat_addr_t)batadv_hash_dat(&ip_dst,
+                                                   BATADV_DAT_ADDR_MAX);
+
+       batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                  "dat_select_candidates(): IP=%pI4 hash(IP)=%u\n", &ip_dst,
+                  ip_key);
+
+       for (select = 0; select < BATADV_DAT_CANDIDATES_NUM; select++)
+               batadv_choose_next_candidate(bat_priv, res, select, ip_key,
+                                            &last_max);
+
+       return res;
+}
+
+/**
+ * batadv_dat_send_data - send a payload to the selected candidates
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: payload to send
+ * @ip: the DHT key
+ * @packet_subtype: unicast4addr packet subtype to use
+ *
+ * In this function the skb is copied by means of pskb_copy() and is sent as
+ * unicast packet to each of the selected candidates
+ *
+ * Returns true if the packet is sent to at least one candidate, false otherwise
+ */
+static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
+                                struct sk_buff *skb, __be32 ip,
+                                int packet_subtype)
+{
+       int i;
+       bool ret = false;
+       int send_status;
+       struct batadv_neigh_node *neigh_node = NULL;
+       struct sk_buff *tmp_skb;
+       struct batadv_dat_candidate *cand;
+
+       cand = batadv_dat_select_candidates(bat_priv, ip);
+       if (!cand)
+               goto out;
+
+       batadv_dbg(BATADV_DBG_DAT, bat_priv, "DHT_SEND for %pI4\n", &ip);
+
+       for (i = 0; i < BATADV_DAT_CANDIDATES_NUM; i++) {
+               if (cand[i].type == BATADV_DAT_CANDIDATE_NOT_FOUND)
+                       continue;
+
+               neigh_node = batadv_orig_node_get_router(cand[i].orig_node);
+               if (!neigh_node)
+                       goto free_orig;
+
+               tmp_skb = pskb_copy(skb, GFP_ATOMIC);
+               if (!batadv_unicast_4addr_prepare_skb(bat_priv, tmp_skb,
+                                                     cand[i].orig_node,
+                                                     packet_subtype)) {
+                       kfree_skb(tmp_skb);
+                       goto free_neigh;
+               }
+
+               send_status = batadv_send_skb_packet(tmp_skb,
+                                                    neigh_node->if_incoming,
+                                                    neigh_node->addr);
+               if (send_status == NET_XMIT_SUCCESS) {
+                       /* count the sent packet */
+                       switch (packet_subtype) {
+                       case BATADV_P_DAT_DHT_GET:
+                               batadv_inc_counter(bat_priv,
+                                                  BATADV_CNT_DAT_GET_TX);
+                               break;
+                       case BATADV_P_DAT_DHT_PUT:
+                               batadv_inc_counter(bat_priv,
+                                                  BATADV_CNT_DAT_PUT_TX);
+                               break;
+                       }
+
+                       /* packet sent to a candidate: return true */
+                       ret = true;
+               }
+free_neigh:
+               batadv_neigh_node_free_ref(neigh_node);
+free_orig:
+               batadv_orig_node_free_ref(cand[i].orig_node);
+       }
+
+out:
+       kfree(cand);
+       return ret;
+}
+
+/**
+ * batadv_dat_hash_free - free the local DAT hash table
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+static void batadv_dat_hash_free(struct batadv_priv *bat_priv)
+{
+       if (!bat_priv->dat.hash)
+               return;
+
+       __batadv_dat_purge(bat_priv, NULL);
+
+       batadv_hash_destroy(bat_priv->dat.hash);
+
+       bat_priv->dat.hash = NULL;
+}
+
+/**
+ * batadv_dat_init - initialise the DAT internals
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+int batadv_dat_init(struct batadv_priv *bat_priv)
+{
+       if (bat_priv->dat.hash)
+               return 0;
+
+       bat_priv->dat.hash = batadv_hash_new(1024);
+
+       if (!bat_priv->dat.hash)
+               return -ENOMEM;
+
+       batadv_dat_start_timer(bat_priv);
+
+       return 0;
+}
+
+/**
+ * batadv_dat_free - free the DAT internals
+ * @bat_priv: the bat priv with all the soft interface information
+ */
+void batadv_dat_free(struct batadv_priv *bat_priv)
+{
+       cancel_delayed_work_sync(&bat_priv->dat.work);
+
+       batadv_dat_hash_free(bat_priv);
+}
+
+/**
+ * batadv_dat_cache_seq_print_text - print the local DAT hash table
+ * @seq: seq file to print on
+ * @offset: not used
+ */
+int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset)
+{
+       struct net_device *net_dev = (struct net_device *)seq->private;
+       struct batadv_priv *bat_priv = netdev_priv(net_dev);
+       struct batadv_hashtable *hash = bat_priv->dat.hash;
+       struct batadv_dat_entry *dat_entry;
+       struct batadv_hard_iface *primary_if;
+       struct hlist_node *node;
+       struct hlist_head *head;
+       unsigned long last_seen_jiffies;
+       int last_seen_msecs, last_seen_secs, last_seen_mins;
+       uint32_t i;
+
+       primary_if = batadv_seq_print_text_primary_if_get(seq);
+       if (!primary_if)
+               goto out;
+
+       seq_printf(seq, "Distributed ARP Table (%s):\n", net_dev->name);
+       seq_printf(seq, "          %-7s          %-13s %5s\n", "IPv4", "MAC",
+                  "last-seen");
+
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
+
+               rcu_read_lock();
+               hlist_for_each_entry_rcu(dat_entry, node, head, hash_entry) {
+                       last_seen_jiffies = jiffies - dat_entry->last_update;
+                       last_seen_msecs = jiffies_to_msecs(last_seen_jiffies);
+                       last_seen_mins = last_seen_msecs / 60000;
+                       last_seen_msecs = last_seen_msecs % 60000;
+                       last_seen_secs = last_seen_msecs / 1000;
+
+                       seq_printf(seq, " * %15pI4 %14pM %6i:%02i\n",
+                                  &dat_entry->ip, dat_entry->mac_addr,
+                                  last_seen_mins, last_seen_secs);
+               }
+               rcu_read_unlock();
+       }
+
+out:
+       if (primary_if)
+               batadv_hardif_free_ref(primary_if);
+       return 0;
+}
+
+/**
+ * batadv_arp_get_type - parse an ARP packet and gets the type
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to analyse
+ * @hdr_size: size of the possible header before the ARP packet in the skb
+ *
+ * Returns the ARP type if the skb contains a valid ARP packet, 0 otherwise
+ */
+static uint16_t batadv_arp_get_type(struct batadv_priv *bat_priv,
+                                   struct sk_buff *skb, int hdr_size)
+{
+       struct arphdr *arphdr;
+       struct ethhdr *ethhdr;
+       __be32 ip_src, ip_dst;
+       uint16_t type = 0;
+
+       /* pull the ethernet header */
+       if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN)))
+               goto out;
+
+       ethhdr = (struct ethhdr *)(skb->data + hdr_size);
+
+       if (ethhdr->h_proto != htons(ETH_P_ARP))
+               goto out;
+
+       /* pull the ARP payload */
+       if (unlikely(!pskb_may_pull(skb, hdr_size + ETH_HLEN +
+                                   arp_hdr_len(skb->dev))))
+               goto out;
+
+       arphdr = (struct arphdr *)(skb->data + hdr_size + ETH_HLEN);
+
+       /* Check whether the ARP packet carries a valid
+        * IP information
+        */
+       if (arphdr->ar_hrd != htons(ARPHRD_ETHER))
+               goto out;
+
+       if (arphdr->ar_pro != htons(ETH_P_IP))
+               goto out;
+
+       if (arphdr->ar_hln != ETH_ALEN)
+               goto out;
+
+       if (arphdr->ar_pln != 4)
+               goto out;
+
+       /* Check for bad reply/request. If the ARP message is not sane, DAT
+        * will simply ignore it
+        */
+       ip_src = batadv_arp_ip_src(skb, hdr_size);
+       ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+       if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) ||
+           ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst))
+               goto out;
+
+       type = ntohs(arphdr->ar_op);
+out:
+       return type;
+}
+
+/**
+ * batadv_dat_snoop_outgoing_arp_request - snoop the ARP request and try to
+ * answer using DAT
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ *
+ * Returns true if the message has been sent to the dht candidates, false
+ * otherwise. In case of true the message has to be enqueued to permit the
+ * fallback
+ */
+bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+                                          struct sk_buff *skb)
+{
+       uint16_t type = 0;
+       __be32 ip_dst, ip_src;
+       uint8_t *hw_src;
+       bool ret = false;
+       struct batadv_dat_entry *dat_entry = NULL;
+       struct sk_buff *skb_new;
+       struct batadv_hard_iface *primary_if = NULL;
+
+       if (!atomic_read(&bat_priv->distributed_arp_table))
+               goto out;
+
+       type = batadv_arp_get_type(bat_priv, skb, 0);
+       /* If the node gets an ARP_REQUEST it has to send a DHT_GET unicast
+        * message to the selected DHT candidates
+        */
+       if (type != ARPOP_REQUEST)
+               goto out;
+
+       batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REQUEST");
+
+       ip_src = batadv_arp_ip_src(skb, 0);
+       hw_src = batadv_arp_hw_src(skb, 0);
+       ip_dst = batadv_arp_ip_dst(skb, 0);
+
+       batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+
+       dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+       if (dat_entry) {
+               primary_if = batadv_primary_if_get_selected(bat_priv);
+               if (!primary_if)
+                       goto out;
+
+               skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
+                                    primary_if->soft_iface, ip_dst, hw_src,
+                                    dat_entry->mac_addr, hw_src);
+               if (!skb_new)
+                       goto out;
+
+               skb_reset_mac_header(skb_new);
+               skb_new->protocol = eth_type_trans(skb_new,
+                                                  primary_if->soft_iface);
+               bat_priv->stats.rx_packets++;
+               bat_priv->stats.rx_bytes += skb->len + ETH_HLEN;
+               primary_if->soft_iface->last_rx = jiffies;
+
+               netif_rx(skb_new);
+               batadv_dbg(BATADV_DBG_DAT, bat_priv, "ARP request replied locally\n");
+               ret = true;
+       } else {
+               /* Send the request on the DHT */
+               ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
+                                          BATADV_P_DAT_DHT_GET);
+       }
+out:
+       if (dat_entry)
+               batadv_dat_entry_free_ref(dat_entry);
+       if (primary_if)
+               batadv_hardif_free_ref(primary_if);
+       return ret;
+}
+
+/**
+ * batadv_dat_snoop_incoming_arp_request - snoop the ARP request and try to
+ * answer using the local DAT storage
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ * @hdr_size: size of the encapsulation header
+ *
+ * Returns true if the request has been answered, false otherwise
+ */
+bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+                                          struct sk_buff *skb, int hdr_size)
+{
+       uint16_t type;
+       __be32 ip_src, ip_dst;
+       uint8_t *hw_src;
+       struct sk_buff *skb_new;
+       struct batadv_hard_iface *primary_if = NULL;
+       struct batadv_dat_entry *dat_entry = NULL;
+       bool ret = false;
+       int err;
+
+       if (!atomic_read(&bat_priv->distributed_arp_table))
+               goto out;
+
+       type = batadv_arp_get_type(bat_priv, skb, hdr_size);
+       if (type != ARPOP_REQUEST)
+               goto out;
+
+       hw_src = batadv_arp_hw_src(skb, hdr_size);
+       ip_src = batadv_arp_ip_src(skb, hdr_size);
+       ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+
+       batadv_dbg_arp(bat_priv, skb, type, hdr_size,
+                      "Parsing incoming ARP REQUEST");
+
+       batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+
+       dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+       if (!dat_entry)
+               goto out;
+
+       primary_if = batadv_primary_if_get_selected(bat_priv);
+       if (!primary_if)
+               goto out;
+
+       skb_new = arp_create(ARPOP_REPLY, ETH_P_ARP, ip_src,
+                            primary_if->soft_iface, ip_dst, hw_src,
+                            dat_entry->mac_addr, hw_src);
+
+       if (!skb_new)
+               goto out;
+
+       /* to preserve backwards compatibility, here the node has to answer
+        * using the same packet type it received for the request. This is due
+        * to that if a node is not using the 4addr packet format it may not
+        * support it.
+        */
+       if (hdr_size == sizeof(struct batadv_unicast_4addr_packet))
+               err = batadv_unicast_4addr_send_skb(bat_priv, skb_new,
+                                                   BATADV_P_DAT_CACHE_REPLY);
+       else
+               err = batadv_unicast_send_skb(bat_priv, skb_new);
+
+       if (!err) {
+               batadv_inc_counter(bat_priv, BATADV_CNT_DAT_CACHED_REPLY_TX);
+               ret = true;
+       }
+out:
+       if (dat_entry)
+               batadv_dat_entry_free_ref(dat_entry);
+       if (primary_if)
+               batadv_hardif_free_ref(primary_if);
+       if (ret)
+               kfree_skb(skb);
+       return ret;
+}
+
+/**
+ * batadv_dat_snoop_outgoing_arp_reply - snoop the ARP reply and fill the DHT
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ */
+void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+                                        struct sk_buff *skb)
+{
+       uint16_t type;
+       __be32 ip_src, ip_dst;
+       uint8_t *hw_src, *hw_dst;
+
+       if (!atomic_read(&bat_priv->distributed_arp_table))
+               return;
+
+       type = batadv_arp_get_type(bat_priv, skb, 0);
+       if (type != ARPOP_REPLY)
+               return;
+
+       batadv_dbg_arp(bat_priv, skb, type, 0, "Parsing outgoing ARP REPLY");
+
+       hw_src = batadv_arp_hw_src(skb, 0);
+       ip_src = batadv_arp_ip_src(skb, 0);
+       hw_dst = batadv_arp_hw_dst(skb, 0);
+       ip_dst = batadv_arp_ip_dst(skb, 0);
+
+       batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+       batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+
+       /* Send the ARP reply to the candidates for both the IP addresses that
+        * the node got within the ARP reply
+        */
+       batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
+       batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
+}
+/**
+ * batadv_dat_snoop_incoming_arp_reply - snoop the ARP reply and fill the local
+ * DAT storage only
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: packet to check
+ * @hdr_size: siaze of the encapsulation header
+ */
+bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+                                        struct sk_buff *skb, int hdr_size)
+{
+       uint16_t type;
+       __be32 ip_src, ip_dst;
+       uint8_t *hw_src, *hw_dst;
+       bool ret = false;
+
+       if (!atomic_read(&bat_priv->distributed_arp_table))
+               goto out;
+
+       type = batadv_arp_get_type(bat_priv, skb, hdr_size);
+       if (type != ARPOP_REPLY)
+               goto out;
+
+       batadv_dbg_arp(bat_priv, skb, type, hdr_size,
+                      "Parsing incoming ARP REPLY");
+
+       hw_src = batadv_arp_hw_src(skb, hdr_size);
+       ip_src = batadv_arp_ip_src(skb, hdr_size);
+       hw_dst = batadv_arp_hw_dst(skb, hdr_size);
+       ip_dst = batadv_arp_ip_dst(skb, hdr_size);
+
+       /* Update our internal cache with both the IP addresses the node got
+        * within the ARP reply
+        */
+       batadv_dat_entry_add(bat_priv, ip_src, hw_src);
+       batadv_dat_entry_add(bat_priv, ip_dst, hw_dst);
+
+       /* if this REPLY is directed to a client of mine, let's deliver the
+        * packet to the interface
+        */
+       ret = !batadv_is_my_client(bat_priv, hw_dst);
+out:
+       /* if ret == false -> packet has to be delivered to the interface */
+       return ret;
+}
+
+/**
+ * batadv_dat_drop_broadcast_packet - check if an ARP request has to be dropped
+ * (because the node has already got the reply via DAT) or not
+ * @bat_priv: the bat priv with all the soft interface information
+ * @forw_packet: the broadcast packet
+ *
+ * Returns true if the node can drop the packet, false otherwise
+ */
+bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+                                     struct batadv_forw_packet *forw_packet)
+{
+       uint16_t type;
+       __be32 ip_dst;
+       struct batadv_dat_entry *dat_entry = NULL;
+       bool ret = false;
+       const size_t bcast_len = sizeof(struct batadv_bcast_packet);
+
+       if (!atomic_read(&bat_priv->distributed_arp_table))
+               goto out;
+
+       /* If this packet is an ARP_REQUEST and the node already has the
+        * information that it is going to ask, then the packet can be dropped
+        */
+       if (forw_packet->num_packets)
+               goto out;
+
+       type = batadv_arp_get_type(bat_priv, forw_packet->skb, bcast_len);
+       if (type != ARPOP_REQUEST)
+               goto out;
+
+       ip_dst = batadv_arp_ip_dst(forw_packet->skb, bcast_len);
+       dat_entry = batadv_dat_entry_hash_find(bat_priv, ip_dst);
+       /* check if the node already got this entry */
+       if (!dat_entry) {
+               batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                          "ARP Request for %pI4: fallback\n", &ip_dst);
+               goto out;
+       }
+
+       batadv_dbg(BATADV_DBG_DAT, bat_priv,
+                  "ARP Request for %pI4: fallback prevented\n", &ip_dst);
+       ret = true;
+
+out:
+       if (dat_entry)
+               batadv_dat_entry_free_ref(dat_entry);
+       return ret;
+}
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h
new file mode 100644 (file)
index 0000000..d060c03
--- /dev/null
@@ -0,0 +1,167 @@
+/* Copyright (C) 2011-2012 B.A.T.M.A.N. contributors:
+ *
+ * Antonio Quartulli
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA
+ */
+
+#ifndef _NET_BATMAN_ADV_ARP_H_
+#define _NET_BATMAN_ADV_ARP_H_
+
+#ifdef CONFIG_BATMAN_ADV_DAT
+
+#include "types.h"
+#include "originator.h"
+
+#include <linux/if_arp.h>
+
+#define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0)
+
+bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+                                          struct sk_buff *skb);
+bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+                                          struct sk_buff *skb, int hdr_size);
+void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+                                        struct sk_buff *skb);
+bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+                                        struct sk_buff *skb, int hdr_size);
+bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+                                     struct batadv_forw_packet *forw_packet);
+
+/**
+ * batadv_dat_init_orig_node_addr - assign a DAT address to the orig_node
+ * @orig_node: the node to assign the DAT address to
+ */
+static inline void
+batadv_dat_init_orig_node_addr(struct batadv_orig_node *orig_node)
+{
+       uint32_t addr;
+
+       addr = batadv_choose_orig(orig_node->orig, BATADV_DAT_ADDR_MAX);
+       orig_node->dat_addr = (batadv_dat_addr_t)addr;
+}
+
+/**
+ * batadv_dat_init_own_addr - assign a DAT address to the node itself
+ * @bat_priv: the bat priv with all the soft interface information
+ * @primary_if: a pointer to the primary interface
+ */
+static inline void
+batadv_dat_init_own_addr(struct batadv_priv *bat_priv,
+                        struct batadv_hard_iface *primary_if)
+{
+       uint32_t addr;
+
+       addr = batadv_choose_orig(primary_if->net_dev->dev_addr,
+                                 BATADV_DAT_ADDR_MAX);
+
+       bat_priv->dat.addr = (batadv_dat_addr_t)addr;
+}
+
+int batadv_dat_init(struct batadv_priv *bat_priv);
+void batadv_dat_free(struct batadv_priv *bat_priv);
+int batadv_dat_cache_seq_print_text(struct seq_file *seq, void *offset);
+
+/**
+ * batadv_dat_inc_counter - increment the correct DAT packet counter
+ * @bat_priv: the bat priv with all the soft interface information
+ * @subtype: the 4addr subtype of the packet to be counted
+ *
+ * Updates the ethtool statistics for the received packet if it is a DAT subtype
+ */
+static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
+                                         uint8_t subtype)
+{
+       switch (subtype) {
+       case BATADV_P_DAT_DHT_GET:
+               batadv_inc_counter(bat_priv,
+                                  BATADV_CNT_DAT_GET_RX);
+               break;
+       case BATADV_P_DAT_DHT_PUT:
+               batadv_inc_counter(bat_priv,
+                                  BATADV_CNT_DAT_PUT_RX);
+               break;
+       }
+}
+
+#else
+
+static inline bool
+batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
+                                     struct sk_buff *skb)
+{
+       return false;
+}
+
+static inline bool
+batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
+                                     struct sk_buff *skb, int hdr_size)
+{
+       return false;
+}
+
+static inline bool
+batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
+                                   struct sk_buff *skb)
+{
+       return false;
+}
+
+static inline bool
+batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
+                                   struct sk_buff *skb, int hdr_size)
+{
+       return false;
+}
+
+static inline bool
+batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
+                                struct batadv_forw_packet *forw_packet)
+{
+       return false;
+}
+
+static inline void
+batadv_dat_init_orig_node_addr(struct batadv_orig_node *orig_node)
+{
+}
+
+static inline void batadv_dat_init_own_addr(struct batadv_priv *bat_priv,
+                                           struct batadv_hard_iface *iface)
+{
+}
+
+static inline void batadv_arp_change_timeout(struct net_device *soft_iface,
+                                            const char *name)
+{
+}
+
+static inline int batadv_dat_init(struct batadv_priv *bat_priv)
+{
+       return 0;
+}
+
+static inline void batadv_dat_free(struct batadv_priv *bat_priv)
+{
+}
+
+static inline void batadv_dat_inc_counter(struct batadv_priv *bat_priv,
+                                         uint8_t subtype)
+{
+}
+
+#endif /* CONFIG_BATMAN_ADV_DAT */
+
+#endif /* _NET_BATMAN_ADV_ARP_H_ */
index 15d67abc10a43b329ef3cf561bd3fdf456c3c286..dd07c7e3654fa4b3e38f9c0665ca705a332203cc 100644 (file)
@@ -477,22 +477,11 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
        struct batadv_hard_iface *primary_if;
        struct batadv_gw_node *gw_node;
        struct hlist_node *node;
-       int gw_count = 0, ret = 0;
+       int gw_count = 0;
 
-       primary_if = batadv_primary_if_get_selected(bat_priv);
-       if (!primary_if) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-                                net_dev->name);
+       primary_if = batadv_seq_print_text_primary_if_get(seq);
+       if (!primary_if)
                goto out;
-       }
-
-       if (primary_if->if_status != BATADV_IF_ACTIVE) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - primary interface not active\n",
-                                net_dev->name);
-               goto out;
-       }
 
        seq_printf(seq,
                   "      %-12s (%s/%i) %17s [%10s]: gw_class ... [B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
@@ -519,7 +508,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset)
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       return ret;
+       return 0;
 }
 
 static bool batadv_is_type_dhcprequest(struct sk_buff *skb, int header_len)
index d112fd6750b0564e1b08232482eb8c1261b749ad..f1d37cd818155ed82b388571a2342afb39509897 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include "main.h"
+#include "distributed-arp-table.h"
 #include "hard-interface.h"
 #include "soft-interface.h"
 #include "send.h"
@@ -29,6 +30,7 @@
 #include "bridge_loop_avoidance.h"
 
 #include <linux/if_arp.h>
+#include <linux/if_ether.h>
 
 void batadv_hardif_free_rcu(struct rcu_head *rcu)
 {
@@ -58,6 +60,45 @@ out:
        return hard_iface;
 }
 
+/**
+ * batadv_is_on_batman_iface - check if a device is a batman iface descendant
+ * @net_dev: the device to check
+ *
+ * If the user creates any virtual device on top of a batman-adv interface, it
+ * is important to prevent this new interface to be used to create a new mesh
+ * network (this behaviour would lead to a batman-over-batman configuration).
+ * This function recursively checks all the fathers of the device passed as
+ * argument looking for a batman-adv soft interface.
+ *
+ * Returns true if the device is descendant of a batman-adv mesh interface (or
+ * if it is a batman-adv interface itself), false otherwise
+ */
+static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
+{
+       struct net_device *parent_dev;
+       bool ret;
+
+       /* check if this is a batman-adv mesh interface */
+       if (batadv_softif_is_valid(net_dev))
+               return true;
+
+       /* no more parents..stop recursion */
+       if (net_dev->iflink == net_dev->ifindex)
+               return false;
+
+       /* recurse over the parent device */
+       parent_dev = dev_get_by_index(&init_net, net_dev->iflink);
+       /* if we got a NULL parent_dev there is something broken.. */
+       if (WARN(!parent_dev, "Cannot find parent device"))
+               return false;
+
+       ret = batadv_is_on_batman_iface(parent_dev);
+
+       if (parent_dev)
+               dev_put(parent_dev);
+       return ret;
+}
+
 static int batadv_is_valid_iface(const struct net_device *net_dev)
 {
        if (net_dev->flags & IFF_LOOPBACK)
@@ -70,7 +111,7 @@ static int batadv_is_valid_iface(const struct net_device *net_dev)
                return 0;
 
        /* no batman over batman */
-       if (batadv_softif_is_valid(net_dev))
+       if (batadv_is_on_batman_iface(net_dev))
                return 0;
 
        return 1;
@@ -109,6 +150,8 @@ static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv,
        if (!primary_if)
                goto out;
 
+       batadv_dat_init_own_addr(bat_priv, primary_if);
+
        skb = bat_priv->vis.my_info->skb_packet;
        vis_packet = (struct batadv_vis_packet *)skb->data;
        memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
@@ -269,7 +312,7 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface,
 {
        struct batadv_priv *bat_priv;
        struct net_device *soft_iface;
-       __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
+       __be16 ethertype = __constant_htons(ETH_P_BATMAN);
        int ret;
 
        if (hard_iface->if_status != BATADV_IF_NOT_IN_USE)
@@ -450,8 +493,8 @@ batadv_hardif_add_interface(struct net_device *net_dev)
        /* This can't be called via a bat_priv callback because
         * we have no bat_priv yet.
         */
-       atomic_set(&hard_iface->seqno, 1);
-       hard_iface->packet_buff = NULL;
+       atomic_set(&hard_iface->bat_iv.ogm_seqno, 1);
+       hard_iface->bat_iv.ogm_buff = NULL;
 
        return hard_iface;
 
index 977de9c75fc27010c1fd98dd3e11e3aa459ebe41..e05333905afd566117bf1267d6e3ac05596c89c1 100644 (file)
@@ -81,6 +81,28 @@ static inline void batadv_hash_delete(struct batadv_hashtable *hash,
        batadv_hash_destroy(hash);
 }
 
+/**
+ *     batadv_hash_bytes - hash some bytes and add them to the previous hash
+ *     @hash: previous hash value
+ *     @data: data to be hashed
+ *     @size: number of bytes to be hashed
+ *
+ *     Returns the new hash value.
+ */
+static inline uint32_t batadv_hash_bytes(uint32_t hash, void *data,
+                                        uint32_t size)
+{
+       const unsigned char *key = data;
+       int i;
+
+       for (i = 0; i < size; i++) {
+               hash += key[i];
+               hash += (hash << 10);
+               hash ^= (hash >> 6);
+       }
+       return hash;
+}
+
 /**
  *     batadv_hash_add - adds data to the hashtable
  *     @hash: storage hash table
index bde3cf74750796142d4a74e1db2be87516152a1c..87ca8095b011517b6f41faf8d1dfa25ef8e0b570 100644 (file)
@@ -42,12 +42,16 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
        unsigned int i;
        struct batadv_socket_client *socket_client;
 
+       if (!try_module_get(THIS_MODULE))
+               return -EBUSY;
+
        nonseekable_open(inode, file);
 
        socket_client = kmalloc(sizeof(*socket_client), GFP_KERNEL);
-
-       if (!socket_client)
+       if (!socket_client) {
+               module_put(THIS_MODULE);
                return -ENOMEM;
+       }
 
        for (i = 0; i < ARRAY_SIZE(batadv_socket_client_hash); i++) {
                if (!batadv_socket_client_hash[i]) {
@@ -59,6 +63,7 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
        if (i == ARRAY_SIZE(batadv_socket_client_hash)) {
                pr_err("Error - can't add another packet client: maximum number of clients reached\n");
                kfree(socket_client);
+               module_put(THIS_MODULE);
                return -EXFULL;
        }
 
@@ -71,7 +76,6 @@ static int batadv_socket_open(struct inode *inode, struct file *file)
 
        file->private_data = socket_client;
 
-       batadv_inc_module_count();
        return 0;
 }
 
@@ -96,7 +100,7 @@ static int batadv_socket_release(struct inode *inode, struct file *file)
        spin_unlock_bh(&socket_client->lock);
 
        kfree(socket_client);
-       batadv_dec_module_count();
+       module_put(THIS_MODULE);
 
        return 0;
 }
@@ -173,13 +177,13 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff,
        if (len >= sizeof(struct batadv_icmp_packet_rr))
                packet_len = sizeof(struct batadv_icmp_packet_rr);
 
-       skb = dev_alloc_skb(packet_len + ETH_HLEN);
+       skb = dev_alloc_skb(packet_len + ETH_HLEN + NET_IP_ALIGN);
        if (!skb) {
                len = -ENOMEM;
                goto out;
        }
 
-       skb_reserve(skb, ETH_HLEN);
+       skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
        icmp_packet = (struct batadv_icmp_packet_rr *)skb_put(skb, packet_len);
 
        if (copy_from_user(icmp_packet, buff, packet_len)) {
index b4aa470bc4a6ec675d84fb373a973dd4d224cd5d..f65a222b7b83c0d691f859f2eef1ea189ac84e2c 100644 (file)
@@ -17,6 +17,8 @@
  * 02110-1301, USA
  */
 
+#include <linux/crc32c.h>
+#include <linux/highmem.h>
 #include "main.h"
 #include "sysfs.h"
 #include "debugfs.h"
@@ -29,6 +31,7 @@
 #include "hard-interface.h"
 #include "gateway_client.h"
 #include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
 #include "vis.h"
 #include "hash.h"
 #include "bat_algo.h"
@@ -128,6 +131,10 @@ int batadv_mesh_init(struct net_device *soft_iface)
        if (ret < 0)
                goto err;
 
+       ret = batadv_dat_init(bat_priv);
+       if (ret < 0)
+               goto err;
+
        atomic_set(&bat_priv->gw.reselect, 0);
        atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE);
 
@@ -155,21 +162,13 @@ void batadv_mesh_free(struct net_device *soft_iface)
 
        batadv_bla_free(bat_priv);
 
+       batadv_dat_free(bat_priv);
+
        free_percpu(bat_priv->bat_counters);
 
        atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE);
 }
 
-void batadv_inc_module_count(void)
-{
-       try_module_get(THIS_MODULE);
-}
-
-void batadv_dec_module_count(void)
-{
-       module_put(THIS_MODULE);
-}
-
 int batadv_is_my_mac(const uint8_t *addr)
 {
        const struct batadv_hard_iface *hard_iface;
@@ -188,6 +187,42 @@ int batadv_is_my_mac(const uint8_t *addr)
        return 0;
 }
 
+/**
+ * batadv_seq_print_text_primary_if_get - called from debugfs table printing
+ *  function that requires the primary interface
+ * @seq: debugfs table seq_file struct
+ *
+ * Returns primary interface if found or NULL otherwise.
+ */
+struct batadv_hard_iface *
+batadv_seq_print_text_primary_if_get(struct seq_file *seq)
+{
+       struct net_device *net_dev = (struct net_device *)seq->private;
+       struct batadv_priv *bat_priv = netdev_priv(net_dev);
+       struct batadv_hard_iface *primary_if;
+
+       primary_if = batadv_primary_if_get_selected(bat_priv);
+
+       if (!primary_if) {
+               seq_printf(seq,
+                          "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
+                          net_dev->name);
+               goto out;
+       }
+
+       if (primary_if->if_status == BATADV_IF_ACTIVE)
+               goto out;
+
+       seq_printf(seq,
+                  "BATMAN mesh %s disabled - primary interface not active\n",
+                  net_dev->name);
+       batadv_hardif_free_ref(primary_if);
+       primary_if = NULL;
+
+out:
+       return primary_if;
+}
+
 static int batadv_recv_unhandled_packet(struct sk_buff *skb,
                                        struct batadv_hard_iface *recv_if)
 {
@@ -274,6 +309,8 @@ static void batadv_recv_handler_init(void)
 
        /* batman icmp packet */
        batadv_rx_handler[BATADV_ICMP] = batadv_recv_icmp_packet;
+       /* unicast with 4 addresses packet */
+       batadv_rx_handler[BATADV_UNICAST_4ADDR] = batadv_recv_unicast_packet;
        /* unicast packet */
        batadv_rx_handler[BATADV_UNICAST] = batadv_recv_unicast_packet;
        /* fragmented unicast packet */
@@ -385,6 +422,38 @@ int batadv_algo_seq_print_text(struct seq_file *seq, void *offset)
        return 0;
 }
 
+/**
+ * batadv_skb_crc32 - calculate CRC32 of the whole packet and skip bytes in
+ *  the header
+ * @skb: skb pointing to fragmented socket buffers
+ * @payload_ptr: Pointer to position inside the head buffer of the skb
+ *  marking the start of the data to be CRC'ed
+ *
+ * payload_ptr must always point to an address in the skb head buffer and not to
+ * a fragment.
+ */
+__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr)
+{
+       u32 crc = 0;
+       unsigned int from;
+       unsigned int to = skb->len;
+       struct skb_seq_state st;
+       const u8 *data;
+       unsigned int len;
+       unsigned int consumed = 0;
+
+       from = (unsigned int)(payload_ptr - skb->data);
+
+       skb_prepare_seq_read(skb, from, to, &st);
+       while ((len = skb_seq_read(consumed, &data, &st)) != 0) {
+               crc = crc32c(crc, data, len);
+               consumed += len;
+       }
+       skb_abort_seq_read(&st);
+
+       return htonl(crc);
+}
+
 static int batadv_param_set_ra(const char *val, const struct kernel_param *kp)
 {
        struct batadv_algo_ops *bat_algo_ops;
index d57b746219de057c931d8459f1ccef84ce711cee..2f85577086a7cf923c6185f84f6efeb3bfb5fe84 100644 (file)
@@ -26,7 +26,7 @@
 #define BATADV_DRIVER_DEVICE "batman-adv"
 
 #ifndef BATADV_SOURCE_VERSION
-#define BATADV_SOURCE_VERSION "2012.4.0"
+#define BATADV_SOURCE_VERSION "2012.5.0"
 #endif
 
 /* B.A.T.M.A.N. parameters */
@@ -44,6 +44,7 @@
 #define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */
 #define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */
 #define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */
+#define BATADV_DAT_ENTRY_TIMEOUT (5*60000) /* 5 mins in milliseconds */
 /* sliding packet range of received originator messages in sequence numbers
  * (should be a multiple of our word size)
  */
 
 #define BATADV_LOG_BUF_LEN 8192          /* has to be a power of 2 */
 
+/* msecs after which an ARP_REQUEST is sent in broadcast as fallback */
+#define ARP_REQ_DELAY 250
+/* numbers of originator to contact for any PUT/GET DHT operation */
+#define BATADV_DAT_CANDIDATES_NUM 3
+
 #define BATADV_VIS_INTERVAL 5000       /* 5 seconds */
 
 /* how much worse secondary interfaces may be to be considered as bonding
@@ -89,6 +95,7 @@
 #define BATADV_BLA_PERIOD_LENGTH       10000   /* 10 seconds */
 #define BATADV_BLA_BACKBONE_TIMEOUT    (BATADV_BLA_PERIOD_LENGTH * 3)
 #define BATADV_BLA_CLAIM_TIMEOUT       (BATADV_BLA_PERIOD_LENGTH * 10)
+#define BATADV_BLA_WAIT_PERIODS                3
 
 #define BATADV_DUPLIST_SIZE            16
 #define BATADV_DUPLIST_TIMEOUT         500     /* 500 ms */
@@ -117,6 +124,9 @@ enum batadv_uev_type {
 
 #define BATADV_GW_THRESHOLD    50
 
+#define BATADV_DAT_CANDIDATE_NOT_FOUND 0
+#define BATADV_DAT_CANDIDATE_ORIG      1
+
 /* Debug Messages */
 #ifdef pr_fmt
 #undef pr_fmt
@@ -150,9 +160,9 @@ extern struct workqueue_struct *batadv_event_workqueue;
 
 int batadv_mesh_init(struct net_device *soft_iface);
 void batadv_mesh_free(struct net_device *soft_iface);
-void batadv_inc_module_count(void);
-void batadv_dec_module_count(void);
 int batadv_is_my_mac(const uint8_t *addr);
+struct batadv_hard_iface *
+batadv_seq_print_text_primary_if_get(struct seq_file *seq);
 int batadv_batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
                           struct packet_type *ptype,
                           struct net_device *orig_dev);
@@ -164,14 +174,24 @@ void batadv_recv_handler_unregister(uint8_t packet_type);
 int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops);
 int batadv_algo_select(struct batadv_priv *bat_priv, char *name);
 int batadv_algo_seq_print_text(struct seq_file *seq, void *offset);
+__be32 batadv_skb_crc32(struct sk_buff *skb, u8 *payload_ptr);
 
-/* all messages related to routing / flooding / broadcasting / etc */
+/**
+ * enum batadv_dbg_level - available log levels
+ * @BATADV_DBG_BATMAN: OGM and TQ computations related messages
+ * @BATADV_DBG_ROUTES: route added / changed / deleted
+ * @BATADV_DBG_TT: translation table messages
+ * @BATADV_DBG_BLA: bridge loop avoidance messages
+ * @BATADV_DBG_DAT: ARP snooping and DAT related messages
+ * @BATADV_DBG_ALL: the union of all the above log levels
+ */
 enum batadv_dbg_level {
        BATADV_DBG_BATMAN = BIT(0),
-       BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */
-       BATADV_DBG_TT     = BIT(2), /* translation table operations */
-       BATADV_DBG_BLA    = BIT(3), /* bridge loop avoidance */
-       BATADV_DBG_ALL    = 15,
+       BATADV_DBG_ROUTES = BIT(1),
+       BATADV_DBG_TT     = BIT(2),
+       BATADV_DBG_BLA    = BIT(3),
+       BATADV_DBG_DAT    = BIT(4),
+       BATADV_DBG_ALL    = 31,
 };
 
 #ifdef CONFIG_BATMAN_ADV_DEBUG
index ac9bdf8f80a63360a9b5bec6069a6222e17db881..8c32cf1c2deca7177945a804afcdf6ad10572ee5 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include "main.h"
+#include "distributed-arp-table.h"
 #include "originator.h"
 #include "hash.h"
 #include "translation-table.h"
@@ -220,9 +221,9 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
        atomic_set(&orig_node->refcount, 2);
 
        orig_node->tt_initialised = false;
-       orig_node->tt_poss_change = false;
        orig_node->bat_priv = bat_priv;
        memcpy(orig_node->orig, addr, ETH_ALEN);
+       batadv_dat_init_orig_node_addr(orig_node);
        orig_node->router = NULL;
        orig_node->tt_crc = 0;
        atomic_set(&orig_node->last_ttvn, 0);
@@ -415,23 +416,10 @@ int batadv_orig_seq_print_text(struct seq_file *seq, void *offset)
        int last_seen_msecs;
        unsigned long last_seen_jiffies;
        uint32_t i;
-       int ret = 0;
 
-       primary_if = batadv_primary_if_get_selected(bat_priv);
-
-       if (!primary_if) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-                                net_dev->name);
-               goto out;
-       }
-
-       if (primary_if->if_status != BATADV_IF_ACTIVE) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - primary interface not active\n",
-                                net_dev->name);
+       primary_if = batadv_seq_print_text_primary_if_get(seq);
+       if (!primary_if)
                goto out;
-       }
 
        seq_printf(seq, "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%pM (%s)]\n",
                   BATADV_SOURCE_VERSION, primary_if->net_dev->name,
@@ -485,7 +473,7 @@ next:
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       return ret;
+       return 0;
 }
 
 static int batadv_orig_node_add_if(struct batadv_orig_node *orig_node,
index 2d23a14c220eb281a839c58650fb9a70802bb415..cb6405bf755cdbdf24b005b38416999e9ec38e19 100644 (file)
 #ifndef _NET_BATMAN_ADV_PACKET_H_
 #define _NET_BATMAN_ADV_PACKET_H_
 
-#define BATADV_ETH_P_BATMAN  0x4305 /* unofficial/not registered Ethertype */
-
 enum batadv_packettype {
-       BATADV_IV_OGM       = 0x01,
-       BATADV_ICMP         = 0x02,
-       BATADV_UNICAST      = 0x03,
-       BATADV_BCAST        = 0x04,
-       BATADV_VIS          = 0x05,
-       BATADV_UNICAST_FRAG = 0x06,
-       BATADV_TT_QUERY     = 0x07,
-       BATADV_ROAM_ADV     = 0x08,
+       BATADV_IV_OGM           = 0x01,
+       BATADV_ICMP             = 0x02,
+       BATADV_UNICAST          = 0x03,
+       BATADV_BCAST            = 0x04,
+       BATADV_VIS              = 0x05,
+       BATADV_UNICAST_FRAG     = 0x06,
+       BATADV_TT_QUERY         = 0x07,
+       BATADV_ROAM_ADV         = 0x08,
+       BATADV_UNICAST_4ADDR    = 0x09,
+};
+
+/**
+ * enum batadv_subtype - packet subtype for unicast4addr
+ * @BATADV_P_DATA: user payload
+ * @BATADV_P_DAT_DHT_GET: DHT request message
+ * @BATADV_P_DAT_DHT_PUT: DHT store message
+ * @BATADV_P_DAT_CACHE_REPLY: ARP reply generated by DAT
+ */
+enum batadv_subtype {
+       BATADV_P_DATA                   = 0x01,
+       BATADV_P_DAT_DHT_GET            = 0x02,
+       BATADV_P_DAT_DHT_PUT            = 0x03,
+       BATADV_P_DAT_CACHE_REPLY        = 0x04,
 };
 
 /* this file is included by batctl which needs these defines */
@@ -106,13 +119,16 @@ struct batadv_bla_claim_dst {
        uint8_t magic[3];       /* FF:43:05 */
        uint8_t type;           /* bla_claimframe */
        __be16 group;           /* group id */
-} __packed;
+};
 
 struct batadv_header {
        uint8_t  packet_type;
        uint8_t  version;  /* batman version field */
        uint8_t  ttl;
-} __packed;
+       /* the parent struct has to add a byte after the header to make
+        * everything 4 bytes aligned again
+        */
+};
 
 struct batadv_ogm_packet {
        struct batadv_header header;
@@ -137,7 +153,7 @@ struct batadv_icmp_packet {
        __be16   seqno;
        uint8_t  uid;
        uint8_t  reserved;
-} __packed;
+};
 
 #define BATADV_RR_LEN 16
 
@@ -153,13 +169,44 @@ struct batadv_icmp_packet_rr {
        uint8_t  uid;
        uint8_t  rr_cur;
        uint8_t  rr[BATADV_RR_LEN][ETH_ALEN];
-} __packed;
+};
+
+/* All packet headers in front of an ethernet header have to be completely
+ * divisible by 2 but not by 4 to make the payload after the ethernet
+ * header again 4 bytes boundary aligned.
+ *
+ * A packing of 2 is necessary to avoid extra padding at the end of the struct
+ * caused by a structure member which is larger than two bytes. Otherwise
+ * the structure would not fulfill the previously mentioned rule to avoid the
+ * misalignment of the payload after the ethernet header. It may also lead to
+ * leakage of information when the padding it not initialized before sending.
+ */
+#pragma pack(2)
 
 struct batadv_unicast_packet {
        struct batadv_header header;
        uint8_t  ttvn; /* destination translation table version number */
        uint8_t  dest[ETH_ALEN];
-} __packed;
+       /* "4 bytes boundary + 2 bytes" long to make the payload after the
+        * following ethernet header again 4 bytes boundary aligned
+        */
+};
+
+/**
+ * struct batadv_unicast_4addr_packet - extended unicast packet
+ * @u: common unicast packet header
+ * @src: address of the source
+ * @subtype: packet subtype
+ */
+struct batadv_unicast_4addr_packet {
+       struct batadv_unicast_packet u;
+       uint8_t src[ETH_ALEN];
+       uint8_t subtype;
+       uint8_t reserved;
+       /* "4 bytes boundary + 2 bytes" long to make the payload after the
+        * following ethernet header again 4 bytes boundary aligned
+        */
+};
 
 struct batadv_unicast_frag_packet {
        struct batadv_header header;
@@ -176,7 +223,12 @@ struct batadv_bcast_packet {
        uint8_t  reserved;
        __be32   seqno;
        uint8_t  orig[ETH_ALEN];
-} __packed;
+       /* "4 bytes boundary + 2 bytes" long to make the payload after the
+        * following ethernet header again 4 bytes boundary aligned
+        */
+};
+
+#pragma pack()
 
 struct batadv_vis_packet {
        struct batadv_header header;
@@ -187,7 +239,7 @@ struct batadv_vis_packet {
        uint8_t  vis_orig[ETH_ALEN];    /* originator reporting its neighbors */
        uint8_t  target_orig[ETH_ALEN]; /* who should receive this packet */
        uint8_t  sender_orig[ETH_ALEN]; /* who sent or forwarded this packet */
-} __packed;
+};
 
 struct batadv_tt_query_packet {
        struct batadv_header header;
index 939fc01371dff0c209665b297b69ec6502887b1a..1aa1722d01870d69738f6be60a7e7868882cab88 100644 (file)
@@ -28,6 +28,7 @@
 #include "vis.h"
 #include "unicast.h"
 #include "bridge_loop_avoidance.h"
+#include "distributed-arp-table.h"
 
 static int batadv_route_unicast_packet(struct sk_buff *skb,
                                       struct batadv_hard_iface *recv_if);
@@ -284,7 +285,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
 {
        struct batadv_hard_iface *primary_if = NULL;
        struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *router = NULL;
        struct batadv_icmp_packet_rr *icmp_packet;
        int ret = NET_RX_DROP;
 
@@ -306,10 +306,6 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
-               goto out;
-
        /* create a copy of the skb, if needed, to modify it. */
        if (skb_cow(skb, ETH_HLEN) < 0)
                goto out;
@@ -321,14 +317,12 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
        icmp_packet->msg_type = BATADV_ECHO_REPLY;
        icmp_packet->header.ttl = BATADV_TTL;
 
-       batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-       ret = NET_RX_SUCCESS;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = NET_RX_SUCCESS;
 
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       if (router)
-               batadv_neigh_node_free_ref(router);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
        return ret;
@@ -339,7 +333,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 {
        struct batadv_hard_iface *primary_if = NULL;
        struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *router = NULL;
        struct batadv_icmp_packet *icmp_packet;
        int ret = NET_RX_DROP;
 
@@ -361,10 +354,6 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
-               goto out;
-
        /* create a copy of the skb, if needed, to modify it. */
        if (skb_cow(skb, ETH_HLEN) < 0)
                goto out;
@@ -376,14 +365,12 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
        icmp_packet->msg_type = BATADV_TTL_EXCEEDED;
        icmp_packet->header.ttl = BATADV_TTL;
 
-       batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-       ret = NET_RX_SUCCESS;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = NET_RX_SUCCESS;
 
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       if (router)
-               batadv_neigh_node_free_ref(router);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
        return ret;
@@ -397,7 +384,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        struct batadv_icmp_packet_rr *icmp_packet;
        struct ethhdr *ethhdr;
        struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *router = NULL;
        int hdr_size = sizeof(struct batadv_icmp_packet);
        int ret = NET_RX_DROP;
 
@@ -446,10 +432,6 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
-               goto out;
-
        /* create a copy of the skb, if needed, to modify it. */
        if (skb_cow(skb, ETH_HLEN) < 0)
                goto out;
@@ -460,12 +442,10 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
        icmp_packet->header.ttl--;
 
        /* route it */
-       batadv_send_skb_packet(skb, router->if_incoming, router->addr);
-       ret = NET_RX_SUCCESS;
+       if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+               ret = NET_RX_SUCCESS;
 
 out:
-       if (router)
-               batadv_neigh_node_free_ref(router);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
        return ret;
@@ -549,25 +529,18 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig,
                if (tmp_neigh_node->if_incoming == recv_if)
                        continue;
 
-               if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+               if (router && tmp_neigh_node->tq_avg <= router->tq_avg)
                        continue;
 
-               /* if we don't have a router yet
-                * or this one is better, choose it.
-                */
-               if ((!router) ||
-                   (tmp_neigh_node->tq_avg > router->tq_avg)) {
-                       /* decrement refcount of
-                        * previously selected router
-                        */
-                       if (router)
-                               batadv_neigh_node_free_ref(router);
+               if (!atomic_inc_not_zero(&tmp_neigh_node->refcount))
+                       continue;
 
-                       router = tmp_neigh_node;
-                       atomic_inc_not_zero(&router->refcount);
-               }
+               /* decrement refcount of previously selected router */
+               if (router)
+                       batadv_neigh_node_free_ref(router);
 
-               batadv_neigh_node_free_ref(tmp_neigh_node);
+               /* we found a better router (or at least one valid router) */
+               router = tmp_neigh_node;
        }
 
        /* use the first candidate if nothing was found. */
@@ -687,21 +660,8 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
        struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
        struct batadv_roam_adv_packet *roam_adv_packet;
        struct batadv_orig_node *orig_node;
-       struct ethhdr *ethhdr;
 
-       /* drop packet if it has not necessary minimum size */
-       if (unlikely(!pskb_may_pull(skb,
-                                   sizeof(struct batadv_roam_adv_packet))))
-               goto out;
-
-       ethhdr = (struct ethhdr *)skb_mac_header(skb);
-
-       /* packet with unicast indication but broadcast recipient */
-       if (is_broadcast_ether_addr(ethhdr->h_dest))
-               goto out;
-
-       /* packet with broadcast sender address */
-       if (is_broadcast_ether_addr(ethhdr->h_source))
+       if (batadv_check_unicast_packet(skb, sizeof(*roam_adv_packet)) < 0)
                goto out;
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_RX);
@@ -730,12 +690,6 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if)
                             BATADV_TT_CLIENT_ROAM,
                             atomic_read(&orig_node->last_ttvn) + 1);
 
-       /* Roaming phase starts: I have new information but the ttvn has not
-        * been incremented yet. This flag will make me check all the incoming
-        * packets for the correct destination.
-        */
-       bat_priv->tt.poss_change = true;
-
        batadv_orig_node_free_ref(orig_node);
 out:
        /* returning NET_RX_DROP will make the caller function kfree the skb */
@@ -907,8 +861,8 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
                           skb->len + ETH_HLEN);
 
        /* route it */
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = NET_RX_SUCCESS;
+       if (batadv_send_skb_to_orig(skb, orig_node, recv_if))
+               ret = NET_RX_SUCCESS;
 
 out:
        if (neigh_node)
@@ -918,80 +872,161 @@ out:
        return ret;
 }
 
+/**
+ * batadv_reroute_unicast_packet - update the unicast header for re-routing
+ * @bat_priv: the bat priv with all the soft interface information
+ * @unicast_packet: the unicast header to be updated
+ * @dst_addr: the payload destination
+ *
+ * Search the translation table for dst_addr and update the unicast header with
+ * the new corresponding information (originator address where the destination
+ * client currently is and its known TTVN)
+ *
+ * Returns true if the packet header has been updated, false otherwise
+ */
+static bool
+batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
+                             struct batadv_unicast_packet *unicast_packet,
+                             uint8_t *dst_addr)
+{
+       struct batadv_orig_node *orig_node = NULL;
+       struct batadv_hard_iface *primary_if = NULL;
+       bool ret = false;
+       uint8_t *orig_addr, orig_ttvn;
+
+       if (batadv_is_my_client(bat_priv, dst_addr)) {
+               primary_if = batadv_primary_if_get_selected(bat_priv);
+               if (!primary_if)
+                       goto out;
+               orig_addr = primary_if->net_dev->dev_addr;
+               orig_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
+       } else {
+               orig_node = batadv_transtable_search(bat_priv, NULL, dst_addr);
+               if (!orig_node)
+                       goto out;
+
+               if (batadv_compare_eth(orig_node->orig, unicast_packet->dest))
+                       goto out;
+
+               orig_addr = orig_node->orig;
+               orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+       }
+
+       /* update the packet header */
+       memcpy(unicast_packet->dest, orig_addr, ETH_ALEN);
+       unicast_packet->ttvn = orig_ttvn;
+
+       ret = true;
+out:
+       if (primary_if)
+               batadv_hardif_free_ref(primary_if);
+       if (orig_node)
+               batadv_orig_node_free_ref(orig_node);
+
+       return ret;
+}
+
 static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
                                     struct sk_buff *skb) {
-       uint8_t curr_ttvn;
+       uint8_t curr_ttvn, old_ttvn;
        struct batadv_orig_node *orig_node;
        struct ethhdr *ethhdr;
        struct batadv_hard_iface *primary_if;
        struct batadv_unicast_packet *unicast_packet;
-       bool tt_poss_change;
        int is_old_ttvn;
 
-       /* I could need to modify it */
-       if (skb_cow(skb, sizeof(struct batadv_unicast_packet)) < 0)
+       /* check if there is enough data before accessing it */
+       if (pskb_may_pull(skb, sizeof(*unicast_packet) + ETH_HLEN) < 0)
+               return 0;
+
+       /* create a copy of the skb (in case of for re-routing) to modify it. */
+       if (skb_cow(skb, sizeof(*unicast_packet)) < 0)
                return 0;
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
+       ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet));
 
-       if (batadv_is_my_mac(unicast_packet->dest)) {
-               tt_poss_change = bat_priv->tt.poss_change;
-               curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
-       } else {
+       /* check if the destination client was served by this node and it is now
+        * roaming. In this case, it means that the node has got a ROAM_ADV
+        * message and that it knows the new destination in the mesh to re-route
+        * the packet to
+        */
+       if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest)) {
+               if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
+                                                 ethhdr->h_dest))
+                       net_ratelimited_function(batadv_dbg, BATADV_DBG_TT,
+                                                bat_priv,
+                                                "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n",
+                                                unicast_packet->dest,
+                                                ethhdr->h_dest);
+               /* at this point the mesh destination should have been
+                * substituted with the originator address found in the global
+                * table. If not, let the packet go untouched anyway because
+                * there is nothing the node can do
+                */
+               return 1;
+       }
+
+       /* retrieve the TTVN known by this node for the packet destination. This
+        * value is used later to check if the node which sent (or re-routed
+        * last time) the packet had an updated information or not
+        */
+       curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn);
+       if (!batadv_is_my_mac(unicast_packet->dest)) {
                orig_node = batadv_orig_hash_find(bat_priv,
                                                  unicast_packet->dest);
-
+               /* if it is not possible to find the orig_node representing the
+                * destination, the packet can immediately be dropped as it will
+                * not be possible to deliver it
+                */
                if (!orig_node)
                        return 0;
 
                curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
-               tt_poss_change = orig_node->tt_poss_change;
                batadv_orig_node_free_ref(orig_node);
        }
 
-       /* Check whether I have to reroute the packet */
+       /* check if the TTVN contained in the packet is fresher than what the
+        * node knows
+        */
        is_old_ttvn = batadv_seq_before(unicast_packet->ttvn, curr_ttvn);
-       if (is_old_ttvn || tt_poss_change) {
-               /* check if there is enough data before accessing it */
-               if (pskb_may_pull(skb, sizeof(struct batadv_unicast_packet) +
-                                 ETH_HLEN) < 0)
-                       return 0;
+       if (!is_old_ttvn)
+               return 1;
 
-               ethhdr = (struct ethhdr *)(skb->data + sizeof(*unicast_packet));
+       old_ttvn = unicast_packet->ttvn;
+       /* the packet was forged based on outdated network information. Its
+        * destination can possibly be updated and forwarded towards the new
+        * target host
+        */
+       if (batadv_reroute_unicast_packet(bat_priv, unicast_packet,
+                                         ethhdr->h_dest)) {
+               net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv,
+                                        "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n",
+                                        unicast_packet->dest, ethhdr->h_dest,
+                                        old_ttvn, curr_ttvn);
+               return 1;
+       }
 
-               /* we don't have an updated route for this client, so we should
-                * not try to reroute the packet!!
-                */
-               if (batadv_tt_global_client_is_roaming(bat_priv,
-                                                      ethhdr->h_dest))
-                       return 1;
+       /* the packet has not been re-routed: either the destination is
+        * currently served by this node or there is no destination at all and
+        * it is possible to drop the packet
+        */
+       if (!batadv_is_my_client(bat_priv, ethhdr->h_dest))
+               return 0;
 
-               orig_node = batadv_transtable_search(bat_priv, NULL,
-                                                    ethhdr->h_dest);
-
-               if (!orig_node) {
-                       if (!batadv_is_my_client(bat_priv, ethhdr->h_dest))
-                               return 0;
-                       primary_if = batadv_primary_if_get_selected(bat_priv);
-                       if (!primary_if)
-                               return 0;
-                       memcpy(unicast_packet->dest,
-                              primary_if->net_dev->dev_addr, ETH_ALEN);
-                       batadv_hardif_free_ref(primary_if);
-               } else {
-                       memcpy(unicast_packet->dest, orig_node->orig,
-                              ETH_ALEN);
-                       curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
-                       batadv_orig_node_free_ref(orig_node);
-               }
+       /* update the header in order to let the packet be delivered to this
+        * node's soft interface
+        */
+       primary_if = batadv_primary_if_get_selected(bat_priv);
+       if (!primary_if)
+               return 0;
 
-               batadv_dbg(BATADV_DBG_ROUTES, bat_priv,
-                          "TTVN mismatch (old_ttvn %u new_ttvn %u)! Rerouting unicast packet (for %pM) to %pM\n",
-                          unicast_packet->ttvn, curr_ttvn, ethhdr->h_dest,
-                          unicast_packet->dest);
+       memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN);
+
+       batadv_hardif_free_ref(primary_if);
+
+       unicast_packet->ttvn = curr_ttvn;
 
-               unicast_packet->ttvn = curr_ttvn;
-       }
        return 1;
 }
 
@@ -1000,7 +1035,19 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
 {
        struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface);
        struct batadv_unicast_packet *unicast_packet;
+       struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+       uint8_t *orig_addr;
+       struct batadv_orig_node *orig_node = NULL;
        int hdr_size = sizeof(*unicast_packet);
+       bool is4addr;
+
+       unicast_packet = (struct batadv_unicast_packet *)skb->data;
+       unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+
+       is4addr = unicast_packet->header.packet_type == BATADV_UNICAST_4ADDR;
+       /* the caller function should have already pulled 2 bytes */
+       if (is4addr)
+               hdr_size = sizeof(*unicast_4addr_packet);
 
        if (batadv_check_unicast_packet(skb, hdr_size) < 0)
                return NET_RX_DROP;
@@ -1008,12 +1055,28 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
        if (!batadv_check_unicast_ttvn(bat_priv, skb))
                return NET_RX_DROP;
 
-       unicast_packet = (struct batadv_unicast_packet *)skb->data;
-
        /* packet for me */
        if (batadv_is_my_mac(unicast_packet->dest)) {
+               if (is4addr) {
+                       batadv_dat_inc_counter(bat_priv,
+                                              unicast_4addr_packet->subtype);
+                       orig_addr = unicast_4addr_packet->src;
+                       orig_node = batadv_orig_hash_find(bat_priv, orig_addr);
+               }
+
+               if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb,
+                                                         hdr_size))
+                       goto rx_success;
+               if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb,
+                                                       hdr_size))
+                       goto rx_success;
+
                batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
-                                   NULL);
+                                   orig_node);
+
+rx_success:
+               if (orig_node)
+                       batadv_orig_node_free_ref(orig_node);
 
                return NET_RX_SUCCESS;
        }
@@ -1050,8 +1113,17 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb,
                if (!new_skb)
                        return NET_RX_SUCCESS;
 
+               if (batadv_dat_snoop_incoming_arp_request(bat_priv, new_skb,
+                                                         hdr_size))
+                       goto rx_success;
+               if (batadv_dat_snoop_incoming_arp_reply(bat_priv, new_skb,
+                                                       hdr_size))
+                       goto rx_success;
+
                batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if,
                                    sizeof(struct batadv_unicast_packet), NULL);
+
+rx_success:
                return NET_RX_SUCCESS;
        }
 
@@ -1125,7 +1197,7 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        spin_unlock_bh(&orig_node->bcast_seqno_lock);
 
        /* check whether this has been sent by another originator before */
-       if (batadv_bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size))
+       if (batadv_bla_check_bcast_duplist(bat_priv, skb))
                goto out;
 
        /* rebroadcast packet */
@@ -1137,9 +1209,16 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
        if (batadv_bla_is_backbone_gw(skb, orig_node, hdr_size))
                goto out;
 
+       if (batadv_dat_snoop_incoming_arp_request(bat_priv, skb, hdr_size))
+               goto rx_success;
+       if (batadv_dat_snoop_incoming_arp_reply(bat_priv, skb, hdr_size))
+               goto rx_success;
+
        /* broadcast for me */
        batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size,
                            orig_node);
+
+rx_success:
        ret = NET_RX_SUCCESS;
        goto out;
 
index 570a8bce0364ea08ea45341b57b362a72beedc45..4425af9dad40e2b9698f48c576c27042c13a8dbb 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include "main.h"
+#include "distributed-arp-table.h"
 #include "send.h"
 #include "routing.h"
 #include "translation-table.h"
@@ -27,6 +28,8 @@
 #include "gateway_common.h"
 #include "originator.h"
 
+#include <linux/if_ether.h>
+
 static void batadv_send_outstanding_bcast_packet(struct work_struct *work);
 
 /* send out an already prepared packet to the given address via the
@@ -59,11 +62,11 @@ int batadv_send_skb_packet(struct sk_buff *skb,
        ethhdr = (struct ethhdr *)skb_mac_header(skb);
        memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN);
        memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN);
-       ethhdr->h_proto = __constant_htons(BATADV_ETH_P_BATMAN);
+       ethhdr->h_proto = __constant_htons(ETH_P_BATMAN);
 
        skb_set_network_header(skb, ETH_HLEN);
        skb->priority = TC_PRIO_CONTROL;
-       skb->protocol = __constant_htons(BATADV_ETH_P_BATMAN);
+       skb->protocol = __constant_htons(ETH_P_BATMAN);
 
        skb->dev = hard_iface->net_dev;
 
@@ -77,6 +80,39 @@ send_skb_err:
        return NET_XMIT_DROP;
 }
 
+/**
+ * batadv_send_skb_to_orig - Lookup next-hop and transmit skb.
+ * @skb: Packet to be transmitted.
+ * @orig_node: Final destination of the packet.
+ * @recv_if: Interface used when receiving the packet (can be NULL).
+ *
+ * Looks up the best next-hop towards the passed originator and passes the
+ * skb on for preparation of MAC header. If the packet originated from this
+ * host, NULL can be passed as recv_if and no interface alternating is
+ * attempted.
+ *
+ * Returns TRUE on success; FALSE otherwise.
+ */
+bool batadv_send_skb_to_orig(struct sk_buff *skb,
+                            struct batadv_orig_node *orig_node,
+                            struct batadv_hard_iface *recv_if)
+{
+       struct batadv_priv *bat_priv = orig_node->bat_priv;
+       struct batadv_neigh_node *neigh_node;
+
+       /* batadv_find_router() increases neigh_nodes refcount if found. */
+       neigh_node = batadv_find_router(bat_priv, orig_node, recv_if);
+       if (!neigh_node)
+               return false;
+
+       /* route it */
+       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
+
+       batadv_neigh_node_free_ref(neigh_node);
+
+       return true;
+}
+
 void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface)
 {
        struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
@@ -209,6 +245,9 @@ static void batadv_send_outstanding_bcast_packet(struct work_struct *work)
        if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
                goto out;
 
+       if (batadv_dat_drop_broadcast_packet(bat_priv, forw_packet))
+               goto out;
+
        /* rebroadcast packet */
        rcu_read_lock();
        list_for_each_entry_rcu(hard_iface, &batadv_hardif_list, list) {
index 643329b787ed125102beb687ad1f18c1b4a0ca8e..0078dece1abcd4cf6784b59cf5441ac150424330 100644 (file)
@@ -23,6 +23,9 @@
 int batadv_send_skb_packet(struct sk_buff *skb,
                           struct batadv_hard_iface *hard_iface,
                           const uint8_t *dst_addr);
+bool batadv_send_skb_to_orig(struct sk_buff *skb,
+                            struct batadv_orig_node *orig_node,
+                            struct batadv_hard_iface *recv_if);
 void batadv_schedule_bat_ogm(struct batadv_hard_iface *hard_iface);
 int batadv_add_bcast_packet_to_list(struct batadv_priv *bat_priv,
                                    const struct sk_buff *skb,
index b9a28d2dd3e8d907526ebd51dfedba9e993fd526..6b548fde8e0435fece3a67f9ea0f94a1f8aae693 100644 (file)
@@ -20,6 +20,7 @@
 #include "main.h"
 #include "soft-interface.h"
 #include "hard-interface.h"
+#include "distributed-arp-table.h"
 #include "routing.h"
 #include "send.h"
 #include "debugfs.h"
@@ -33,6 +34,7 @@
 #include <linux/ethtool.h>
 #include <linux/etherdevice.h>
 #include <linux/if_vlan.h>
+#include <linux/if_ether.h>
 #include "unicast.h"
 #include "bridge_loop_avoidance.h"
 
@@ -145,14 +147,17 @@ static int batadv_interface_tx(struct sk_buff *skb,
        struct batadv_hard_iface *primary_if = NULL;
        struct batadv_bcast_packet *bcast_packet;
        struct vlan_ethhdr *vhdr;
-       __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
-       static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00, 0x00,
-                                                  0x00};
+       __be16 ethertype = __constant_htons(ETH_P_BATMAN);
+       static const uint8_t stp_addr[ETH_ALEN] = {0x01, 0x80, 0xC2, 0x00,
+                                                  0x00, 0x00};
+       static const uint8_t ectp_addr[ETH_ALEN] = {0xCF, 0x00, 0x00, 0x00,
+                                                   0x00, 0x00};
        unsigned int header_len = 0;
        int data_len = skb->len, ret;
        short vid __maybe_unused = -1;
        bool do_bcast = false;
        uint32_t seqno;
+       unsigned long brd_delay = 1;
 
        if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE)
                goto dropped;
@@ -168,7 +173,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
                        break;
 
                /* fall through */
-       case BATADV_ETH_P_BATMAN:
+       case ETH_P_BATMAN:
                goto dropped;
        }
 
@@ -180,10 +185,16 @@ static int batadv_interface_tx(struct sk_buff *skb,
 
        /* don't accept stp packets. STP does not help in meshes.
         * better use the bridge loop avoidance ...
+        *
+        * The same goes for ECTP sent at least by some Cisco Switches,
+        * it might confuse the mesh when used with bridge loop avoidance.
         */
        if (batadv_compare_eth(ethhdr->h_dest, stp_addr))
                goto dropped;
 
+       if (batadv_compare_eth(ethhdr->h_dest, ectp_addr))
+               goto dropped;
+
        if (is_multicast_ether_addr(ethhdr->h_dest)) {
                do_bcast = true;
 
@@ -216,6 +227,13 @@ static int batadv_interface_tx(struct sk_buff *skb,
                if (!primary_if)
                        goto dropped;
 
+               /* in case of ARP request, we do not immediately broadcasti the
+                * packet, instead we first wait for DAT to try to retrieve the
+                * correct ARP entry
+                */
+               if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
+                       brd_delay = msecs_to_jiffies(ARP_REQ_DELAY);
+
                if (batadv_skb_head_push(skb, sizeof(*bcast_packet)) < 0)
                        goto dropped;
 
@@ -237,7 +255,7 @@ static int batadv_interface_tx(struct sk_buff *skb,
                seqno = atomic_inc_return(&bat_priv->bcast_seqno);
                bcast_packet->seqno = htonl(seqno);
 
-               batadv_add_bcast_packet_to_list(bat_priv, skb, 1);
+               batadv_add_bcast_packet_to_list(bat_priv, skb, brd_delay);
 
                /* a copy is stored in the bcast list, therefore removing
                 * the original skb.
@@ -252,7 +270,12 @@ static int batadv_interface_tx(struct sk_buff *skb,
                                goto dropped;
                }
 
-               ret = batadv_unicast_send_skb(skb, bat_priv);
+               if (batadv_dat_snoop_outgoing_arp_request(bat_priv, skb))
+                       goto dropped;
+
+               batadv_dat_snoop_outgoing_arp_reply(bat_priv, skb);
+
+               ret = batadv_unicast_send_skb(bat_priv, skb);
                if (ret != 0)
                        goto dropped_freed;
        }
@@ -280,7 +303,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
        struct vlan_ethhdr *vhdr;
        struct batadv_header *batadv_header = (struct batadv_header *)skb->data;
        short vid __maybe_unused = -1;
-       __be16 ethertype = __constant_htons(BATADV_ETH_P_BATMAN);
+       __be16 ethertype = __constant_htons(ETH_P_BATMAN);
        bool is_bcast;
 
        is_bcast = (batadv_header->packet_type == BATADV_BCAST);
@@ -303,7 +326,7 @@ void batadv_interface_rx(struct net_device *soft_iface,
                        break;
 
                /* fall through */
-       case BATADV_ETH_P_BATMAN:
+       case ETH_P_BATMAN:
                goto dropped;
        }
 
@@ -325,6 +348,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
 
        soft_iface->last_rx = jiffies;
 
+       /* Let the bridge loop avoidance check the packet. If will
+        * not handle it, we can safely push it up.
+        */
+       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
+               goto out;
+
        if (orig_node)
                batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
                                                     ethhdr->h_source);
@@ -332,12 +361,6 @@ void batadv_interface_rx(struct net_device *soft_iface,
        if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
                goto dropped;
 
-       /* Let the bridge loop avoidance check the packet. If will
-        * not handle it, we can safely push it up.
-        */
-       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
-               goto out;
-
        netif_rx(skb);
        goto out;
 
@@ -347,7 +370,51 @@ out:
        return;
 }
 
+/* batman-adv network devices have devices nesting below it and are a special
+ * "super class" of normal network devices; split their locks off into a
+ * separate class since they always nest.
+ */
+static struct lock_class_key batadv_netdev_xmit_lock_key;
+static struct lock_class_key batadv_netdev_addr_lock_key;
+
+/**
+ * batadv_set_lockdep_class_one - Set lockdep class for a single tx queue
+ * @dev: device which owns the tx queue
+ * @txq: tx queue to modify
+ * @_unused: always NULL
+ */
+static void batadv_set_lockdep_class_one(struct net_device *dev,
+                                        struct netdev_queue *txq,
+                                        void *_unused)
+{
+       lockdep_set_class(&txq->_xmit_lock, &batadv_netdev_xmit_lock_key);
+}
+
+/**
+ * batadv_set_lockdep_class - Set txq and addr_list lockdep class
+ * @dev: network device to modify
+ */
+static void batadv_set_lockdep_class(struct net_device *dev)
+{
+       lockdep_set_class(&dev->addr_list_lock, &batadv_netdev_addr_lock_key);
+       netdev_for_each_tx_queue(dev, batadv_set_lockdep_class_one, NULL);
+}
+
+/**
+ * batadv_softif_init - Late stage initialization of soft interface
+ * @dev: registered network device to modify
+ *
+ * Returns error code on failures
+ */
+static int batadv_softif_init(struct net_device *dev)
+{
+       batadv_set_lockdep_class(dev);
+
+       return 0;
+}
+
 static const struct net_device_ops batadv_netdev_ops = {
+       .ndo_init = batadv_softif_init,
        .ndo_open = batadv_interface_open,
        .ndo_stop = batadv_interface_release,
        .ndo_get_stats = batadv_interface_stats,
@@ -414,6 +481,9 @@ struct net_device *batadv_softif_create(const char *name)
        atomic_set(&bat_priv->aggregated_ogms, 1);
        atomic_set(&bat_priv->bonding, 0);
        atomic_set(&bat_priv->bridge_loop_avoidance, 0);
+#ifdef CONFIG_BATMAN_ADV_DAT
+       atomic_set(&bat_priv->distributed_arp_table, 1);
+#endif
        atomic_set(&bat_priv->ap_isolation, 0);
        atomic_set(&bat_priv->vis_mode, BATADV_VIS_TYPE_CLIENT_UPDATE);
        atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF);
@@ -436,7 +506,6 @@ struct net_device *batadv_softif_create(const char *name)
 #endif
        bat_priv->tt.last_changeset = NULL;
        bat_priv->tt.last_changeset_len = 0;
-       bat_priv->tt.poss_change = false;
 
        bat_priv->primary_if = NULL;
        bat_priv->num_ifaces = 0;
@@ -556,6 +625,13 @@ static const struct {
        { "tt_response_rx" },
        { "tt_roam_adv_tx" },
        { "tt_roam_adv_rx" },
+#ifdef CONFIG_BATMAN_ADV_DAT
+       { "dat_get_tx" },
+       { "dat_get_rx" },
+       { "dat_put_tx" },
+       { "dat_put_rx" },
+       { "dat_cached_reply_tx" },
+#endif
 };
 
 static void batadv_get_strings(struct net_device *dev, uint32_t stringset,
index 66518c75c217459d39f7bc8e79aed34b25b20e22..84a55cb19b0b9b2d4e5c9f2d787bf916059556db 100644 (file)
@@ -20,6 +20,7 @@
 #include "main.h"
 #include "sysfs.h"
 #include "translation-table.h"
+#include "distributed-arp-table.h"
 #include "originator.h"
 #include "hard-interface.h"
 #include "gateway_common.h"
@@ -122,55 +123,6 @@ ssize_t batadv_show_##_name(struct kobject *kobj,                  \
                           batadv_store_##_name)
 
 
-#define BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)      \
-ssize_t batadv_store_##_name(struct kobject *kobj,                     \
-                            struct attribute *attr, char *buff,        \
-                            size_t count)                              \
-{                                                                      \
-       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
-       struct batadv_hard_iface *hard_iface;                           \
-       ssize_t length;                                                 \
-                                                                       \
-       hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
-       if (!hard_iface)                                                \
-               return 0;                                               \
-                                                                       \
-       length = __batadv_store_uint_attr(buff, count, _min, _max,      \
-                                         _post_func, attr,             \
-                                         &hard_iface->_name, net_dev); \
-                                                                       \
-       batadv_hardif_free_ref(hard_iface);                             \
-       return length;                                                  \
-}
-
-#define BATADV_ATTR_HIF_SHOW_UINT(_name)                               \
-ssize_t batadv_show_##_name(struct kobject *kobj,                      \
-                           struct attribute *attr, char *buff)         \
-{                                                                      \
-       struct net_device *net_dev = batadv_kobj_to_netdev(kobj);       \
-       struct batadv_hard_iface *hard_iface;                           \
-       ssize_t length;                                                 \
-                                                                       \
-       hard_iface = batadv_hardif_get_by_netdev(net_dev);              \
-       if (!hard_iface)                                                \
-               return 0;                                               \
-                                                                       \
-       length = sprintf(buff, "%i\n", atomic_read(&hard_iface->_name));\
-                                                                       \
-       batadv_hardif_free_ref(hard_iface);                             \
-       return length;                                                  \
-}
-
-/* Use this, if you are going to set [name] in hard_iface to an
- * unsigned integer value
- */
-#define BATADV_ATTR_HIF_UINT(_name, _mode, _min, _max, _post_func)     \
-       static BATADV_ATTR_HIF_STORE_UINT(_name, _min, _max, _post_func)\
-       static BATADV_ATTR_HIF_SHOW_UINT(_name)                         \
-       static BATADV_ATTR(_name, _mode, batadv_show_##_name,           \
-                          batadv_store_##_name)
-
-
 static int batadv_store_bool_attr(char *buff, size_t count,
                                  struct net_device *net_dev,
                                  const char *attr_name, atomic_t *attr)
@@ -469,6 +421,9 @@ BATADV_ATTR_SIF_BOOL(bonding, S_IRUGO | S_IWUSR, NULL);
 #ifdef CONFIG_BATMAN_ADV_BLA
 BATADV_ATTR_SIF_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL);
 #endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+BATADV_ATTR_SIF_BOOL(distributed_arp_table, S_IRUGO | S_IWUSR, NULL);
+#endif
 BATADV_ATTR_SIF_BOOL(fragmentation, S_IRUGO | S_IWUSR, batadv_update_min_mtu);
 BATADV_ATTR_SIF_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL);
 static BATADV_ATTR(vis_mode, S_IRUGO | S_IWUSR, batadv_show_vis_mode,
@@ -493,6 +448,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = {
        &batadv_attr_bonding,
 #ifdef CONFIG_BATMAN_ADV_BLA
        &batadv_attr_bridge_loop_avoidance,
+#endif
+#ifdef CONFIG_BATMAN_ADV_DAT
+       &batadv_attr_distributed_arp_table,
 #endif
        &batadv_attr_fragmentation,
        &batadv_attr_ap_isolation,
@@ -730,7 +688,7 @@ int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type,
                        enum batadv_uev_action action, const char *data)
 {
        int ret = -ENOMEM;
-       struct batadv_hard_iface *primary_if = NULL;
+       struct batadv_hard_iface *primary_if;
        struct kobject *bat_kobj;
        char *uevent_env[4] = { NULL, NULL, NULL, NULL };
 
index 112edd371b2f81c79f431c6e99402165405c1b10..22457a7952baae3fc85c3ce43bd14bbeb5acf068 100644 (file)
@@ -238,92 +238,134 @@ static int batadv_tt_local_init(struct batadv_priv *bat_priv)
        return 0;
 }
 
+static void batadv_tt_global_free(struct batadv_priv *bat_priv,
+                                 struct batadv_tt_global_entry *tt_global,
+                                 const char *message)
+{
+       batadv_dbg(BATADV_DBG_TT, bat_priv,
+                  "Deleting global tt entry %pM: %s\n",
+                  tt_global->common.addr, message);
+
+       batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
+                          batadv_choose_orig, tt_global->common.addr);
+       batadv_tt_global_entry_free_ref(tt_global);
+
+}
+
 void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
                         int ifindex)
 {
        struct batadv_priv *bat_priv = netdev_priv(soft_iface);
-       struct batadv_tt_local_entry *tt_local_entry = NULL;
-       struct batadv_tt_global_entry *tt_global_entry = NULL;
+       struct batadv_tt_local_entry *tt_local;
+       struct batadv_tt_global_entry *tt_global;
        struct hlist_head *head;
        struct hlist_node *node;
        struct batadv_tt_orig_list_entry *orig_entry;
        int hash_added;
+       bool roamed_back = false;
 
-       tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
+       tt_local = batadv_tt_local_hash_find(bat_priv, addr);
+       tt_global = batadv_tt_global_hash_find(bat_priv, addr);
 
-       if (tt_local_entry) {
-               tt_local_entry->last_seen = jiffies;
-               /* possibly unset the BATADV_TT_CLIENT_PENDING flag */
-               tt_local_entry->common.flags &= ~BATADV_TT_CLIENT_PENDING;
-               goto out;
+       if (tt_local) {
+               tt_local->last_seen = jiffies;
+               if (tt_local->common.flags & BATADV_TT_CLIENT_PENDING) {
+                       batadv_dbg(BATADV_DBG_TT, bat_priv,
+                                  "Re-adding pending client %pM\n", addr);
+                       /* whatever the reason why the PENDING flag was set,
+                        * this is a client which was enqueued to be removed in
+                        * this orig_interval. Since it popped up again, the
+                        * flag can be reset like it was never enqueued
+                        */
+                       tt_local->common.flags &= ~BATADV_TT_CLIENT_PENDING;
+                       goto add_event;
+               }
+
+               if (tt_local->common.flags & BATADV_TT_CLIENT_ROAM) {
+                       batadv_dbg(BATADV_DBG_TT, bat_priv,
+                                  "Roaming client %pM came back to its original location\n",
+                                  addr);
+                       /* the ROAM flag is set because this client roamed away
+                        * and the node got a roaming_advertisement message. Now
+                        * that the client popped up again at its original
+                        * location such flag can be unset
+                        */
+                       tt_local->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+                       roamed_back = true;
+               }
+               goto check_roaming;
        }
 
-       tt_local_entry = kmalloc(sizeof(*tt_local_entry), GFP_ATOMIC);
-       if (!tt_local_entry)
+       tt_local = kmalloc(sizeof(*tt_local), GFP_ATOMIC);
+       if (!tt_local)
                goto out;
 
        batadv_dbg(BATADV_DBG_TT, bat_priv,
                   "Creating new local tt entry: %pM (ttvn: %d)\n", addr,
                   (uint8_t)atomic_read(&bat_priv->tt.vn));
 
-       memcpy(tt_local_entry->common.addr, addr, ETH_ALEN);
-       tt_local_entry->common.flags = BATADV_NO_FLAGS;
+       memcpy(tt_local->common.addr, addr, ETH_ALEN);
+       tt_local->common.flags = BATADV_NO_FLAGS;
        if (batadv_is_wifi_iface(ifindex))
-               tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI;
-       atomic_set(&tt_local_entry->common.refcount, 2);
-       tt_local_entry->last_seen = jiffies;
-       tt_local_entry->common.added_at = tt_local_entry->last_seen;
+               tt_local->common.flags |= BATADV_TT_CLIENT_WIFI;
+       atomic_set(&tt_local->common.refcount, 2);
+       tt_local->last_seen = jiffies;
+       tt_local->common.added_at = tt_local->last_seen;
 
        /* the batman interface mac address should never be purged */
        if (batadv_compare_eth(addr, soft_iface->dev_addr))
-               tt_local_entry->common.flags |= BATADV_TT_CLIENT_NOPURGE;
+               tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE;
 
        /* The local entry has to be marked as NEW to avoid to send it in
         * a full table response going out before the next ttvn increment
         * (consistency check)
         */
-       tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW;
+       tt_local->common.flags |= BATADV_TT_CLIENT_NEW;
 
        hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt,
-                                    batadv_choose_orig,
-                                    &tt_local_entry->common,
-                                    &tt_local_entry->common.hash_entry);
+                                    batadv_choose_orig, &tt_local->common,
+                                    &tt_local->common.hash_entry);
 
        if (unlikely(hash_added != 0)) {
                /* remove the reference for the hash */
-               batadv_tt_local_entry_free_ref(tt_local_entry);
+               batadv_tt_local_entry_free_ref(tt_local);
                goto out;
        }
 
-       batadv_tt_local_event(bat_priv, addr, tt_local_entry->common.flags);
-
-       /* remove address from global hash if present */
-       tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
+add_event:
+       batadv_tt_local_event(bat_priv, addr, tt_local->common.flags);
 
-       /* Check whether it is a roaming! */
-       if (tt_global_entry) {
+check_roaming:
+       /* Check whether it is a roaming, but don't do anything if the roaming
+        * process has already been handled
+        */
+       if (tt_global && !(tt_global->common.flags & BATADV_TT_CLIENT_ROAM)) {
                /* These node are probably going to update their tt table */
-               head = &tt_global_entry->orig_list;
+               head = &tt_global->orig_list;
                rcu_read_lock();
                hlist_for_each_entry_rcu(orig_entry, node, head, list) {
-                       orig_entry->orig_node->tt_poss_change = true;
-
-                       batadv_send_roam_adv(bat_priv,
-                                            tt_global_entry->common.addr,
+                       batadv_send_roam_adv(bat_priv, tt_global->common.addr,
                                             orig_entry->orig_node);
                }
                rcu_read_unlock();
-               /* The global entry has to be marked as ROAMING and
-                * has to be kept for consistency purpose
-                */
-               tt_global_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
-               tt_global_entry->roam_at = jiffies;
+               if (roamed_back) {
+                       batadv_tt_global_free(bat_priv, tt_global,
+                                             "Roaming canceled");
+                       tt_global = NULL;
+               } else {
+                       /* The global entry has to be marked as ROAMING and
+                        * has to be kept for consistency purpose
+                        */
+                       tt_global->common.flags |= BATADV_TT_CLIENT_ROAM;
+                       tt_global->roam_at = jiffies;
+               }
        }
+
 out:
-       if (tt_local_entry)
-               batadv_tt_local_entry_free_ref(tt_local_entry);
-       if (tt_global_entry)
-               batadv_tt_global_entry_free_ref(tt_global_entry);
+       if (tt_local)
+               batadv_tt_local_entry_free_ref(tt_local);
+       if (tt_global)
+               batadv_tt_global_entry_free_ref(tt_global);
 }
 
 static void batadv_tt_realloc_packet_buff(unsigned char **packet_buff,
@@ -434,22 +476,10 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
        struct hlist_node *node;
        struct hlist_head *head;
        uint32_t i;
-       int ret = 0;
-
-       primary_if = batadv_primary_if_get_selected(bat_priv);
-       if (!primary_if) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-                                net_dev->name);
-               goto out;
-       }
 
-       if (primary_if->if_status != BATADV_IF_ACTIVE) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - primary interface not active\n",
-                                net_dev->name);
+       primary_if = batadv_seq_print_text_primary_if_get(seq);
+       if (!primary_if)
                goto out;
-       }
 
        seq_printf(seq,
                   "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n",
@@ -479,7 +509,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       return ret;
+       return 0;
 }
 
 static void
@@ -501,24 +531,57 @@ batadv_tt_local_set_pending(struct batadv_priv *bat_priv,
                   tt_local_entry->common.addr, message);
 }
 
-void batadv_tt_local_remove(struct batadv_priv *bat_priv, const uint8_t *addr,
-                           const char *message, bool roaming)
+/**
+ * batadv_tt_local_remove - logically remove an entry from the local table
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: the MAC address of the client to remove
+ * @message: message to append to the log on deletion
+ * @roaming: true if the deletion is due to a roaming event
+ *
+ * Returns the flags assigned to the local entry before being deleted
+ */
+uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
+                               const uint8_t *addr, const char *message,
+                               bool roaming)
 {
-       struct batadv_tt_local_entry *tt_local_entry = NULL;
-       uint16_t flags;
+       struct batadv_tt_local_entry *tt_local_entry;
+       uint16_t flags, curr_flags = BATADV_NO_FLAGS;
 
        tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
        if (!tt_local_entry)
                goto out;
 
+       curr_flags = tt_local_entry->common.flags;
+
        flags = BATADV_TT_CLIENT_DEL;
-       if (roaming)
+       /* if this global entry addition is due to a roaming, the node has to
+        * mark the local entry as "roamed" in order to correctly reroute
+        * packets later
+        */
+       if (roaming) {
                flags |= BATADV_TT_CLIENT_ROAM;
+               /* mark the local client as ROAMed */
+               tt_local_entry->common.flags |= BATADV_TT_CLIENT_ROAM;
+       }
+
+       if (!(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW)) {
+               batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags,
+                                           message);
+               goto out;
+       }
+       /* if this client has been added right now, it is possible to
+        * immediately purge it
+        */
+       batadv_tt_local_event(bat_priv, tt_local_entry->common.addr,
+                             curr_flags | BATADV_TT_CLIENT_DEL);
+       hlist_del_rcu(&tt_local_entry->common.hash_entry);
+       batadv_tt_local_entry_free_ref(tt_local_entry);
 
-       batadv_tt_local_set_pending(bat_priv, tt_local_entry, flags, message);
 out:
        if (tt_local_entry)
                batadv_tt_local_entry_free_ref(tt_local_entry);
+
+       return curr_flags;
 }
 
 static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv,
@@ -721,12 +784,23 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
                         const unsigned char *tt_addr, uint8_t flags,
                         uint8_t ttvn)
 {
-       struct batadv_tt_global_entry *tt_global_entry = NULL;
+       struct batadv_tt_global_entry *tt_global_entry;
+       struct batadv_tt_local_entry *tt_local_entry;
        int ret = 0;
        int hash_added;
        struct batadv_tt_common_entry *common;
+       uint16_t local_flags;
 
        tt_global_entry = batadv_tt_global_hash_find(bat_priv, tt_addr);
+       tt_local_entry = batadv_tt_local_hash_find(bat_priv, tt_addr);
+
+       /* if the node already has a local client for this entry, it has to wait
+        * for a roaming advertisement instead of manually messing up the global
+        * table
+        */
+       if ((flags & BATADV_TT_CLIENT_TEMP) && tt_local_entry &&
+           !(tt_local_entry->common.flags & BATADV_TT_CLIENT_NEW))
+               goto out;
 
        if (!tt_global_entry) {
                tt_global_entry = kzalloc(sizeof(*tt_global_entry), GFP_ATOMIC);
@@ -738,6 +812,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
 
                common->flags = flags;
                tt_global_entry->roam_at = 0;
+               /* node must store current time in case of roaming. This is
+                * needed to purge this entry out on timeout (if nobody claims
+                * it)
+                */
+               if (flags & BATADV_TT_CLIENT_ROAM)
+                       tt_global_entry->roam_at = jiffies;
                atomic_set(&common->refcount, 2);
                common->added_at = jiffies;
 
@@ -755,19 +835,37 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
                        goto out_remove;
                }
        } else {
+               common = &tt_global_entry->common;
                /* If there is already a global entry, we can use this one for
                 * our processing.
-                * But if we are trying to add a temporary client we can exit
-                * directly because the temporary information should never
-                * override any already known client state (whatever it is)
+                * But if we are trying to add a temporary client then here are
+                * two options at this point:
+                * 1) the global client is not a temporary client: the global
+                *    client has to be left as it is, temporary information
+                *    should never override any already known client state
+                * 2) the global client is a temporary client: purge the
+                *    originator list and add the new one orig_entry
                 */
-               if (flags & BATADV_TT_CLIENT_TEMP)
-                       goto out;
+               if (flags & BATADV_TT_CLIENT_TEMP) {
+                       if (!(common->flags & BATADV_TT_CLIENT_TEMP))
+                               goto out;
+                       if (batadv_tt_global_entry_has_orig(tt_global_entry,
+                                                           orig_node))
+                               goto out_remove;
+                       batadv_tt_global_del_orig_list(tt_global_entry);
+                       goto add_orig_entry;
+               }
 
                /* if the client was temporary added before receiving the first
                 * OGM announcing it, we have to clear the TEMP flag
                 */
-               tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
+               common->flags &= ~BATADV_TT_CLIENT_TEMP;
+
+               /* the change can carry possible "attribute" flags like the
+                * TT_CLIENT_WIFI, therefore they have to be copied in the
+                * client entry
+                */
+               tt_global_entry->common.flags |= flags;
 
                /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
                 * one originator left in the list and we previously received a
@@ -776,33 +874,81 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
                 * We should first delete the old originator before adding the
                 * new one.
                 */
-               if (tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM) {
+               if (common->flags & BATADV_TT_CLIENT_ROAM) {
                        batadv_tt_global_del_orig_list(tt_global_entry);
-                       tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+                       common->flags &= ~BATADV_TT_CLIENT_ROAM;
                        tt_global_entry->roam_at = 0;
                }
        }
+add_orig_entry:
        /* add the new orig_entry (if needed) or update it */
        batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
 
        batadv_dbg(BATADV_DBG_TT, bat_priv,
                   "Creating new global tt entry: %pM (via %pM)\n",
-                  tt_global_entry->common.addr, orig_node->orig);
+                  common->addr, orig_node->orig);
+       ret = 1;
 
 out_remove:
+
        /* remove address from local hash if present */
-       batadv_tt_local_remove(bat_priv, tt_global_entry->common.addr,
-                              "global tt received",
-                              flags & BATADV_TT_CLIENT_ROAM);
-       ret = 1;
+       local_flags = batadv_tt_local_remove(bat_priv, tt_addr,
+                                            "global tt received",
+                                            !!(flags & BATADV_TT_CLIENT_ROAM));
+       tt_global_entry->common.flags |= local_flags & BATADV_TT_CLIENT_WIFI;
+
+       if (!(flags & BATADV_TT_CLIENT_ROAM))
+               /* this is a normal global add. Therefore the client is not in a
+                * roaming state anymore.
+                */
+               tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM;
+
 out:
        if (tt_global_entry)
                batadv_tt_global_entry_free_ref(tt_global_entry);
+       if (tt_local_entry)
+               batadv_tt_local_entry_free_ref(tt_local_entry);
        return ret;
 }
 
-/* print all orig nodes who announce the address for this global entry.
- * it is assumed that the caller holds rcu_read_lock();
+/* batadv_transtable_best_orig - Get best originator list entry from tt entry
+ * @tt_global_entry: global translation table entry to be analyzed
+ *
+ * This functon assumes the caller holds rcu_read_lock().
+ * Returns best originator list entry or NULL on errors.
+ */
+static struct batadv_tt_orig_list_entry *
+batadv_transtable_best_orig(struct batadv_tt_global_entry *tt_global_entry)
+{
+       struct batadv_neigh_node *router = NULL;
+       struct hlist_head *head;
+       struct hlist_node *node;
+       struct batadv_tt_orig_list_entry *orig_entry, *best_entry = NULL;
+       int best_tq = 0;
+
+       head = &tt_global_entry->orig_list;
+       hlist_for_each_entry_rcu(orig_entry, node, head, list) {
+               router = batadv_orig_node_get_router(orig_entry->orig_node);
+               if (!router)
+                       continue;
+
+               if (router->tq_avg > best_tq) {
+                       best_entry = orig_entry;
+                       best_tq = router->tq_avg;
+               }
+
+               batadv_neigh_node_free_ref(router);
+       }
+
+       return best_entry;
+}
+
+/* batadv_tt_global_print_entry - print all orig nodes who announce the address
+ * for this global entry
+ * @tt_global_entry: global translation table entry to be printed
+ * @seq: debugfs table seq_file struct
+ *
+ * This functon assumes the caller holds rcu_read_lock().
  */
 static void
 batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
@@ -810,21 +956,37 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry,
 {
        struct hlist_head *head;
        struct hlist_node *node;
-       struct batadv_tt_orig_list_entry *orig_entry;
+       struct batadv_tt_orig_list_entry *orig_entry, *best_entry;
        struct batadv_tt_common_entry *tt_common_entry;
        uint16_t flags;
        uint8_t last_ttvn;
 
        tt_common_entry = &tt_global_entry->common;
+       flags = tt_common_entry->flags;
+
+       best_entry = batadv_transtable_best_orig(tt_global_entry);
+       if (best_entry) {
+               last_ttvn = atomic_read(&best_entry->orig_node->last_ttvn);
+               seq_printf(seq, " %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
+                          '*', tt_global_entry->common.addr,
+                          best_entry->ttvn, best_entry->orig_node->orig,
+                          last_ttvn,
+                          (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
+                          (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
+                          (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
+       }
 
        head = &tt_global_entry->orig_list;
 
        hlist_for_each_entry_rcu(orig_entry, node, head, list) {
-               flags = tt_common_entry->flags;
+               if (best_entry == orig_entry)
+                       continue;
+
                last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn);
-               seq_printf(seq, " * %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
-                          tt_global_entry->common.addr, orig_entry->ttvn,
-                          orig_entry->orig_node->orig, last_ttvn,
+               seq_printf(seq, " %c %pM  (%3u) via %pM     (%3u)   [%c%c%c]\n",
+                          '+', tt_global_entry->common.addr,
+                          orig_entry->ttvn, orig_entry->orig_node->orig,
+                          last_ttvn,
                           (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'),
                           (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'),
                           (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.'));
@@ -842,22 +1004,10 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
        struct hlist_node *node;
        struct hlist_head *head;
        uint32_t i;
-       int ret = 0;
 
-       primary_if = batadv_primary_if_get_selected(bat_priv);
-       if (!primary_if) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - please specify interfaces to enable it\n",
-                                net_dev->name);
-               goto out;
-       }
-
-       if (primary_if->if_status != BATADV_IF_ACTIVE) {
-               ret = seq_printf(seq,
-                                "BATMAN mesh %s disabled - primary interface not active\n",
-                                net_dev->name);
+       primary_if = batadv_seq_print_text_primary_if_get(seq);
+       if (!primary_if)
                goto out;
-       }
 
        seq_printf(seq,
                   "Globally announced TT entries received via the mesh %s\n",
@@ -881,7 +1031,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset)
 out:
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
-       return ret;
+       return 0;
 }
 
 /* deletes the orig list of a tt_global_entry */
@@ -927,21 +1077,6 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv,
        spin_unlock_bh(&tt_global_entry->list_lock);
 }
 
-static void
-batadv_tt_global_del_struct(struct batadv_priv *bat_priv,
-                           struct batadv_tt_global_entry *tt_global_entry,
-                           const char *message)
-{
-       batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Deleting global tt entry %pM: %s\n",
-                  tt_global_entry->common.addr, message);
-
-       batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt,
-                          batadv_choose_orig, tt_global_entry->common.addr);
-       batadv_tt_global_entry_free_ref(tt_global_entry);
-
-}
-
 /* If the client is to be deleted, we check if it is the last origantor entry
  * within tt_global entry. If yes, we set the BATADV_TT_CLIENT_ROAM flag and the
  * timer, otherwise we simply remove the originator scheduled for deletion.
@@ -990,7 +1125,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
                                 const unsigned char *addr,
                                 const char *message, bool roaming)
 {
-       struct batadv_tt_global_entry *tt_global_entry = NULL;
+       struct batadv_tt_global_entry *tt_global_entry;
        struct batadv_tt_local_entry *local_entry = NULL;
 
        tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr);
@@ -1002,8 +1137,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
                                                orig_node, message);
 
                if (hlist_empty(&tt_global_entry->orig_list))
-                       batadv_tt_global_del_struct(bat_priv, tt_global_entry,
-                                                   message);
+                       batadv_tt_global_free(bat_priv, tt_global_entry,
+                                             message);
 
                goto out;
        }
@@ -1026,7 +1161,7 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv,
        if (local_entry) {
                /* local entry exists, case 2: client roamed to us. */
                batadv_tt_global_del_orig_list(tt_global_entry);
-               batadv_tt_global_del_struct(bat_priv, tt_global_entry, message);
+               batadv_tt_global_free(bat_priv, tt_global_entry, message);
        } else
                /* no local entry exists, case 1: check for roaming */
                batadv_tt_global_del_roaming(bat_priv, tt_global_entry,
@@ -1197,15 +1332,12 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
        struct batadv_tt_local_entry *tt_local_entry = NULL;
        struct batadv_tt_global_entry *tt_global_entry = NULL;
        struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *router = NULL;
-       struct hlist_head *head;
-       struct hlist_node *node;
-       struct batadv_tt_orig_list_entry *orig_entry;
-       int best_tq;
+       struct batadv_tt_orig_list_entry *best_entry;
 
        if (src && atomic_read(&bat_priv->ap_isolation)) {
                tt_local_entry = batadv_tt_local_hash_find(bat_priv, src);
-               if (!tt_local_entry)
+               if (!tt_local_entry ||
+                   (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING))
                        goto out;
        }
 
@@ -1220,25 +1352,15 @@ struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv,
            _batadv_is_ap_isolated(tt_local_entry, tt_global_entry))
                goto out;
 
-       best_tq = 0;
-
        rcu_read_lock();
-       head = &tt_global_entry->orig_list;
-       hlist_for_each_entry_rcu(orig_entry, node, head, list) {
-               router = batadv_orig_node_get_router(orig_entry->orig_node);
-               if (!router)
-                       continue;
-
-               if (router->tq_avg > best_tq) {
-                       orig_node = orig_entry->orig_node;
-                       best_tq = router->tq_avg;
-               }
-               batadv_neigh_node_free_ref(router);
-       }
+       best_entry = batadv_transtable_best_orig(tt_global_entry);
        /* found anything? */
+       if (best_entry)
+               orig_node = best_entry->orig_node;
        if (orig_node && !atomic_inc_not_zero(&orig_node->refcount))
                orig_node = NULL;
        rcu_read_unlock();
+
 out:
        if (tt_global_entry)
                batadv_tt_global_entry_free_ref(tt_global_entry);
@@ -1471,11 +1593,11 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
        tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
        len = tt_query_size + tt_len;
-       skb = dev_alloc_skb(len + ETH_HLEN);
+       skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
        if (!skb)
                goto out;
 
-       skb_reserve(skb, ETH_HLEN);
+       skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
        tt_response = (struct batadv_tt_query_packet *)skb_put(skb, len);
        tt_response->ttvn = ttvn;
 
@@ -1496,7 +1618,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
 
                        memcpy(tt_change->addr, tt_common_entry->addr,
                               ETH_ALEN);
-                       tt_change->flags = BATADV_NO_FLAGS;
+                       tt_change->flags = tt_common_entry->flags;
 
                        tt_count++;
                        tt_change++;
@@ -1520,7 +1642,6 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
 {
        struct sk_buff *skb = NULL;
        struct batadv_tt_query_packet *tt_request;
-       struct batadv_neigh_node *neigh_node = NULL;
        struct batadv_hard_iface *primary_if;
        struct batadv_tt_req_node *tt_req_node = NULL;
        int ret = 1;
@@ -1537,11 +1658,11 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
        if (!tt_req_node)
                goto out;
 
-       skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN);
+       skb = dev_alloc_skb(sizeof(*tt_request) + ETH_HLEN + NET_IP_ALIGN);
        if (!skb)
                goto out;
 
-       skb_reserve(skb, ETH_HLEN);
+       skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
 
        tt_req_len = sizeof(*tt_request);
        tt_request = (struct batadv_tt_query_packet *)skb_put(skb, tt_req_len);
@@ -1558,23 +1679,15 @@ static int batadv_send_tt_request(struct batadv_priv *bat_priv,
        if (full_table)
                tt_request->flags |= BATADV_TT_FULL_TABLE;
 
-       neigh_node = batadv_orig_node_get_router(dst_orig_node);
-       if (!neigh_node)
-               goto out;
-
-       batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Sending TT_REQUEST to %pM via %pM [%c]\n",
-                  dst_orig_node->orig, neigh_node->addr,
-                  (full_table ? 'F' : '.'));
+       batadv_dbg(BATADV_DBG_TT, bat_priv, "Sending TT_REQUEST to %pM [%c]\n",
+                  dst_orig_node->orig, (full_table ? 'F' : '.'));
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_REQUEST_TX);
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = 0;
+       if (batadv_send_skb_to_orig(skb, dst_orig_node, NULL))
+               ret = 0;
 
 out:
-       if (neigh_node)
-               batadv_neigh_node_free_ref(neigh_node);
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
        if (ret)
@@ -1592,9 +1705,8 @@ static bool
 batadv_send_other_tt_response(struct batadv_priv *bat_priv,
                              struct batadv_tt_query_packet *tt_request)
 {
-       struct batadv_orig_node *req_dst_orig_node = NULL;
+       struct batadv_orig_node *req_dst_orig_node;
        struct batadv_orig_node *res_dst_orig_node = NULL;
-       struct batadv_neigh_node *neigh_node = NULL;
        struct batadv_hard_iface *primary_if = NULL;
        uint8_t orig_ttvn, req_ttvn, ttvn;
        int ret = false;
@@ -1620,10 +1732,6 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
        if (!res_dst_orig_node)
                goto out;
 
-       neigh_node = batadv_orig_node_get_router(res_dst_orig_node);
-       if (!neigh_node)
-               goto out;
-
        primary_if = batadv_primary_if_get_selected(bat_priv);
        if (!primary_if)
                goto out;
@@ -1652,11 +1760,11 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
                tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
                len = sizeof(*tt_response) + tt_len;
-               skb = dev_alloc_skb(len + ETH_HLEN);
+               skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
                if (!skb)
                        goto unlock;
 
-               skb_reserve(skb, ETH_HLEN);
+               skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
                packet_pos = skb_put(skb, len);
                tt_response = (struct batadv_tt_query_packet *)packet_pos;
                tt_response->ttvn = req_ttvn;
@@ -1695,14 +1803,13 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv,
                tt_response->flags |= BATADV_TT_FULL_TABLE;
 
        batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Sending TT_RESPONSE %pM via %pM for %pM (ttvn: %u)\n",
-                  res_dst_orig_node->orig, neigh_node->addr,
-                  req_dst_orig_node->orig, req_ttvn);
+                  "Sending TT_RESPONSE %pM for %pM (ttvn: %u)\n",
+                  res_dst_orig_node->orig, req_dst_orig_node->orig, req_ttvn);
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = true;
+       if (batadv_send_skb_to_orig(skb, res_dst_orig_node, NULL))
+               ret = true;
        goto out;
 
 unlock:
@@ -1713,8 +1820,6 @@ out:
                batadv_orig_node_free_ref(res_dst_orig_node);
        if (req_dst_orig_node)
                batadv_orig_node_free_ref(req_dst_orig_node);
-       if (neigh_node)
-               batadv_neigh_node_free_ref(neigh_node);
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
        if (!ret)
@@ -1727,8 +1832,7 @@ static bool
 batadv_send_my_tt_response(struct batadv_priv *bat_priv,
                           struct batadv_tt_query_packet *tt_request)
 {
-       struct batadv_orig_node *orig_node = NULL;
-       struct batadv_neigh_node *neigh_node = NULL;
+       struct batadv_orig_node *orig_node;
        struct batadv_hard_iface *primary_if = NULL;
        uint8_t my_ttvn, req_ttvn, ttvn;
        int ret = false;
@@ -1753,10 +1857,6 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       neigh_node = batadv_orig_node_get_router(orig_node);
-       if (!neigh_node)
-               goto out;
-
        primary_if = batadv_primary_if_get_selected(bat_priv);
        if (!primary_if)
                goto out;
@@ -1779,11 +1879,11 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
                tt_tot = tt_len / sizeof(struct batadv_tt_change);
 
                len = sizeof(*tt_response) + tt_len;
-               skb = dev_alloc_skb(len + ETH_HLEN);
+               skb = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
                if (!skb)
                        goto unlock;
 
-               skb_reserve(skb, ETH_HLEN);
+               skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
                packet_pos = skb_put(skb, len);
                tt_response = (struct batadv_tt_query_packet *)packet_pos;
                tt_response->ttvn = req_ttvn;
@@ -1820,14 +1920,14 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv,
                tt_response->flags |= BATADV_TT_FULL_TABLE;
 
        batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Sending TT_RESPONSE to %pM via %pM [%c]\n",
-                  orig_node->orig, neigh_node->addr,
+                  "Sending TT_RESPONSE to %pM [%c]\n",
+                  orig_node->orig,
                   (tt_response->flags & BATADV_TT_FULL_TABLE ? 'F' : '.'));
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_RESPONSE_TX);
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = true;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = true;
        goto out;
 
 unlock:
@@ -1835,8 +1935,6 @@ unlock:
 out:
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
-       if (neigh_node)
-               batadv_neigh_node_free_ref(neigh_node);
        if (primary_if)
                batadv_hardif_free_ref(primary_if);
        if (!ret)
@@ -1893,7 +1991,7 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv,
 static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv,
                                  struct batadv_tt_query_packet *tt_response)
 {
-       struct batadv_orig_node *orig_node = NULL;
+       struct batadv_orig_node *orig_node;
 
        orig_node = batadv_orig_hash_find(bat_priv, tt_response->src);
        if (!orig_node)
@@ -1935,7 +2033,7 @@ static void batadv_tt_update_changes(struct batadv_priv *bat_priv,
 
 bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
 {
-       struct batadv_tt_local_entry *tt_local_entry = NULL;
+       struct batadv_tt_local_entry *tt_local_entry;
        bool ret = false;
 
        tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
@@ -1944,7 +2042,8 @@ bool batadv_is_my_client(struct batadv_priv *bat_priv, const uint8_t *addr)
        /* Check if the client has been logically deleted (but is kept for
         * consistency purpose)
         */
-       if (tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING)
+       if ((tt_local_entry->common.flags & BATADV_TT_CLIENT_PENDING) ||
+           (tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM))
                goto out;
        ret = true;
 out:
@@ -1995,10 +2094,6 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv,
 
        /* Recalculate the CRC for this orig_node and store it */
        orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node);
-       /* Roaming phase is over: tables are in sync again. I can
-        * unset the flag
-        */
-       orig_node->tt_poss_change = false;
 out:
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
@@ -2104,7 +2199,6 @@ unlock:
 static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
                                 struct batadv_orig_node *orig_node)
 {
-       struct batadv_neigh_node *neigh_node = NULL;
        struct sk_buff *skb = NULL;
        struct batadv_roam_adv_packet *roam_adv_packet;
        int ret = 1;
@@ -2117,11 +2211,11 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
        if (!batadv_tt_check_roam_count(bat_priv, client))
                goto out;
 
-       skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN);
+       skb = dev_alloc_skb(sizeof(*roam_adv_packet) + ETH_HLEN + NET_IP_ALIGN);
        if (!skb)
                goto out;
 
-       skb_reserve(skb, ETH_HLEN);
+       skb_reserve(skb, ETH_HLEN + NET_IP_ALIGN);
 
        roam_adv_packet = (struct batadv_roam_adv_packet *)skb_put(skb, len);
 
@@ -2137,23 +2231,17 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client,
        memcpy(roam_adv_packet->dst, orig_node->orig, ETH_ALEN);
        memcpy(roam_adv_packet->client, client, ETH_ALEN);
 
-       neigh_node = batadv_orig_node_get_router(orig_node);
-       if (!neigh_node)
-               goto out;
-
        batadv_dbg(BATADV_DBG_TT, bat_priv,
-                  "Sending ROAMING_ADV to %pM (client %pM) via %pM\n",
-                  orig_node->orig, client, neigh_node->addr);
+                  "Sending ROAMING_ADV to %pM (client %pM)\n",
+                  orig_node->orig, client);
 
        batadv_inc_counter(bat_priv, BATADV_CNT_TT_ROAM_ADV_TX);
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = 0;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = 0;
 
 out:
-       if (neigh_node)
-               batadv_neigh_node_free_ref(neigh_node);
-       if (ret)
+       if (ret && skb)
                kfree_skb(skb);
        return;
 }
@@ -2289,7 +2377,6 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv,
        batadv_dbg(BATADV_DBG_TT, bat_priv,
                   "Local changes committed, updating to ttvn %u\n",
                   (uint8_t)atomic_read(&bat_priv->tt.vn));
-       bat_priv->tt.poss_change = false;
 
        /* reset the sending counter */
        atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX);
@@ -2401,11 +2488,6 @@ void batadv_tt_update_orig(struct batadv_priv *bat_priv,
                 */
                if (orig_node->tt_crc != tt_crc)
                        goto request_table;
-
-               /* Roaming phase is over: tables are in sync again. I can
-                * unset the flag
-                */
-               orig_node->tt_poss_change = false;
        } else {
                /* if we missed more than one change or our tables are not
                 * in sync anymore -> request fresh tt data
@@ -2438,18 +2520,51 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
        if (!tt_global_entry)
                goto out;
 
-       ret = tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM;
+       ret = !!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM);
        batadv_tt_global_entry_free_ref(tt_global_entry);
 out:
        return ret;
 }
 
+/**
+ * batadv_tt_local_client_is_roaming - tells whether the client is roaming
+ * @bat_priv: the bat priv with all the soft interface information
+ * @addr: the MAC address of the local client to query
+ *
+ * Returns true if the local client is known to be roaming (it is not served by
+ * this node anymore) or not. If yes, the client is still present in the table
+ * to keep the latter consistent with the node TTVN
+ */
+bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
+                                      uint8_t *addr)
+{
+       struct batadv_tt_local_entry *tt_local_entry;
+       bool ret = false;
+
+       tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr);
+       if (!tt_local_entry)
+               goto out;
+
+       ret = tt_local_entry->common.flags & BATADV_TT_CLIENT_ROAM;
+       batadv_tt_local_entry_free_ref(tt_local_entry);
+out:
+       return ret;
+
+}
+
 bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
                                          struct batadv_orig_node *orig_node,
                                          const unsigned char *addr)
 {
        bool ret = false;
 
+       /* if the originator is a backbone node (meaning it belongs to the same
+        * LAN of this node) the temporary client must not be added because to
+        * reach such destination the node must use the LAN instead of the mesh
+        */
+       if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
+               goto out;
+
        if (!batadv_tt_global_add(bat_priv, orig_node, addr,
                                  BATADV_TT_CLIENT_TEMP,
                                  atomic_read(&orig_node->last_ttvn)))
index 811fffd4760c3678a60994e027896277289e751a..46d4451a59ee8feb6ce895473d6df838e97f8326 100644 (file)
@@ -24,9 +24,9 @@ int batadv_tt_len(int changes_num);
 int batadv_tt_init(struct batadv_priv *bat_priv);
 void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,
                         int ifindex);
-void batadv_tt_local_remove(struct batadv_priv *bat_priv,
-                           const uint8_t *addr, const char *message,
-                           bool roaming);
+uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
+                               const uint8_t *addr, const char *message,
+                               bool roaming);
 int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset);
 void batadv_tt_global_add_orig(struct batadv_priv *bat_priv,
                               struct batadv_orig_node *orig_node,
@@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv,
                          int packet_min_len);
 bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv,
                                        uint8_t *addr);
+bool batadv_tt_local_client_is_roaming(struct batadv_priv *bat_priv,
+                                      uint8_t *addr);
 bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
                                          struct batadv_orig_node *orig_node,
                                          const unsigned char *addr);
index 2ed82caacdca4bfa0cf429d74a7311523874b4c2..ae9ac9aca8c53d5ffd93b015cb6ff779f55c86fe 100644 (file)
        (ETH_HLEN + max(sizeof(struct batadv_unicast_packet), \
                        sizeof(struct batadv_bcast_packet)))
 
+#ifdef CONFIG_BATMAN_ADV_DAT
+
+/* batadv_dat_addr_t is the type used for all DHT addresses. If it is changed,
+ * BATADV_DAT_ADDR_MAX is changed as well.
+ *
+ * *Please be careful: batadv_dat_addr_t must be UNSIGNED*
+ */
+#define batadv_dat_addr_t uint16_t
+
+#endif /* CONFIG_BATMAN_ADV_DAT */
+
+/**
+ * struct batadv_hard_iface_bat_iv - per hard interface B.A.T.M.A.N. IV data
+ * @ogm_buff: buffer holding the OGM packet
+ * @ogm_buff_len: length of the OGM packet buffer
+ * @ogm_seqno: OGM sequence number - used to identify each OGM
+ */
+struct batadv_hard_iface_bat_iv {
+       unsigned char *ogm_buff;
+       int ogm_buff_len;
+       atomic_t ogm_seqno;
+};
+
 struct batadv_hard_iface {
        struct list_head list;
        int16_t if_num;
        char if_status;
        struct net_device *net_dev;
-       atomic_t seqno;
        atomic_t frag_seqno;
-       unsigned char *packet_buff;
-       int packet_len;
        struct kobject *hardif_obj;
        atomic_t refcount;
        struct packet_type batman_adv_ptype;
        struct net_device *soft_iface;
        struct rcu_head rcu;
+       struct batadv_hard_iface_bat_iv bat_iv;
 };
 
 /**
@@ -63,6 +84,9 @@ struct batadv_orig_node {
        uint8_t orig[ETH_ALEN];
        uint8_t primary_addr[ETH_ALEN];
        struct batadv_neigh_node __rcu *router; /* rcu protected pointer */
+#ifdef CONFIG_BATMAN_ADV_DAT
+       batadv_dat_addr_t dat_addr;
+#endif
        unsigned long *bcast_own;
        uint8_t *bcast_own_sum;
        unsigned long last_seen;
@@ -77,13 +101,6 @@ struct batadv_orig_node {
        spinlock_t tt_buff_lock; /* protects tt_buff */
        atomic_t tt_size;
        bool tt_initialised;
-       /* The tt_poss_change flag is used to detect an ongoing roaming phase.
-        * If true, then I sent a Roaming_adv to this orig_node and I have to
-        * inspect every packet directed to it to check whether it is still
-        * the true destination or not. This flag will be reset to false as
-        * soon as I receive a new TTVN from this orig_node
-        */
-       bool tt_poss_change;
        uint32_t last_real_seqno;
        uint8_t last_ttl;
        DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE);
@@ -139,7 +156,7 @@ struct batadv_neigh_node {
 #ifdef CONFIG_BATMAN_ADV_BLA
 struct batadv_bcast_duplist_entry {
        uint8_t orig[ETH_ALEN];
-       uint16_t crc;
+       __be32 crc;
        unsigned long entrytime;
 };
 #endif
@@ -162,6 +179,13 @@ enum batadv_counters {
        BATADV_CNT_TT_RESPONSE_RX,
        BATADV_CNT_TT_ROAM_ADV_TX,
        BATADV_CNT_TT_ROAM_ADV_RX,
+#ifdef CONFIG_BATMAN_ADV_DAT
+       BATADV_CNT_DAT_GET_TX,
+       BATADV_CNT_DAT_GET_RX,
+       BATADV_CNT_DAT_PUT_TX,
+       BATADV_CNT_DAT_PUT_RX,
+       BATADV_CNT_DAT_CACHED_REPLY_TX,
+#endif
        BATADV_CNT_NUM,
 };
 
@@ -181,7 +205,6 @@ struct batadv_priv_tt {
        atomic_t vn;
        atomic_t ogm_append_cnt;
        atomic_t local_changes;
-       bool poss_change;
        struct list_head changes_list;
        struct batadv_hashtable *local_hash;
        struct batadv_hashtable *global_hash;
@@ -205,6 +228,8 @@ struct batadv_priv_bla {
        struct batadv_hashtable *backbone_hash;
        struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
        int bcast_duplist_curr;
+       /* protects bcast_duplist and bcast_duplist_curr */
+       spinlock_t bcast_duplist_lock;
        struct batadv_bla_claim_dst claim_dest;
        struct delayed_work work;
 };
@@ -226,6 +251,20 @@ struct batadv_priv_vis {
        struct batadv_vis_info *my_info;
 };
 
+/**
+ * struct batadv_priv_dat - per mesh interface DAT private data
+ * @addr: node DAT address
+ * @hash: hashtable representing the local ARP cache
+ * @work: work queue callback item for cache purging
+ */
+#ifdef CONFIG_BATMAN_ADV_DAT
+struct batadv_priv_dat {
+       batadv_dat_addr_t addr;
+       struct batadv_hashtable *hash;
+       struct delayed_work work;
+};
+#endif
+
 struct batadv_priv {
        atomic_t mesh_state;
        struct net_device_stats stats;
@@ -235,6 +274,9 @@ struct batadv_priv {
        atomic_t fragmentation;         /* boolean */
        atomic_t ap_isolation;          /* boolean */
        atomic_t bridge_loop_avoidance; /* boolean */
+#ifdef CONFIG_BATMAN_ADV_DAT
+       atomic_t distributed_arp_table; /* boolean */
+#endif
        atomic_t vis_mode;              /* VIS_TYPE_* */
        atomic_t gw_mode;               /* GW_MODE_* */
        atomic_t gw_sel_class;          /* uint */
@@ -253,7 +295,7 @@ struct batadv_priv {
        struct hlist_head forw_bcast_list;
        struct batadv_hashtable *orig_hash;
        spinlock_t forw_bat_list_lock; /* protects forw_bat_list */
-       spinlock_t forw_bcast_list_lock; /* protects  */
+       spinlock_t forw_bcast_list_lock; /* protects forw_bcast_list */
        struct delayed_work orig_work;
        struct batadv_hard_iface __rcu *primary_if;  /* rcu protected pointer */
        struct batadv_algo_ops *bat_algo_ops;
@@ -263,6 +305,9 @@ struct batadv_priv {
        struct batadv_priv_gw gw;
        struct batadv_priv_tt tt;
        struct batadv_priv_vis vis;
+#ifdef CONFIG_BATMAN_ADV_DAT
+       struct batadv_priv_dat dat;
+#endif
 };
 
 struct batadv_socket_client {
@@ -316,6 +361,7 @@ struct batadv_backbone_gw {
        struct hlist_node hash_entry;
        struct batadv_priv *bat_priv;
        unsigned long lasttime; /* last time we heard of this backbone gw */
+       atomic_t wait_periods;
        atomic_t request_sent;
        atomic_t refcount;
        struct rcu_head rcu;
@@ -435,4 +481,36 @@ struct batadv_algo_ops {
        void (*bat_ogm_emit)(struct batadv_forw_packet *forw_packet);
 };
 
+/**
+ * struct batadv_dat_entry - it is a single entry of batman-adv ARP backend. It
+ * is used to stored ARP entries needed for the global DAT cache
+ * @ip: the IPv4 corresponding to this DAT/ARP entry
+ * @mac_addr: the MAC address associated to the stored IPv4
+ * @last_update: time in jiffies when this entry was refreshed last time
+ * @hash_entry: hlist node for batadv_priv_dat::hash
+ * @refcount: number of contexts the object is used
+ * @rcu: struct used for freeing in an RCU-safe manner
+ */
+struct batadv_dat_entry {
+       __be32 ip;
+       uint8_t mac_addr[ETH_ALEN];
+       unsigned long last_update;
+       struct hlist_node hash_entry;
+       atomic_t refcount;
+       struct rcu_head rcu;
+};
+
+/**
+ * struct batadv_dat_candidate - candidate destination for DAT operations
+ * @type: the type of the selected candidate. It can one of the following:
+ *       - BATADV_DAT_CANDIDATE_NOT_FOUND
+ *       - BATADV_DAT_CANDIDATE_ORIG
+ * @orig_node: if type is BATADV_DAT_CANDIDATE_ORIG this field points to the
+ *            corresponding originator node structure
+ */
+struct batadv_dat_candidate {
+       int type;
+       struct batadv_orig_node *orig_node;
+};
+
 #endif /* _NET_BATMAN_ADV_TYPES_H_ */
index f39723281ca1f7cd96dd9f7535a2bea8fbc5aa07..10aff49fcf25adb106cefb020309e456d8f04a2f 100644 (file)
@@ -291,14 +291,118 @@ out:
        return ret;
 }
 
-int batadv_unicast_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv)
+/**
+ * batadv_unicast_push_and_fill_skb - extends the buffer and initializes the
+ * common fields for unicast packets
+ * @skb: packet
+ * @hdr_size: amount of bytes to push at the beginning of the skb
+ * @orig_node: the destination node
+ *
+ * Returns false if the buffer extension was not possible or true otherwise
+ */
+static bool batadv_unicast_push_and_fill_skb(struct sk_buff *skb, int hdr_size,
+                                            struct batadv_orig_node *orig_node)
+{
+       struct batadv_unicast_packet *unicast_packet;
+       uint8_t ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
+
+       if (batadv_skb_head_push(skb, hdr_size) < 0)
+               return false;
+
+       unicast_packet = (struct batadv_unicast_packet *)skb->data;
+       unicast_packet->header.version = BATADV_COMPAT_VERSION;
+       /* batman packet type: unicast */
+       unicast_packet->header.packet_type = BATADV_UNICAST;
+       /* set unicast ttl */
+       unicast_packet->header.ttl = BATADV_TTL;
+       /* copy the destination for faster routing */
+       memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
+       /* set the destination tt version number */
+       unicast_packet->ttvn = ttvn;
+
+       return true;
+}
+
+/**
+ * batadv_unicast_prepare_skb - encapsulate an skb with a unicast header
+ * @skb: the skb containing the payload to encapsulate
+ * @orig_node: the destination node
+ *
+ * Returns false if the payload could not be encapsulated or true otherwise
+ */
+static bool batadv_unicast_prepare_skb(struct sk_buff *skb,
+                                      struct batadv_orig_node *orig_node)
+{
+       size_t uni_size = sizeof(struct batadv_unicast_packet);
+       return batadv_unicast_push_and_fill_skb(skb, uni_size, orig_node);
+}
+
+/**
+ * batadv_unicast_4addr_prepare_skb - encapsulate an skb with a unicast4addr
+ * header
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the skb containing the payload to encapsulate
+ * @orig_node: the destination node
+ * @packet_subtype: the batman 4addr packet subtype to use
+ *
+ * Returns false if the payload could not be encapsulated or true otherwise
+ */
+bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
+                                     struct sk_buff *skb,
+                                     struct batadv_orig_node *orig,
+                                     int packet_subtype)
+{
+       struct batadv_hard_iface *primary_if;
+       struct batadv_unicast_4addr_packet *unicast_4addr_packet;
+       bool ret = false;
+
+       primary_if = batadv_primary_if_get_selected(bat_priv);
+       if (!primary_if)
+               goto out;
+
+       /* pull the header space and fill the unicast_packet substructure.
+        * We can do that because the first member of the unicast_4addr_packet
+        * is of type struct unicast_packet
+        */
+       if (!batadv_unicast_push_and_fill_skb(skb,
+                                             sizeof(*unicast_4addr_packet),
+                                             orig))
+               goto out;
+
+       unicast_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data;
+       unicast_4addr_packet->u.header.packet_type = BATADV_UNICAST_4ADDR;
+       memcpy(unicast_4addr_packet->src, primary_if->net_dev->dev_addr,
+              ETH_ALEN);
+       unicast_4addr_packet->subtype = packet_subtype;
+       unicast_4addr_packet->reserved = 0;
+
+       ret = true;
+out:
+       if (primary_if)
+               batadv_hardif_free_ref(primary_if);
+       return ret;
+}
+
+/**
+ * batadv_unicast_generic_send_skb - send an skb as unicast
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: payload to send
+ * @packet_type: the batman unicast packet type to use
+ * @packet_subtype: the batman packet subtype. It is ignored if packet_type is
+ *                 not BATADV_UNICAT_4ADDR
+ *
+ * Returns 1 in case of error or 0 otherwise
+ */
+int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
+                                   struct sk_buff *skb, int packet_type,
+                                   int packet_subtype)
 {
        struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
        struct batadv_unicast_packet *unicast_packet;
        struct batadv_orig_node *orig_node;
        struct batadv_neigh_node *neigh_node;
        int data_len = skb->len;
-       int ret = 1;
+       int ret = NET_RX_DROP;
        unsigned int dev_mtu;
 
        /* get routing information */
@@ -324,21 +428,23 @@ find_router:
        if (!neigh_node)
                goto out;
 
-       if (batadv_skb_head_push(skb, sizeof(*unicast_packet)) < 0)
+       switch (packet_type) {
+       case BATADV_UNICAST:
+               batadv_unicast_prepare_skb(skb, orig_node);
+               break;
+       case BATADV_UNICAST_4ADDR:
+               batadv_unicast_4addr_prepare_skb(bat_priv, skb, orig_node,
+                                                packet_subtype);
+               break;
+       default:
+               /* this function supports UNICAST and UNICAST_4ADDR only. It
+                * should never be invoked with any other packet type
+                */
                goto out;
+       }
 
        unicast_packet = (struct batadv_unicast_packet *)skb->data;
 
-       unicast_packet->header.version = BATADV_COMPAT_VERSION;
-       /* batman packet type: unicast */
-       unicast_packet->header.packet_type = BATADV_UNICAST;
-       /* set unicast ttl */
-       unicast_packet->header.ttl = BATADV_TTL;
-       /* copy the destination for faster routing */
-       memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN);
-       /* set the destination tt version number */
-       unicast_packet->ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn);
-
        /* inform the destination node that we are still missing a correct route
         * for this client. The destination will receive this packet and will
         * try to reroute it because the ttvn contained in the header is less
@@ -348,7 +454,9 @@ find_router:
                unicast_packet->ttvn = unicast_packet->ttvn - 1;
 
        dev_mtu = neigh_node->if_incoming->net_dev->mtu;
-       if (atomic_read(&bat_priv->fragmentation) &&
+       /* fragmentation mechanism only works for UNICAST (now) */
+       if (packet_type == BATADV_UNICAST &&
+           atomic_read(&bat_priv->fragmentation) &&
            data_len + sizeof(*unicast_packet) > dev_mtu) {
                /* send frag skb decreases ttl */
                unicast_packet->header.ttl++;
@@ -358,16 +466,15 @@ find_router:
                goto out;
        }
 
-       batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr);
-       ret = 0;
-       goto out;
+       if (batadv_send_skb_to_orig(skb, orig_node, NULL))
+               ret = 0;
 
 out:
        if (neigh_node)
                batadv_neigh_node_free_ref(neigh_node);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
-       if (ret == 1)
+       if (ret == NET_RX_DROP)
                kfree_skb(skb);
        return ret;
 }
index 1c46e2eb1ef92615bcdb536cf9d134f3cee0c4b1..61abba58bd8fee1ac6be8b043927d52ddf9f141b 100644 (file)
@@ -29,10 +29,44 @@ int batadv_frag_reassemble_skb(struct sk_buff *skb,
                               struct batadv_priv *bat_priv,
                               struct sk_buff **new_skb);
 void batadv_frag_list_free(struct list_head *head);
-int batadv_unicast_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv);
 int batadv_frag_send_skb(struct sk_buff *skb, struct batadv_priv *bat_priv,
                         struct batadv_hard_iface *hard_iface,
                         const uint8_t dstaddr[]);
+bool batadv_unicast_4addr_prepare_skb(struct batadv_priv *bat_priv,
+                                     struct sk_buff *skb,
+                                     struct batadv_orig_node *orig_node,
+                                     int packet_subtype);
+int batadv_unicast_generic_send_skb(struct batadv_priv *bat_priv,
+                                   struct sk_buff *skb, int packet_type,
+                                   int packet_subtype);
+
+
+/**
+ * batadv_unicast_send_skb - send the skb encapsulated in a unicast packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the payload to send
+ */
+static inline int batadv_unicast_send_skb(struct batadv_priv *bat_priv,
+                                         struct sk_buff *skb)
+{
+       return batadv_unicast_generic_send_skb(bat_priv, skb, BATADV_UNICAST,
+                                              0);
+}
+
+/**
+ * batadv_unicast_send_skb - send the skb encapsulated in a unicast4addr packet
+ * @bat_priv: the bat priv with all the soft interface information
+ * @skb: the payload to send
+ * @packet_subtype: the batman 4addr packet subtype to use
+ */
+static inline int batadv_unicast_4addr_send_skb(struct batadv_priv *bat_priv,
+                                               struct sk_buff *skb,
+                                               int packet_subtype)
+{
+       return batadv_unicast_generic_send_skb(bat_priv, skb,
+                                              BATADV_UNICAST_4ADDR,
+                                              packet_subtype);
+}
 
 static inline int batadv_frag_can_reassemble(const struct sk_buff *skb, int mtu)
 {
index 5abd1454fb07d3025184de6731afad654176ae02..0f65a9de5f749719b9b778cd8c989680b0b1eb4d 100644 (file)
@@ -396,12 +396,12 @@ batadv_add_packet(struct batadv_priv *bat_priv,
                return NULL;
 
        len = sizeof(*packet) + vis_info_len;
-       info->skb_packet = dev_alloc_skb(len + ETH_HLEN);
+       info->skb_packet = dev_alloc_skb(len + ETH_HLEN + NET_IP_ALIGN);
        if (!info->skb_packet) {
                kfree(info);
                return NULL;
        }
-       skb_reserve(info->skb_packet, ETH_HLEN);
+       skb_reserve(info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
        packet = (struct batadv_vis_packet *)skb_put(info->skb_packet, len);
 
        kref_init(&info->refcount);
@@ -698,15 +698,12 @@ static void batadv_purge_vis_packets(struct batadv_priv *bat_priv)
 static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
                                        struct batadv_vis_info *info)
 {
-       struct batadv_neigh_node *router;
        struct batadv_hashtable *hash = bat_priv->orig_hash;
        struct hlist_node *node;
        struct hlist_head *head;
        struct batadv_orig_node *orig_node;
        struct batadv_vis_packet *packet;
        struct sk_buff *skb;
-       struct batadv_hard_iface *hard_iface;
-       uint8_t dstaddr[ETH_ALEN];
        uint32_t i;
 
 
@@ -722,30 +719,20 @@ static void batadv_broadcast_vis_packet(struct batadv_priv *bat_priv,
                        if (!(orig_node->flags & BATADV_VIS_SERVER))
                                continue;
 
-                       router = batadv_orig_node_get_router(orig_node);
-                       if (!router)
-                               continue;
-
                        /* don't send it if we already received the packet from
                         * this node.
                         */
                        if (batadv_recv_list_is_in(bat_priv, &info->recv_list,
-                                                  orig_node->orig)) {
-                               batadv_neigh_node_free_ref(router);
+                                                  orig_node->orig))
                                continue;
-                       }
 
                        memcpy(packet->target_orig, orig_node->orig, ETH_ALEN);
-                       hard_iface = router->if_incoming;
-                       memcpy(dstaddr, router->addr, ETH_ALEN);
-
-                       batadv_neigh_node_free_ref(router);
-
                        skb = skb_clone(info->skb_packet, GFP_ATOMIC);
-                       if (skb)
-                               batadv_send_skb_packet(skb, hard_iface,
-                                                      dstaddr);
+                       if (!skb)
+                               continue;
 
+                       if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
+                               kfree_skb(skb);
                }
                rcu_read_unlock();
        }
@@ -755,7 +742,6 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
                                      struct batadv_vis_info *info)
 {
        struct batadv_orig_node *orig_node;
-       struct batadv_neigh_node *router = NULL;
        struct sk_buff *skb;
        struct batadv_vis_packet *packet;
 
@@ -765,17 +751,14 @@ static void batadv_unicast_vis_packet(struct batadv_priv *bat_priv,
        if (!orig_node)
                goto out;
 
-       router = batadv_orig_node_get_router(orig_node);
-       if (!router)
+       skb = skb_clone(info->skb_packet, GFP_ATOMIC);
+       if (!skb)
                goto out;
 
-       skb = skb_clone(info->skb_packet, GFP_ATOMIC);
-       if (skb)
-               batadv_send_skb_packet(skb, router->if_incoming, router->addr);
+       if (!batadv_send_skb_to_orig(skb, orig_node, NULL))
+               kfree_skb(skb);
 
 out:
-       if (router)
-               batadv_neigh_node_free_ref(router);
        if (orig_node)
                batadv_orig_node_free_ref(orig_node);
 }
@@ -873,12 +856,13 @@ int batadv_vis_init(struct batadv_priv *bat_priv)
        if (!bat_priv->vis.my_info)
                goto err;
 
-       len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN;
+       len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE;
+       len += ETH_HLEN + NET_IP_ALIGN;
        bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len);
        if (!bat_priv->vis.my_info->skb_packet)
                goto free_info;
 
-       skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN);
+       skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN + NET_IP_ALIGN);
        tmp_skb = bat_priv->vis.my_info->skb_packet;
        packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet));
 
index d0359ea8ee7901472adee37ff9f22e62d51ce585..e859098f5ee9b11468e4de7159b9d2cdeaa8e84b 100644 (file)
@@ -12,6 +12,6 @@ bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
 
 bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o
 
-bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o
+bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o
 
 obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/
index 070e8a68cfc63f856b281b4f19e08181cbd5172f..7c78e264019000fe48d4bed8c22a86f6b7b4131d 100644 (file)
@@ -313,6 +313,8 @@ static const struct net_device_ops br_netdev_ops = {
        .ndo_fdb_add             = br_fdb_add,
        .ndo_fdb_del             = br_fdb_delete,
        .ndo_fdb_dump            = br_fdb_dump,
+       .ndo_bridge_getlink      = br_getlink,
+       .ndo_bridge_setlink      = br_setlink,
 };
 
 static void br_dev_free(struct net_device *dev)
@@ -356,7 +358,7 @@ void br_dev_setup(struct net_device *dev)
        br->bridge_id.prio[0] = 0x80;
        br->bridge_id.prio[1] = 0x00;
 
-       memcpy(br->group_addr, br_group_address, ETH_ALEN);
+       memcpy(br->group_addr, eth_reserved_addr_base, ETH_ALEN);
 
        br->stp_enabled = BR_NO_STP;
        br->group_fwd_mask = BR_GROUPFWD_DEFAULT;
index 76f15fda0212b9756d6110ea0f105edca4b3d25f..4b34207419b1cfbe39ca54321cf9087101bab155 100644 (file)
@@ -19,9 +19,6 @@
 #include <linux/export.h>
 #include "br_private.h"
 
-/* Bridge group multicast address 802.1d (pg 51). */
-const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 };
-
 /* Hook for brouter */
 br_should_route_hook_t __rcu *br_should_route_hook __read_mostly;
 EXPORT_SYMBOL(br_should_route_hook);
@@ -127,18 +124,6 @@ static int br_handle_local_finish(struct sk_buff *skb)
        return 0;        /* process further */
 }
 
-/* Does address match the link local multicast address.
- * 01:80:c2:00:00:0X
- */
-static inline int is_link_local(const unsigned char *dest)
-{
-       __be16 *a = (__be16 *)dest;
-       static const __be16 *b = (const __be16 *)br_group_address;
-       static const __be16 m = cpu_to_be16(0xfff0);
-
-       return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | ((a[2] ^ b[2]) & m)) == 0;
-}
-
 /*
  * Return NULL if skb is handled
  * note: already called with rcu_read_lock
@@ -162,7 +147,7 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
 
        p = br_port_get_rcu(skb->dev);
 
-       if (unlikely(is_link_local(dest))) {
+       if (unlikely(is_link_local_ether_addr(dest))) {
                /*
                 * See IEEE 802.1D Table 7-10 Reserved addresses
                 *
index 7222fe1d5460203ad5d1edff1ee5331d49fdb036..cd8c3a44ab7dccbdb82ddb0cba3fe0a8c2e978c0 100644 (file)
@@ -85,13 +85,14 @@ static int get_fdb_entries(struct net_bridge *br, void __user *userbuf,
 /* called with RTNL */
 static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
 {
+       struct net *net = dev_net(br->dev);
        struct net_device *dev;
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
-       dev = __dev_get_by_index(dev_net(br->dev), ifindex);
+       dev = __dev_get_by_index(net, ifindex);
        if (dev == NULL)
                return -EINVAL;
 
@@ -178,25 +179,25 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        }
 
        case BRCTL_SET_BRIDGE_FORWARD_DELAY:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                return br_set_forward_delay(br, args[1]);
 
        case BRCTL_SET_BRIDGE_HELLO_TIME:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                return br_set_hello_time(br, args[1]);
 
        case BRCTL_SET_BRIDGE_MAX_AGE:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                return br_set_max_age(br, args[1]);
 
        case BRCTL_SET_AGEING_TIME:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                br->ageing_time = clock_t_to_jiffies(args[1]);
@@ -236,14 +237,14 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        }
 
        case BRCTL_SET_BRIDGE_STP_STATE:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                br_stp_set_enabled(br, args[1]);
                return 0;
 
        case BRCTL_SET_BRIDGE_PRIORITY:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                spin_lock_bh(&br->lock);
@@ -256,7 +257,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                struct net_bridge_port *p;
                int ret;
 
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                spin_lock_bh(&br->lock);
@@ -273,7 +274,7 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                struct net_bridge_port *p;
                int ret;
 
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(dev_net(dev)->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                spin_lock_bh(&br->lock);
@@ -330,7 +331,7 @@ static int old_deviceless(struct net *net, void __user *uarg)
        {
                char buf[IFNAMSIZ];
 
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                if (copy_from_user(buf, (void __user *)args[1], IFNAMSIZ))
@@ -360,7 +361,7 @@ int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uar
        {
                char buf[IFNAMSIZ];
 
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                if (copy_from_user(buf, uarg, IFNAMSIZ))
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
new file mode 100644 (file)
index 0000000..ccc43a9
--- /dev/null
@@ -0,0 +1,161 @@
+#include <linux/err.h>
+#include <linux/igmp.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/rculist.h>
+#include <linux/skbuff.h>
+#include <net/ip.h>
+#include <net/netlink.h>
+#if IS_ENABLED(CONFIG_IPV6)
+#include <net/ipv6.h>
+#endif
+
+#include "br_private.h"
+
+static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
+                              struct net_device *dev)
+{
+       struct net_bridge *br = netdev_priv(dev);
+       struct net_bridge_port *p;
+       struct hlist_node *n;
+       struct nlattr *nest;
+
+       if (!br->multicast_router || hlist_empty(&br->router_list))
+               return 0;
+
+       nest = nla_nest_start(skb, MDBA_ROUTER);
+       if (nest == NULL)
+               return -EMSGSIZE;
+
+       hlist_for_each_entry_rcu(p, n, &br->router_list, rlist) {
+               if (p && nla_put_u32(skb, MDBA_ROUTER_PORT, p->dev->ifindex))
+                       goto fail;
+       }
+
+       nla_nest_end(skb, nest);
+       return 0;
+fail:
+       nla_nest_cancel(skb, nest);
+       return -EMSGSIZE;
+}
+
+static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
+                           struct net_device *dev)
+{
+       struct net_bridge *br = netdev_priv(dev);
+       struct net_bridge_mdb_htable *mdb;
+       struct nlattr *nest, *nest2;
+       int i, err = 0;
+       int idx = 0, s_idx = cb->args[1];
+
+       if (br->multicast_disabled)
+               return 0;
+
+       mdb = rcu_dereference(br->mdb);
+       if (!mdb)
+               return 0;
+
+       nest = nla_nest_start(skb, MDBA_MDB);
+       if (nest == NULL)
+               return -EMSGSIZE;
+
+       for (i = 0; i < mdb->max; i++) {
+               struct hlist_node *h;
+               struct net_bridge_mdb_entry *mp;
+               struct net_bridge_port_group *p, **pp;
+               struct net_bridge_port *port;
+
+               hlist_for_each_entry_rcu(mp, h, &mdb->mhash[i], hlist[mdb->ver]) {
+                       if (idx < s_idx)
+                               goto skip;
+
+                       nest2 = nla_nest_start(skb, MDBA_MDB_ENTRY);
+                       if (nest2 == NULL) {
+                               err = -EMSGSIZE;
+                               goto out;
+                       }
+
+                       for (pp = &mp->ports;
+                            (p = rcu_dereference(*pp)) != NULL;
+                             pp = &p->next) {
+                               port = p->port;
+                               if (port) {
+                                       struct br_mdb_entry e;
+                                       e.ifindex = port->dev->ifindex;
+                                       e.addr.u.ip4 = p->addr.u.ip4;
+#if IS_ENABLED(CONFIG_IPV6)
+                                       e.addr.u.ip6 = p->addr.u.ip6;
+#endif
+                                       e.addr.proto = p->addr.proto;
+                                       if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) {
+                                               nla_nest_cancel(skb, nest2);
+                                               err = -EMSGSIZE;
+                                               goto out;
+                                       }
+                               }
+                       }
+                       nla_nest_end(skb, nest2);
+               skip:
+                       idx++;
+               }
+       }
+
+out:
+       cb->args[1] = idx;
+       nla_nest_end(skb, nest);
+       return err;
+}
+
+static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct net_device *dev;
+       struct net *net = sock_net(skb->sk);
+       struct nlmsghdr *nlh = NULL;
+       int idx = 0, s_idx;
+
+       s_idx = cb->args[0];
+
+       rcu_read_lock();
+
+       /* In theory this could be wrapped to 0... */
+       cb->seq = net->dev_base_seq + br_mdb_rehash_seq;
+
+       for_each_netdev_rcu(net, dev) {
+               if (dev->priv_flags & IFF_EBRIDGE) {
+                       struct br_port_msg *bpm;
+
+                       if (idx < s_idx)
+                               goto skip;
+
+                       nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid,
+                                       cb->nlh->nlmsg_seq, RTM_GETMDB,
+                                       sizeof(*bpm), NLM_F_MULTI);
+                       if (nlh == NULL)
+                               break;
+
+                       bpm = nlmsg_data(nlh);
+                       bpm->ifindex = dev->ifindex;
+                       if (br_mdb_fill_info(skb, cb, dev) < 0)
+                               goto out;
+                       if (br_rports_fill_info(skb, cb, dev) < 0)
+                               goto out;
+
+                       cb->args[1] = 0;
+                       nlmsg_end(skb, nlh);
+               skip:
+                       idx++;
+               }
+       }
+
+out:
+       if (nlh)
+               nlmsg_end(skb, nlh);
+       rcu_read_unlock();
+       cb->args[0] = idx;
+       return skb->len;
+}
+
+void br_mdb_init(void)
+{
+       rtnl_register(PF_BRIDGE, RTM_GETMDB, NULL, br_mdb_dump, NULL);
+}
index 241743417f498bdc9c8c63fe2500a78f9a4d2126..847b98a1d5e06f145d3eca92f5baa148d9c91352 100644 (file)
@@ -37,6 +37,7 @@
        rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock))
 
 static void br_multicast_start_querier(struct net_bridge *br);
+unsigned int br_mdb_rehash_seq;
 
 #if IS_ENABLED(CONFIG_IPV6)
 static inline int ipv6_is_transient_multicast(const struct in6_addr *addr)
@@ -338,6 +339,7 @@ static int br_mdb_rehash(struct net_bridge_mdb_htable __rcu **mdbp, int max,
                return err;
        }
 
+       br_mdb_rehash_seq++;
        call_rcu_bh(&mdb->rcu, br_mdb_free);
 
 out:
@@ -1225,6 +1227,27 @@ static void br_multicast_leave_group(struct net_bridge *br,
        if (!mp)
                goto out;
 
+       if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
+               struct net_bridge_port_group __rcu **pp;
+
+               for (pp = &mp->ports;
+                    (p = mlock_dereference(*pp, br)) != NULL;
+                    pp = &p->next) {
+                       if (p->port != port)
+                               continue;
+
+                       rcu_assign_pointer(*pp, p->next);
+                       hlist_del_init(&p->mglist);
+                       del_timer(&p->timer);
+                       call_rcu_bh(&p->rcu, br_multicast_free_pg);
+
+                       if (!mp->ports && !mp->mglist &&
+                           netif_running(br->dev))
+                               mod_timer(&mp->timer, jiffies);
+               }
+               goto out;
+       }
+
        now = jiffies;
        time = now + br->multicast_last_member_count *
                     br->multicast_last_member_interval;
@@ -1584,6 +1607,7 @@ void br_multicast_init(struct net_bridge *br)
                    br_multicast_querier_expired, (unsigned long)br);
        setup_timer(&br->multicast_query_timer, br_multicast_query_expired,
                    (unsigned long)br);
+       br_mdb_init();
 }
 
 void br_multicast_open(struct net_bridge *br)
index 093f527276a39c097de23cea8ab7e4016df438cc..dead9dfe865b517247723d025cb0006cc5b44621 100644 (file)
 #include "br_private.h"
 #include "br_private_stp.h"
 
+static inline size_t br_port_info_size(void)
+{
+       return nla_total_size(1)        /* IFLA_BRPORT_STATE  */
+               + nla_total_size(2)     /* IFLA_BRPORT_PRIORITY */
+               + nla_total_size(4)     /* IFLA_BRPORT_COST */
+               + nla_total_size(1)     /* IFLA_BRPORT_MODE */
+               + nla_total_size(1)     /* IFLA_BRPORT_GUARD */
+               + nla_total_size(1)     /* IFLA_BRPORT_PROTECT */
+               + 0;
+}
+
 static inline size_t br_nlmsg_size(void)
 {
        return NLMSG_ALIGN(sizeof(struct ifinfomsg))
-              + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
-              + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
-              + nla_total_size(4) /* IFLA_MASTER */
-              + nla_total_size(4) /* IFLA_MTU */
-              + nla_total_size(4) /* IFLA_LINK */
-              + nla_total_size(1) /* IFLA_OPERSTATE */
-              + nla_total_size(1); /* IFLA_PROTINFO */
+               + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
+               + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
+               + nla_total_size(4) /* IFLA_MASTER */
+               + nla_total_size(4) /* IFLA_MTU */
+               + nla_total_size(4) /* IFLA_LINK */
+               + nla_total_size(1) /* IFLA_OPERSTATE */
+               + nla_total_size(br_port_info_size()); /* IFLA_PROTINFO */
+}
+
+static int br_port_fill_attrs(struct sk_buff *skb,
+                             const struct net_bridge_port *p)
+{
+       u8 mode = !!(p->flags & BR_HAIRPIN_MODE);
+
+       if (nla_put_u8(skb, IFLA_BRPORT_STATE, p->state) ||
+           nla_put_u16(skb, IFLA_BRPORT_PRIORITY, p->priority) ||
+           nla_put_u32(skb, IFLA_BRPORT_COST, p->path_cost) ||
+           nla_put_u8(skb, IFLA_BRPORT_MODE, mode) ||
+           nla_put_u8(skb, IFLA_BRPORT_GUARD, !!(p->flags & BR_BPDU_GUARD)) ||
+           nla_put_u8(skb, IFLA_BRPORT_PROTECT, !!(p->flags & BR_ROOT_BLOCK)) ||
+           nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, !!(p->flags & BR_MULTICAST_FAST_LEAVE)))
+               return -EMSGSIZE;
+
+       return 0;
 }
 
 /*
@@ -67,10 +95,18 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
            (dev->addr_len &&
             nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
            (dev->ifindex != dev->iflink &&
-            nla_put_u32(skb, IFLA_LINK, dev->iflink)) ||
-           (event == RTM_NEWLINK &&
-            nla_put_u8(skb, IFLA_PROTINFO, port->state)))
+            nla_put_u32(skb, IFLA_LINK, dev->iflink)))
                goto nla_put_failure;
+
+       if (event == RTM_NEWLINK) {
+               struct nlattr *nest
+                       = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
+
+               if (nest == NULL || br_port_fill_attrs(skb, port) < 0)
+                       goto nla_put_failure;
+               nla_nest_end(skb, nest);
+       }
+
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
@@ -111,89 +147,134 @@ errout:
 /*
  * Dump information about all ports, in response to GETLINK
  */
-static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
+int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+              struct net_device *dev)
 {
-       struct net *net = sock_net(skb->sk);
-       struct net_device *dev;
-       int idx;
-
-       idx = 0;
-       rcu_read_lock();
-       for_each_netdev_rcu(net, dev) {
-               struct net_bridge_port *port = br_port_get_rcu(dev);
-
-               /* not a bridge port */
-               if (!port || idx < cb->args[0])
-                       goto skip;
-
-               if (br_fill_ifinfo(skb, port,
-                                  NETLINK_CB(cb->skb).portid,
-                                  cb->nlh->nlmsg_seq, RTM_NEWLINK,
-                                  NLM_F_MULTI) < 0)
-                       break;
-skip:
-               ++idx;
+       int err = 0;
+       struct net_bridge_port *port = br_port_get_rcu(dev);
+
+       /* not a bridge port */
+       if (!port)
+               goto out;
+
+       err = br_fill_ifinfo(skb, port, pid, seq, RTM_NEWLINK, NLM_F_MULTI);
+out:
+       return err;
+}
+
+static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
+       [IFLA_BRPORT_STATE]     = { .type = NLA_U8 },
+       [IFLA_BRPORT_COST]      = { .type = NLA_U32 },
+       [IFLA_BRPORT_PRIORITY]  = { .type = NLA_U16 },
+       [IFLA_BRPORT_MODE]      = { .type = NLA_U8 },
+       [IFLA_BRPORT_GUARD]     = { .type = NLA_U8 },
+       [IFLA_BRPORT_PROTECT]   = { .type = NLA_U8 },
+};
+
+/* Change the state of the port and notify spanning tree */
+static int br_set_port_state(struct net_bridge_port *p, u8 state)
+{
+       if (state > BR_STATE_BLOCKING)
+               return -EINVAL;
+
+       /* if kernel STP is running, don't allow changes */
+       if (p->br->stp_enabled == BR_KERNEL_STP)
+               return -EBUSY;
+
+       if (!netif_running(p->dev) ||
+           (!netif_carrier_ok(p->dev) && state != BR_STATE_DISABLED))
+               return -ENETDOWN;
+
+       p->state = state;
+       br_log_state(p);
+       br_port_state_selection(p->br);
+       return 0;
+}
+
+/* Set/clear or port flags based on attribute */
+static void br_set_port_flag(struct net_bridge_port *p, struct nlattr *tb[],
+                          int attrtype, unsigned long mask)
+{
+       if (tb[attrtype]) {
+               u8 flag = nla_get_u8(tb[attrtype]);
+               if (flag)
+                       p->flags |= mask;
+               else
+                       p->flags &= ~mask;
        }
-       rcu_read_unlock();
-       cb->args[0] = idx;
+}
+
+/* Process bridge protocol info on port */
+static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
+{
+       int err;
 
-       return skb->len;
+       br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
+       br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
+       br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
+
+       if (tb[IFLA_BRPORT_COST]) {
+               err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
+               if (err)
+                       return err;
+       }
+
+       if (tb[IFLA_BRPORT_PRIORITY]) {
+               err = br_stp_set_port_priority(p, nla_get_u16(tb[IFLA_BRPORT_PRIORITY]));
+               if (err)
+                       return err;
+       }
+
+       if (tb[IFLA_BRPORT_STATE]) {
+               err = br_set_port_state(p, nla_get_u8(tb[IFLA_BRPORT_STATE]));
+               if (err)
+                       return err;
+       }
+       return 0;
 }
 
-/*
- * Change state of port (ie from forwarding to blocking etc)
- * Used by spanning tree in user space.
- */
-static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
+/* Change state and parameters on port. */
+int br_setlink(struct net_device *dev, struct nlmsghdr *nlh)
 {
-       struct net *net = sock_net(skb->sk);
        struct ifinfomsg *ifm;
        struct nlattr *protinfo;
-       struct net_device *dev;
        struct net_bridge_port *p;
-       u8 new_state;
-
-       if (nlmsg_len(nlh) < sizeof(*ifm))
-               return -EINVAL;
+       struct nlattr *tb[IFLA_BRPORT_MAX + 1];
+       int err;
 
        ifm = nlmsg_data(nlh);
-       if (ifm->ifi_family != AF_BRIDGE)
-               return -EPFNOSUPPORT;
 
        protinfo = nlmsg_find_attr(nlh, sizeof(*ifm), IFLA_PROTINFO);
-       if (!protinfo || nla_len(protinfo) < sizeof(u8))
-               return -EINVAL;
-
-       new_state = nla_get_u8(protinfo);
-       if (new_state > BR_STATE_BLOCKING)
-               return -EINVAL;
-
-       dev = __dev_get_by_index(net, ifm->ifi_index);
-       if (!dev)
-               return -ENODEV;
+       if (!protinfo)
+               return 0;
 
        p = br_port_get_rtnl(dev);
        if (!p)
                return -EINVAL;
 
-       /* if kernel STP is running, don't allow changes */
-       if (p->br->stp_enabled == BR_KERNEL_STP)
-               return -EBUSY;
-
-       if (!netif_running(dev) ||
-           (!netif_carrier_ok(dev) && new_state != BR_STATE_DISABLED))
-               return -ENETDOWN;
-
-       p->state = new_state;
-       br_log_state(p);
+       if (protinfo->nla_type & NLA_F_NESTED) {
+               err = nla_parse_nested(tb, IFLA_BRPORT_MAX,
+                                      protinfo, ifla_brport_policy);
+               if (err)
+                       return err;
+
+               spin_lock_bh(&p->br->lock);
+               err = br_setport(p, tb);
+               spin_unlock_bh(&p->br->lock);
+       } else {
+               /* Binary compatability with old RSTP */
+               if (nla_len(protinfo) < sizeof(u8))
+                       return -EINVAL;
 
-       spin_lock_bh(&p->br->lock);
-       br_port_state_selection(p->br);
-       spin_unlock_bh(&p->br->lock);
+               spin_lock_bh(&p->br->lock);
+               err = br_set_port_state(p, nla_get_u8(protinfo));
+               spin_unlock_bh(&p->br->lock);
+       }
 
-       br_ifinfo_notify(RTM_NEWLINK, p);
+       if (err == 0)
+               br_ifinfo_notify(RTM_NEWLINK, p);
 
-       return 0;
+       return err;
 }
 
 static int br_validate(struct nlattr *tb[], struct nlattr *data[])
@@ -218,29 +299,7 @@ struct rtnl_link_ops br_link_ops __read_mostly = {
 
 int __init br_netlink_init(void)
 {
-       int err;
-
-       err = rtnl_link_register(&br_link_ops);
-       if (err < 0)
-               goto err1;
-
-       err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL,
-                             br_dump_ifinfo, NULL);
-       if (err)
-               goto err2;
-       err = __rtnl_register(PF_BRIDGE, RTM_SETLINK,
-                             br_rtm_setlink, NULL, NULL);
-       if (err)
-               goto err3;
-
-       return 0;
-
-err3:
-       rtnl_unregister_all(PF_BRIDGE);
-err2:
-       rtnl_link_unregister(&br_link_ops);
-err1:
-       return err;
+       return rtnl_link_register(&br_link_ops);
 }
 
 void __exit br_netlink_fini(void)
index 9b278c4ebee10efb45ee07f480f749e609ca891e..f95b766c7a98c5693d56d71a3775c9b22249aad5 100644 (file)
@@ -135,6 +135,9 @@ struct net_bridge_port
 
        unsigned long                   flags;
 #define BR_HAIRPIN_MODE                0x00000001
+#define BR_BPDU_GUARD           0x00000002
+#define BR_ROOT_BLOCK          0x00000004
+#define BR_MULTICAST_FAST_LEAVE        0x00000008
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
        u32                             multicast_startup_queries_sent;
@@ -158,7 +161,9 @@ struct net_bridge_port
 
 static inline struct net_bridge_port *br_port_get_rcu(const struct net_device *dev)
 {
-       struct net_bridge_port *port = rcu_dereference(dev->rx_handler_data);
+       struct net_bridge_port *port =
+                       rcu_dereference_rtnl(dev->rx_handler_data);
+
        return br_port_exists(dev) ? port : NULL;
 }
 
@@ -288,7 +293,6 @@ struct br_input_skb_cb {
        pr_debug("%s: " format,  (br)->dev->name, ##args)
 
 extern struct notifier_block br_device_notifier;
-extern const u8 br_group_address[ETH_ALEN];
 
 /* called under bridge lock */
 static inline int br_is_root_bridge(const struct net_bridge *br)
@@ -407,6 +411,7 @@ extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __us
 
 /* br_multicast.c */
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
+extern unsigned int br_mdb_rehash_seq;
 extern int br_multicast_rcv(struct net_bridge *br,
                            struct net_bridge_port *port,
                            struct sk_buff *skb);
@@ -429,6 +434,7 @@ extern int br_multicast_set_port_router(struct net_bridge_port *p,
 extern int br_multicast_toggle(struct net_bridge *br, unsigned long val);
 extern int br_multicast_set_querier(struct net_bridge *br, unsigned long val);
 extern int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val);
+extern void br_mdb_init(void);
 
 static inline bool br_multicast_is_router(struct net_bridge *br)
 {
@@ -553,6 +559,9 @@ extern struct rtnl_link_ops br_link_ops;
 extern int br_netlink_init(void);
 extern void br_netlink_fini(void);
 extern void br_ifinfo_notify(int event, struct net_bridge_port *port);
+extern int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg);
+extern int br_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+                     struct net_device *dev);
 
 #ifdef CONFIG_SYSFS
 /* br_sysfs_if.c */
@@ -566,10 +575,10 @@ extern void br_sysfs_delbr(struct net_device *dev);
 
 #else
 
-#define br_sysfs_addif(p)      (0)
-#define br_sysfs_renameif(p)   (0)
-#define br_sysfs_addbr(dev)    (0)
-#define br_sysfs_delbr(dev)    do { } while(0)
+static inline int br_sysfs_addif(struct net_bridge_port *p) { return 0; }
+static inline int br_sysfs_renameif(struct net_bridge_port *p) { return 0; }
+static inline int br_sysfs_addbr(struct net_device *dev) { return 0; }
+static inline void br_sysfs_delbr(struct net_device *dev) { return; }
 #endif /* CONFIG_SYSFS */
 
 #endif
index af9a12099ba4add30e66055fd1a356e16e6813fa..b01849a743101a16e99eebb3a0ef653242c98330 100644 (file)
@@ -100,6 +100,21 @@ static int br_should_become_root_port(const struct net_bridge_port *p,
        return 0;
 }
 
+static void br_root_port_block(const struct net_bridge *br,
+                              struct net_bridge_port *p)
+{
+
+       br_notice(br, "port %u(%s) tried to become root port (blocked)",
+                 (unsigned int) p->port_no, p->dev->name);
+
+       p->state = BR_STATE_LISTENING;
+       br_log_state(p);
+       br_ifinfo_notify(RTM_NEWLINK, p);
+
+       if (br->forward_delay > 0)
+               mod_timer(&p->forward_delay_timer, jiffies + br->forward_delay);
+}
+
 /* called under bridge lock */
 static void br_root_selection(struct net_bridge *br)
 {
@@ -107,7 +122,12 @@ static void br_root_selection(struct net_bridge *br)
        u16 root_port = 0;
 
        list_for_each_entry(p, &br->port_list, list) {
-               if (br_should_become_root_port(p, root_port))
+               if (!br_should_become_root_port(p, root_port))
+                       continue;
+
+               if (p->flags & BR_ROOT_BLOCK)
+                       br_root_port_block(br, p);
+               else
                        root_port = p->port_no;
        }
 
index fd30a6022dea94311ea7002dc872d978b87d9c3a..7f884e3fb9554328b1e39650d5708a21b9f92a57 100644 (file)
@@ -170,6 +170,13 @@ void br_stp_rcv(const struct stp_proto *proto, struct sk_buff *skb,
        if (!ether_addr_equal(dest, br->group_addr))
                goto out;
 
+       if (p->flags & BR_BPDU_GUARD) {
+               br_notice(br, "BPDU received on blocked port %u(%s)\n",
+                         (unsigned int) p->port_no, p->dev->name);
+               br_stp_disable_port(p);
+               goto out;
+       }
+
        buf = skb_pull(skb, 3);
 
        if (buf[0] == BPDU_TYPE_CONFIG) {
index c5c059333eab675aeb73d4bf640f2b784d274902..5913a3a0047b35575fa45ebfd7d3a74cad7b75d9 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/capability.h>
 #include <linux/kernel.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/if_bridge.h>
 #include <linux/rtnetlink.h>
 #include <linux/spinlock.h>
@@ -36,7 +37,7 @@ static ssize_t store_bridge_parm(struct device *d,
        unsigned long val;
        int err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        val = simple_strtoul(buf, &endp, 0);
@@ -132,7 +133,7 @@ static ssize_t store_stp_state(struct device *d,
        char *endp;
        unsigned long val;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        val = simple_strtoul(buf, &endp, 0);
@@ -165,7 +166,7 @@ static ssize_t store_group_fwd_mask(struct device *d,
        char *endp;
        unsigned long val;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        val = simple_strtoul(buf, &endp, 0);
@@ -297,23 +298,18 @@ static ssize_t store_group_addr(struct device *d,
                                const char *buf, size_t len)
 {
        struct net_bridge *br = to_bridge(d);
-       unsigned int new_addr[6];
+       u8 new_addr[6];
        int i;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
-       if (sscanf(buf, "%x:%x:%x:%x:%x:%x",
+       if (sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
                   &new_addr[0], &new_addr[1], &new_addr[2],
                   &new_addr[3], &new_addr[4], &new_addr[5]) != 6)
                return -EINVAL;
 
-       /* Must be 01:80:c2:00:00:0X */
-       for (i = 0; i < 5; i++)
-               if (new_addr[i] != br_group_address[i])
-                       return -EINVAL;
-
-       if (new_addr[5] & ~0xf)
+       if (!is_link_local_ether_addr(new_addr))
                return -EINVAL;
 
        if (new_addr[5] == 1 ||         /* 802.3x Pause address */
@@ -337,7 +333,7 @@ static ssize_t store_flush(struct device *d,
 {
        struct net_bridge *br = to_bridge(d);
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(dev_net(br->dev)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        br_fdb_flush(br);
index 13b36bdc76a79f19d48ac3ad35b460dfb77e5e8e..a1ef1b6e14dc0df71bc72bf6a5ca18bdc8d255cc 100644 (file)
@@ -34,6 +34,28 @@ const struct brport_attribute brport_attr_##_name = {                \
        .store  = _store,                                       \
 };
 
+#define BRPORT_ATTR_FLAG(_name, _mask)                         \
+static ssize_t show_##_name(struct net_bridge_port *p, char *buf) \
+{                                                              \
+       return sprintf(buf, "%d\n", !!(p->flags & _mask));      \
+}                                                              \
+static int store_##_name(struct net_bridge_port *p, unsigned long v) \
+{                                                              \
+       unsigned long flags = p->flags;                         \
+       if (v)                                                  \
+               flags |= _mask;                                 \
+       else                                                    \
+               flags &= ~_mask;                                \
+       if (flags != p->flags) {                                \
+               p->flags = flags;                               \
+               br_ifinfo_notify(RTM_NEWLINK, p);               \
+       }                                                       \
+       return 0;                                               \
+}                                                              \
+static BRPORT_ATTR(_name, S_IRUGO | S_IWUSR,                   \
+                  show_##_name, store_##_name)
+
+
 static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
 {
        return sprintf(buf, "%d\n", p->path_cost);
@@ -133,21 +155,9 @@ static int store_flush(struct net_bridge_port *p, unsigned long v)
 }
 static BRPORT_ATTR(flush, S_IWUSR, NULL, store_flush);
 
-static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf)
-{
-       int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0;
-       return sprintf(buf, "%d\n", hairpin_mode);
-}
-static int store_hairpin_mode(struct net_bridge_port *p, unsigned long v)
-{
-       if (v)
-               p->flags |= BR_HAIRPIN_MODE;
-       else
-               p->flags &= ~BR_HAIRPIN_MODE;
-       return 0;
-}
-static BRPORT_ATTR(hairpin_mode, S_IRUGO | S_IWUSR,
-                  show_hairpin_mode, store_hairpin_mode);
+BRPORT_ATTR_FLAG(hairpin_mode, BR_HAIRPIN_MODE);
+BRPORT_ATTR_FLAG(bpdu_guard, BR_BPDU_GUARD);
+BRPORT_ATTR_FLAG(root_block, BR_ROOT_BLOCK);
 
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
 static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf)
@@ -162,6 +172,8 @@ static int store_multicast_router(struct net_bridge_port *p,
 }
 static BRPORT_ATTR(multicast_router, S_IRUGO | S_IWUSR, show_multicast_router,
                   store_multicast_router);
+
+BRPORT_ATTR_FLAG(multicast_fast_leave, BR_MULTICAST_FAST_LEAVE);
 #endif
 
 static const struct brport_attribute *brport_attrs[] = {
@@ -181,8 +193,11 @@ static const struct brport_attribute *brport_attrs[] = {
        &brport_attr_hold_timer,
        &brport_attr_flush,
        &brport_attr_hairpin_mode,
+       &brport_attr_bpdu_guard,
+       &brport_attr_root_block,
 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
        &brport_attr_multicast_router,
+       &brport_attr_multicast_fast_leave,
 #endif
        NULL
 };
@@ -209,7 +224,7 @@ static ssize_t brport_store(struct kobject * kobj,
        char *endp;
        unsigned long val;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(dev_net(p->dev)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        val = simple_strtoul(buf, &endp, 0);
index fd7cbf5aa8956732f51637eeab3f512e00743fcb..3ebc8cbc91fff419097799784dad4aa374ced101 100644 (file)
@@ -126,20 +126,16 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what,
        struct net_device *dev = arg;
        struct caif_dev_common common;
        struct cflayer *layer, *link_support;
-       struct usbnet   *usbnet = netdev_priv(dev);
-       struct usb_device       *usbdev = usbnet->udev;
-       struct ethtool_drvinfo drvinfo;
+       struct usbnet *usbnet;
+       struct usb_device *usbdev;
 
-       /*
-        * Quirks: High-jack ethtool to find if we have a NCM device,
-        * and find it's VID/PID.
-        */
-       if (dev->ethtool_ops == NULL || dev->ethtool_ops->get_drvinfo == NULL)
+       /* Check whether we have a NCM device, and find its VID/PID. */
+       if (!(dev->dev.parent && dev->dev.parent->driver &&
+             strcmp(dev->dev.parent->driver->name, "cdc_ncm") == 0))
                return 0;
 
-       dev->ethtool_ops->get_drvinfo(dev, &drvinfo);
-       if (strncmp(drvinfo.driver, "cdc_ncm", 7) != 0)
-               return 0;
+       usbnet = netdev_priv(dev);
+       usbdev = usbnet->udev;
 
        pr_debug("USB CDC NCM device VID:0x%4x PID:0x%4x\n",
                le16_to_cpu(usbdev->descriptor.idVendor),
index 44f270fc2d0672207e42de6747948e430a576311..a376ec1ac0a7b086354b24f498af65bc4d5fc6b2 100644 (file)
@@ -515,8 +515,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt)
                                                          client_layer : NULL);
                        }
 
-                       if (req != NULL)
-                               kfree(req);
+                       kfree(req);
 
                        spin_unlock_bh(&cfctrl->info_list_lock);
                }
index 6f747582718ed28464b4eaa2bd45740939c13506..969b7cdff59d9480e4a7a77cbff72acb0e12eae7 100644 (file)
@@ -1084,6 +1084,9 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                op->sk = sk;
                op->ifindex = ifindex;
 
+               /* ifindex for timeout events w/o previous frame reception */
+               op->rx_ifindex = ifindex;
+
                /* initialize uninitialized (kzalloc) structure */
                hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
                op->timer.function = bcm_rx_timeout_handler;
index 1f5c9785a262e02748b844e325f510f7a8c08dcc..574dda78eb0f0d747eeeb44fb9da74be9618068f 100644 (file)
@@ -751,6 +751,9 @@ static int cgw_create_job(struct sk_buff *skb,  struct nlmsghdr *nlh,
        struct cgw_job *gwj;
        int err = 0;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (nlmsg_len(nlh) < sizeof(*r))
                return -EINVAL;
 
@@ -839,6 +842,9 @@ static int cgw_remove_job(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
        struct can_can_gw ccgw;
        int err = 0;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (nlmsg_len(nlh) < sizeof(*r))
                return -EINVAL;
 
index 159aa8bef9e7fe2f89f9b508c39a209aa92d3c0d..3ef1759403b411fe53595e2ddf1eb6314a4f9ef8 100644 (file)
@@ -2300,10 +2300,11 @@ restart:
                        mutex_unlock(&con->mutex);
                        return;
                } else {
-                       con->ops->put(con);
                        dout("con_work %p FAILED to back off %lu\n", con,
                             con->delay);
+                       set_bit(CON_FLAG_BACKOFF, &con->flags);
                }
+               goto done;
        }
 
        if (con->state == CON_STATE_STANDBY) {
@@ -2749,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)
                msg = con->ops->alloc_msg(con, hdr, skip);
                mutex_lock(&con->mutex);
                if (con->state != CON_STATE_OPEN) {
-                       ceph_msg_put(msg);
+                       if (msg)
+                               ceph_msg_put(msg);
                        return -EAGAIN;
                }
                con->in_msg = msg;
index 09cb3f6dc40c4a573a9597ca851b9a91a09a1c3d..47838509f5fd91ef01f2d6012821c071e1e512dc 100644 (file)
 #define PTYPE_HASH_MASK        (PTYPE_HASH_SIZE - 1)
 
 static DEFINE_SPINLOCK(ptype_lock);
+static DEFINE_SPINLOCK(offload_lock);
 static struct list_head ptype_base[PTYPE_HASH_SIZE] __read_mostly;
 static struct list_head ptype_all __read_mostly;       /* Taps */
+static struct list_head offload_base __read_mostly;
 
 /*
  * The @dev_base_head list is protected by @dev_base_lock and the rtnl
@@ -201,6 +203,8 @@ static struct list_head ptype_all __read_mostly;    /* Taps */
 DEFINE_RWLOCK(dev_base_lock);
 EXPORT_SYMBOL(dev_base_lock);
 
+DEFINE_SEQLOCK(devnet_rename_seq);
+
 static inline void dev_base_seq_inc(struct net *net)
 {
        while (++net->dev_base_seq == 0);
@@ -470,6 +474,82 @@ void dev_remove_pack(struct packet_type *pt)
 }
 EXPORT_SYMBOL(dev_remove_pack);
 
+
+/**
+ *     dev_add_offload - register offload handlers
+ *     @po: protocol offload declaration
+ *
+ *     Add protocol offload handlers to the networking stack. The passed
+ *     &proto_offload is linked into kernel lists and may not be freed until
+ *     it has been removed from the kernel lists.
+ *
+ *     This call does not sleep therefore it can not
+ *     guarantee all CPU's that are in middle of receiving packets
+ *     will see the new offload handlers (until the next received packet).
+ */
+void dev_add_offload(struct packet_offload *po)
+{
+       struct list_head *head = &offload_base;
+
+       spin_lock(&offload_lock);
+       list_add_rcu(&po->list, head);
+       spin_unlock(&offload_lock);
+}
+EXPORT_SYMBOL(dev_add_offload);
+
+/**
+ *     __dev_remove_offload     - remove offload handler
+ *     @po: packet offload declaration
+ *
+ *     Remove a protocol offload handler that was previously added to the
+ *     kernel offload handlers by dev_add_offload(). The passed &offload_type
+ *     is removed from the kernel lists and can be freed or reused once this
+ *     function returns.
+ *
+ *      The packet type might still be in use by receivers
+ *     and must not be freed until after all the CPU's have gone
+ *     through a quiescent state.
+ */
+void __dev_remove_offload(struct packet_offload *po)
+{
+       struct list_head *head = &offload_base;
+       struct packet_offload *po1;
+
+       spin_lock(&offload_lock);
+
+       list_for_each_entry(po1, head, list) {
+               if (po == po1) {
+                       list_del_rcu(&po->list);
+                       goto out;
+               }
+       }
+
+       pr_warn("dev_remove_offload: %p not found\n", po);
+out:
+       spin_unlock(&offload_lock);
+}
+EXPORT_SYMBOL(__dev_remove_offload);
+
+/**
+ *     dev_remove_offload       - remove packet offload handler
+ *     @po: packet offload declaration
+ *
+ *     Remove a packet offload handler that was previously added to the kernel
+ *     offload handlers by dev_add_offload(). The passed &offload_type is
+ *     removed from the kernel lists and can be freed or reused once this
+ *     function returns.
+ *
+ *     This call sleeps to guarantee that no CPU is looking at the packet
+ *     type after return.
+ */
+void dev_remove_offload(struct packet_offload *po)
+{
+       __dev_remove_offload(po);
+
+       synchronize_net();
+}
+EXPORT_SYMBOL(dev_remove_offload);
+
 /******************************************************************************
 
                      Device Boot-time Settings Routines
@@ -1013,22 +1093,31 @@ int dev_change_name(struct net_device *dev, const char *newname)
        if (dev->flags & IFF_UP)
                return -EBUSY;
 
-       if (strncmp(newname, dev->name, IFNAMSIZ) == 0)
+       write_seqlock(&devnet_rename_seq);
+
+       if (strncmp(newname, dev->name, IFNAMSIZ) == 0) {
+               write_sequnlock(&devnet_rename_seq);
                return 0;
+       }
 
        memcpy(oldname, dev->name, IFNAMSIZ);
 
        err = dev_get_valid_name(net, dev, newname);
-       if (err < 0)
+       if (err < 0) {
+               write_sequnlock(&devnet_rename_seq);
                return err;
+       }
 
 rollback:
        ret = device_rename(&dev->dev, dev->name);
        if (ret) {
                memcpy(dev->name, oldname, IFNAMSIZ);
+               write_sequnlock(&devnet_rename_seq);
                return ret;
        }
 
+       write_sequnlock(&devnet_rename_seq);
+
        write_lock_bh(&dev_base_lock);
        hlist_del_rcu(&dev->name_hlist);
        write_unlock_bh(&dev_base_lock);
@@ -1046,6 +1135,7 @@ rollback:
                /* err >= 0 after dev_alloc_name() or stores the first errno */
                if (err >= 0) {
                        err = ret;
+                       write_seqlock(&devnet_rename_seq);
                        memcpy(dev->name, oldname, IFNAMSIZ);
                        goto rollback;
                } else {
@@ -1075,10 +1165,8 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len)
                return -EINVAL;
 
        if (!len) {
-               if (dev->ifalias) {
-                       kfree(dev->ifalias);
-                       dev->ifalias = NULL;
-               }
+               kfree(dev->ifalias);
+               dev->ifalias = NULL;
                return 0;
        }
 
@@ -1666,7 +1754,7 @@ static inline int deliver_skb(struct sk_buff *skb,
 
 static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)
 {
-       if (ptype->af_packet_priv == NULL)
+       if (!ptype->af_packet_priv || !skb->sk)
                return false;
 
        if (ptype->id_match)
@@ -1994,7 +2082,7 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb,
        netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
-       struct packet_type *ptype;
+       struct packet_offload *ptype;
        __be16 type = skb->protocol;
        int vlan_depth = ETH_HLEN;
        int err;
@@ -2023,18 +2111,17 @@ struct sk_buff *skb_gso_segment(struct sk_buff *skb,
        }
 
        rcu_read_lock();
-       list_for_each_entry_rcu(ptype,
-                       &ptype_base[ntohs(type) & PTYPE_HASH_MASK], list) {
-               if (ptype->type == type && !ptype->dev && ptype->gso_segment) {
+       list_for_each_entry_rcu(ptype, &offload_base, list) {
+               if (ptype->type == type && ptype->callbacks.gso_segment) {
                        if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL)) {
-                               err = ptype->gso_send_check(skb);
+                               err = ptype->callbacks.gso_send_check(skb);
                                segs = ERR_PTR(err);
                                if (err || skb_gso_ok(skb, features))
                                        break;
                                __skb_push(skb, (skb->data -
                                                 skb_network_header(skb)));
                        }
-                       segs = ptype->gso_segment(skb, features);
+                       segs = ptype->callbacks.gso_segment(skb, features);
                        break;
                }
        }
@@ -2237,6 +2324,13 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                        skb->vlan_tci = 0;
                }
 
+               /* If encapsulation offload request, verify we are testing
+                * hardware encapsulation features instead of standard
+                * features for the netdev
+                */
+               if (skb->encapsulation)
+                       features &= dev->hw_enc_features;
+
                if (netif_needs_gso(skb, features)) {
                        if (unlikely(dev_gso_segment(skb, features)))
                                goto out_kfree_skb;
@@ -2252,8 +2346,12 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                         * checksumming here.
                         */
                        if (skb->ip_summed == CHECKSUM_PARTIAL) {
-                               skb_set_transport_header(skb,
-                                       skb_checksum_start_offset(skb));
+                               if (skb->encapsulation)
+                                       skb_set_inner_transport_header(skb,
+                                               skb_checksum_start_offset(skb));
+                               else
+                                       skb_set_transport_header(skb,
+                                               skb_checksum_start_offset(skb));
                                if (!(features & NETIF_F_ALL_CSUM) &&
                                     skb_checksum_help(skb))
                                        goto out_kfree_skb;
@@ -2818,8 +2916,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
                if (unlikely(tcpu != next_cpu) &&
                    (tcpu == RPS_NO_CPU || !cpu_online(tcpu) ||
                     ((int)(per_cpu(softnet_data, tcpu).input_queue_head -
-                     rflow->last_qtail)) >= 0))
+                     rflow->last_qtail)) >= 0)) {
+                       tcpu = next_cpu;
                        rflow = set_rps_cpu(dev, skb, rflow, next_cpu);
+               }
 
                if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) {
                        *rflowp = rflow;
@@ -3444,9 +3544,9 @@ static void flush_backlog(void *arg)
 
 static int napi_gro_complete(struct sk_buff *skb)
 {
-       struct packet_type *ptype;
+       struct packet_offload *ptype;
        __be16 type = skb->protocol;
-       struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
+       struct list_head *head = &offload_base;
        int err = -ENOENT;
 
        if (NAPI_GRO_CB(skb)->count == 1) {
@@ -3456,10 +3556,10 @@ static int napi_gro_complete(struct sk_buff *skb)
 
        rcu_read_lock();
        list_for_each_entry_rcu(ptype, head, list) {
-               if (ptype->type != type || ptype->dev || !ptype->gro_complete)
+               if (ptype->type != type || !ptype->callbacks.gro_complete)
                        continue;
 
-               err = ptype->gro_complete(skb);
+               err = ptype->callbacks.gro_complete(skb);
                break;
        }
        rcu_read_unlock();
@@ -3503,12 +3603,34 @@ void napi_gro_flush(struct napi_struct *napi, bool flush_old)
 }
 EXPORT_SYMBOL(napi_gro_flush);
 
-enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
+static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb)
+{
+       struct sk_buff *p;
+       unsigned int maclen = skb->dev->hard_header_len;
+
+       for (p = napi->gro_list; p; p = p->next) {
+               unsigned long diffs;
+
+               diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
+               diffs |= p->vlan_tci ^ skb->vlan_tci;
+               if (maclen == ETH_HLEN)
+                       diffs |= compare_ether_header(skb_mac_header(p),
+                                                     skb_gro_mac_header(skb));
+               else if (!diffs)
+                       diffs = memcmp(skb_mac_header(p),
+                                      skb_gro_mac_header(skb),
+                                      maclen);
+               NAPI_GRO_CB(p)->same_flow = !diffs;
+               NAPI_GRO_CB(p)->flush = 0;
+       }
+}
+
+static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        struct sk_buff **pp = NULL;
-       struct packet_type *ptype;
+       struct packet_offload *ptype;
        __be16 type = skb->protocol;
-       struct list_head *head = &ptype_base[ntohs(type) & PTYPE_HASH_MASK];
+       struct list_head *head = &offload_base;
        int same_flow;
        int mac_len;
        enum gro_result ret;
@@ -3519,9 +3641,11 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
        if (skb_is_gso(skb) || skb_has_frag_list(skb))
                goto normal;
 
+       gro_list_prepare(napi, skb);
+
        rcu_read_lock();
        list_for_each_entry_rcu(ptype, head, list) {
-               if (ptype->type != type || ptype->dev || !ptype->gro_receive)
+               if (ptype->type != type || !ptype->callbacks.gro_receive)
                        continue;
 
                skb_set_network_header(skb, skb_gro_offset(skb));
@@ -3531,7 +3655,7 @@ enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
                NAPI_GRO_CB(skb)->flush = 0;
                NAPI_GRO_CB(skb)->free = 0;
 
-               pp = ptype->gro_receive(&napi->gro_list, skb);
+               pp = ptype->callbacks.gro_receive(&napi->gro_list, skb);
                break;
        }
        rcu_read_unlock();
@@ -3594,34 +3718,9 @@ normal:
        ret = GRO_NORMAL;
        goto pull;
 }
-EXPORT_SYMBOL(dev_gro_receive);
-
-static inline gro_result_t
-__napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
-{
-       struct sk_buff *p;
-       unsigned int maclen = skb->dev->hard_header_len;
-
-       for (p = napi->gro_list; p; p = p->next) {
-               unsigned long diffs;
-
-               diffs = (unsigned long)p->dev ^ (unsigned long)skb->dev;
-               diffs |= p->vlan_tci ^ skb->vlan_tci;
-               if (maclen == ETH_HLEN)
-                       diffs |= compare_ether_header(skb_mac_header(p),
-                                                     skb_gro_mac_header(skb));
-               else if (!diffs)
-                       diffs = memcmp(skb_mac_header(p),
-                                      skb_gro_mac_header(skb),
-                                      maclen);
-               NAPI_GRO_CB(p)->same_flow = !diffs;
-               NAPI_GRO_CB(p)->flush = 0;
-       }
 
-       return dev_gro_receive(napi, skb);
-}
 
-gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
+static gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 {
        switch (ret) {
        case GRO_NORMAL:
@@ -3647,7 +3746,6 @@ gro_result_t napi_skb_finish(gro_result_t ret, struct sk_buff *skb)
 
        return ret;
 }
-EXPORT_SYMBOL(napi_skb_finish);
 
 static void skb_gro_reset_offset(struct sk_buff *skb)
 {
@@ -3670,7 +3768,7 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb)
 {
        skb_gro_reset_offset(skb);
 
-       return napi_skb_finish(__napi_gro_receive(napi, skb), skb);
+       return napi_skb_finish(dev_gro_receive(napi, skb), skb);
 }
 EXPORT_SYMBOL(napi_gro_receive);
 
@@ -3699,7 +3797,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi)
 }
 EXPORT_SYMBOL(napi_get_frags);
 
-gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
+static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
                               gro_result_t ret)
 {
        switch (ret) {
@@ -3724,7 +3822,6 @@ gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb,
 
        return ret;
 }
-EXPORT_SYMBOL(napi_frags_finish);
 
 static struct sk_buff *napi_frags_skb(struct napi_struct *napi)
 {
@@ -3769,7 +3866,7 @@ gro_result_t napi_gro_frags(struct napi_struct *napi)
        if (!skb)
                return GRO_DROP;
 
-       return napi_frags_finish(napi, skb, __napi_gro_receive(napi, skb));
+       return napi_frags_finish(napi, skb, dev_gro_receive(napi, skb));
 }
 EXPORT_SYMBOL(napi_gro_frags);
 
@@ -4071,6 +4168,7 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg)
 {
        struct net_device *dev;
        struct ifreq ifr;
+       unsigned seq;
 
        /*
         *      Fetch the caller's info block.
@@ -4079,6 +4177,8 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg)
        if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
                return -EFAULT;
 
+retry:
+       seq = read_seqbegin(&devnet_rename_seq);
        rcu_read_lock();
        dev = dev_get_by_index_rcu(net, ifr.ifr_ifindex);
        if (!dev) {
@@ -4088,6 +4188,8 @@ static int dev_ifname(struct net *net, struct ifreq __user *arg)
 
        strcpy(ifr.ifr_name, dev->name);
        rcu_read_unlock();
+       if (read_seqretry(&devnet_rename_seq, seq))
+               goto retry;
 
        if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
                return -EFAULT;
@@ -4880,7 +4982,7 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
        else
                dev->mtu = new_mtu;
 
-       if (!err && dev->flags & IFF_UP)
+       if (!err)
                call_netdevice_notifiers(NETDEV_CHANGEMTU, dev);
        return err;
 }
@@ -5200,7 +5302,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        case SIOCGMIIPHY:
        case SIOCGMIIREG:
        case SIOCSIFNAME:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
                dev_load(net, ifr.ifr_name);
                rtnl_lock();
@@ -5221,16 +5323,25 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
         *      - require strict serialization.
         *      - do not return a value
         */
+       case SIOCSIFMAP:
+       case SIOCSIFTXQLEN:
+               if (!capable(CAP_NET_ADMIN))
+                       return -EPERM;
+               /* fall through */
+       /*
+        *      These ioctl calls:
+        *      - require local superuser power.
+        *      - require strict serialization.
+        *      - do not return a value
+        */
        case SIOCSIFFLAGS:
        case SIOCSIFMETRIC:
        case SIOCSIFMTU:
-       case SIOCSIFMAP:
        case SIOCSIFHWADDR:
        case SIOCSIFSLAVE:
        case SIOCADDMULTI:
        case SIOCDELMULTI:
        case SIOCSIFHWBROADCAST:
-       case SIOCSIFTXQLEN:
        case SIOCSMIIREG:
        case SIOCBONDENSLAVE:
        case SIOCBONDRELEASE:
@@ -5239,7 +5350,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        case SIOCBRADDIF:
        case SIOCBRDELIF:
        case SIOCSHWTSTAMP:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
                /* fall through */
        case SIOCBONDSLAVEINFOQUERY:
@@ -6264,7 +6375,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
                goto out;
 
        /* Ensure the device has been registrered */
-       err = -EINVAL;
        if (dev->reg_state != NETREG_REGISTERED)
                goto out;
 
@@ -6319,6 +6429,9 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
        dev_uc_flush(dev);
        dev_mc_flush(dev);
 
+       /* Send a netdev-removed uevent to the old namespace */
+       kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE);
+
        /* Actually switch the network namespace */
        dev_net_set(dev, net);
 
@@ -6330,6 +6443,9 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
                        dev->iflink = dev->ifindex;
        }
 
+       /* Send a netdev-add uevent to the new namespace */
+       kobject_uevent(&dev->dev.kobj, KOBJ_ADD);
+
        /* Fixup kobjects */
        err = device_rename(&dev->dev, dev->name);
        WARN_ON(err);
@@ -6662,6 +6778,8 @@ static int __init net_dev_init(void)
        for (i = 0; i < PTYPE_HASH_SIZE; i++)
                INIT_LIST_HEAD(&ptype_base[i]);
 
+       INIT_LIST_HEAD(&offload_base);
+
        if (register_pernet_subsys(&netdev_net_ops))
                goto out;
 
index 87cc17db2d566e5846601d6eb03ba38ce64b2ddb..b079c7bbc157a3c047db12e7a39595da380071e8 100644 (file)
@@ -319,7 +319,8 @@ int dev_addr_del(struct net_device *dev, const unsigned char *addr,
         */
        ha = list_first_entry(&dev->dev_addrs.list,
                              struct netdev_hw_addr, list);
-       if (ha->addr == dev->dev_addr && ha->refcount == 1)
+       if (!memcmp(ha->addr, addr, dev->addr_len) &&
+           ha->type == addr_type && ha->refcount == 1)
                return -ENOENT;
 
        err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
index 4d64cc2e3fa9bf1246ea3504f582616f98060bf1..a8705432e4b1923073b5ed3565daa3baa9d39fa7 100644 (file)
@@ -1460,7 +1460,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr)
        case ETHTOOL_GEEE:
                break;
        default:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
        }
 
index 3d92ebb7fbcf71471d4b3d90e5309f459c47bea0..c23543cba132bc19a213ed242e47386e8e41ca65 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/reciprocal_div.h>
 #include <linux/ratelimit.h>
 #include <linux/seccomp.h>
+#include <linux/if_vlan.h>
 
 /* No hurry in this branch
  *
@@ -341,6 +342,12 @@ load_b:
                case BPF_S_ANC_CPU:
                        A = raw_smp_processor_id();
                        continue;
+               case BPF_S_ANC_VLAN_TAG:
+                       A = vlan_tx_tag_get(skb);
+                       continue;
+               case BPF_S_ANC_VLAN_TAG_PRESENT:
+                       A = !!vlan_tx_tag_present(skb);
+                       continue;
                case BPF_S_ANC_NLATTR: {
                        struct nlattr *nla;
 
@@ -600,6 +607,8 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen)
                        ANCILLARY(RXHASH);
                        ANCILLARY(CPU);
                        ANCILLARY(ALU_XOR_X);
+                       ANCILLARY(VLAN_TAG);
+                       ANCILLARY(VLAN_TAG_PRESENT);
                        }
                }
                ftest->code = code;
@@ -751,3 +760,133 @@ int sk_detach_filter(struct sock *sk)
        return ret;
 }
 EXPORT_SYMBOL_GPL(sk_detach_filter);
+
+static void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to)
+{
+       static const u16 decodes[] = {
+               [BPF_S_ALU_ADD_K]       = BPF_ALU|BPF_ADD|BPF_K,
+               [BPF_S_ALU_ADD_X]       = BPF_ALU|BPF_ADD|BPF_X,
+               [BPF_S_ALU_SUB_K]       = BPF_ALU|BPF_SUB|BPF_K,
+               [BPF_S_ALU_SUB_X]       = BPF_ALU|BPF_SUB|BPF_X,
+               [BPF_S_ALU_MUL_K]       = BPF_ALU|BPF_MUL|BPF_K,
+               [BPF_S_ALU_MUL_X]       = BPF_ALU|BPF_MUL|BPF_X,
+               [BPF_S_ALU_DIV_X]       = BPF_ALU|BPF_DIV|BPF_X,
+               [BPF_S_ALU_MOD_K]       = BPF_ALU|BPF_MOD|BPF_K,
+               [BPF_S_ALU_MOD_X]       = BPF_ALU|BPF_MOD|BPF_X,
+               [BPF_S_ALU_AND_K]       = BPF_ALU|BPF_AND|BPF_K,
+               [BPF_S_ALU_AND_X]       = BPF_ALU|BPF_AND|BPF_X,
+               [BPF_S_ALU_OR_K]        = BPF_ALU|BPF_OR|BPF_K,
+               [BPF_S_ALU_OR_X]        = BPF_ALU|BPF_OR|BPF_X,
+               [BPF_S_ALU_XOR_K]       = BPF_ALU|BPF_XOR|BPF_K,
+               [BPF_S_ALU_XOR_X]       = BPF_ALU|BPF_XOR|BPF_X,
+               [BPF_S_ALU_LSH_K]       = BPF_ALU|BPF_LSH|BPF_K,
+               [BPF_S_ALU_LSH_X]       = BPF_ALU|BPF_LSH|BPF_X,
+               [BPF_S_ALU_RSH_K]       = BPF_ALU|BPF_RSH|BPF_K,
+               [BPF_S_ALU_RSH_X]       = BPF_ALU|BPF_RSH|BPF_X,
+               [BPF_S_ALU_NEG]         = BPF_ALU|BPF_NEG,
+               [BPF_S_LD_W_ABS]        = BPF_LD|BPF_W|BPF_ABS,
+               [BPF_S_LD_H_ABS]        = BPF_LD|BPF_H|BPF_ABS,
+               [BPF_S_LD_B_ABS]        = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_PROTOCOL]    = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_PKTTYPE]     = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_IFINDEX]     = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_NLATTR]      = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_NLATTR_NEST] = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_MARK]        = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_QUEUE]       = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_HATYPE]      = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_RXHASH]      = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_CPU]         = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_ALU_XOR_X]   = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_VLAN_TAG]    = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS,
+               [BPF_S_LD_W_LEN]        = BPF_LD|BPF_W|BPF_LEN,
+               [BPF_S_LD_W_IND]        = BPF_LD|BPF_W|BPF_IND,
+               [BPF_S_LD_H_IND]        = BPF_LD|BPF_H|BPF_IND,
+               [BPF_S_LD_B_IND]        = BPF_LD|BPF_B|BPF_IND,
+               [BPF_S_LD_IMM]          = BPF_LD|BPF_IMM,
+               [BPF_S_LDX_W_LEN]       = BPF_LDX|BPF_W|BPF_LEN,
+               [BPF_S_LDX_B_MSH]       = BPF_LDX|BPF_B|BPF_MSH,
+               [BPF_S_LDX_IMM]         = BPF_LDX|BPF_IMM,
+               [BPF_S_MISC_TAX]        = BPF_MISC|BPF_TAX,
+               [BPF_S_MISC_TXA]        = BPF_MISC|BPF_TXA,
+               [BPF_S_RET_K]           = BPF_RET|BPF_K,
+               [BPF_S_RET_A]           = BPF_RET|BPF_A,
+               [BPF_S_ALU_DIV_K]       = BPF_ALU|BPF_DIV|BPF_K,
+               [BPF_S_LD_MEM]          = BPF_LD|BPF_MEM,
+               [BPF_S_LDX_MEM]         = BPF_LDX|BPF_MEM,
+               [BPF_S_ST]              = BPF_ST,
+               [BPF_S_STX]             = BPF_STX,
+               [BPF_S_JMP_JA]          = BPF_JMP|BPF_JA,
+               [BPF_S_JMP_JEQ_K]       = BPF_JMP|BPF_JEQ|BPF_K,
+               [BPF_S_JMP_JEQ_X]       = BPF_JMP|BPF_JEQ|BPF_X,
+               [BPF_S_JMP_JGE_K]       = BPF_JMP|BPF_JGE|BPF_K,
+               [BPF_S_JMP_JGE_X]       = BPF_JMP|BPF_JGE|BPF_X,
+               [BPF_S_JMP_JGT_K]       = BPF_JMP|BPF_JGT|BPF_K,
+               [BPF_S_JMP_JGT_X]       = BPF_JMP|BPF_JGT|BPF_X,
+               [BPF_S_JMP_JSET_K]      = BPF_JMP|BPF_JSET|BPF_K,
+               [BPF_S_JMP_JSET_X]      = BPF_JMP|BPF_JSET|BPF_X,
+       };
+       u16 code;
+
+       code = filt->code;
+
+       to->code = decodes[code];
+       to->jt = filt->jt;
+       to->jf = filt->jf;
+
+       if (code == BPF_S_ALU_DIV_K) {
+               /*
+                * When loaded this rule user gave us X, which was
+                * translated into R = r(X). Now we calculate the
+                * RR = r(R) and report it back. If next time this
+                * value is loaded and RRR = r(RR) is calculated
+                * then the R == RRR will be true.
+                *
+                * One exception. X == 1 translates into R == 0 and
+                * we can't calculate RR out of it with r().
+                */
+
+               if (filt->k == 0)
+                       to->k = 1;
+               else
+                       to->k = reciprocal_value(filt->k);
+
+               BUG_ON(reciprocal_value(to->k) != filt->k);
+       } else
+               to->k = filt->k;
+}
+
+int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len)
+{
+       struct sk_filter *filter;
+       int i, ret;
+
+       lock_sock(sk);
+       filter = rcu_dereference_protected(sk->sk_filter,
+                       sock_owned_by_user(sk));
+       ret = 0;
+       if (!filter)
+               goto out;
+       ret = filter->len;
+       if (!len)
+               goto out;
+       ret = -EINVAL;
+       if (len < filter->len)
+               goto out;
+
+       ret = -EFAULT;
+       for (i = 0; i < filter->len; i++) {
+               struct sock_filter fb;
+
+               sk_decode_filter(&filter->insns[i], &fb);
+               if (copy_to_user(&ubuf[i], &fb, sizeof(fb)))
+                       goto out;
+       }
+
+       ret = filter->len;
+out:
+       release_sock(sk);
+       return ret;
+}
index e318c7e98042ffcfd1fc43a1d04b5cf816d651a8..b0901ee5a0025f93e32287c1acbb3ef0ded0f47a 100644 (file)
@@ -327,11 +327,9 @@ static void flow_cache_flush_tasklet(unsigned long data)
 static void flow_cache_flush_per_cpu(void *data)
 {
        struct flow_flush_info *info = data;
-       int cpu;
        struct tasklet_struct *tasklet;
 
-       cpu = smp_processor_id();
-       tasklet = &per_cpu_ptr(info->cache->percpu, cpu)->flush_tasklet;
+       tasklet = this_cpu_ptr(&info->cache->percpu->flush_tasklet);
        tasklet->data = (unsigned long)info;
        tasklet_schedule(tasklet);
 }
index 22571488730a7d1bbc2f5f2ec545abf850dcdf4a..c815f285e5ab76e354dd7752f7ef1c1049154570 100644 (file)
@@ -1787,8 +1787,7 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
            nla_put_u32(skb, NDTPA_QUEUE_LENBYTES, parms->queue_len_bytes) ||
            /* approximative value for deprecated QUEUE_LEN (in packets) */
            nla_put_u32(skb, NDTPA_QUEUE_LEN,
-                       DIV_ROUND_UP(parms->queue_len_bytes,
-                                    SKB_TRUESIZE(ETH_FRAME_LEN))) ||
+                       parms->queue_len_bytes / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
            nla_put_u32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen) ||
            nla_put_u32(skb, NDTPA_APP_PROBES, parms->app_probes) ||
            nla_put_u32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes) ||
@@ -2770,6 +2769,8 @@ EXPORT_SYMBOL(neigh_app_ns);
 #endif /* CONFIG_ARPD */
 
 #ifdef CONFIG_SYSCTL
+static int zero;
+static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
 
 static int proc_unres_qlen(ctl_table *ctl, int write, void __user *buffer,
                           size_t *lenp, loff_t *ppos)
@@ -2777,9 +2778,13 @@ static int proc_unres_qlen(ctl_table *ctl, int write, void __user *buffer,
        int size, ret;
        ctl_table tmp = *ctl;
 
+       tmp.extra1 = &zero;
+       tmp.extra2 = &unres_qlen_max;
        tmp.data = &size;
-       size = DIV_ROUND_UP(*(int *)ctl->data, SKB_TRUESIZE(ETH_FRAME_LEN));
-       ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);
+
+       size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
+       ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+
        if (write && !ret)
                *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
        return ret;
@@ -2865,7 +2870,8 @@ static struct neigh_sysctl_table {
                        .procname       = "unres_qlen_bytes",
                        .maxlen         = sizeof(int),
                        .mode           = 0644,
-                       .proc_handler   = proc_dointvec,
+                       .extra1         = &zero,
+                       .proc_handler   = proc_dointvec_minmax,
                },
                [NEIGH_VAR_PROXY_QLEN] = {
                        .procname       = "proxy_qlen",
@@ -2987,6 +2993,10 @@ int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
                t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].extra1 = dev;
        }
 
+       /* Don't export sysctls to unprivileged users */
+       if (neigh_parms_net(p)->user_ns != &init_user_ns)
+               t->neigh_vars[0].procname = NULL;
+
        snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
                p_name, dev_name_source);
        t->sysctl_header =
index 017a8bacfb2773483c97c8fa3b162e03f09f454a..334efd5d67a9efe9706fcd0feca4f0afc3621f2e 100644 (file)
 #include <net/sock.h>
 #include <net/net_namespace.h>
 #include <linux/rtnetlink.h>
-#include <linux/wireless.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
 #include <linux/jiffies.h>
-#include <net/wext.h>
 
 #include "net-sysfs.h"
 
@@ -73,11 +71,12 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
                            const char *buf, size_t len,
                            int (*set)(struct net_device *, unsigned long))
 {
-       struct net_device *net = to_net_dev(dev);
+       struct net_device *netdev = to_net_dev(dev);
+       struct net *net = dev_net(netdev);
        unsigned long new;
        int ret = -EINVAL;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        ret = kstrtoul(buf, 0, &new);
@@ -87,8 +86,8 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr,
        if (!rtnl_trylock())
                return restart_syscall();
 
-       if (dev_isalive(net)) {
-               if ((ret = (*set)(net, new)) == 0)
+       if (dev_isalive(netdev)) {
+               if ((ret = (*set)(netdev, new)) == 0)
                        ret = len;
        }
        rtnl_unlock();
@@ -264,6 +263,9 @@ static ssize_t store_tx_queue_len(struct device *dev,
                                  struct device_attribute *attr,
                                  const char *buf, size_t len)
 {
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        return netdev_store(dev, attr, buf, len, change_tx_queue_len);
 }
 
@@ -271,10 +273,11 @@ static ssize_t store_ifalias(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t len)
 {
        struct net_device *netdev = to_net_dev(dev);
+       struct net *net = dev_net(netdev);
        size_t count = len;
        ssize_t ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        /* ignore trailing newline */
index 42f1e1c7514f67ad56df06ffe53e6c94a094681a..6456439cbbd9e4160c05105554db665226892620 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/proc_fs.h>
 #include <linux/file.h>
 #include <linux/export.h>
+#include <linux/user_namespace.h>
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
@@ -145,7 +146,7 @@ static void ops_free_list(const struct pernet_operations *ops,
 /*
  * setup_net runs the initializers for the network namespace object.
  */
-static __net_init int setup_net(struct net *net)
+static __net_init int setup_net(struct net *net, struct user_namespace *user_ns)
 {
        /* Must be called with net_mutex held */
        const struct pernet_operations *ops, *saved_ops;
@@ -155,6 +156,7 @@ static __net_init int setup_net(struct net *net)
        atomic_set(&net->count, 1);
        atomic_set(&net->passive, 1);
        net->dev_base_seq = 1;
+       net->user_ns = user_ns;
 
 #ifdef NETNS_REFCNT_DEBUG
        atomic_set(&net->use_count, 0);
@@ -232,7 +234,8 @@ void net_drop_ns(void *p)
                net_free(ns);
 }
 
-struct net *copy_net_ns(unsigned long flags, struct net *old_net)
+struct net *copy_net_ns(unsigned long flags,
+                       struct user_namespace *user_ns, struct net *old_net)
 {
        struct net *net;
        int rv;
@@ -243,8 +246,11 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
        net = net_alloc();
        if (!net)
                return ERR_PTR(-ENOMEM);
+
+       get_user_ns(user_ns);
+
        mutex_lock(&net_mutex);
-       rv = setup_net(net);
+       rv = setup_net(net, user_ns);
        if (rv == 0) {
                rtnl_lock();
                list_add_tail_rcu(&net->list, &net_namespace_list);
@@ -252,6 +258,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
        }
        mutex_unlock(&net_mutex);
        if (rv < 0) {
+               put_user_ns(user_ns);
                net_drop_ns(net);
                return ERR_PTR(rv);
        }
@@ -308,6 +315,7 @@ static void cleanup_net(struct work_struct *work)
        /* Finally it is safe to free my network namespace structure */
        list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
                list_del_init(&net->exit_list);
+               put_user_ns(net->user_ns);
                net_drop_ns(net);
        }
 }
@@ -347,13 +355,6 @@ struct net *get_net_ns_by_fd(int fd)
 }
 
 #else
-struct net *copy_net_ns(unsigned long flags, struct net *old_net)
-{
-       if (flags & CLONE_NEWNET)
-               return ERR_PTR(-EINVAL);
-       return old_net;
-}
-
 struct net *get_net_ns_by_fd(int fd)
 {
        return ERR_PTR(-EINVAL);
@@ -402,7 +403,7 @@ static int __init net_ns_init(void)
        rcu_assign_pointer(init_net.gen, ng);
 
        mutex_lock(&net_mutex);
-       if (setup_net(&init_net))
+       if (setup_net(&init_net, &init_user_ns))
                panic("Could not setup the initial network namespace");
 
        rtnl_lock();
index 77a0388fc3beccbf39187e357c7a1b4c93f09d73..3151acf5ec13afb34480a28a3f4a73deae69990a 100644 (file)
@@ -674,7 +674,8 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
                if ((delim = strchr(cur, '@')) == NULL)
                        goto parse_failed;
                *delim = 0;
-               np->local_port = simple_strtol(cur, NULL, 10);
+               if (kstrtou16(cur, 10, &np->local_port))
+                       goto parse_failed;
                cur = delim;
        }
        cur++;
@@ -705,7 +706,8 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
                *delim = 0;
                if (*cur == ' ' || *cur == '\t')
                        np_info(np, "warning: whitespace is not allowed\n");
-               np->remote_port = simple_strtol(cur, NULL, 10);
+               if (kstrtou16(cur, 10, &np->remote_port))
+                       goto parse_failed;
                cur = delim;
        }
        cur++;
index 79285a36035ffa6624c49ee1a0a865558f66859e..847c02b197b0f8b8fdb3624d661d0329c4a9ddd6 100644 (file)
@@ -248,7 +248,7 @@ static int update_netprio(const void *v, struct file *file, unsigned n)
        return 0;
 }
 
-void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
+static void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
 {
        struct task_struct *p;
        void *v;
index d1dc14c2aac4ee00fa6dab706131bbe41d3790f7..b29dacf900f9496a42a565a3b2c48ad9cf502c74 100644 (file)
@@ -419,20 +419,6 @@ struct pktgen_thread {
 #define REMOVE 1
 #define FIND   0
 
-static inline ktime_t ktime_now(void)
-{
-       struct timespec ts;
-       ktime_get_ts(&ts);
-
-       return timespec_to_ktime(ts);
-}
-
-/* This works even if 32 bit because of careful byte order choice */
-static inline int ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
-{
-       return cmp1.tv64 < cmp2.tv64;
-}
-
 static const char version[] =
        "Packet Generator for packet performance testing. "
        "Version: " VERSION "\n";
@@ -675,7 +661,7 @@ static int pktgen_if_show(struct seq_file *seq, void *v)
        seq_puts(seq, "\n");
 
        /* not really stopped, more like last-running-at */
-       stopped = pkt_dev->running ? ktime_now() : pkt_dev->stopped_at;
+       stopped = pkt_dev->running ? ktime_get() : pkt_dev->stopped_at;
        idle = pkt_dev->idle_acc;
        do_div(idle, NSEC_PER_USEC);
 
@@ -2141,12 +2127,12 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
                return;
        }
 
-       start_time = ktime_now();
+       start_time = ktime_get();
        if (remaining < 100000) {
                /* for small delays (<100us), just loop until limit is reached */
                do {
-                       end_time = ktime_now();
-               } while (ktime_lt(end_time, spin_until));
+                       end_time = ktime_get();
+               } while (ktime_compare(end_time, spin_until) < 0);
        } else {
                /* see do_nanosleep */
                hrtimer_init_sleeper(&t, current);
@@ -2162,7 +2148,7 @@ static void spin(struct pktgen_dev *pkt_dev, ktime_t spin_until)
                        hrtimer_cancel(&t.timer);
                } while (t.task && pkt_dev->running && !signal_pending(current));
                __set_current_state(TASK_RUNNING);
-               end_time = ktime_now();
+               end_time = ktime_get();
        }
 
        pkt_dev->idle_acc += ktime_to_ns(ktime_sub(end_time, start_time));
@@ -2427,11 +2413,7 @@ static void mod_cur_headers(struct pktgen_dev *pkt_dev)
                }
        } else {                /* IPV6 * */
 
-               if (pkt_dev->min_in6_daddr.s6_addr32[0] == 0 &&
-                   pkt_dev->min_in6_daddr.s6_addr32[1] == 0 &&
-                   pkt_dev->min_in6_daddr.s6_addr32[2] == 0 &&
-                   pkt_dev->min_in6_daddr.s6_addr32[3] == 0) ;
-               else {
+               if (!ipv6_addr_any(&pkt_dev->min_in6_daddr)) {
                        int i;
 
                        /* Only random destinations yet */
@@ -2916,8 +2898,7 @@ static void pktgen_run(struct pktgen_thread *t)
                        pktgen_clear_counters(pkt_dev);
                        pkt_dev->running = 1;   /* Cranke yeself! */
                        pkt_dev->skb = NULL;
-                       pkt_dev->started_at =
-                               pkt_dev->next_tx = ktime_now();
+                       pkt_dev->started_at = pkt_dev->next_tx = ktime_get();
 
                        set_pkt_overhead(pkt_dev);
 
@@ -3076,7 +3057,7 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev)
 
        kfree_skb(pkt_dev->skb);
        pkt_dev->skb = NULL;
-       pkt_dev->stopped_at = ktime_now();
+       pkt_dev->stopped_at = ktime_get();
        pkt_dev->running = 0;
 
        show_results(pkt_dev, nr_frags);
@@ -3095,7 +3076,7 @@ static struct pktgen_dev *next_to_run(struct pktgen_thread *t)
                        continue;
                if (best == NULL)
                        best = pkt_dev;
-               else if (ktime_lt(pkt_dev->next_tx, best->next_tx))
+               else if (ktime_compare(pkt_dev->next_tx, best->next_tx) < 0)
                        best = pkt_dev;
        }
        if_unlock(t);
@@ -3180,14 +3161,14 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
 
 static void pktgen_resched(struct pktgen_dev *pkt_dev)
 {
-       ktime_t idle_start = ktime_now();
+       ktime_t idle_start = ktime_get();
        schedule();
-       pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
+       pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_get(), idle_start));
 }
 
 static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
 {
-       ktime_t idle_start = ktime_now();
+       ktime_t idle_start = ktime_get();
 
        while (atomic_read(&(pkt_dev->skb->users)) != 1) {
                if (signal_pending(current))
@@ -3198,7 +3179,7 @@ static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
                else
                        cpu_relax();
        }
-       pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_now(), idle_start));
+       pkt_dev->idle_acc += ktime_to_ns(ktime_sub(ktime_get(), idle_start));
 }
 
 static void pktgen_xmit(struct pktgen_dev *pkt_dev)
@@ -3220,7 +3201,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
         * "never transmit"
         */
        if (unlikely(pkt_dev->delay == ULLONG_MAX)) {
-               pkt_dev->next_tx = ktime_add_ns(ktime_now(), ULONG_MAX);
+               pkt_dev->next_tx = ktime_add_ns(ktime_get(), ULONG_MAX);
                return;
        }
 
index 76d4c2c3c89b9d170e89c39fbf0ed5729621a0bc..1868625af25e096d1c7886d29ce6c5967ac1040f 100644 (file)
@@ -128,7 +128,7 @@ static rtnl_doit_func rtnl_get_doit(int protocol, int msgindex)
        if (tab == NULL || tab[msgindex].doit == NULL)
                tab = rtnl_msg_handlers[PF_UNSPEC];
 
-       return tab ? tab[msgindex].doit : NULL;
+       return tab[msgindex].doit;
 }
 
 static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
@@ -143,7 +143,7 @@ static rtnl_dumpit_func rtnl_get_dumpit(int protocol, int msgindex)
        if (tab == NULL || tab[msgindex].dumpit == NULL)
                tab = rtnl_msg_handlers[PF_UNSPEC];
 
-       return tab ? tab[msgindex].dumpit : NULL;
+       return tab[msgindex].dumpit;
 }
 
 static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
@@ -158,7 +158,7 @@ static rtnl_calcit_func rtnl_get_calcit(int protocol, int msgindex)
        if (tab == NULL || tab[msgindex].calcit == NULL)
                tab = rtnl_msg_handlers[PF_UNSPEC];
 
-       return tab ? tab[msgindex].calcit : NULL;
+       return tab[msgindex].calcit;
 }
 
 /**
@@ -1316,6 +1316,10 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
                        err = PTR_ERR(net);
                        goto errout;
                }
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
+                       err = -EPERM;
+                       goto errout;
+               }
                err = dev_change_net_namespace(dev, net, ifname);
                put_net(net);
                if (err)
@@ -1638,7 +1642,7 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm)
 }
 EXPORT_SYMBOL(rtnl_configure_link);
 
-struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
+struct net_device *rtnl_create_link(struct net *net,
        char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[])
 {
        int err;
@@ -1836,7 +1840,7 @@ replay:
                if (IS_ERR(dest_net))
                        return PTR_ERR(dest_net);
 
-               dev = rtnl_create_link(net, dest_net, ifname, ops, tb);
+               dev = rtnl_create_link(dest_net, ifname, ops, tb);
                if (IS_ERR(dev)) {
                        err = PTR_ERR(dev);
                        goto out;
@@ -2057,6 +2061,9 @@ static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        u8 *addr;
        int err;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
        if (err < 0)
                return err;
@@ -2123,6 +2130,9 @@ static int rtnl_fdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        int err = -EINVAL;
        __u8 *addr;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (nlmsg_len(nlh) < sizeof(*ndm))
                return -EINVAL;
 
@@ -2192,7 +2202,8 @@ static int nlmsg_populate_fdb(struct sk_buff *skb,
                        goto skip;
 
                err = nlmsg_populate_fdb_fill(skb, dev, ha->addr,
-                                             portid, seq, 0, NTF_SELF);
+                                             portid, seq,
+                                             RTM_NEWNEIGH, NTF_SELF);
                if (err < 0)
                        return err;
 skip:
@@ -2252,6 +2263,211 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
        return skb->len;
 }
 
+int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
+                           struct net_device *dev, u16 mode)
+{
+       struct nlmsghdr *nlh;
+       struct ifinfomsg *ifm;
+       struct nlattr *br_afspec;
+       u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
+
+       nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*ifm), NLM_F_MULTI);
+       if (nlh == NULL)
+               return -EMSGSIZE;
+
+       ifm = nlmsg_data(nlh);
+       ifm->ifi_family = AF_BRIDGE;
+       ifm->__ifi_pad = 0;
+       ifm->ifi_type = dev->type;
+       ifm->ifi_index = dev->ifindex;
+       ifm->ifi_flags = dev_get_flags(dev);
+       ifm->ifi_change = 0;
+
+
+       if (nla_put_string(skb, IFLA_IFNAME, dev->name) ||
+           nla_put_u32(skb, IFLA_MTU, dev->mtu) ||
+           nla_put_u8(skb, IFLA_OPERSTATE, operstate) ||
+           (dev->master &&
+            nla_put_u32(skb, IFLA_MASTER, dev->master->ifindex)) ||
+           (dev->addr_len &&
+            nla_put(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr)) ||
+           (dev->ifindex != dev->iflink &&
+            nla_put_u32(skb, IFLA_LINK, dev->iflink)))
+               goto nla_put_failure;
+
+       br_afspec = nla_nest_start(skb, IFLA_AF_SPEC);
+       if (!br_afspec)
+               goto nla_put_failure;
+
+       if (nla_put_u16(skb, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF) ||
+           nla_put_u16(skb, IFLA_BRIDGE_MODE, mode)) {
+               nla_nest_cancel(skb, br_afspec);
+               goto nla_put_failure;
+       }
+       nla_nest_end(skb, br_afspec);
+
+       return nlmsg_end(skb, nlh);
+nla_put_failure:
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
+}
+EXPORT_SYMBOL(ndo_dflt_bridge_getlink);
+
+static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct net *net = sock_net(skb->sk);
+       struct net_device *dev;
+       int idx = 0;
+       u32 portid = NETLINK_CB(cb->skb).portid;
+       u32 seq = cb->nlh->nlmsg_seq;
+
+       rcu_read_lock();
+       for_each_netdev_rcu(net, dev) {
+               const struct net_device_ops *ops = dev->netdev_ops;
+               struct net_device *master = dev->master;
+
+               if (master && master->netdev_ops->ndo_bridge_getlink) {
+                       if (idx >= cb->args[0] &&
+                           master->netdev_ops->ndo_bridge_getlink(
+                                   skb, portid, seq, dev) < 0)
+                               break;
+                       idx++;
+               }
+
+               if (ops->ndo_bridge_getlink) {
+                       if (idx >= cb->args[0] &&
+                           ops->ndo_bridge_getlink(skb, portid, seq, dev) < 0)
+                               break;
+                       idx++;
+               }
+       }
+       rcu_read_unlock();
+       cb->args[0] = idx;
+
+       return skb->len;
+}
+
+static inline size_t bridge_nlmsg_size(void)
+{
+       return NLMSG_ALIGN(sizeof(struct ifinfomsg))
+               + nla_total_size(IFNAMSIZ)      /* IFLA_IFNAME */
+               + nla_total_size(MAX_ADDR_LEN)  /* IFLA_ADDRESS */
+               + nla_total_size(sizeof(u32))   /* IFLA_MASTER */
+               + nla_total_size(sizeof(u32))   /* IFLA_MTU */
+               + nla_total_size(sizeof(u32))   /* IFLA_LINK */
+               + nla_total_size(sizeof(u32))   /* IFLA_OPERSTATE */
+               + nla_total_size(sizeof(u8))    /* IFLA_PROTINFO */
+               + nla_total_size(sizeof(struct nlattr)) /* IFLA_AF_SPEC */
+               + nla_total_size(sizeof(u16))   /* IFLA_BRIDGE_FLAGS */
+               + nla_total_size(sizeof(u16));  /* IFLA_BRIDGE_MODE */
+}
+
+static int rtnl_bridge_notify(struct net_device *dev, u16 flags)
+{
+       struct net *net = dev_net(dev);
+       struct net_device *master = dev->master;
+       struct sk_buff *skb;
+       int err = -EOPNOTSUPP;
+
+       skb = nlmsg_new(bridge_nlmsg_size(), GFP_ATOMIC);
+       if (!skb) {
+               err = -ENOMEM;
+               goto errout;
+       }
+
+       if ((!flags || (flags & BRIDGE_FLAGS_MASTER)) &&
+           master && master->netdev_ops->ndo_bridge_getlink) {
+               err = master->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
+               if (err < 0)
+                       goto errout;
+       }
+
+       if ((flags & BRIDGE_FLAGS_SELF) &&
+           dev->netdev_ops->ndo_bridge_getlink) {
+               err = dev->netdev_ops->ndo_bridge_getlink(skb, 0, 0, dev);
+               if (err < 0)
+                       goto errout;
+       }
+
+       rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
+       return 0;
+errout:
+       WARN_ON(err == -EMSGSIZE);
+       kfree_skb(skb);
+       rtnl_set_sk_err(net, RTNLGRP_LINK, err);
+       return err;
+}
+
+static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
+                              void *arg)
+{
+       struct net *net = sock_net(skb->sk);
+       struct ifinfomsg *ifm;
+       struct net_device *dev;
+       struct nlattr *br_spec, *attr = NULL;
+       int rem, err = -EOPNOTSUPP;
+       u16 oflags, flags = 0;
+       bool have_flags = false;
+
+       if (nlmsg_len(nlh) < sizeof(*ifm))
+               return -EINVAL;
+
+       ifm = nlmsg_data(nlh);
+       if (ifm->ifi_family != AF_BRIDGE)
+               return -EPFNOSUPPORT;
+
+       dev = __dev_get_by_index(net, ifm->ifi_index);
+       if (!dev) {
+               pr_info("PF_BRIDGE: RTM_SETLINK with unknown ifindex\n");
+               return -ENODEV;
+       }
+
+       br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
+       if (br_spec) {
+               nla_for_each_nested(attr, br_spec, rem) {
+                       if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
+                               have_flags = true;
+                               flags = nla_get_u16(attr);
+                               break;
+                       }
+               }
+       }
+
+       oflags = flags;
+
+       if (!flags || (flags & BRIDGE_FLAGS_MASTER)) {
+               if (!dev->master ||
+                   !dev->master->netdev_ops->ndo_bridge_setlink) {
+                       err = -EOPNOTSUPP;
+                       goto out;
+               }
+
+               err = dev->master->netdev_ops->ndo_bridge_setlink(dev, nlh);
+               if (err)
+                       goto out;
+
+               flags &= ~BRIDGE_FLAGS_MASTER;
+       }
+
+       if ((flags & BRIDGE_FLAGS_SELF)) {
+               if (!dev->netdev_ops->ndo_bridge_setlink)
+                       err = -EOPNOTSUPP;
+               else
+                       err = dev->netdev_ops->ndo_bridge_setlink(dev, nlh);
+
+               if (!err)
+                       flags &= ~BRIDGE_FLAGS_SELF;
+       }
+
+       if (have_flags)
+               memcpy(nla_data(attr), &flags, sizeof(flags));
+       /* Generate event to notify upper layer of bridge change */
+       if (!err)
+               err = rtnl_bridge_notify(dev, oflags);
+out:
+       return err;
+}
+
 /* Protected by RTNL sempahore.  */
 static struct rtattr **rta_buf;
 static int rtattr_max;
@@ -2282,7 +2498,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        sz_idx = type>>2;
        kind = type&3;
 
-       if (kind != 2 && !capable(CAP_NET_ADMIN))
+       if (kind != 2 && !ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
@@ -2433,5 +2649,8 @@ void __init rtnetlink_init(void)
        rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, rtnl_fdb_add, NULL, NULL);
        rtnl_register(PF_BRIDGE, RTM_DELNEIGH, rtnl_fdb_del, NULL, NULL);
        rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, rtnl_fdb_dump, NULL);
+
+       rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, rtnl_bridge_getlink, NULL);
+       rtnl_register(PF_BRIDGE, RTM_SETLINK, rtnl_bridge_setlink, NULL, NULL);
 }
 
index ab570841a532ea318b5133596f1957192ff01354..57fb1ee6649f65a0994d86c6f8763fe6e14ba081 100644 (file)
@@ -51,11 +51,11 @@ static __inline__ int scm_check_creds(struct ucred *creds)
        if (!uid_valid(uid) || !gid_valid(gid))
                return -EINVAL;
 
-       if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) &&
+       if ((creds->pid == task_tgid_vnr(current) || nsown_capable(CAP_SYS_ADMIN)) &&
            ((uid_eq(uid, cred->uid)   || uid_eq(uid, cred->euid) ||
-             uid_eq(uid, cred->suid)) || capable(CAP_SETUID)) &&
+             uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&
            ((gid_eq(gid, cred->gid)   || gid_eq(gid, cred->egid) ||
-             gid_eq(gid, cred->sgid)) || capable(CAP_SETGID))) {
+             gid_eq(gid, cred->sgid)) || nsown_capable(CAP_SETGID))) {
               return 0;
        }
        return -EPERM;
index 6e04b1fa11f2d4c6d0e0aacb27441688c5fe1438..ac9e44a6ab2bf31cafac577d151babed96779580 100644 (file)
@@ -519,7 +519,7 @@ static void skb_release_data(struct sk_buff *skb)
 
                        uarg = skb_shinfo(skb)->destructor_arg;
                        if (uarg->callback)
-                               uarg->callback(uarg);
+                               uarg->callback(uarg, true);
                }
 
                if (skb_has_frag_list(skb))
@@ -634,6 +634,26 @@ void kfree_skb(struct sk_buff *skb)
 }
 EXPORT_SYMBOL(kfree_skb);
 
+/**
+ *     skb_tx_error - report an sk_buff xmit error
+ *     @skb: buffer that triggered an error
+ *
+ *     Report xmit error if a device callback is tracking this skb.
+ *     skb must be freed afterwards.
+ */
+void skb_tx_error(struct sk_buff *skb)
+{
+       if (skb_shinfo(skb)->tx_flags & SKBTX_DEV_ZEROCOPY) {
+               struct ubuf_info *uarg;
+
+               uarg = skb_shinfo(skb)->destructor_arg;
+               if (uarg->callback)
+                       uarg->callback(uarg, false);
+               skb_shinfo(skb)->tx_flags &= ~SKBTX_DEV_ZEROCOPY;
+       }
+}
+EXPORT_SYMBOL(skb_tx_error);
+
 /**
  *     consume_skb - free an skbuff
  *     @skb: buffer to free
@@ -662,11 +682,14 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->transport_header   = old->transport_header;
        new->network_header     = old->network_header;
        new->mac_header         = old->mac_header;
+       new->inner_transport_header = old->inner_transport_header;
+       new->inner_network_header = old->inner_transport_header;
        skb_dst_copy(new, old);
        new->rxhash             = old->rxhash;
        new->ooo_okay           = old->ooo_okay;
        new->l4_rxhash          = old->l4_rxhash;
        new->no_fcs             = old->no_fcs;
+       new->encapsulation      = old->encapsulation;
 #ifdef CONFIG_XFRM
        new->sp                 = secpath_get(old->sp);
 #endif
@@ -797,7 +820,7 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)
        for (i = 0; i < num_frags; i++)
                skb_frag_unref(skb, i);
 
-       uarg->callback(uarg);
+       uarg->callback(uarg, false);
 
        /* skb frags point to kernel buffers */
        for (i = num_frags - 1; i >= 0; i--) {
@@ -872,6 +895,8 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->network_header   += offset;
        if (skb_mac_header_was_set(new))
                new->mac_header       += offset;
+       new->inner_transport_header += offset;
+       new->inner_network_header   += offset;
 #endif
        skb_shinfo(new)->gso_size = skb_shinfo(old)->gso_size;
        skb_shinfo(new)->gso_segs = skb_shinfo(old)->gso_segs;
@@ -1069,6 +1094,8 @@ int pskb_expand_head(struct sk_buff *skb, int nhead, int ntail,
        skb->network_header   += off;
        if (skb_mac_header_was_set(skb))
                skb->mac_header += off;
+       skb->inner_transport_header += off;
+       skb->inner_network_header += off;
        /* Only adjust this if it actually is csum_start rather than csum */
        if (skb->ip_summed == CHECKSUM_PARTIAL)
                skb->csum_start += nhead;
@@ -1168,6 +1195,8 @@ struct sk_buff *skb_copy_expand(const struct sk_buff *skb,
        n->network_header   += off;
        if (skb_mac_header_was_set(skb))
                n->mac_header += off;
+       n->inner_transport_header += off;
+       n->inner_network_header    += off;
 #endif
 
        return n;
@@ -2999,7 +3028,6 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
        memcpy(skb_mac_header(nskb), skb_mac_header(p),
               p->data - skb_mac_header(p));
 
-       *NAPI_GRO_CB(nskb) = *NAPI_GRO_CB(p);
        skb_shinfo(nskb)->frag_list = p;
        skb_shinfo(nskb)->gso_size = pinfo->gso_size;
        pinfo->gso_size = 0;
@@ -3379,10 +3407,12 @@ EXPORT_SYMBOL(__skb_warn_lro_forwarding);
 
 void kfree_skb_partial(struct sk_buff *skb, bool head_stolen)
 {
-       if (head_stolen)
+       if (head_stolen) {
+               skb_release_head_state(skb);
                kmem_cache_free(skbuff_head_cache, skb);
-       else
+       } else {
                __kfree_skb(skb);
+       }
 }
 EXPORT_SYMBOL(kfree_skb_partial);
 
index 8a146cfcc366fbead42d31d882893a74ec8dcf4e..a692ef49c9bb9b2d996f0538049a135a93c26812 100644 (file)
@@ -505,7 +505,8 @@ struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie)
 }
 EXPORT_SYMBOL(sk_dst_check);
 
-static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
+static int sock_setbindtodevice(struct sock *sk, char __user *optval,
+                               int optlen)
 {
        int ret = -ENOPROTOOPT;
 #ifdef CONFIG_NETDEVICES
@@ -515,7 +516,7 @@ static int sock_bindtodevice(struct sock *sk, char __user *optval, int optlen)
 
        /* Sorry... */
        ret = -EPERM;
-       if (!capable(CAP_NET_RAW))
+       if (!ns_capable(net->user_ns, CAP_NET_RAW))
                goto out;
 
        ret = -EINVAL;
@@ -562,6 +563,59 @@ out:
        return ret;
 }
 
+static int sock_getbindtodevice(struct sock *sk, char __user *optval,
+                               int __user *optlen, int len)
+{
+       int ret = -ENOPROTOOPT;
+#ifdef CONFIG_NETDEVICES
+       struct net *net = sock_net(sk);
+       struct net_device *dev;
+       char devname[IFNAMSIZ];
+       unsigned seq;
+
+       if (sk->sk_bound_dev_if == 0) {
+               len = 0;
+               goto zero;
+       }
+
+       ret = -EINVAL;
+       if (len < IFNAMSIZ)
+               goto out;
+
+retry:
+       seq = read_seqbegin(&devnet_rename_seq);
+       rcu_read_lock();
+       dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
+       ret = -ENODEV;
+       if (!dev) {
+               rcu_read_unlock();
+               goto out;
+       }
+
+       strcpy(devname, dev->name);
+       rcu_read_unlock();
+       if (read_seqretry(&devnet_rename_seq, seq))
+               goto retry;
+
+       len = strlen(devname) + 1;
+
+       ret = -EFAULT;
+       if (copy_to_user(optval, devname, len))
+               goto out;
+
+zero:
+       ret = -EFAULT;
+       if (put_user(len, optlen))
+               goto out;
+
+       ret = 0;
+
+out:
+#endif
+
+       return ret;
+}
+
 static inline void sock_valbool_flag(struct sock *sk, int bit, int valbool)
 {
        if (valbool)
@@ -589,7 +643,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
         */
 
        if (optname == SO_BINDTODEVICE)
-               return sock_bindtodevice(sk, optval, optlen);
+               return sock_setbindtodevice(sk, optval, optlen);
 
        if (optlen < sizeof(int))
                return -EINVAL;
@@ -696,7 +750,8 @@ set_rcvbuf:
                break;
 
        case SO_PRIORITY:
-               if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN))
+               if ((val >= 0 && val <= 6) ||
+                   ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                        sk->sk_priority = val;
                else
                        ret = -EPERM;
@@ -813,7 +868,7 @@ set_rcvbuf:
                        clear_bit(SOCK_PASSSEC, &sock->flags);
                break;
        case SO_MARK:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                        ret = -EPERM;
                else
                        sk->sk_mark = val;
@@ -1074,6 +1129,17 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
        case SO_NOFCS:
                v.val = sock_flag(sk, SOCK_NOFCS);
                break;
+
+       case SO_BINDTODEVICE:
+               return sock_getbindtodevice(sk, optval, optlen, len);
+
+       case SO_GET_FILTER:
+               len = sk_get_filter(sk, (struct sock_filter __user *)optval, len);
+               if (len < 0)
+                       return len;
+
+               goto lenout;
+
        default:
                return -ENOPROTOOPT;
        }
@@ -1214,13 +1280,11 @@ static void sk_prot_free(struct proto *prot, struct sock *sk)
 
 #ifdef CONFIG_CGROUPS
 #if IS_ENABLED(CONFIG_NET_CLS_CGROUP)
-void sock_update_classid(struct sock *sk)
+void sock_update_classid(struct sock *sk, struct task_struct *task)
 {
        u32 classid;
 
-       rcu_read_lock();  /* doing current task, which cannot vanish. */
-       classid = task_cls_classid(current);
-       rcu_read_unlock();
+       classid = task_cls_classid(task);
        if (classid != sk->sk_classid)
                sk->sk_classid = classid;
 }
@@ -1263,7 +1327,7 @@ struct sock *sk_alloc(struct net *net, int family, gfp_t priority,
                sock_net_set(sk, get_net(net));
                atomic_set(&sk->sk_wmem_alloc, 1);
 
-               sock_update_classid(sk);
+               sock_update_classid(sk, current);
                sock_update_netprioidx(sk, current);
        }
 
index a7c36845b123c09f727931cfe3ef3e4ad0365432..d1b08045a9dfbf4dbee4255c68cdcd6ad1e026a2 100644 (file)
@@ -216,6 +216,11 @@ static __net_init int sysctl_core_net_init(struct net *net)
                        goto err_dup;
 
                tbl[0].data = &net->core.sysctl_somaxconn;
+
+               /* Don't export any sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns) {
+                       tbl[0].procname = NULL;
+               }
        }
 
        net->core.sysctl_hdr = register_net_sysctl(net, "net/core", tbl);
index 70989e672304938a39cdf7b7a0dfd87b7497d2a9..1b588e23cf80b561632b9b5e16b851dff218a933 100644 (file)
@@ -1662,8 +1662,8 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        struct nlmsghdr *reply_nlh = NULL;
        const struct reply_func *fn;
 
-       if (!net_eq(net, &init_net))
-               return -EINVAL;
+       if ((nlh->nlmsg_type == RTM_SETDCB) && !capable(CAP_NET_ADMIN))
+               return -EPERM;
 
        ret = nlmsg_parse(nlh, sizeof(*dcb), tb, DCB_ATTR_MAX,
                          dcbnl_rtnl_policy);
@@ -1681,7 +1681,7 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        if (!tb[DCB_ATTR_IFNAME])
                return -EINVAL;
 
-       netdev = dev_get_by_name(&init_net, nla_data(tb[DCB_ATTR_IFNAME]));
+       netdev = dev_get_by_name(net, nla_data(tb[DCB_ATTR_IFNAME]));
        if (!netdev)
                return -ENODEV;
 
@@ -1705,7 +1705,7 @@ static int dcb_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
 
        nlmsg_end(reply_skb, reply_nlh);
 
-       ret = rtnl_unicast(reply_skb, &init_net, portid);
+       ret = rtnl_unicast(reply_skb, net, portid);
 out:
        dev_put(netdev);
        return ret;
index ea850ce35d4acef9ef80cf342a55cbe5e44dae56..662071b249cc627130cf90eeaa8e5b7bcd8b829d 100644 (file)
@@ -174,8 +174,7 @@ struct sock *dccp_check_req(struct sock *sk, struct sk_buff *skb,
                         * To protect against Request floods, increment retrans
                         * counter (backoff, monitored by dccp_response_timer).
                         */
-                       req->retrans++;
-                       req->rsk_ops->rtx_syn_ack(sk, req, NULL);
+                       inet_rtx_syn_ack(sk, req);
                }
                /* Network Duplicate, discard packet */
                return NULL;
index 7b7e561412d379380a54678b1505da796184c49c..e47ba9fc4a0e6ce47295d85108f1d573290a2aa7 100644 (file)
@@ -573,6 +573,9 @@ static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        struct dn_ifaddr __rcu **ifap;
        int err = -EINVAL;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!net_eq(net, &init_net))
                goto errout;
 
@@ -614,6 +617,9 @@ static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
        struct dn_ifaddr *ifa;
        int err;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!net_eq(net, &init_net))
                return -EINVAL;
 
index 102d6106a942fc32a8dedb7832711cbe94b4822b..e36614eccc0476d8c9fd1a3ebfbcb59bf14ffe4f 100644 (file)
@@ -520,6 +520,9 @@ static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *
        struct rtattr **rta = arg;
        struct rtmsg *r = NLMSG_DATA(nlh);
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!net_eq(net, &init_net))
                return -EINVAL;
 
@@ -540,6 +543,9 @@ static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh, void *
        struct rtattr **rta = arg;
        struct rtmsg *r = NLMSG_DATA(nlh);
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!net_eq(net, &init_net))
                return -EINVAL;
 
index 274791cd7a35df1274e9120d199af84ea9f60dd0..f5eede1d6cb8eb92cbf97b1b37de1362f13ac095 100644 (file)
@@ -1,26 +1,24 @@
+config HAVE_NET_DSA
+       def_bool y
+       depends on NETDEVICES && !S390
+
+# Drivers must select NET_DSA and the appropriate tagging format
+
 config NET_DSA
-       tristate "Distributed Switch Architecture support"
-       default n
-       depends on EXPERIMENTAL && NETDEVICES && !S390
+       tristate
+       depends on HAVE_NET_DSA
        select PHYLIB
-       ---help---
-         This allows you to use hardware switch chips that use
-         the Distributed Switch Architecture.
-
 
 if NET_DSA
 
 # tagging formats
 config NET_DSA_TAG_DSA
        bool
-       default n
 
 config NET_DSA_TAG_EDSA
        bool
-       default n
 
 config NET_DSA_TAG_TRAILER
        bool
-       default n
 
 endif
index 6d42c17af96b4a606a545d2d72ad5e32cb53c3da..f651da60f1618f089c2d21eef069ac5b3648218d 100644 (file)
@@ -1047,7 +1047,8 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev)
                goto error;
        }
 
-       if (skb->len <= IEEE802154_MTU) {
+       /* Send directly if less than the MTU minus the 2 checksum bytes. */
+       if (skb->len <= IEEE802154_MTU - IEEE802154_MFR_SIZE) {
                err = dev_queue_xmit(skb);
                goto out;
        }
index 766c596585631e1001bdd64c80639554c6ab7831..24b384b7903ea7a59a11e7a4cbf06db996498924 100644 (file)
@@ -346,7 +346,8 @@ lookup_protocol:
        }
 
        err = -EPERM;
-       if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
+       if (sock->type == SOCK_RAW && !kern &&
+           !ns_capable(net->user_ns, CAP_NET_RAW))
                goto out_rcu_unlock;
 
        err = -EAFNOSUPPORT;
@@ -473,6 +474,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct sockaddr_in *addr = (struct sockaddr_in *)uaddr;
        struct sock *sk = sock->sk;
        struct inet_sock *inet = inet_sk(sk);
+       struct net *net = sock_net(sk);
        unsigned short snum;
        int chk_addr_ret;
        int err;
@@ -496,7 +498,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                        goto out;
        }
 
-       chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+       chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr);
 
        /* Not specified by any standard per-se, however it breaks too
         * many applications when removed.  It is unfortunate since
@@ -516,7 +518,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        snum = ntohs(addr->sin_port);
        err = -EACCES;
-       if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+       if (snum && snum < PROT_SOCK &&
+           !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
                goto out;
 
        /*      We keep a pair of addresses. rcv_saddr is the one
@@ -1251,7 +1254,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header);
 
 static int inet_gso_send_check(struct sk_buff *skb)
 {
-       const struct net_protocol *ops;
+       const struct net_offload *ops;
        const struct iphdr *iph;
        int proto;
        int ihl;
@@ -1275,9 +1278,9 @@ static int inet_gso_send_check(struct sk_buff *skb)
        err = -EPROTONOSUPPORT;
 
        rcu_read_lock();
-       ops = rcu_dereference(inet_protos[proto]);
-       if (likely(ops && ops->gso_send_check))
-               err = ops->gso_send_check(skb);
+       ops = rcu_dereference(inet_offloads[proto]);
+       if (likely(ops && ops->callbacks.gso_send_check))
+               err = ops->callbacks.gso_send_check(skb);
        rcu_read_unlock();
 
 out:
@@ -1288,7 +1291,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
        netdev_features_t features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
-       const struct net_protocol *ops;
+       const struct net_offload *ops;
        struct iphdr *iph;
        int proto;
        int ihl;
@@ -1325,9 +1328,9 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
        segs = ERR_PTR(-EPROTONOSUPPORT);
 
        rcu_read_lock();
-       ops = rcu_dereference(inet_protos[proto]);
-       if (likely(ops && ops->gso_segment))
-               segs = ops->gso_segment(skb, features);
+       ops = rcu_dereference(inet_offloads[proto]);
+       if (likely(ops && ops->callbacks.gso_segment))
+               segs = ops->callbacks.gso_segment(skb, features);
        rcu_read_unlock();
 
        if (!segs || IS_ERR(segs))
@@ -1356,7 +1359,7 @@ out:
 static struct sk_buff **inet_gro_receive(struct sk_buff **head,
                                         struct sk_buff *skb)
 {
-       const struct net_protocol *ops;
+       const struct net_offload *ops;
        struct sk_buff **pp = NULL;
        struct sk_buff *p;
        const struct iphdr *iph;
@@ -1378,8 +1381,8 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
        proto = iph->protocol;
 
        rcu_read_lock();
-       ops = rcu_dereference(inet_protos[proto]);
-       if (!ops || !ops->gro_receive)
+       ops = rcu_dereference(inet_offloads[proto]);
+       if (!ops || !ops->callbacks.gro_receive)
                goto out_unlock;
 
        if (*(u8 *)iph != 0x45)
@@ -1420,7 +1423,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head,
        skb_gro_pull(skb, sizeof(*iph));
        skb_set_transport_header(skb, skb_gro_offset(skb));
 
-       pp = ops->gro_receive(head, skb);
+       pp = ops->callbacks.gro_receive(head, skb);
 
 out_unlock:
        rcu_read_unlock();
@@ -1435,7 +1438,7 @@ static int inet_gro_complete(struct sk_buff *skb)
 {
        __be16 newlen = htons(skb->len - skb_network_offset(skb));
        struct iphdr *iph = ip_hdr(skb);
-       const struct net_protocol *ops;
+       const struct net_offload *ops;
        int proto = iph->protocol;
        int err = -ENOSYS;
 
@@ -1443,11 +1446,11 @@ static int inet_gro_complete(struct sk_buff *skb)
        iph->tot_len = newlen;
 
        rcu_read_lock();
-       ops = rcu_dereference(inet_protos[proto]);
-       if (WARN_ON(!ops || !ops->gro_complete))
+       ops = rcu_dereference(inet_offloads[proto]);
+       if (WARN_ON(!ops || !ops->callbacks.gro_complete))
                goto out_unlock;
 
-       err = ops->gro_complete(skb);
+       err = ops->callbacks.gro_complete(skb);
 
 out_unlock:
        rcu_read_unlock();
@@ -1558,23 +1561,33 @@ static const struct net_protocol tcp_protocol = {
        .early_demux    =       tcp_v4_early_demux,
        .handler        =       tcp_v4_rcv,
        .err_handler    =       tcp_v4_err,
-       .gso_send_check =       tcp_v4_gso_send_check,
-       .gso_segment    =       tcp_tso_segment,
-       .gro_receive    =       tcp4_gro_receive,
-       .gro_complete   =       tcp4_gro_complete,
        .no_policy      =       1,
        .netns_ok       =       1,
 };
 
+static const struct net_offload tcp_offload = {
+       .callbacks = {
+               .gso_send_check =       tcp_v4_gso_send_check,
+               .gso_segment    =       tcp_tso_segment,
+               .gro_receive    =       tcp4_gro_receive,
+               .gro_complete   =       tcp4_gro_complete,
+       },
+};
+
 static const struct net_protocol udp_protocol = {
        .handler =      udp_rcv,
        .err_handler =  udp_err,
-       .gso_send_check = udp4_ufo_send_check,
-       .gso_segment = udp4_ufo_fragment,
        .no_policy =    1,
        .netns_ok =     1,
 };
 
+static const struct net_offload udp_offload = {
+       .callbacks = {
+               .gso_send_check = udp4_ufo_send_check,
+               .gso_segment = udp4_ufo_fragment,
+       },
+};
+
 static const struct net_protocol icmp_protocol = {
        .handler =      icmp_rcv,
        .err_handler =  ping_err,
@@ -1659,13 +1672,35 @@ static int ipv4_proc_init(void);
  *     IP protocol layer initialiser
  */
 
+static struct packet_offload ip_packet_offload __read_mostly = {
+       .type = cpu_to_be16(ETH_P_IP),
+       .callbacks = {
+               .gso_send_check = inet_gso_send_check,
+               .gso_segment = inet_gso_segment,
+               .gro_receive = inet_gro_receive,
+               .gro_complete = inet_gro_complete,
+       },
+};
+
+static int __init ipv4_offload_init(void)
+{
+       /*
+        * Add offloads
+        */
+       if (inet_add_offload(&udp_offload, IPPROTO_UDP) < 0)
+               pr_crit("%s: Cannot add UDP protocol offload\n", __func__);
+       if (inet_add_offload(&tcp_offload, IPPROTO_TCP) < 0)
+               pr_crit("%s: Cannot add TCP protocol offlaod\n", __func__);
+
+       dev_add_offload(&ip_packet_offload);
+       return 0;
+}
+
+fs_initcall(ipv4_offload_init);
+
 static struct packet_type ip_packet_type __read_mostly = {
        .type = cpu_to_be16(ETH_P_IP),
        .func = ip_rcv,
-       .gso_send_check = inet_gso_send_check,
-       .gso_segment = inet_gso_segment,
-       .gro_receive = inet_gro_receive,
-       .gro_complete = inet_gro_complete,
 };
 
 static int __init inet_init(void)
index 47800459e4cb341c395f54f2d161c300a112c1cf..ce6fbdfd40b893edc29aa090052663024039eadc 100644 (file)
@@ -1161,7 +1161,7 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        switch (cmd) {
        case SIOCDARP:
        case SIOCSARP:
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
        case SIOCGARP:
                err = copy_from_user(&r, arg, sizeof(struct arpreq));
index 2a6abc163ed2fa9cc15d4be2f4e9e795ec9f08b5..cc06a47f12163ad8b93cae060a8c211bb13fcc73 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/sysctl.h>
 #endif
 #include <linux/kmod.h>
+#include <linux/netconf.h>
 
 #include <net/arp.h>
 #include <net/ip.h>
@@ -723,7 +724,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
 
        case SIOCSIFFLAGS:
                ret = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto out;
                break;
        case SIOCSIFADDR:       /* Set interface address (and family) */
@@ -731,7 +732,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        case SIOCSIFDSTADDR:    /* Set the destination address */
        case SIOCSIFNETMASK:    /* Set the netmask for the interface */
                ret = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto out;
                ret = -EINVAL;
                if (sin->sin_family != AF_INET)
@@ -1442,6 +1443,155 @@ static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla)
        return 0;
 }
 
+static int inet_netconf_msgsize_devconf(int type)
+{
+       int size = NLMSG_ALIGN(sizeof(struct netconfmsg))
+                  + nla_total_size(4); /* NETCONFA_IFINDEX */
+
+       /* type -1 is used for ALL */
+       if (type == -1 || type == NETCONFA_FORWARDING)
+               size += nla_total_size(4);
+       if (type == -1 || type == NETCONFA_RP_FILTER)
+               size += nla_total_size(4);
+       if (type == -1 || type == NETCONFA_MC_FORWARDING)
+               size += nla_total_size(4);
+
+       return size;
+}
+
+static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
+                                    struct ipv4_devconf *devconf, u32 portid,
+                                    u32 seq, int event, unsigned int flags,
+                                    int type)
+{
+       struct nlmsghdr  *nlh;
+       struct netconfmsg *ncm;
+
+       nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg),
+                       flags);
+       if (nlh == NULL)
+               return -EMSGSIZE;
+
+       ncm = nlmsg_data(nlh);
+       ncm->ncm_family = AF_INET;
+
+       if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
+               goto nla_put_failure;
+
+       /* type -1 is used for ALL */
+       if ((type == -1 || type == NETCONFA_FORWARDING) &&
+           nla_put_s32(skb, NETCONFA_FORWARDING,
+                       IPV4_DEVCONF(*devconf, FORWARDING)) < 0)
+               goto nla_put_failure;
+       if ((type == -1 || type == NETCONFA_RP_FILTER) &&
+           nla_put_s32(skb, NETCONFA_RP_FILTER,
+                       IPV4_DEVCONF(*devconf, RP_FILTER)) < 0)
+               goto nla_put_failure;
+       if ((type == -1 || type == NETCONFA_MC_FORWARDING) &&
+           nla_put_s32(skb, NETCONFA_MC_FORWARDING,
+                       IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0)
+               goto nla_put_failure;
+
+       return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
+}
+
+void inet_netconf_notify_devconf(struct net *net, int type, int ifindex,
+                                struct ipv4_devconf *devconf)
+{
+       struct sk_buff *skb;
+       int err = -ENOBUFS;
+
+       skb = nlmsg_new(inet_netconf_msgsize_devconf(type), GFP_ATOMIC);
+       if (skb == NULL)
+               goto errout;
+
+       err = inet_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
+                                       RTM_NEWNETCONF, 0, type);
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
+       rtnl_notify(skb, net, 0, RTNLGRP_IPV4_NETCONF, NULL, GFP_ATOMIC);
+       return;
+errout:
+       if (err < 0)
+               rtnl_set_sk_err(net, RTNLGRP_IPV4_NETCONF, err);
+}
+
+static const struct nla_policy devconf_ipv4_policy[NETCONFA_MAX+1] = {
+       [NETCONFA_IFINDEX]      = { .len = sizeof(int) },
+       [NETCONFA_FORWARDING]   = { .len = sizeof(int) },
+       [NETCONFA_RP_FILTER]    = { .len = sizeof(int) },
+};
+
+static int inet_netconf_get_devconf(struct sk_buff *in_skb,
+                                   struct nlmsghdr *nlh,
+                                   void *arg)
+{
+       struct net *net = sock_net(in_skb->sk);
+       struct nlattr *tb[NETCONFA_MAX+1];
+       struct netconfmsg *ncm;
+       struct sk_buff *skb;
+       struct ipv4_devconf *devconf;
+       struct in_device *in_dev;
+       struct net_device *dev;
+       int ifindex;
+       int err;
+
+       err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX,
+                         devconf_ipv4_policy);
+       if (err < 0)
+               goto errout;
+
+       err = EINVAL;
+       if (!tb[NETCONFA_IFINDEX])
+               goto errout;
+
+       ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
+       switch (ifindex) {
+       case NETCONFA_IFINDEX_ALL:
+               devconf = net->ipv4.devconf_all;
+               break;
+       case NETCONFA_IFINDEX_DEFAULT:
+               devconf = net->ipv4.devconf_dflt;
+               break;
+       default:
+               dev = __dev_get_by_index(net, ifindex);
+               if (dev == NULL)
+                       goto errout;
+               in_dev = __in_dev_get_rtnl(dev);
+               if (in_dev == NULL)
+                       goto errout;
+               devconf = &in_dev->cnf;
+               break;
+       }
+
+       err = -ENOBUFS;
+       skb = nlmsg_new(inet_netconf_msgsize_devconf(-1), GFP_ATOMIC);
+       if (skb == NULL)
+               goto errout;
+
+       err = inet_netconf_fill_devconf(skb, ifindex, devconf,
+                                       NETLINK_CB(in_skb).portid,
+                                       nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
+                                       -1);
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet_netconf_msgsize_devconf() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
+       err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
+errout:
+       return err;
+}
+
 #ifdef CONFIG_SYSCTL
 
 static void devinet_copy_dflt_conf(struct net *net, int i)
@@ -1467,6 +1617,12 @@ static void inet_forward_change(struct net *net)
 
        IPV4_DEVCONF_ALL(net, ACCEPT_REDIRECTS) = !on;
        IPV4_DEVCONF_DFLT(net, FORWARDING) = on;
+       inet_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+                                   NETCONFA_IFINDEX_ALL,
+                                   net->ipv4.devconf_all);
+       inet_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+                                   NETCONFA_IFINDEX_DEFAULT,
+                                   net->ipv4.devconf_dflt);
 
        for_each_netdev(net, dev) {
                struct in_device *in_dev;
@@ -1474,8 +1630,11 @@ static void inet_forward_change(struct net *net)
                        dev_disable_lro(dev);
                rcu_read_lock();
                in_dev = __in_dev_get_rcu(dev);
-               if (in_dev)
+               if (in_dev) {
                        IN_DEV_CONF_SET(in_dev, FORWARDING, on);
+                       inet_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+                                                   dev->ifindex, &in_dev->cnf);
+               }
                rcu_read_unlock();
        }
 }
@@ -1501,6 +1660,23 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
                    i == IPV4_DEVCONF_ROUTE_LOCALNET - 1)
                        if ((new_value == 0) && (old_value != 0))
                                rt_cache_flush(net);
+               if (i == IPV4_DEVCONF_RP_FILTER - 1 &&
+                   new_value != old_value) {
+                       int ifindex;
+
+                       if (cnf == net->ipv4.devconf_dflt)
+                               ifindex = NETCONFA_IFINDEX_DEFAULT;
+                       else if (cnf == net->ipv4.devconf_all)
+                               ifindex = NETCONFA_IFINDEX_ALL;
+                       else {
+                               struct in_device *idev =
+                                       container_of(cnf, struct in_device,
+                                                    cnf);
+                               ifindex = idev->dev->ifindex;
+                       }
+                       inet_netconf_notify_devconf(net, NETCONFA_RP_FILTER,
+                                                   ifindex, cnf);
+               }
        }
 
        return ret;
@@ -1527,15 +1703,23 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
                        }
                        if (valp == &IPV4_DEVCONF_ALL(net, FORWARDING)) {
                                inet_forward_change(net);
-                       } else if (*valp) {
+                       } else {
                                struct ipv4_devconf *cnf = ctl->extra1;
                                struct in_device *idev =
                                        container_of(cnf, struct in_device, cnf);
-                               dev_disable_lro(idev->dev);
+                               if (*valp)
+                                       dev_disable_lro(idev->dev);
+                               inet_netconf_notify_devconf(net,
+                                                           NETCONFA_FORWARDING,
+                                                           idev->dev->ifindex,
+                                                           cnf);
                        }
                        rtnl_unlock();
                        rt_cache_flush(net);
-               }
+               } else
+                       inet_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+                                                   NETCONFA_IFINDEX_DEFAULT,
+                                                   net->ipv4.devconf_dflt);
        }
 
        return ret;
@@ -1809,5 +1993,7 @@ void __init devinet_init(void)
        rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL, NULL);
        rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, NULL);
        rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, NULL);
+       rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
+                     NULL, NULL);
 }
 
index 825c608826de1c4b5dea08c46e6ff4255117c990..5cd75e2dab2c17377d7250680c6b32717fe9cce9 100644 (file)
@@ -488,7 +488,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        switch (cmd) {
        case SIOCADDRT:         /* Add a route */
        case SIOCDELRT:         /* Delete a route */
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
                if (copy_from_user(&rt, arg, sizeof(rt)))
index 71b125cd5db18a3af37d124d4eb3495f3e03fdea..4797a800faf809dd7fae7c958de67181d67e58d2 100644 (file)
@@ -803,7 +803,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
                unsigned int bytes;
 
                if (!new_size)
-                       new_size = 1;
+                       new_size = 16;
                bytes = new_size * sizeof(struct hlist_head *);
                new_info_hash = fib_info_hash_alloc(bytes);
                new_laddrhash = fib_info_hash_alloc(bytes);
index f2eccd531746bea19eb269fa0d75266b20f69ebc..17ff9fd7cddab0db42c718173cfd85a9586d6d16 100644 (file)
@@ -257,7 +257,8 @@ static inline bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
                struct inet_peer *peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, 1);
                rc = inet_peer_xrlim_allow(peer,
                                           net->ipv4.sysctl_icmp_ratelimit);
-               inet_putpeer(peer);
+               if (peer)
+                       inet_putpeer(peer);
        }
 out:
        return rc;
index d34ce2972c8f90bca6809342aab5451c9138241e..2026542d683647b1199c02a8d634d3e0d11f7ff4 100644 (file)
@@ -521,21 +521,31 @@ static inline void syn_ack_recalc(struct request_sock *req, const int thresh,
                                  int *expire, int *resend)
 {
        if (!rskq_defer_accept) {
-               *expire = req->retrans >= thresh;
+               *expire = req->num_timeout >= thresh;
                *resend = 1;
                return;
        }
-       *expire = req->retrans >= thresh &&
-                 (!inet_rsk(req)->acked || req->retrans >= max_retries);
+       *expire = req->num_timeout >= thresh &&
+                 (!inet_rsk(req)->acked || req->num_timeout >= max_retries);
        /*
         * Do not resend while waiting for data after ACK,
         * start to resend on end of deferring period to give
         * last chance for data or ACK to create established socket.
         */
        *resend = !inet_rsk(req)->acked ||
-                 req->retrans >= rskq_defer_accept - 1;
+                 req->num_timeout >= rskq_defer_accept - 1;
 }
 
+int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req)
+{
+       int err = req->rsk_ops->rtx_syn_ack(parent, req, NULL);
+
+       if (!err)
+               req->num_retrans++;
+       return err;
+}
+EXPORT_SYMBOL(inet_rtx_syn_ack);
+
 void inet_csk_reqsk_queue_prune(struct sock *parent,
                                const unsigned long interval,
                                const unsigned long timeout,
@@ -599,13 +609,14 @@ void inet_csk_reqsk_queue_prune(struct sock *parent,
                                req->rsk_ops->syn_ack_timeout(parent, req);
                                if (!expire &&
                                    (!resend ||
-                                    !req->rsk_ops->rtx_syn_ack(parent, req, NULL) ||
+                                    !inet_rtx_syn_ack(parent, req) ||
                                     inet_rsk(req)->acked)) {
                                        unsigned long timeo;
 
-                                       if (req->retrans++ == 0)
+                                       if (req->num_timeout++ == 0)
                                                lopt->qlen_young--;
-                                       timeo = min((timeout << req->retrans), max_rto);
+                                       timeo = min(timeout << req->num_timeout,
+                                                   max_rto);
                                        req->expires = now + timeo;
                                        reqp = &req->dl_next;
                                        continue;
index 535584c00f9118fe33a17e79b858e66935f424f9..cb98cbed197376876d0eb91b9f0fa92651472642 100644 (file)
@@ -105,6 +105,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
        r->id.idiag_src[0] = inet->inet_rcv_saddr;
        r->id.idiag_dst[0] = inet->inet_daddr;
 
+       if (nla_put_u8(skb, INET_DIAG_SHUTDOWN, sk->sk_shutdown))
+               goto errout;
+
        /* IPv6 dual-stack sockets use inet->tos for IPv4 connections,
         * hence this needs to be included regardless of socket family.
         */
@@ -617,7 +620,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
        r->idiag_family = sk->sk_family;
        r->idiag_state = TCP_SYN_RECV;
        r->idiag_timer = 1;
-       r->idiag_retrans = req->retrans;
+       r->idiag_retrans = req->num_retrans;
 
        r->id.idiag_if = sk->sk_bound_dev_if;
        sock_diag_save_cookie(req, r->id.idiag_cookie);
@@ -892,13 +895,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
                struct inet_diag_req_v2 *r, struct nlattr *bc)
 {
        const struct inet_diag_handler *handler;
+       int err = 0;
 
        handler = inet_diag_lock_handler(r->sdiag_protocol);
        if (!IS_ERR(handler))
                handler->dump(skb, cb, r, bc);
+       else
+               err = PTR_ERR(handler);
        inet_diag_unlock_handler(handler);
 
-       return skb->len;
+       return err ? : skb->len;
 }
 
 static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
index 7880af97020885a3ae1b1fdbfbddbeaf9c4d2bbc..fa3ae814871082e22121855a4033ddc4ec21b1c7 100644 (file)
@@ -237,12 +237,14 @@ struct sock *__inet_lookup_established(struct net *net,
        rcu_read_lock();
 begin:
        sk_nulls_for_each_rcu(sk, node, &head->chain) {
-               if (INET_MATCH(sk, net, hash, acookie,
-                                       saddr, daddr, ports, dif)) {
+               if (sk->sk_hash != hash)
+                       continue;
+               if (likely(INET_MATCH(sk, net, acookie,
+                                     saddr, daddr, ports, dif))) {
                        if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
                                goto begintw;
-                       if (unlikely(!INET_MATCH(sk, net, hash, acookie,
-                               saddr, daddr, ports, dif))) {
+                       if (unlikely(!INET_MATCH(sk, net, acookie,
+                                                saddr, daddr, ports, dif))) {
                                sock_put(sk);
                                goto begin;
                        }
@@ -260,14 +262,18 @@ begin:
 begintw:
        /* Must check for a TIME_WAIT'er before going to listener hash. */
        sk_nulls_for_each_rcu(sk, node, &head->twchain) {
-               if (INET_TW_MATCH(sk, net, hash, acookie,
-                                       saddr, daddr, ports, dif)) {
+               if (sk->sk_hash != hash)
+                       continue;
+               if (likely(INET_TW_MATCH(sk, net, acookie,
+                                        saddr, daddr, ports,
+                                        dif))) {
                        if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) {
                                sk = NULL;
                                goto out;
                        }
-                       if (unlikely(!INET_TW_MATCH(sk, net, hash, acookie,
-                                saddr, daddr, ports, dif))) {
+                       if (unlikely(!INET_TW_MATCH(sk, net, acookie,
+                                                   saddr, daddr, ports,
+                                                   dif))) {
                                sock_put(sk);
                                goto begintw;
                        }
@@ -314,10 +320,12 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
 
        /* Check TIME-WAIT sockets first. */
        sk_nulls_for_each(sk2, node, &head->twchain) {
-               tw = inet_twsk(sk2);
+               if (sk2->sk_hash != hash)
+                       continue;
 
-               if (INET_TW_MATCH(sk2, net, hash, acookie,
-                                       saddr, daddr, ports, dif)) {
+               if (likely(INET_TW_MATCH(sk2, net, acookie,
+                                        saddr, daddr, ports, dif))) {
+                       tw = inet_twsk(sk2);
                        if (twsk_unique(sk, sk2, twp))
                                goto unique;
                        else
@@ -328,8 +336,10 @@ static int __inet_check_established(struct inet_timewait_death_row *death_row,
 
        /* And established part... */
        sk_nulls_for_each(sk2, node, &head->chain) {
-               if (INET_MATCH(sk2, net, hash, acookie,
-                                       saddr, daddr, ports, dif))
+               if (sk2->sk_hash != hash)
+                       continue;
+               if (likely(INET_MATCH(sk2, net, acookie,
+                                     saddr, daddr, ports, dif)))
                        goto not_unique;
        }
 
index 448e68546827431098c980bafc4a63967764942f..1cf6a768cd53d7a0effdca659dff243689cb9bf6 100644 (file)
@@ -802,6 +802,10 @@ static int __net_init ip4_frags_ns_ctl_register(struct net *net)
                table[0].data = &net->ipv4.frags.high_thresh;
                table[1].data = &net->ipv4.frags.low_thresh;
                table[2].data = &net->ipv4.frags.timeout;
+
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       table[0].procname = NULL;
        }
 
        hdr = register_net_sysctl(net, "net/ipv4", table);
index 7240f8e2dd4511dde4de0bd08290bb718eab140f..a85ae2f7a21cb15502bd69e9c63a1ec29020fa40 100644 (file)
@@ -164,21 +164,6 @@ struct ipgre_net {
 #define tunnels_r      tunnels[2]
 #define tunnels_l      tunnels[1]
 #define tunnels_wc     tunnels[0]
-/*
- * Locking : hash tables are protected by RCU and RTNL
- */
-
-#define for_each_ip_tunnel_rcu(start) \
-       for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
-       u64     rx_packets;
-       u64     rx_bytes;
-       u64     tx_packets;
-       u64     tx_bytes;
-       struct u64_stats_sync   syncp;
-};
 
 static struct rtnl_link_stats64 *ipgre_get_stats64(struct net_device *dev,
                                                   struct rtnl_link_stats64 *tot)
@@ -250,7 +235,7 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
                       ARPHRD_ETHER : ARPHRD_IPGRE;
        int score, cand_score = 4;
 
-       for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) {
+       for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) {
                if (local != t->parms.iph.saddr ||
                    remote != t->parms.iph.daddr ||
                    !(t->dev->flags & IFF_UP))
@@ -277,7 +262,7 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
                }
        }
 
-       for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) {
+       for_each_ip_tunnel_rcu(t, ign->tunnels_r[h0 ^ h1]) {
                if (remote != t->parms.iph.daddr ||
                    !(t->dev->flags & IFF_UP))
                        continue;
@@ -303,7 +288,7 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
                }
        }
 
-       for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
+       for_each_ip_tunnel_rcu(t, ign->tunnels_l[h1]) {
                if ((local != t->parms.iph.saddr &&
                     (local != t->parms.iph.daddr ||
                      !ipv4_is_multicast(local))) ||
@@ -331,7 +316,7 @@ static struct ip_tunnel *ipgre_tunnel_lookup(struct net_device *dev,
                }
        }
 
-       for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) {
+       for_each_ip_tunnel_rcu(t, ign->tunnels_wc[h1]) {
                if (t->parms.i_key != key ||
                    !(t->dev->flags & IFF_UP))
                        continue;
@@ -753,7 +738,6 @@ drop:
 static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
-       struct pcpu_tstats *tstats;
        const struct iphdr  *old_iph = ip_hdr(skb);
        const struct iphdr  *tiph;
        struct flowi4 fl4;
@@ -977,9 +961,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
                }
        }
 
-       nf_reset(skb);
-       tstats = this_cpu_ptr(dev->tstats);
-       __IPTUNNEL_XMIT(tstats, &dev->stats);
+       iptunnel_xmit(skb, dev);
        return NETDEV_TX_OK;
 
 #if IS_ENABLED(CONFIG_IPV6)
@@ -1082,7 +1064,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCADDTUNNEL:
        case SIOCCHGTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                err = -EFAULT;
@@ -1157,7 +1139,7 @@ ipgre_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 
        case SIOCDELTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                if (dev == ign->fb_tunnel_dev) {
index 1dc01f9793d59120a713213e7e65cc855bfb37b9..f6289bf6f3325edc2c78541eca88e546e5ec97c9 100644 (file)
@@ -409,7 +409,7 @@ int ip_options_compile(struct net *net,
                                        optptr[2] += 8;
                                        break;
                                      default:
-                                       if (!skb && !capable(CAP_NET_RAW)) {
+                                       if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
                                                pp_ptr = optptr + 3;
                                                goto error;
                                        }
@@ -445,7 +445,7 @@ int ip_options_compile(struct net *net,
                                opt->router_alert = optptr - iph;
                        break;
                      case IPOPT_CIPSO:
-                       if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) {
+                       if ((!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) || opt->cipso) {
                                pp_ptr = optptr;
                                goto error;
                        }
@@ -458,7 +458,7 @@ int ip_options_compile(struct net *net,
                      case IPOPT_SEC:
                      case IPOPT_SID:
                      default:
-                       if (!skb && !capable(CAP_NET_RAW)) {
+                       if (!skb && !ns_capable(net->user_ns, CAP_NET_RAW)) {
                                pp_ptr = optptr;
                                goto error;
                        }
index 6537a408a4fb451d906b574def4746c064399fd9..3e98ed2bff55d7328aae7209ecbda4f78445c87a 100644 (file)
@@ -595,6 +595,10 @@ slow_path_clean:
        }
 
 slow_path:
+       /* for offloaded checksums cleanup checksum before fragmentation */
+       if ((skb->ip_summed == CHECKSUM_PARTIAL) && skb_checksum_help(skb))
+               goto fail;
+
        left = skb->len - hlen;         /* Space per frame */
        ptr = hlen;             /* Where to start from */
 
index 5eea4a811042adaf3df8e65308c2aeeb23c845e9..3c9d20880283de0f9b5244eae8184e76d9a20dcd 100644 (file)
@@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level,
        struct inet_sock *inet = inet_sk(sk);
        int val = 0, err;
 
-       if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
-                            (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
-                            (1<<IP_RETOPTS) | (1<<IP_TOS) |
-                            (1<<IP_TTL) | (1<<IP_HDRINCL) |
-                            (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
-                            (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
-                            (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
-                            (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
-           optname == IP_UNICAST_IF ||
-           optname == IP_MULTICAST_TTL ||
-           optname == IP_MULTICAST_ALL ||
-           optname == IP_MULTICAST_LOOP ||
-           optname == IP_RECVORIGDSTADDR) {
+       switch (optname) {
+       case IP_PKTINFO:
+       case IP_RECVTTL:
+       case IP_RECVOPTS:
+       case IP_RECVTOS:
+       case IP_RETOPTS:
+       case IP_TOS:
+       case IP_TTL:
+       case IP_HDRINCL:
+       case IP_MTU_DISCOVER:
+       case IP_RECVERR:
+       case IP_ROUTER_ALERT:
+       case IP_FREEBIND:
+       case IP_PASSSEC:
+       case IP_TRANSPARENT:
+       case IP_MINTTL:
+       case IP_NODEFRAG:
+       case IP_UNICAST_IF:
+       case IP_MULTICAST_TTL:
+       case IP_MULTICAST_ALL:
+       case IP_MULTICAST_LOOP:
+       case IP_RECVORIGDSTADDR:
                if (optlen >= sizeof(int)) {
                        if (get_user(val, (int __user *) optval))
                                return -EFAULT;
@@ -980,13 +989,14 @@ mc_msf_out:
        case IP_IPSEC_POLICY:
        case IP_XFRM_POLICY:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                        break;
                err = xfrm_user_policy(sk, optname, optval, optlen);
                break;
 
        case IP_TRANSPARENT:
-               if (!!val && !capable(CAP_NET_RAW) && !capable(CAP_NET_ADMIN)) {
+               if (!!val && !ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) &&
+                   !ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
                        err = -EPERM;
                        break;
                }
index 1831092f999fb32880f2d5e721c242236b000228..c3a4233c0ac290394c819882aeff5ba3800378f4 100644 (file)
@@ -66,20 +66,6 @@ static void vti_tunnel_setup(struct net_device *dev);
 static void vti_dev_free(struct net_device *dev);
 static int vti_tunnel_bind_dev(struct net_device *dev);
 
-/* Locking : hash tables are protected by RCU and RTNL */
-
-#define for_each_ip_tunnel_rcu(start) \
-       for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
-       u64     rx_packets;
-       u64     rx_bytes;
-       u64     tx_packets;
-       u64     tx_bytes;
-       struct  u64_stats_sync  syncp;
-};
-
 #define VTI_XMIT(stats1, stats2) do {                          \
        int err;                                                \
        int pkt_len = skb->len;                                 \
@@ -142,19 +128,19 @@ static struct ip_tunnel *vti_tunnel_lookup(struct net *net,
        struct ip_tunnel *t;
        struct vti_net *ipn = net_generic(net, vti_net_id);
 
-       for_each_ip_tunnel_rcu(ipn->tunnels_r_l[h0 ^ h1])
+       for_each_ip_tunnel_rcu(t, ipn->tunnels_r_l[h0 ^ h1])
                if (local == t->parms.iph.saddr &&
                    remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
                        return t;
-       for_each_ip_tunnel_rcu(ipn->tunnels_r[h0])
+       for_each_ip_tunnel_rcu(t, ipn->tunnels_r[h0])
                if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
                        return t;
 
-       for_each_ip_tunnel_rcu(ipn->tunnels_l[h1])
+       for_each_ip_tunnel_rcu(t, ipn->tunnels_l[h1])
                if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
                        return t;
 
-       for_each_ip_tunnel_rcu(ipn->tunnels_wc[0])
+       for_each_ip_tunnel_rcu(t, ipn->tunnels_wc[0])
                if (t && (t->dev->flags&IFF_UP))
                        return t;
        return NULL;
@@ -338,12 +324,17 @@ static int vti_rcv(struct sk_buff *skb)
        if (tunnel != NULL) {
                struct pcpu_tstats *tstats;
 
+               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+                       return -1;
+
                tstats = this_cpu_ptr(tunnel->dev->tstats);
                u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
                u64_stats_update_end(&tstats->syncp);
 
+               skb->mark = 0;
+               secpath_reset(skb);
                skb->dev = tunnel->dev;
                return 1;
        }
@@ -497,7 +488,7 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCADDTUNNEL:
        case SIOCCHGTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                err = -EFAULT;
@@ -562,7 +553,7 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
        case SIOCDELTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                if (dev == ipn->fb_tunnel_dev) {
index 798358b107171664823de1b13cc3ffd020dc7f94..d763701cff1b4aca032e60f335a4208e054a4e06 100644 (file)
@@ -1500,8 +1500,10 @@ static int __init ip_auto_config(void)
         * Clue in the operator.
         */
        pr_info("IP-Config: Complete:\n");
-       pr_info("     device=%s, addr=%pI4, mask=%pI4, gw=%pI4\n",
-               ic_dev->name, &ic_myaddr, &ic_netmask, &ic_gateway);
+
+       pr_info("     device=%s, hwaddr=%*phC, ipaddr=%pI4, mask=%pI4, gw=%pI4\n",
+               ic_dev->name, ic_dev->addr_len, ic_dev->dev_addr,
+               &ic_myaddr, &ic_netmask, &ic_gateway);
        pr_info("     host=%s, domain=%s, nis-domain=%s\n",
                utsname()->nodename, ic_domain, utsname()->domainname);
        pr_info("     bootserver=%pI4, rootserver=%pI4, rootpath=%s",
index e15b45297c09f0043bda21ad366ce36d5a6e5824..191fc24a745a9668332f74106fd39831d9f01c53 100644 (file)
@@ -138,22 +138,7 @@ struct ipip_net {
 static int ipip_tunnel_init(struct net_device *dev);
 static void ipip_tunnel_setup(struct net_device *dev);
 static void ipip_dev_free(struct net_device *dev);
-
-/*
- * Locking : hash tables are protected by RCU and RTNL
- */
-
-#define for_each_ip_tunnel_rcu(start) \
-       for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
-       u64     rx_packets;
-       u64     rx_bytes;
-       u64     tx_packets;
-       u64     tx_bytes;
-       struct u64_stats_sync   syncp;
-};
+static struct rtnl_link_ops ipip_link_ops __read_mostly;
 
 static struct rtnl_link_stats64 *ipip_get_stats64(struct net_device *dev,
                                                  struct rtnl_link_stats64 *tot)
@@ -197,16 +182,16 @@ static struct ip_tunnel *ipip_tunnel_lookup(struct net *net,
        struct ip_tunnel *t;
        struct ipip_net *ipn = net_generic(net, ipip_net_id);
 
-       for_each_ip_tunnel_rcu(ipn->tunnels_r_l[h0 ^ h1])
+       for_each_ip_tunnel_rcu(t, ipn->tunnels_r_l[h0 ^ h1])
                if (local == t->parms.iph.saddr &&
                    remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
                        return t;
 
-       for_each_ip_tunnel_rcu(ipn->tunnels_r[h0])
+       for_each_ip_tunnel_rcu(t, ipn->tunnels_r[h0])
                if (remote == t->parms.iph.daddr && (t->dev->flags&IFF_UP))
                        return t;
 
-       for_each_ip_tunnel_rcu(ipn->tunnels_l[h1])
+       for_each_ip_tunnel_rcu(t, ipn->tunnels_l[h1])
                if (local == t->parms.iph.saddr && (t->dev->flags&IFF_UP))
                        return t;
 
@@ -264,6 +249,32 @@ static void ipip_tunnel_link(struct ipip_net *ipn, struct ip_tunnel *t)
        rcu_assign_pointer(*tp, t);
 }
 
+static int ipip_tunnel_create(struct net_device *dev)
+{
+       struct ip_tunnel *t = netdev_priv(dev);
+       struct net *net = dev_net(dev);
+       struct ipip_net *ipn = net_generic(net, ipip_net_id);
+       int err;
+
+       err = ipip_tunnel_init(dev);
+       if (err < 0)
+               goto out;
+
+       err = register_netdevice(dev);
+       if (err < 0)
+               goto out;
+
+       strcpy(t->parms.name, dev->name);
+       dev->rtnl_link_ops = &ipip_link_ops;
+
+       dev_hold(dev);
+       ipip_tunnel_link(ipn, t);
+       return 0;
+
+out:
+       return err;
+}
+
 static struct ip_tunnel *ipip_tunnel_locate(struct net *net,
                struct ip_tunnel_parm *parms, int create)
 {
@@ -298,16 +309,9 @@ static struct ip_tunnel *ipip_tunnel_locate(struct net *net,
        nt = netdev_priv(dev);
        nt->parms = *parms;
 
-       if (ipip_tunnel_init(dev) < 0)
+       if (ipip_tunnel_create(dev) < 0)
                goto failed_free;
 
-       if (register_netdevice(dev) < 0)
-               goto failed_free;
-
-       strcpy(nt->parms.name, dev->name);
-
-       dev_hold(dev);
-       ipip_tunnel_link(ipn, nt);
        return nt;
 
 failed_free:
@@ -463,7 +467,6 @@ drop:
 static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
-       struct pcpu_tstats *tstats;
        const struct iphdr  *tiph = &tunnel->parms.iph;
        u8     tos = tunnel->parms.iph.tos;
        __be16 df = tiph->frag_off;
@@ -479,6 +482,10 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        if (skb->protocol != htons(ETH_P_IP))
                goto tx_error;
 
+       if (skb->ip_summed == CHECKSUM_PARTIAL &&
+           skb_checksum_help(skb))
+               goto tx_error;
+
        if (tos & 1)
                tos = old_iph->tos;
 
@@ -586,9 +593,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
        if ((iph->ttl = tiph->ttl) == 0)
                iph->ttl        =       old_iph->ttl;
 
-       nf_reset(skb);
-       tstats = this_cpu_ptr(dev->tstats);
-       __IPTUNNEL_XMIT(tstats, &dev->stats);
+       iptunnel_xmit(skb, dev);
        return NETDEV_TX_OK;
 
 tx_error_icmp:
@@ -635,6 +640,28 @@ static void ipip_tunnel_bind_dev(struct net_device *dev)
        dev->iflink = tunnel->parms.link;
 }
 
+static void ipip_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
+{
+       struct net *net = dev_net(t->dev);
+       struct ipip_net *ipn = net_generic(net, ipip_net_id);
+
+       ipip_tunnel_unlink(ipn, t);
+       synchronize_net();
+       t->parms.iph.saddr = p->iph.saddr;
+       t->parms.iph.daddr = p->iph.daddr;
+       memcpy(t->dev->dev_addr, &p->iph.saddr, 4);
+       memcpy(t->dev->broadcast, &p->iph.daddr, 4);
+       ipip_tunnel_link(ipn, t);
+       t->parms.iph.ttl = p->iph.ttl;
+       t->parms.iph.tos = p->iph.tos;
+       t->parms.iph.frag_off = p->iph.frag_off;
+       if (t->parms.link != p->link) {
+               t->parms.link = p->link;
+               ipip_tunnel_bind_dev(t->dev);
+       }
+       netdev_state_change(t->dev);
+}
+
 static int
 ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 {
@@ -664,7 +691,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCADDTUNNEL:
        case SIOCCHGTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                err = -EFAULT;
@@ -693,29 +720,13 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
                                        break;
                                }
                                t = netdev_priv(dev);
-                               ipip_tunnel_unlink(ipn, t);
-                               synchronize_net();
-                               t->parms.iph.saddr = p.iph.saddr;
-                               t->parms.iph.daddr = p.iph.daddr;
-                               memcpy(dev->dev_addr, &p.iph.saddr, 4);
-                               memcpy(dev->broadcast, &p.iph.daddr, 4);
-                               ipip_tunnel_link(ipn, t);
-                               netdev_state_change(dev);
                        }
+
+                       ipip_tunnel_update(t, &p);
                }
 
                if (t) {
                        err = 0;
-                       if (cmd == SIOCCHGTUNNEL) {
-                               t->parms.iph.ttl = p.iph.ttl;
-                               t->parms.iph.tos = p.iph.tos;
-                               t->parms.iph.frag_off = p.iph.frag_off;
-                               if (t->parms.link != p.link) {
-                                       t->parms.link = p.link;
-                                       ipip_tunnel_bind_dev(dev);
-                                       netdev_state_change(dev);
-                               }
-                       }
                        if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
                                err = -EFAULT;
                } else
@@ -724,7 +735,7 @@ ipip_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 
        case SIOCDELTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                if (dev == ipn->fb_tunnel_dev) {
@@ -773,6 +784,11 @@ static void ipip_dev_free(struct net_device *dev)
        free_netdev(dev);
 }
 
+#define IPIP_FEATURES (NETIF_F_SG |            \
+                      NETIF_F_FRAGLIST |       \
+                      NETIF_F_HIGHDMA |        \
+                      NETIF_F_HW_CSUM)
+
 static void ipip_tunnel_setup(struct net_device *dev)
 {
        dev->netdev_ops         = &ipip_netdev_ops;
@@ -787,6 +803,9 @@ static void ipip_tunnel_setup(struct net_device *dev)
        dev->features           |= NETIF_F_NETNS_LOCAL;
        dev->features           |= NETIF_F_LLTX;
        dev->priv_flags         &= ~IFF_XMIT_DST_RELEASE;
+
+       dev->features           |= IPIP_FEATURES;
+       dev->hw_features        |= IPIP_FEATURES;
 }
 
 static int ipip_tunnel_init(struct net_device *dev)
@@ -829,6 +848,142 @@ static int __net_init ipip_fb_tunnel_init(struct net_device *dev)
        return 0;
 }
 
+static void ipip_netlink_parms(struct nlattr *data[],
+                              struct ip_tunnel_parm *parms)
+{
+       memset(parms, 0, sizeof(*parms));
+
+       parms->iph.version = 4;
+       parms->iph.protocol = IPPROTO_IPIP;
+       parms->iph.ihl = 5;
+
+       if (!data)
+               return;
+
+       if (data[IFLA_IPTUN_LINK])
+               parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
+
+       if (data[IFLA_IPTUN_LOCAL])
+               parms->iph.saddr = nla_get_be32(data[IFLA_IPTUN_LOCAL]);
+
+       if (data[IFLA_IPTUN_REMOTE])
+               parms->iph.daddr = nla_get_be32(data[IFLA_IPTUN_REMOTE]);
+
+       if (data[IFLA_IPTUN_TTL]) {
+               parms->iph.ttl = nla_get_u8(data[IFLA_IPTUN_TTL]);
+               if (parms->iph.ttl)
+                       parms->iph.frag_off = htons(IP_DF);
+       }
+
+       if (data[IFLA_IPTUN_TOS])
+               parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
+
+       if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
+               parms->iph.frag_off = htons(IP_DF);
+}
+
+static int ipip_newlink(struct net *src_net, struct net_device *dev,
+                       struct nlattr *tb[], struct nlattr *data[])
+{
+       struct net *net = dev_net(dev);
+       struct ip_tunnel *nt;
+
+       nt = netdev_priv(dev);
+       ipip_netlink_parms(data, &nt->parms);
+
+       if (ipip_tunnel_locate(net, &nt->parms, 0))
+               return -EEXIST;
+
+       return ipip_tunnel_create(dev);
+}
+
+static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
+                          struct nlattr *data[])
+{
+       struct ip_tunnel *t;
+       struct ip_tunnel_parm p;
+       struct net *net = dev_net(dev);
+       struct ipip_net *ipn = net_generic(net, ipip_net_id);
+
+       if (dev == ipn->fb_tunnel_dev)
+               return -EINVAL;
+
+       ipip_netlink_parms(data, &p);
+
+       if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
+           (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
+               return -EINVAL;
+
+       t = ipip_tunnel_locate(net, &p, 0);
+
+       if (t) {
+               if (t->dev != dev)
+                       return -EEXIST;
+       } else
+               t = netdev_priv(dev);
+
+       ipip_tunnel_update(t, &p);
+       return 0;
+}
+
+static size_t ipip_get_size(const struct net_device *dev)
+{
+       return
+               /* IFLA_IPTUN_LINK */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_LOCAL */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_REMOTE */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_TTL */
+               nla_total_size(1) +
+               /* IFLA_IPTUN_TOS */
+               nla_total_size(1) +
+               /* IFLA_IPTUN_PMTUDISC */
+               nla_total_size(1) +
+               0;
+}
+
+static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct ip_tunnel *tunnel = netdev_priv(dev);
+       struct ip_tunnel_parm *parm = &tunnel->parms;
+
+       if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
+           nla_put_be32(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
+           nla_put_be32(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
+           nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
+           nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
+           nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
+                      !!(parm->iph.frag_off & htons(IP_DF))))
+               goto nla_put_failure;
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
+static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
+       [IFLA_IPTUN_LINK]               = { .type = NLA_U32 },
+       [IFLA_IPTUN_LOCAL]              = { .type = NLA_U32 },
+       [IFLA_IPTUN_REMOTE]             = { .type = NLA_U32 },
+       [IFLA_IPTUN_TTL]                = { .type = NLA_U8 },
+       [IFLA_IPTUN_TOS]                = { .type = NLA_U8 },
+       [IFLA_IPTUN_PMTUDISC]           = { .type = NLA_U8 },
+};
+
+static struct rtnl_link_ops ipip_link_ops __read_mostly = {
+       .kind           = "ipip",
+       .maxtype        = IFLA_IPTUN_MAX,
+       .policy         = ipip_policy,
+       .priv_size      = sizeof(struct ip_tunnel),
+       .setup          = ipip_tunnel_setup,
+       .newlink        = ipip_newlink,
+       .changelink     = ipip_changelink,
+       .get_size       = ipip_get_size,
+       .fill_info      = ipip_fill_info,
+};
+
 static struct xfrm_tunnel ipip_handler __read_mostly = {
        .handler        =       ipip_rcv,
        .err_handler    =       ipip_err,
@@ -925,14 +1080,26 @@ static int __init ipip_init(void)
                return err;
        err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
        if (err < 0) {
-               unregister_pernet_device(&ipip_net_ops);
                pr_info("%s: can't register tunnel\n", __func__);
+               goto xfrm_tunnel_failed;
        }
+       err = rtnl_link_register(&ipip_link_ops);
+       if (err < 0)
+               goto rtnl_link_failed;
+
+out:
        return err;
+
+rtnl_link_failed:
+       xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
+xfrm_tunnel_failed:
+       unregister_pernet_device(&ipip_net_ops);
+       goto out;
 }
 
 static void __exit ipip_fini(void)
 {
+       rtnl_link_unregister(&ipip_link_ops);
        if (xfrm4_tunnel_deregister(&ipip_handler, AF_INET))
                pr_info("%s: can't deregister tunnel\n", __func__);
 
index 6168c4dc58b1db546c567ef0c55842ab42edee16..a9454cbd953ce700139fdb010a333128b565b800 100644 (file)
@@ -65,6 +65,7 @@
 #include <net/checksum.h>
 #include <net/netlink.h>
 #include <net/fib_rules.h>
+#include <linux/netconf.h>
 
 #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
 #define CONFIG_IP_PIMSM        1
@@ -83,8 +84,8 @@ struct mr_table {
        struct vif_device       vif_table[MAXVIFS];
        int                     maxvif;
        atomic_t                cache_resolve_queue_len;
-       int                     mroute_do_assert;
-       int                     mroute_do_pim;
+       bool                    mroute_do_assert;
+       bool                    mroute_do_pim;
 #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
        int                     mroute_reg_vif_num;
 #endif
@@ -133,6 +134,8 @@ static int ipmr_cache_report(struct mr_table *mrt,
                             struct sk_buff *pkt, vifi_t vifi, int assert);
 static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
                              struct mfc_cache *c, struct rtmsg *rtm);
+static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
+                                int cmd);
 static void mroute_clean_tables(struct mr_table *mrt);
 static void ipmr_expire_process(unsigned long arg);
 
@@ -582,6 +585,9 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify,
        in_dev = __in_dev_get_rtnl(dev);
        if (in_dev) {
                IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
+               inet_netconf_notify_devconf(dev_net(dev),
+                                           NETCONFA_MC_FORWARDING,
+                                           dev->ifindex, &in_dev->cnf);
                ip_rt_multicast_event(in_dev);
        }
 
@@ -665,6 +671,7 @@ static void ipmr_expire_process(unsigned long arg)
                }
 
                list_del(&c->list);
+               mroute_netlink_event(mrt, c, RTM_DELROUTE);
                ipmr_destroy_unres(mrt, c);
        }
 
@@ -772,6 +779,8 @@ static int vif_add(struct net *net, struct mr_table *mrt,
                return -EADDRNOTAVAIL;
        }
        IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
+       inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING, dev->ifindex,
+                                   &in_dev->cnf);
        ip_rt_multicast_event(in_dev);
 
        /* Fill in the VIF structures */
@@ -1020,6 +1029,7 @@ ipmr_cache_unresolved(struct mr_table *mrt, vifi_t vifi, struct sk_buff *skb)
 
                atomic_inc(&mrt->cache_resolve_queue_len);
                list_add(&c->list, &mrt->mfc_unres_queue);
+               mroute_netlink_event(mrt, c, RTM_NEWROUTE);
 
                if (atomic_read(&mrt->cache_resolve_queue_len) == 1)
                        mod_timer(&mrt->ipmr_expire_timer, c->mfc_un.unres.expires);
@@ -1054,7 +1064,7 @@ static int ipmr_mfc_delete(struct mr_table *mrt, struct mfcctl *mfc)
                if (c->mfc_origin == mfc->mfcc_origin.s_addr &&
                    c->mfc_mcastgrp == mfc->mfcc_mcastgrp.s_addr) {
                        list_del_rcu(&c->list);
-
+                       mroute_netlink_event(mrt, c, RTM_DELROUTE);
                        ipmr_cache_free(c);
                        return 0;
                }
@@ -1089,6 +1099,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
                if (!mrtsock)
                        c->mfc_flags |= MFC_STATIC;
                write_unlock_bh(&mrt_lock);
+               mroute_netlink_event(mrt, c, RTM_NEWROUTE);
                return 0;
        }
 
@@ -1131,6 +1142,7 @@ static int ipmr_mfc_add(struct net *net, struct mr_table *mrt,
                ipmr_cache_resolve(net, mrt, uc, c);
                ipmr_cache_free(uc);
        }
+       mroute_netlink_event(mrt, c, RTM_NEWROUTE);
        return 0;
 }
 
@@ -1159,6 +1171,7 @@ static void mroute_clean_tables(struct mr_table *mrt)
                        if (c->mfc_flags & MFC_STATIC)
                                continue;
                        list_del_rcu(&c->list);
+                       mroute_netlink_event(mrt, c, RTM_DELROUTE);
                        ipmr_cache_free(c);
                }
        }
@@ -1167,6 +1180,7 @@ static void mroute_clean_tables(struct mr_table *mrt)
                spin_lock_bh(&mfc_unres_lock);
                list_for_each_entry_safe(c, next, &mrt->mfc_unres_queue, list) {
                        list_del(&c->list);
+                       mroute_netlink_event(mrt, c, RTM_DELROUTE);
                        ipmr_destroy_unres(mrt, c);
                }
                spin_unlock_bh(&mfc_unres_lock);
@@ -1185,6 +1199,9 @@ static void mrtsock_destruct(struct sock *sk)
        ipmr_for_each_table(mrt, net) {
                if (sk == rtnl_dereference(mrt->mroute_sk)) {
                        IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
+                       inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+                                                   NETCONFA_IFINDEX_ALL,
+                                                   net->ipv4.devconf_all);
                        RCU_INIT_POINTER(mrt->mroute_sk, NULL);
                        mroute_clean_tables(mrt);
                }
@@ -1207,23 +1224,24 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
        struct net *net = sock_net(sk);
        struct mr_table *mrt;
 
+       if (sk->sk_type != SOCK_RAW ||
+           inet_sk(sk)->inet_num != IPPROTO_IGMP)
+               return -EOPNOTSUPP;
+
        mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
        if (mrt == NULL)
                return -ENOENT;
 
        if (optname != MRT_INIT) {
                if (sk != rcu_access_pointer(mrt->mroute_sk) &&
-                   !capable(CAP_NET_ADMIN))
+                   !ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EACCES;
        }
 
        switch (optname) {
        case MRT_INIT:
-               if (sk->sk_type != SOCK_RAW ||
-                   inet_sk(sk)->inet_num != IPPROTO_IGMP)
-                       return -EOPNOTSUPP;
                if (optlen != sizeof(int))
-                       return -ENOPROTOOPT;
+                       return -EINVAL;
 
                rtnl_lock();
                if (rtnl_dereference(mrt->mroute_sk)) {
@@ -1235,6 +1253,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
                if (ret == 0) {
                        rcu_assign_pointer(mrt->mroute_sk, sk);
                        IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
+                       inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+                                                   NETCONFA_IFINDEX_ALL,
+                                                   net->ipv4.devconf_all);
                }
                rtnl_unlock();
                return ret;
@@ -1284,9 +1305,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
        case MRT_ASSERT:
        {
                int v;
+               if (optlen != sizeof(v))
+                       return -EINVAL;
                if (get_user(v, (int __user *)optval))
                        return -EFAULT;
-               mrt->mroute_do_assert = (v) ? 1 : 0;
+               mrt->mroute_do_assert = v;
                return 0;
        }
 #ifdef CONFIG_IP_PIMSM
@@ -1294,9 +1317,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
        {
                int v;
 
+               if (optlen != sizeof(v))
+                       return -EINVAL;
                if (get_user(v, (int __user *)optval))
                        return -EFAULT;
-               v = (v) ? 1 : 0;
+               v = !!v;
 
                rtnl_lock();
                ret = 0;
@@ -1318,6 +1343,10 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
                if (get_user(v, (u32 __user *)optval))
                        return -EFAULT;
 
+               /* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */
+               if (v != RT_TABLE_DEFAULT && v >= 1000000000)
+                       return -EINVAL;
+
                rtnl_lock();
                ret = 0;
                if (sk == rtnl_dereference(mrt->mroute_sk)) {
@@ -1325,7 +1354,8 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
                } else {
                        if (!ipmr_new_table(net, v))
                                ret = -ENOMEM;
-                       raw_sk(sk)->ipmr_table = v;
+                       else
+                               raw_sk(sk)->ipmr_table = v;
                }
                rtnl_unlock();
                return ret;
@@ -1351,6 +1381,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int
        struct net *net = sock_net(sk);
        struct mr_table *mrt;
 
+       if (sk->sk_type != SOCK_RAW ||
+           inet_sk(sk)->inet_num != IPPROTO_IGMP)
+               return -EOPNOTSUPP;
+
        mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
        if (mrt == NULL)
                return -ENOENT;
@@ -2020,6 +2054,7 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
        int ct;
        struct rtnexthop *nhp;
        struct nlattr *mp_attr;
+       struct rta_mfc_stats mfcs;
 
        /* If cache is unresolved, don't try to parse IIF and OIF */
        if (c->mfc_parent >= MAXVIFS)
@@ -2048,6 +2083,12 @@ static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
 
        nla_nest_end(skb, mp_attr);
 
+       mfcs.mfcs_packets = c->mfc_un.res.pkt;
+       mfcs.mfcs_bytes = c->mfc_un.res.bytes;
+       mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if;
+       if (nla_put(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs) < 0)
+               return -EMSGSIZE;
+
        rtm->rtm_type = RTN_MULTICAST;
        return 1;
 }
@@ -2117,12 +2158,13 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
 }
 
 static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
-                           u32 portid, u32 seq, struct mfc_cache *c)
+                           u32 portid, u32 seq, struct mfc_cache *c, int cmd)
 {
        struct nlmsghdr *nlh;
        struct rtmsg *rtm;
+       int err;
 
-       nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
        if (nlh == NULL)
                return -EMSGSIZE;
 
@@ -2136,13 +2178,18 @@ static int ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
                goto nla_put_failure;
        rtm->rtm_type     = RTN_MULTICAST;
        rtm->rtm_scope    = RT_SCOPE_UNIVERSE;
-       rtm->rtm_protocol = RTPROT_UNSPEC;
+       if (c->mfc_flags & MFC_STATIC)
+               rtm->rtm_protocol = RTPROT_STATIC;
+       else
+               rtm->rtm_protocol = RTPROT_MROUTED;
        rtm->rtm_flags    = 0;
 
        if (nla_put_be32(skb, RTA_SRC, c->mfc_origin) ||
            nla_put_be32(skb, RTA_DST, c->mfc_mcastgrp))
                goto nla_put_failure;
-       if (__ipmr_fill_mroute(mrt, skb, c, rtm) < 0)
+       err = __ipmr_fill_mroute(mrt, skb, c, rtm);
+       /* do not break the dump if cache is unresolved */
+       if (err < 0 && err != -ENOENT)
                goto nla_put_failure;
 
        return nlmsg_end(skb, nlh);
@@ -2152,6 +2199,52 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
+static size_t mroute_msgsize(bool unresolved, int maxvif)
+{
+       size_t len =
+               NLMSG_ALIGN(sizeof(struct rtmsg))
+               + nla_total_size(4)     /* RTA_TABLE */
+               + nla_total_size(4)     /* RTA_SRC */
+               + nla_total_size(4)     /* RTA_DST */
+               ;
+
+       if (!unresolved)
+               len = len
+                     + nla_total_size(4)       /* RTA_IIF */
+                     + nla_total_size(0)       /* RTA_MULTIPATH */
+                     + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
+                                               /* RTA_MFC_STATS */
+                     + nla_total_size(sizeof(struct rta_mfc_stats))
+               ;
+
+       return len;
+}
+
+static void mroute_netlink_event(struct mr_table *mrt, struct mfc_cache *mfc,
+                                int cmd)
+{
+       struct net *net = read_pnet(&mrt->net);
+       struct sk_buff *skb;
+       int err = -ENOBUFS;
+
+       skb = nlmsg_new(mroute_msgsize(mfc->mfc_parent >= MAXVIFS, mrt->maxvif),
+                       GFP_ATOMIC);
+       if (skb == NULL)
+               goto errout;
+
+       err = ipmr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
+       if (err < 0)
+               goto errout;
+
+       rtnl_notify(skb, net, 0, RTNLGRP_IPV4_MROUTE, NULL, GFP_ATOMIC);
+       return;
+
+errout:
+       kfree_skb(skb);
+       if (err < 0)
+               rtnl_set_sk_err(net, RTNLGRP_IPV4_MROUTE, err);
+}
+
 static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
 {
        struct net *net = sock_net(skb->sk);
@@ -2178,13 +2271,29 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
                                if (ipmr_fill_mroute(mrt, skb,
                                                     NETLINK_CB(cb->skb).portid,
                                                     cb->nlh->nlmsg_seq,
-                                                    mfc) < 0)
+                                                    mfc, RTM_NEWROUTE) < 0)
                                        goto done;
 next_entry:
                                e++;
                        }
                        e = s_e = 0;
                }
+               spin_lock_bh(&mfc_unres_lock);
+               list_for_each_entry(mfc, &mrt->mfc_unres_queue, list) {
+                       if (e < s_e)
+                               goto next_entry2;
+                       if (ipmr_fill_mroute(mrt, skb,
+                                            NETLINK_CB(cb->skb).portid,
+                                            cb->nlh->nlmsg_seq,
+                                            mfc, RTM_NEWROUTE) < 0) {
+                               spin_unlock_bh(&mfc_unres_lock);
+                               goto done;
+                       }
+next_entry2:
+                       e++;
+               }
+               spin_unlock_bh(&mfc_unres_lock);
+               e = s_e = 0;
                s_h = 0;
 next_table:
                t++;
index 97e61eadf5800f8df1054da565beb227e0479568..3ea4127404d662f6756155128054d4a4c9b4ba0a 100644 (file)
@@ -1533,7 +1533,7 @@ static int compat_do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user,
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -1677,7 +1677,7 @@ static int compat_do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user,
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -1698,7 +1698,7 @@ static int do_arpt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -1722,7 +1722,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
index 170b1fdd6b72e26060edb584812be07493fb2f04..17c5e06da6628b7ec12495471d3bfcc943acf969 100644 (file)
@@ -1846,7 +1846,7 @@ compat_do_ipt_set_ctl(struct sock *sk,    int cmd, void __user *user,
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -1961,7 +1961,7 @@ compat_do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -1983,7 +1983,7 @@ do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -2008,7 +2008,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
index fe5daea5214d9907bb742d0ee6e18ca900f07d16..75e33a7048f8b759eee7e4f8cf6729a194c1d3cd 100644 (file)
@@ -661,6 +661,7 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
 #define PROC_WRITELEN  10
        char buffer[PROC_WRITELEN+1];
        unsigned long nodenum;
+       int rc;
 
        if (size > PROC_WRITELEN)
                return -EIO;
@@ -669,11 +670,15 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
        buffer[size] = 0;
 
        if (*buffer == '+') {
-               nodenum = simple_strtoul(buffer+1, NULL, 10);
+               rc = kstrtoul(buffer+1, 10, &nodenum);
+               if (rc)
+                       return rc;
                if (clusterip_add_node(c, nodenum))
                        return -ENOMEM;
        } else if (*buffer == '-') {
-               nodenum = simple_strtoul(buffer+1, NULL,10);
+               rc = kstrtoul(buffer+1, 10, &nodenum);
+               if (rc)
+                       return rc;
                if (clusterip_del_node(c, nodenum))
                        return -ENOENT;
        } else
index 9e0ffaf1d942624cf44d9693922e13312fc77ff2..da2c8a368f68d9c6b72c605593aa5b83e0622344 100644 (file)
@@ -134,6 +134,10 @@ nf_nat_ipv4_fn(unsigned int hooknum,
                /* ESTABLISHED */
                NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
                             ctinfo == IP_CT_ESTABLISHED_REPLY);
+               if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) {
+                       nf_ct_kill_acct(ct, ctinfo, skb);
+                       return NF_DROP;
+               }
        }
 
        return nf_nat_packet(ct, ctinfo, hooknum, skb);
@@ -184,7 +188,8 @@ nf_nat_ipv4_out(unsigned int hooknum,
 
                if ((ct->tuplehash[dir].tuple.src.u3.ip !=
                     ct->tuplehash[!dir].tuple.dst.u3.ip) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
                                ret = NF_DROP;
@@ -221,6 +226,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET) < 0)
@@ -274,9 +280,7 @@ static int __net_init iptable_nat_net_init(struct net *net)
                return -ENOMEM;
        net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
        kfree(repl);
-       if (IS_ERR(net->ipv4.nat_table))
-               return PTR_ERR(net->ipv4.nat_table);
-       return 0;
+       return PTR_RET(net->ipv4.nat_table);
 }
 
 static void __net_exit iptable_nat_net_exit(struct net *net)
index 8918eff1426d2e5da3aeaa41cb4d34824482da5a..0f9d09f54bd9d781bb74d577185c571fe632b270 100644 (file)
@@ -29,6 +29,7 @@
 #include <net/protocol.h>
 
 const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS] __read_mostly;
+const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS] __read_mostly;
 
 /*
  *     Add a protocol handler to the hash tables
@@ -41,6 +42,13 @@ int inet_add_protocol(const struct net_protocol *prot, unsigned char protocol)
 }
 EXPORT_SYMBOL(inet_add_protocol);
 
+int inet_add_offload(const struct net_offload *prot, unsigned char protocol)
+{
+       return !cmpxchg((const struct net_offload **)&inet_offloads[protocol],
+                       NULL, prot) ? 0 : -1;
+}
+EXPORT_SYMBOL(inet_add_offload);
+
 /*
  *     Remove a protocol from the hash tables.
  */
@@ -57,3 +65,16 @@ int inet_del_protocol(const struct net_protocol *prot, unsigned char protocol)
        return ret;
 }
 EXPORT_SYMBOL(inet_del_protocol);
+
+int inet_del_offload(const struct net_offload *prot, unsigned char protocol)
+{
+       int ret;
+
+       ret = (cmpxchg((const struct net_offload **)&inet_offloads[protocol],
+                      prot, NULL) == prot) ? 0 : -1;
+
+       synchronize_net();
+
+       return ret;
+}
+EXPORT_SYMBOL(inet_del_offload);
index 432f4bb77238fcc5c80d5ab7c6ad35bb55609c53..844a9ef60dbd89f459515101ebb0db6e7cfaa8a3 100644 (file)
@@ -1163,8 +1163,12 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
        spin_lock_bh(&fnhe_lock);
 
        if (daddr == fnhe->fnhe_daddr) {
-               struct rtable *orig;
-
+               struct rtable *orig = rcu_dereference(fnhe->fnhe_rth);
+               if (orig && rt_is_expired(orig)) {
+                       fnhe->fnhe_gw = 0;
+                       fnhe->fnhe_pmtu = 0;
+                       fnhe->fnhe_expires = 0;
+               }
                if (fnhe->fnhe_pmtu) {
                        unsigned long expires = fnhe->fnhe_expires;
                        unsigned long diff = expires - jiffies;
@@ -1181,7 +1185,6 @@ static bool rt_bind_exception(struct rtable *rt, struct fib_nh_exception *fnhe,
                } else if (!rt->rt_gateway)
                        rt->rt_gateway = daddr;
 
-               orig = rcu_dereference(fnhe->fnhe_rth);
                rcu_assign_pointer(fnhe->fnhe_rth, rt);
                if (orig)
                        rt_free(orig);
@@ -1782,6 +1785,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        if (dev_out->flags & IFF_LOOPBACK)
                flags |= RTCF_LOCAL;
 
+       do_cache = true;
        if (type == RTN_BROADCAST) {
                flags |= RTCF_BROADCAST | RTCF_LOCAL;
                fi = NULL;
@@ -1790,6 +1794,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
                if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr,
                                     fl4->flowi4_proto))
                        flags &= ~RTCF_LOCAL;
+               else
+                       do_cache = false;
                /* If multicast route do not exist use
                 * default one, but do not gateway in this case.
                 * Yes, it is hack.
@@ -1799,8 +1805,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        }
 
        fnhe = NULL;
-       do_cache = fi != NULL;
-       if (fi) {
+       do_cache &= fi != NULL;
+       if (do_cache) {
                struct rtable __rcu **prth;
                struct fib_nh *nh = &FIB_RES_NH(*res);
 
@@ -2226,8 +2232,27 @@ static int rt_fill_info(struct net *net,  __be32 dst, __be32 src,
        error = rt->dst.error;
 
        if (rt_is_input_route(rt)) {
-               if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
-                       goto nla_put_failure;
+#ifdef CONFIG_IP_MROUTE
+               if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) &&
+                   IPV4_DEVCONF_ALL(net, MC_FORWARDING)) {
+                       int err = ipmr_get_route(net, skb,
+                                                fl4->saddr, fl4->daddr,
+                                                r, nowait);
+                       if (err <= 0) {
+                               if (!nowait) {
+                                       if (err == 0)
+                                               return 0;
+                                       goto nla_put_failure;
+                               } else {
+                                       if (err == -EMSGSIZE)
+                                               goto nla_put_failure;
+                                       error = err;
+                               }
+                       }
+               } else
+#endif
+                       if (nla_put_u32(skb, RTA_IIF, rt->rt_iif))
+                               goto nla_put_failure;
        }
 
        if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, error) < 0)
@@ -2490,6 +2515,10 @@ static __net_init int sysctl_route_net_init(struct net *net)
                tbl = kmemdup(tbl, sizeof(ipv4_route_flush_table), GFP_KERNEL);
                if (tbl == NULL)
                        goto err_dup;
+
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       tbl[0].procname = NULL;
        }
        tbl[0].extra1 = net;
 
@@ -2594,7 +2623,7 @@ int __init ip_rt_init(void)
                pr_err("Unable to create route proc files\n");
 #ifdef CONFIG_XFRM
        xfrm_init();
-       xfrm4_init(ip_rt_max_size);
+       xfrm4_init();
 #endif
        rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
 
index ba48e799b031b3a45c902dff2f8690a8ce2627fa..b236ef04914f99585455269fe2c9a18241088461 100644 (file)
@@ -340,7 +340,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
        }
 
        req->expires    = 0UL;
-       req->retrans    = 0;
+       req->num_retrans = 0;
 
        /*
         * We need to lookup the route here to get at the correct
index 63d4eccc674ddd1d297368166792e99c636658f6..d84400b65049e61bc64f8f8eef37e2be2aaf2eda 100644 (file)
@@ -883,6 +883,9 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
                table[6].data =
                        &net->ipv4.sysctl_ping_group_range;
 
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       table[0].procname = NULL;
        }
 
        /*
index f32c02e2a54346cf4e120d39e17d4d1b5e966189..8fc5b3bd6075064acc73813eb8da5349d80f4803 100644 (file)
@@ -536,30 +536,29 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        int answ;
+       bool slow;
 
        switch (cmd) {
        case SIOCINQ:
                if (sk->sk_state == TCP_LISTEN)
                        return -EINVAL;
 
-               lock_sock(sk);
+               slow = lock_sock_fast(sk);
                if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
                        answ = 0;
                else if (sock_flag(sk, SOCK_URGINLINE) ||
                         !tp->urg_data ||
                         before(tp->urg_seq, tp->copied_seq) ||
                         !before(tp->urg_seq, tp->rcv_nxt)) {
-                       struct sk_buff *skb;
 
                        answ = tp->rcv_nxt - tp->copied_seq;
 
-                       /* Subtract 1, if FIN is in queue. */
-                       skb = skb_peek_tail(&sk->sk_receive_queue);
-                       if (answ && skb)
-                               answ -= tcp_hdr(skb)->fin;
+                       /* Subtract 1, if FIN was received */
+                       if (answ && sock_flag(sk, SOCK_DONE))
+                               answ--;
                } else
                        answ = tp->urg_seq - tp->copied_seq;
-               release_sock(sk);
+               unlock_sock_fast(sk, slow);
                break;
        case SIOCATMARK:
                answ = tp->urg_data && tp->urg_seq == tp->copied_seq;
@@ -1214,7 +1213,7 @@ new_segment:
 wait_for_sndbuf:
                        set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 wait_for_memory:
-                       if (copied && likely(!tp->repair))
+                       if (copied)
                                tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
 
                        if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
@@ -1225,7 +1224,7 @@ wait_for_memory:
        }
 
 out:
-       if (copied && likely(!tp->repair))
+       if (copied)
                tcp_push(sk, flags, mss_now, tp->nonagle);
        release_sock(sk);
        return copied + copied_syn;
@@ -1495,15 +1494,19 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
                                copied += used;
                                offset += used;
                        }
-                       /*
-                        * If recv_actor drops the lock (e.g. TCP splice
+                       /* If recv_actor drops the lock (e.g. TCP splice
                         * receive) the skb pointer might be invalid when
                         * getting here: tcp_collapse might have deleted it
                         * while aggregating skbs from the socket queue.
                         */
-                       skb = tcp_recv_skb(sk, seq-1, &offset);
-                       if (!skb || (offset+1 != skb->len))
+                       skb = tcp_recv_skb(sk, seq - 1, &offset);
+                       if (!skb)
                                break;
+                       /* TCP coalescing might have appended data to the skb.
+                        * Try to splice more frags
+                        */
+                       if (offset + 1 != skb->len)
+                               continue;
                }
                if (tcp_hdr(skb)->fin) {
                        sk_eat_skb(sk, skb, false);
@@ -2305,7 +2308,7 @@ void tcp_sock_destruct(struct sock *sk)
 
 static inline bool tcp_can_repair_sock(const struct sock *sk)
 {
-       return capable(CAP_NET_ADMIN) &&
+       return ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN) &&
                ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
 }
 
@@ -2766,6 +2769,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info)
                info->tcpi_options |= TCPI_OPT_ECN;
        if (tp->ecn_flags & TCP_ECN_SEEN)
                info->tcpi_options |= TCPI_OPT_ECN_SEEN;
+       if (tp->syn_data_acked)
+               info->tcpi_options |= TCPI_OPT_SYN_DATA;
 
        info->tcpi_rto = jiffies_to_usecs(icsk->icsk_rto);
        info->tcpi_ato = jiffies_to_usecs(icsk->icsk_ack.ato);
@@ -3589,8 +3594,7 @@ void __init tcp_init(void)
                alloc_large_system_hash("TCP established",
                                        sizeof(struct inet_ehash_bucket),
                                        thash_entries,
-                                       (totalram_pages >= 128 * 1024) ?
-                                       13 : 15,
+                                       17, /* one slot per 128 KB of memory */
                                        0,
                                        NULL,
                                        &tcp_hashinfo.ehash_mask,
@@ -3606,8 +3610,7 @@ void __init tcp_init(void)
                alloc_large_system_hash("TCP bind",
                                        sizeof(struct inet_bind_hashbucket),
                                        tcp_hashinfo.ehash_mask + 1,
-                                       (totalram_pages >= 128 * 1024) ?
-                                       13 : 15,
+                                       17, /* one slot per 128 KB of memory */
                                        0,
                                        &tcp_hashinfo.bhash_size,
                                        NULL,
index 1432cdb0644c2b16f893de842bcd3b9fdd3c5538..baf28611b3345030d42ea73d40a14284648717bb 100644 (file)
@@ -259,7 +259,8 @@ int tcp_set_congestion_control(struct sock *sk, const char *name)
        if (!ca)
                err = -ENOENT;
 
-       else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || capable(CAP_NET_ADMIN)))
+       else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) ||
+                  ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)))
                err = -EPERM;
 
        else if (!try_module_get(ca->owner))
index 813b43a76fece71e2614878a5830962d55f35a22..834857f3c8713e8d8b80ab7b4f413725ec0ca9b4 100644 (file)
@@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,
                        .tcpv_rttcnt = ca->cnt_rtt,
                        .tcpv_minrtt = ca->base_rtt,
                };
-               u64 t = ca->sum_rtt;
 
-               do_div(t, ca->cnt_rtt);
-               info.tcpv_rtt = t;
+               if (info.tcpv_rttcnt > 0) {
+                       u64 t = ca->sum_rtt;
 
+                       do_div(t, info.tcpv_rttcnt);
+                       info.tcpv_rtt = t;
+               }
                nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
        }
 }
index 432c36649db3dd8d579ddb05ae886dd3251dcb66..fc67831656e5d00a833c81409ff07bf48fd7e41b 100644 (file)
@@ -3552,6 +3552,24 @@ static bool tcp_process_frto(struct sock *sk, int flag)
        return false;
 }
 
+/* RFC 5961 7 [ACK Throttling] */
+static void tcp_send_challenge_ack(struct sock *sk)
+{
+       /* unprotected vars, we dont care of overwrites */
+       static u32 challenge_timestamp;
+       static unsigned int challenge_count;
+       u32 now = jiffies / HZ;
+
+       if (now != challenge_timestamp) {
+               challenge_timestamp = now;
+               challenge_count = 0;
+       }
+       if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
+               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
+               tcp_send_ack(sk);
+       }
+}
+
 /* This routine deals with incoming acks, but not outgoing ones. */
 static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 {
@@ -3571,8 +3589,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        /* If the ack is older than previous acks
         * then we can probably ignore it.
         */
-       if (before(ack, prior_snd_una))
+       if (before(ack, prior_snd_una)) {
+               /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
+               if (before(ack, prior_snd_una - tp->max_window)) {
+                       tcp_send_challenge_ack(sk);
+                       return -1;
+               }
                goto old_ack;
+       }
 
        /* If the ack includes data we haven't sent yet, discard
         * this segment (RFC793 Section 3.9).
@@ -4529,6 +4553,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)
        struct tcphdr *th;
        bool fragstolen;
 
+       if (size == 0)
+               return 0;
+
        skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);
        if (!skb)
                goto err;
@@ -5241,23 +5268,6 @@ out:
 }
 #endif /* CONFIG_NET_DMA */
 
-static void tcp_send_challenge_ack(struct sock *sk)
-{
-       /* unprotected vars, we dont care of overwrites */
-       static u32 challenge_timestamp;
-       static unsigned int challenge_count;
-       u32 now = jiffies / HZ;
-
-       if (now != challenge_timestamp) {
-               challenge_timestamp = now;
-               challenge_count = 0;
-       }
-       if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
-               NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
-               tcp_send_ack(sk);
-       }
-}
-
 /* Does PAWS and seqno based validation of an incoming segment, flags will
  * play significant role here.
  */
@@ -5310,11 +5320,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
                goto discard;
        }
 
-       /* ts_recent update must be made after we are sure that the packet
-        * is in window.
-        */
-       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
        /* step 3: check security and precedence [ignored] */
 
        /* step 4: Check for a SYN
@@ -5549,6 +5554,11 @@ step5:
        if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
                goto discard;
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        tcp_rcv_rtt_measure_ts(sk, skb);
 
        /* Process urgent data. */
@@ -5646,6 +5656,7 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack,
                tcp_rearm_rto(sk);
                return true;
        }
+       tp->syn_data_acked = tp->syn_data;
        return false;
 }
 
@@ -5963,7 +5974,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
 
        req = tp->fastopen_rsk;
        if (req != NULL) {
-               BUG_ON(sk->sk_state != TCP_SYN_RECV &&
+               WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
                    sk->sk_state != TCP_FIN_WAIT1);
 
                if (tcp_check_req(sk, skb, req, NULL, true) == NULL)
@@ -5984,7 +5995,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                                 */
                                if (req) {
                                        tcp_synack_rtt_meas(sk, req);
-                                       tp->total_retrans = req->retrans;
+                                       tp->total_retrans = req->num_retrans;
 
                                        reqsk_fastopen_remove(sk, req, false);
                                } else {
@@ -6052,7 +6063,15 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
                         * ACK we have received, this would have acknowledged
                         * our SYNACK so stop the SYNACK timer.
                         */
-                       if (acceptable && req != NULL) {
+                       if (req != NULL) {
+                               /* Return RST if ack_seq is invalid.
+                                * Note that RFC793 only says to generate a
+                                * DUPACK for it but for TCP Fast Open it seems
+                                * better to treat this case like TCP_SYN_RECV
+                                * above.
+                                */
+                               if (!acceptable)
+                                       return 1;
                                /* We no longer need the request sock. */
                                reqsk_fastopen_remove(sk, req, false);
                                tcp_rearm_rto(sk);
@@ -6118,6 +6137,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
        } else
                goto discard;
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        /* step 6: check the URG bit */
        tcp_urg(sk, skb, th);
 
index ef998b008a570ba0976b911d85d0b98bb6d834fb..1ed230716d51baa64501e5c6354ec5e50ff20048 100644 (file)
@@ -138,14 +138,6 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
 }
 EXPORT_SYMBOL_GPL(tcp_twsk_unique);
 
-static int tcp_repair_connect(struct sock *sk)
-{
-       tcp_connect_init(sk);
-       tcp_finish_connect(sk, NULL);
-
-       return 0;
-}
-
 /* This will initiate an outgoing connection. */
 int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
@@ -250,10 +242,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 
        inet->inet_id = tp->write_seq ^ jiffies;
 
-       if (likely(!tp->repair))
-               err = tcp_connect(sk);
-       else
-               err = tcp_repair_connect(sk);
+       err = tcp_connect(sk);
 
        rt = NULL;
        if (err)
@@ -877,10 +866,13 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst,
 }
 
 static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req,
-                             struct request_values *rvp)
+                            struct request_values *rvp)
 {
-       TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
-       return tcp_v4_send_synack(sk, NULL, req, rvp, 0, false);
+       int res = tcp_v4_send_synack(sk, NULL, req, rvp, 0, false);
+
+       if (!res)
+               TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
+       return res;
 }
 
 /*
@@ -1070,7 +1062,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family)
 }
 EXPORT_SYMBOL(tcp_md5_do_del);
 
-void tcp_clear_md5_list(struct sock *sk)
+static void tcp_clear_md5_list(struct sock *sk)
 {
        struct tcp_sock *tp = tcp_sk(sk);
        struct tcp_md5sig_key *key;
@@ -1386,7 +1378,8 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
        struct sock *child;
        int err;
 
-       req->retrans = 0;
+       req->num_retrans = 0;
+       req->num_timeout = 0;
        req->sk = NULL;
 
        child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL);
@@ -1461,6 +1454,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk,
                skb_set_owner_r(skb, child);
                __skb_queue_tail(&child->sk_receive_queue, skb);
                tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+               tp->syn_data_acked = 1;
        }
        sk->sk_data_ready(sk, 0);
        bh_unlock_sock(child);
@@ -1740,7 +1734,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 
        tcp_initialize_rcv_mss(newsk);
        tcp_synack_rtt_meas(newsk, req);
-       newtp->total_retrans = req->retrans;
+       newtp->total_retrans = req->num_retrans;
 
 #ifdef CONFIG_TCP_MD5SIG
        /* Copy over the MD5 key from the original socket */
@@ -1918,7 +1912,6 @@ EXPORT_SYMBOL(tcp_v4_do_rcv);
 
 void tcp_v4_early_demux(struct sk_buff *skb)
 {
-       struct net *net = dev_net(skb->dev);
        const struct iphdr *iph;
        const struct tcphdr *th;
        struct sock *sk;
@@ -1926,16 +1919,16 @@ void tcp_v4_early_demux(struct sk_buff *skb)
        if (skb->pkt_type != PACKET_HOST)
                return;
 
-       if (!pskb_may_pull(skb, ip_hdrlen(skb) + sizeof(struct tcphdr)))
+       if (!pskb_may_pull(skb, skb_transport_offset(skb) + sizeof(struct tcphdr)))
                return;
 
        iph = ip_hdr(skb);
-       th = (struct tcphdr *) ((char *)iph + ip_hdrlen(skb));
+       th = tcp_hdr(skb);
 
        if (th->doff < sizeof(struct tcphdr) / 4)
                return;
 
-       sk = __inet_lookup_established(net, &tcp_hashinfo,
+       sk = __inet_lookup_established(dev_net(skb->dev), &tcp_hashinfo,
                                       iph->saddr, th->source,
                                       iph->daddr, ntohs(th->dest),
                                       skb->skb_iif);
@@ -2639,7 +2632,7 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req,
                0, 0, /* could print option size, but that is af dependent. */
                1,    /* timers active (only the expire timer) */
                jiffies_delta_to_clock_t(delta),
-               req->retrans,
+               req->num_timeout,
                from_kuid_munged(seq_user_ns(f), uid),
                0,  /* non standard timer */
                0, /* open_requests have no inode */
index 4c752a6e0bcd91b0b932b483a2b9f988908c04a2..f696d7c2e9faac9b2fbfd2e61472d47a7c2fa823 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/rcupdate.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
-#include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/cache.h>
 #include <linux/slab.h>
@@ -9,6 +8,7 @@
 #include <linux/tcp.h>
 #include <linux/hash.h>
 #include <linux/tcp_metrics.h>
+#include <linux/vmalloc.h>
 
 #include <net/inet_connection_sock.h>
 #include <net/net_namespace.h>
@@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
        }
        a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
        if (a) {
-               if (nla_len(a) != sizeof(sizeof(struct in6_addr)))
+               if (nla_len(a) != sizeof(struct in6_addr))
                        return -EINVAL;
                addr->family = AF_INET6;
                memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
@@ -1034,7 +1034,10 @@ static int __net_init tcp_net_metrics_init(struct net *net)
        net->ipv4.tcp_metrics_hash_log = order_base_2(slots);
        size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log;
 
-       net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL);
+       net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+       if (!net->ipv4.tcp_metrics_hash)
+               net->ipv4.tcp_metrics_hash = vzalloc(size);
+
        if (!net->ipv4.tcp_metrics_hash)
                return -ENOMEM;
 
@@ -1055,7 +1058,10 @@ static void __net_exit tcp_net_metrics_exit(struct net *net)
                        tm = next;
                }
        }
-       kfree(net->ipv4.tcp_metrics_hash);
+       if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash))
+               vfree(net->ipv4.tcp_metrics_hash);
+       else
+               kfree(net->ipv4.tcp_metrics_hash);
 }
 
 static __net_initdata struct pernet_operations tcp_net_metrics_ops = {
index 27536ba16c9da7b89d5385073c7ae4d4f9e27f3c..f35f2dfb64017cc3fedd3cd29d0682c14dcaf5ba 100644 (file)
@@ -510,6 +510,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req,
                newtp->rx_opt.mss_clamp = req->mss;
                TCP_ECN_openreq_child(newtp, req);
                newtp->fastopen_rsk = NULL;
+               newtp->syn_data_acked = 0;
 
                TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS);
        }
@@ -552,7 +553,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
                         * it can be estimated (approximately)
                         * from another data.
                         */
-                       tmp_opt.ts_recent_stamp = get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<<req->retrans);
+                       tmp_opt.ts_recent_stamp = get_seconds() - ((TCP_TIMEOUT_INIT/HZ)<<req->num_timeout);
                        paws_reject = tcp_paws_reject(&tmp_opt, th->rst);
                }
        }
@@ -581,7 +582,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
                 * Note that even if there is new data in the SYN packet
                 * they will be thrown away too.
                 */
-               req->rsk_ops->rtx_syn_ack(sk, req, NULL);
+               inet_rtx_syn_ack(sk, req);
                return NULL;
        }
 
@@ -695,7 +696,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
        /* Got ACK for our SYNACK, so update baseline for SYNACK RTT sample. */
        if (tmp_opt.saw_tstamp && tmp_opt.rcv_tsecr)
                tcp_rsk(req)->snt_synack = tmp_opt.rcv_tsecr;
-       else if (req->retrans) /* don't take RTT sample if retrans && ~TS */
+       else if (req->num_retrans) /* don't take RTT sample if retrans && ~TS */
                tcp_rsk(req)->snt_synack = 0;
 
        /* For Fast Open no more processing is needed (sk is the
@@ -705,7 +706,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
                return sk;
 
        /* While TCP_DEFER_ACCEPT is active, drop bare ACK. */
-       if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
+       if (req->num_timeout < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept &&
            TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) {
                inet_rsk(req)->acked = 1;
                NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPDEFERACCEPTDROP);
index cfe6ffe1c1778b6517297ad3ac9b87d17ce14582..8ac085573217b32cc2cc74e3b77408c607db971e 100644 (file)
@@ -1986,6 +1986,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
                BUG_ON(!tso_segs);
 
+               if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE)
+                       goto repair; /* Skip network transmission */
+
                cwnd_quota = tcp_cwnd_test(tp, skb);
                if (!cwnd_quota)
                        break;
@@ -2026,6 +2029,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
                        break;
 
+repair:
                /* Advance the send_head.  This one is sent out.
                 * This call will increment packets_out.
                 */
@@ -2983,6 +2987,11 @@ int tcp_connect(struct sock *sk)
 
        tcp_connect_init(sk);
 
+       if (unlikely(tp->repair)) {
+               tcp_finish_connect(sk, NULL);
+               return 0;
+       }
+
        buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation);
        if (unlikely(buff == NULL))
                return -ENOBUFS;
index fc04711e80c89dd0dc92ff1027efaa7324b218c3..b78aac30c4986dc78fcd8dae03a527326baa32a3 100644 (file)
@@ -318,7 +318,7 @@ static void tcp_fastopen_synack_timer(struct sock *sk)
        req = tcp_sk(sk)->fastopen_rsk;
        req->rsk_ops->syn_ack_timeout(sk, req);
 
-       if (req->retrans >= max_retries) {
+       if (req->num_timeout >= max_retries) {
                tcp_write_err(sk);
                return;
        }
@@ -327,10 +327,10 @@ static void tcp_fastopen_synack_timer(struct sock *sk)
         * regular retransmit because if the child socket has been accepted
         * it's not good to give up too easily.
         */
-       req->rsk_ops->rtx_syn_ack(sk, req, NULL);
-       req->retrans++;
+       inet_rtx_syn_ack(sk, req);
+       req->num_timeout++;
        inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
-                         TCP_TIMEOUT_INIT << req->retrans, TCP_RTO_MAX);
+                         TCP_TIMEOUT_INIT << req->num_timeout, TCP_RTO_MAX);
 }
 
 /*
@@ -347,8 +347,8 @@ void tcp_retransmit_timer(struct sock *sk)
                return;
        }
        if (tp->fastopen_rsk) {
-               BUG_ON(sk->sk_state != TCP_SYN_RECV &&
-                   sk->sk_state != TCP_FIN_WAIT1);
+               WARN_ON_ONCE(sk->sk_state != TCP_SYN_RECV &&
+                            sk->sk_state != TCP_FIN_WAIT1);
                tcp_fastopen_synack_timer(sk);
                /* Before we receive ACK to our SYN-ACK don't retransmit
                 * anything else (e.g., data or FIN segments).
index 05c5ab8d983c462f75ab6143ca653669d36c1005..3be0ac2c1920e668be3f53f44a3df731a44204fc 100644 (file)
@@ -279,19 +279,8 @@ static void __exit xfrm4_policy_fini(void)
        xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
 }
 
-void __init xfrm4_init(int rt_max_size)
+void __init xfrm4_init(void)
 {
-       /*
-        * Select a default value for the gc_thresh based on the main route
-        * table hash size.  It seems to me the worst case scenario is when
-        * we have ipsec operating in transport mode, in which we create a
-        * dst_entry per socket.  The xfrm gc algorithm starts trying to remove
-        * entries at gc_thresh, and prevents new allocations as 2*gc_thresh
-        * so lets set an initial xfrm gc_thresh value at the rt_max_size/2.
-        * That will let us store an ipsec connection per route table entry,
-        * and start cleaning when were 1/2 full
-        */
-       xfrm4_dst_ops.gc_thresh = rt_max_size/2;
        dst_entries_init(&xfrm4_dst_ops);
 
        xfrm4_state_init();
index b6d3f79151e28251f3b3b5a062869fa9acb64526..2068ac4fbdad43346a1e7d460e8fc20549de0f44 100644 (file)
@@ -7,9 +7,11 @@ obj-$(CONFIG_IPV6) += ipv6.o
 ipv6-objs :=   af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \
                addrlabel.o \
                route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \
-               raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
+               raw.o icmp.o mcast.o reassembly.o tcp_ipv6.o \
                exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o
 
+ipv6-offload :=        ip6_offload.o tcpv6_offload.o udp_offload.o exthdrs_offload.o
+
 ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o
 ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o
 
@@ -39,5 +41,6 @@ obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o
 obj-$(CONFIG_IPV6_GRE) += ip6_gre.o
 
 obj-y += addrconf_core.o exthdrs_core.o
+obj-$(CONFIG_INET) += output_core.o protocol.o $(ipv6_offload)
 
 obj-$(subst m,y,$(CONFIG_IPV6)) += inet6_hashtables.o
index d7c56f8a5b4e76028ebd4f66e5a928ea4ea0887e..6fca01f136ad7ca3528dc19729bd8a7b07c24874 100644 (file)
@@ -81,6 +81,7 @@
 #include <net/pkt_sched.h>
 #include <linux/if_tunnel.h>
 #include <linux/rtnetlink.h>
+#include <linux/netconf.h>
 
 #ifdef CONFIG_IPV6_PRIVACY
 #include <linux/random.h>
@@ -401,7 +402,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
        if (dev->flags & (IFF_NOARP | IFF_LOOPBACK))
                ndev->cnf.accept_dad = -1;
 
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
        if (dev->type == ARPHRD_SIT && (dev->priv_flags & IFF_ISATAP)) {
                pr_info("%s: Disabled Multicast RS\n", dev->name);
                ndev->cnf.rtr_solicits = 0;
@@ -460,6 +461,150 @@ static struct inet6_dev *ipv6_find_idev(struct net_device *dev)
        return idev;
 }
 
+static int inet6_netconf_msgsize_devconf(int type)
+{
+       int size =  NLMSG_ALIGN(sizeof(struct netconfmsg))
+                   + nla_total_size(4);        /* NETCONFA_IFINDEX */
+
+       /* type -1 is used for ALL */
+       if (type == -1 || type == NETCONFA_FORWARDING)
+               size += nla_total_size(4);
+#ifdef CONFIG_IPV6_MROUTE
+       if (type == -1 || type == NETCONFA_MC_FORWARDING)
+               size += nla_total_size(4);
+#endif
+
+       return size;
+}
+
+static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
+                                     struct ipv6_devconf *devconf, u32 portid,
+                                     u32 seq, int event, unsigned int flags,
+                                     int type)
+{
+       struct nlmsghdr  *nlh;
+       struct netconfmsg *ncm;
+
+       nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg),
+                       flags);
+       if (nlh == NULL)
+               return -EMSGSIZE;
+
+       ncm = nlmsg_data(nlh);
+       ncm->ncm_family = AF_INET6;
+
+       if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
+               goto nla_put_failure;
+
+       /* type -1 is used for ALL */
+       if ((type == -1 || type == NETCONFA_FORWARDING) &&
+           nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
+               goto nla_put_failure;
+#ifdef CONFIG_IPV6_MROUTE
+       if ((type == -1 || type == NETCONFA_MC_FORWARDING) &&
+           nla_put_s32(skb, NETCONFA_MC_FORWARDING,
+                       devconf->mc_forwarding) < 0)
+               goto nla_put_failure;
+#endif
+       return nlmsg_end(skb, nlh);
+
+nla_put_failure:
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
+}
+
+void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+                                 struct ipv6_devconf *devconf)
+{
+       struct sk_buff *skb;
+       int err = -ENOBUFS;
+
+       skb = nlmsg_new(inet6_netconf_msgsize_devconf(type), GFP_ATOMIC);
+       if (skb == NULL)
+               goto errout;
+
+       err = inet6_netconf_fill_devconf(skb, ifindex, devconf, 0, 0,
+                                        RTM_NEWNETCONF, 0, type);
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
+       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC);
+       return;
+errout:
+       if (err < 0)
+               rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
+}
+
+static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
+       [NETCONFA_IFINDEX]      = { .len = sizeof(int) },
+       [NETCONFA_FORWARDING]   = { .len = sizeof(int) },
+};
+
+static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
+                                    struct nlmsghdr *nlh,
+                                    void *arg)
+{
+       struct net *net = sock_net(in_skb->sk);
+       struct nlattr *tb[NETCONFA_MAX+1];
+       struct netconfmsg *ncm;
+       struct sk_buff *skb;
+       struct ipv6_devconf *devconf;
+       struct inet6_dev *in6_dev;
+       struct net_device *dev;
+       int ifindex;
+       int err;
+
+       err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX,
+                         devconf_ipv6_policy);
+       if (err < 0)
+               goto errout;
+
+       err = EINVAL;
+       if (!tb[NETCONFA_IFINDEX])
+               goto errout;
+
+       ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
+       switch (ifindex) {
+       case NETCONFA_IFINDEX_ALL:
+               devconf = net->ipv6.devconf_all;
+               break;
+       case NETCONFA_IFINDEX_DEFAULT:
+               devconf = net->ipv6.devconf_dflt;
+               break;
+       default:
+               dev = __dev_get_by_index(net, ifindex);
+               if (dev == NULL)
+                       goto errout;
+               in6_dev = __in6_dev_get(dev);
+               if (in6_dev == NULL)
+                       goto errout;
+               devconf = &in6_dev->cnf;
+               break;
+       }
+
+       err = -ENOBUFS;
+       skb = nlmsg_new(inet6_netconf_msgsize_devconf(-1), GFP_ATOMIC);
+       if (skb == NULL)
+               goto errout;
+
+       err = inet6_netconf_fill_devconf(skb, ifindex, devconf,
+                                        NETLINK_CB(in_skb).portid,
+                                        nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
+                                        -1);
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
+       err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
+errout:
+       return err;
+}
+
 #ifdef CONFIG_SYSCTL
 static void dev_forward_change(struct inet6_dev *idev)
 {
@@ -471,7 +616,7 @@ static void dev_forward_change(struct inet6_dev *idev)
        dev = idev->dev;
        if (idev->cnf.forwarding)
                dev_disable_lro(dev);
-       if (dev && (dev->flags & IFF_MULTICAST)) {
+       if (dev->flags & IFF_MULTICAST) {
                if (idev->cnf.forwarding)
                        ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters);
                else
@@ -486,6 +631,8 @@ static void dev_forward_change(struct inet6_dev *idev)
                else
                        addrconf_leave_anycast(ifa);
        }
+       inet6_netconf_notify_devconf(dev_net(dev), NETCONFA_FORWARDING,
+                                    dev->ifindex, &idev->cnf);
 }
 
 
@@ -518,6 +665,10 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
        *p = newf;
 
        if (p == &net->ipv6.devconf_dflt->forwarding) {
+               if ((!newf) ^ (!old))
+                       inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+                                                    NETCONFA_IFINDEX_DEFAULT,
+                                                    net->ipv6.devconf_dflt);
                rtnl_unlock();
                return 0;
        }
@@ -525,6 +676,10 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf)
        if (p == &net->ipv6.devconf_all->forwarding) {
                net->ipv6.devconf_dflt->forwarding = newf;
                addrconf_forward_change(net, newf);
+               if ((!newf) ^ (!old))
+                       inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING,
+                                                    NETCONFA_IFINDEX_ALL,
+                                                    net->ipv6.devconf_all);
        } else if ((!newf) ^ (!old))
                dev_forward_change((struct inet6_dev *)table->extra1);
        rtnl_unlock();
@@ -553,7 +708,7 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp)
                pr_warn("Freeing alive inet6 address %p\n", ifp);
                return;
        }
-       dst_release(&ifp->rt->dst);
+       ip6_rt_put(ifp->rt);
 
        kfree_rcu(ifp, rcu);
 }
@@ -805,7 +960,7 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp)
                                rt6_set_expires(rt, expires);
                        }
                }
-               dst_release(&rt->dst);
+               ip6_rt_put(rt);
        }
 
        /* clean up prefsrc entries */
@@ -1692,7 +1847,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev,
           This thing is done here expecting that the whole
           class of non-broadcast devices need not cloning.
         */
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
        if (dev->type == ARPHRD_SIT && (dev->flags & IFF_POINTOPOINT))
                cfg.fc_flags |= RTF_NONEXTHOP;
 #endif
@@ -1752,7 +1907,7 @@ static void addrconf_add_mroute(struct net_device *dev)
        ip6_route_add(&cfg);
 }
 
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
 static void sit_route_add(struct net_device *dev)
 {
        struct fib6_config cfg = {
@@ -1881,8 +2036,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
                        addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len,
                                              dev, expires, flags);
                }
-               if (rt)
-                       dst_release(&rt->dst);
+               ip6_rt_put(rt);
        }
 
        /* Try to figure out our local address for this prefix */
@@ -2104,7 +2258,7 @@ int addrconf_set_dstaddr(struct net *net, void __user *arg)
        if (dev == NULL)
                goto err_exit;
 
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
        if (dev->type == ARPHRD_SIT) {
                const struct net_device_ops *ops = dev->netdev_ops;
                struct ifreq ifr;
@@ -2268,7 +2422,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
        struct in6_ifreq ireq;
        int err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
@@ -2287,7 +2441,7 @@ int addrconf_del_ifaddr(struct net *net, void __user *arg)
        struct in6_ifreq ireq;
        int err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
@@ -2315,7 +2469,7 @@ static void add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        }
 }
 
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
 static void sit_add_v4_addrs(struct inet6_dev *idev)
 {
        struct in6_addr addr;
@@ -2434,7 +2588,7 @@ static void addrconf_dev_config(struct net_device *dev)
                addrconf_add_linklocal(idev, &addr);
 }
 
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
 static void addrconf_sit_config(struct net_device *dev)
 {
        struct inet6_dev *idev;
@@ -2471,7 +2625,7 @@ static void addrconf_sit_config(struct net_device *dev)
 }
 #endif
 
-#if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE)
+#if IS_ENABLED(CONFIG_NET_IPGRE)
 static void addrconf_gre_config(struct net_device *dev)
 {
        struct inet6_dev *idev;
@@ -2601,12 +2755,12 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
                }
 
                switch (dev->type) {
-#if defined(CONFIG_IPV6_SIT) || defined(CONFIG_IPV6_SIT_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_SIT)
                case ARPHRD_SIT:
                        addrconf_sit_config(dev);
                        break;
 #endif
-#if defined(CONFIG_NET_IPGRE) || defined(CONFIG_NET_IPGRE_MODULE)
+#if IS_ENABLED(CONFIG_NET_IPGRE)
                case ARPHRD_IPGRE:
                        addrconf_gre_config(dev);
                        break;
@@ -2843,7 +2997,7 @@ static void addrconf_rs_timer(unsigned long data)
        if (idev->dead || !(idev->if_flags & IF_READY))
                goto out;
 
-       if (idev->cnf.forwarding)
+       if (!ipv6_accept_ra(idev))
                goto out;
 
        /* Announcement received after solicitation was sent */
@@ -3005,8 +3159,7 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp)
           router advertisements, start sending router solicitations.
         */
 
-       if (((ifp->idev->cnf.accept_ra == 1 && !ifp->idev->cnf.forwarding) ||
-            ifp->idev->cnf.accept_ra == 2) &&
+       if (ipv6_accept_ra(ifp->idev) &&
            ifp->idev->cnf.rtr_solicits > 0 &&
            (dev->flags&IFF_LOOPBACK) == 0 &&
            (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) {
@@ -3064,14 +3217,15 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos)
                struct hlist_node *n;
                hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket],
                                         addr_lst) {
+                       if (!net_eq(dev_net(ifa->idev->dev), net))
+                               continue;
                        /* sync with offset */
                        if (p < state->offset) {
                                p++;
                                continue;
                        }
                        state->offset++;
-                       if (net_eq(dev_net(ifa->idev->dev), net))
-                               return ifa;
+                       return ifa;
                }
 
                /* prepare for next bucket */
@@ -3089,18 +3243,20 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq,
        struct hlist_node *n = &ifa->addr_lst;
 
        hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) {
+               if (!net_eq(dev_net(ifa->idev->dev), net))
+                       continue;
                state->offset++;
-               if (net_eq(dev_net(ifa->idev->dev), net))
-                       return ifa;
+               return ifa;
        }
 
        while (++state->bucket < IN6_ADDR_HSIZE) {
                state->offset = 0;
                hlist_for_each_entry_rcu_bh(ifa, n,
                                     &inet6_addr_lst[state->bucket], addr_lst) {
+                       if (!net_eq(dev_net(ifa->idev->dev), net))
+                               continue;
                        state->offset++;
-                       if (net_eq(dev_net(ifa->idev->dev), net))
-                               return ifa;
+                       return ifa;
                }
        }
 
@@ -3191,7 +3347,7 @@ void if6_proc_exit(void)
 }
 #endif /* CONFIG_PROC_FS */
 
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
 /* Check if address is a home address configured on any interface. */
 int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr)
 {
@@ -3889,6 +4045,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
        array[DEVCONF_DISABLE_IPV6] = cnf->disable_ipv6;
        array[DEVCONF_ACCEPT_DAD] = cnf->accept_dad;
        array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao;
+       array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify;
 }
 
 static inline size_t inet6_ifla6_size(void)
@@ -4556,6 +4713,13 @@ static struct addrconf_sysctl_table
                        .mode           = 0644,
                        .proc_handler   = proc_dointvec
                },
+               {
+                       .procname       = "ndisc_notify",
+                       .data           = &ipv6_devconf.ndisc_notify,
+                       .maxlen         = sizeof(int),
+                       .mode           = 0644,
+                       .proc_handler   = proc_dointvec
+               },
                {
                        /* sentinel */
                }
@@ -4781,6 +4945,8 @@ int __init addrconf_init(void)
                        inet6_dump_ifmcaddr, NULL);
        __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
                        inet6_dump_ifacaddr, NULL);
+       __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
+                       NULL, NULL);
 
        ipv6_addr_label_rtnl_register();
 
index a974247a9ae40bdb6c83cf5a60a6432761bd84e7..b043c60429bd45529111d56893dac55aae91427a 100644 (file)
@@ -160,7 +160,8 @@ lookup_protocol:
        }
 
        err = -EPERM;
-       if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW))
+       if (sock->type == SOCK_RAW && !kern &&
+           !ns_capable(net->user_ns, CAP_NET_RAW))
                goto out_rcu_unlock;
 
        sock->ops = answer->ops;
@@ -282,7 +283,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                return -EINVAL;
 
        snum = ntohs(addr->sin6_port);
-       if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+       if (snum && snum < PROT_SOCK && !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
                return -EACCES;
 
        lock_sock(sk);
@@ -699,249 +700,9 @@ bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb)
 }
 EXPORT_SYMBOL_GPL(ipv6_opt_accepted);
 
-static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
-{
-       const struct inet6_protocol *ops = NULL;
-
-       for (;;) {
-               struct ipv6_opt_hdr *opth;
-               int len;
-
-               if (proto != NEXTHDR_HOP) {
-                       ops = rcu_dereference(inet6_protos[proto]);
-
-                       if (unlikely(!ops))
-                               break;
-
-                       if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
-                               break;
-               }
-
-               if (unlikely(!pskb_may_pull(skb, 8)))
-                       break;
-
-               opth = (void *)skb->data;
-               len = ipv6_optlen(opth);
-
-               if (unlikely(!pskb_may_pull(skb, len)))
-                       break;
-
-               proto = opth->nexthdr;
-               __skb_pull(skb, len);
-       }
-
-       return proto;
-}
-
-static int ipv6_gso_send_check(struct sk_buff *skb)
-{
-       const struct ipv6hdr *ipv6h;
-       const struct inet6_protocol *ops;
-       int err = -EINVAL;
-
-       if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
-               goto out;
-
-       ipv6h = ipv6_hdr(skb);
-       __skb_pull(skb, sizeof(*ipv6h));
-       err = -EPROTONOSUPPORT;
-
-       rcu_read_lock();
-       ops = rcu_dereference(inet6_protos[
-               ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
-
-       if (likely(ops && ops->gso_send_check)) {
-               skb_reset_transport_header(skb);
-               err = ops->gso_send_check(skb);
-       }
-       rcu_read_unlock();
-
-out:
-       return err;
-}
-
-static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
-       netdev_features_t features)
-{
-       struct sk_buff *segs = ERR_PTR(-EINVAL);
-       struct ipv6hdr *ipv6h;
-       const struct inet6_protocol *ops;
-       int proto;
-       struct frag_hdr *fptr;
-       unsigned int unfrag_ip6hlen;
-       u8 *prevhdr;
-       int offset = 0;
-
-       if (!(features & NETIF_F_V6_CSUM))
-               features &= ~NETIF_F_SG;
-
-       if (unlikely(skb_shinfo(skb)->gso_type &
-                    ~(SKB_GSO_UDP |
-                      SKB_GSO_DODGY |
-                      SKB_GSO_TCP_ECN |
-                      SKB_GSO_TCPV6 |
-                      0)))
-               goto out;
-
-       if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
-               goto out;
-
-       ipv6h = ipv6_hdr(skb);
-       __skb_pull(skb, sizeof(*ipv6h));
-       segs = ERR_PTR(-EPROTONOSUPPORT);
-
-       proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
-       rcu_read_lock();
-       ops = rcu_dereference(inet6_protos[proto]);
-       if (likely(ops && ops->gso_segment)) {
-               skb_reset_transport_header(skb);
-               segs = ops->gso_segment(skb, features);
-       }
-       rcu_read_unlock();
-
-       if (IS_ERR(segs))
-               goto out;
-
-       for (skb = segs; skb; skb = skb->next) {
-               ipv6h = ipv6_hdr(skb);
-               ipv6h->payload_len = htons(skb->len - skb->mac_len -
-                                          sizeof(*ipv6h));
-               if (proto == IPPROTO_UDP) {
-                       unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
-                       fptr = (struct frag_hdr *)(skb_network_header(skb) +
-                               unfrag_ip6hlen);
-                       fptr->frag_off = htons(offset);
-                       if (skb->next != NULL)
-                               fptr->frag_off |= htons(IP6_MF);
-                       offset += (ntohs(ipv6h->payload_len) -
-                                  sizeof(struct frag_hdr));
-               }
-       }
-
-out:
-       return segs;
-}
-
-static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
-{
-       const struct inet6_protocol *ops;
-       struct sk_buff **pp = NULL;
-       struct sk_buff *p;
-       struct ipv6hdr *iph;
-       unsigned int nlen;
-       unsigned int hlen;
-       unsigned int off;
-       int flush = 1;
-       int proto;
-       __wsum csum;
-
-       off = skb_gro_offset(skb);
-       hlen = off + sizeof(*iph);
-       iph = skb_gro_header_fast(skb, off);
-       if (skb_gro_header_hard(skb, hlen)) {
-               iph = skb_gro_header_slow(skb, hlen, off);
-               if (unlikely(!iph))
-                       goto out;
-       }
-
-       skb_gro_pull(skb, sizeof(*iph));
-       skb_set_transport_header(skb, skb_gro_offset(skb));
-
-       flush += ntohs(iph->payload_len) != skb_gro_len(skb);
-
-       rcu_read_lock();
-       proto = iph->nexthdr;
-       ops = rcu_dereference(inet6_protos[proto]);
-       if (!ops || !ops->gro_receive) {
-               __pskb_pull(skb, skb_gro_offset(skb));
-               proto = ipv6_gso_pull_exthdrs(skb, proto);
-               skb_gro_pull(skb, -skb_transport_offset(skb));
-               skb_reset_transport_header(skb);
-               __skb_push(skb, skb_gro_offset(skb));
-
-               ops = rcu_dereference(inet6_protos[proto]);
-               if (!ops || !ops->gro_receive)
-                       goto out_unlock;
-
-               iph = ipv6_hdr(skb);
-       }
-
-       NAPI_GRO_CB(skb)->proto = proto;
-
-       flush--;
-       nlen = skb_network_header_len(skb);
-
-       for (p = *head; p; p = p->next) {
-               const struct ipv6hdr *iph2;
-               __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
-
-               if (!NAPI_GRO_CB(p)->same_flow)
-                       continue;
-
-               iph2 = ipv6_hdr(p);
-               first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
-
-               /* All fields must match except length and Traffic Class. */
-               if (nlen != skb_network_header_len(p) ||
-                   (first_word & htonl(0xF00FFFFF)) ||
-                   memcmp(&iph->nexthdr, &iph2->nexthdr,
-                          nlen - offsetof(struct ipv6hdr, nexthdr))) {
-                       NAPI_GRO_CB(p)->same_flow = 0;
-                       continue;
-               }
-               /* flush if Traffic Class fields are different */
-               NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
-               NAPI_GRO_CB(p)->flush |= flush;
-       }
-
-       NAPI_GRO_CB(skb)->flush |= flush;
-
-       csum = skb->csum;
-       skb_postpull_rcsum(skb, iph, skb_network_header_len(skb));
-
-       pp = ops->gro_receive(head, skb);
-
-       skb->csum = csum;
-
-out_unlock:
-       rcu_read_unlock();
-
-out:
-       NAPI_GRO_CB(skb)->flush |= flush;
-
-       return pp;
-}
-
-static int ipv6_gro_complete(struct sk_buff *skb)
-{
-       const struct inet6_protocol *ops;
-       struct ipv6hdr *iph = ipv6_hdr(skb);
-       int err = -ENOSYS;
-
-       iph->payload_len = htons(skb->len - skb_network_offset(skb) -
-                                sizeof(*iph));
-
-       rcu_read_lock();
-       ops = rcu_dereference(inet6_protos[NAPI_GRO_CB(skb)->proto]);
-       if (WARN_ON(!ops || !ops->gro_complete))
-               goto out_unlock;
-
-       err = ops->gro_complete(skb);
-
-out_unlock:
-       rcu_read_unlock();
-
-       return err;
-}
-
 static struct packet_type ipv6_packet_type __read_mostly = {
        .type = cpu_to_be16(ETH_P_IPV6),
        .func = ipv6_rcv,
-       .gso_send_check = ipv6_gso_send_check,
-       .gso_segment = ipv6_gso_segment,
-       .gro_receive = ipv6_gro_receive,
-       .gro_complete = ipv6_gro_complete,
 };
 
 static int __init ipv6_packet_init(void)
index 7e6139508ee7616f10996f33d75ae88e56bc5ca8..ecc35b93314bb1b73c70df219c9cf8f125c77908 100644 (file)
@@ -44,7 +44,7 @@
 #define IPV6HDR_BASELEN 8
 
 struct tmp_ext {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                struct in6_addr saddr;
 #endif
                struct in6_addr daddr;
@@ -152,7 +152,7 @@ bad:
        return false;
 }
 
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
 /**
  *     ipv6_rearrange_destopt - rearrange IPv6 destination options header
  *     @iph: IPv6 header
@@ -320,7 +320,7 @@ static void ah6_output_done(struct crypto_async_request *base, int err)
        memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
 
        if (extlen) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                memcpy(&top_iph->saddr, iph_ext, extlen);
 #else
                memcpy(&top_iph->daddr, iph_ext, extlen);
@@ -385,7 +385,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
        memcpy(iph_base, top_iph, IPV6HDR_BASELEN);
 
        if (extlen) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                memcpy(iph_ext, &top_iph->saddr, extlen);
 #else
                memcpy(iph_ext, &top_iph->daddr, extlen);
@@ -434,7 +434,7 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
        memcpy(top_iph, iph_base, IPV6HDR_BASELEN);
 
        if (extlen) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                memcpy(&top_iph->saddr, iph_ext, extlen);
 #else
                memcpy(&top_iph->daddr, iph_ext, extlen);
index cdf02be5f191405de1587f4d03b3c12f3fe4cc9d..757a810d8f15a5270bbcdf1f734768371d892e73 100644 (file)
@@ -64,7 +64,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
        int     ishost = !net->ipv6.devconf_all->forwarding;
        int     err = 0;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
        if (ipv6_addr_is_multicast(addr))
                return -EINVAL;
@@ -84,7 +84,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
                rt = rt6_lookup(net, addr, NULL, 0, 0);
                if (rt) {
                        dev = rt->dst.dev;
-                       dst_release(&rt->dst);
+                       ip6_rt_put(rt);
                } else if (ishost) {
                        err = -EADDRNOTAVAIL;
                        goto error;
@@ -189,6 +189,9 @@ void ipv6_sock_ac_close(struct sock *sk)
        struct net *net = sock_net(sk);
        int     prev_index;
 
+       if (!np->ipv6_ac_list)
+               return;
+
        write_lock_bh(&ipv6_sk_ac_lock);
        pac = np->ipv6_ac_list;
        np->ipv6_ac_list = NULL;
index be2b67d631e5195fcc7df5b48a4b3d172d5eccdc..8edf2601065af07790500809b8dee9fad0fc8eaa 100644 (file)
@@ -701,7 +701,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
                                err = -EINVAL;
                                goto exit_f;
                        }
-                       if (!capable(CAP_NET_RAW)) {
+                       if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
                                err = -EPERM;
                                goto exit_f;
                        }
@@ -721,7 +721,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
                                err = -EINVAL;
                                goto exit_f;
                        }
-                       if (!capable(CAP_NET_RAW)) {
+                       if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
                                err = -EPERM;
                                goto exit_f;
                        }
@@ -746,7 +746,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
                                err = -EINVAL;
                                goto exit_f;
                        }
-                       if (!capable(CAP_NET_RAW)) {
+                       if (!ns_capable(net->user_ns, CAP_NET_RAW)) {
                                err = -EPERM;
                                goto exit_f;
                        }
@@ -769,7 +769,7 @@ int datagram_send_ctl(struct net *net, struct sock *sk,
                        rthdr = (struct ipv6_rt_hdr *)CMSG_DATA(cmsg);
 
                        switch (rthdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                        case IPV6_SRCRT_TYPE_2:
                                if (rthdr->hdrlen != 2 ||
                                    rthdr->segments_left != 1) {
index fa3d9c3280927934bd7b082077674c3c31d4ad4c..473f628f9f203d2e0c58466f32603ce50a330402 100644 (file)
 #include <net/ndisc.h>
 #include <net/ip6_route.h>
 #include <net/addrconf.h>
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
 #include <net/xfrm.h>
 #endif
 
 #include <asm/uaccess.h>
 
-int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
-{
-       const unsigned char *nh = skb_network_header(skb);
-       int packet_len = skb->tail - skb->network_header;
-       struct ipv6_opt_hdr *hdr;
-       int len;
-
-       if (offset + 2 > packet_len)
-               goto bad;
-       hdr = (struct ipv6_opt_hdr *)(nh + offset);
-       len = ((hdr->hdrlen + 1) << 3);
-
-       if (offset + len > packet_len)
-               goto bad;
-
-       offset += 2;
-       len -= 2;
-
-       while (len > 0) {
-               int opttype = nh[offset];
-               int optlen;
-
-               if (opttype == type)
-                       return offset;
-
-               switch (opttype) {
-               case IPV6_TLV_PAD1:
-                       optlen = 1;
-                       break;
-               default:
-                       optlen = nh[offset + 1] + 2;
-                       if (optlen > len)
-                               goto bad;
-                       break;
-               }
-               offset += optlen;
-               len -= optlen;
-       }
-       /* not_found */
- bad:
-       return -1;
-}
-EXPORT_SYMBOL_GPL(ipv6_find_tlv);
-
 /*
  *     Parsing tlv encoded headers.
  *
@@ -224,7 +180,7 @@ bad:
   Destination options header.
  *****************************/
 
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
 static bool ipv6_dest_hao(struct sk_buff *skb, int optoff)
 {
        struct ipv6_destopt_hao *hao;
@@ -288,7 +244,7 @@ static bool ipv6_dest_hao(struct sk_buff *skb, int optoff)
 #endif
 
 static const struct tlvtype_proc tlvprocdestopt_lst[] = {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
        {
                .type   = IPV6_TLV_HAO,
                .func   = ipv6_dest_hao,
@@ -300,7 +256,7 @@ static const struct tlvtype_proc tlvprocdestopt_lst[] = {
 static int ipv6_destopt_rcv(struct sk_buff *skb)
 {
        struct inet6_skb_parm *opt = IP6CB(skb);
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
        __u16 dstbuf;
 #endif
        struct dst_entry *dst = skb_dst(skb);
@@ -315,14 +271,14 @@ static int ipv6_destopt_rcv(struct sk_buff *skb)
        }
 
        opt->lastopt = opt->dst1 = skb_network_header_len(skb);
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
        dstbuf = opt->dst1;
 #endif
 
        if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) {
                skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3;
                opt = IP6CB(skb);
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                opt->nhoff = dstbuf;
 #else
                opt->nhoff = opt->dst1;
@@ -378,7 +334,7 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
 looped_back:
        if (hdr->segments_left == 0) {
                switch (hdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                case IPV6_SRCRT_TYPE_2:
                        /* Silently discard type 2 header unless it was
                         * processed by own
@@ -404,7 +360,7 @@ looped_back:
        }
 
        switch (hdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
        case IPV6_SRCRT_TYPE_2:
                if (accept_source_route < 0)
                        goto unknown_rh;
@@ -461,7 +417,7 @@ looped_back:
        addr += i - 1;
 
        switch (hdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
        case IPV6_SRCRT_TYPE_2:
                if (xfrm6_input_addr(skb, (xfrm_address_t *)addr,
                                     (xfrm_address_t *)&ipv6_hdr(skb)->saddr,
@@ -528,12 +484,12 @@ unknown_rh:
 
 static const struct inet6_protocol rthdr_protocol = {
        .handler        =       ipv6_rthdr_rcv,
-       .flags          =       INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
+       .flags          =       INET6_PROTO_NOPOLICY,
 };
 
 static const struct inet6_protocol destopt_protocol = {
        .handler        =       ipv6_destopt_rcv,
-       .flags          =       INET6_PROTO_NOPOLICY | INET6_PROTO_GSO_EXTHDR,
+       .flags          =       INET6_PROTO_NOPOLICY,
 };
 
 static const struct inet6_protocol nodata_protocol = {
@@ -559,10 +515,10 @@ int __init ipv6_exthdrs_init(void)
 
 out:
        return ret;
-out_rthdr:
-       inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
 out_destopt:
        inet6_del_protocol(&destopt_protocol, IPPROTO_DSTOPTS);
+out_rthdr:
+       inet6_del_protocol(&rthdr_protocol, IPPROTO_ROUTING);
        goto out;
 };
 
index f73d59a141316a12286849e89b6f0213e43f42d5..c5e83fae4df423ccbe02bed8bf31ffd415014ad2 100644 (file)
@@ -111,3 +111,171 @@ int ipv6_skip_exthdr(const struct sk_buff *skb, int start, u8 *nexthdrp,
        return start;
 }
 EXPORT_SYMBOL(ipv6_skip_exthdr);
+
+int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
+{
+       const unsigned char *nh = skb_network_header(skb);
+       int packet_len = skb->tail - skb->network_header;
+       struct ipv6_opt_hdr *hdr;
+       int len;
+
+       if (offset + 2 > packet_len)
+               goto bad;
+       hdr = (struct ipv6_opt_hdr *)(nh + offset);
+       len = ((hdr->hdrlen + 1) << 3);
+
+       if (offset + len > packet_len)
+               goto bad;
+
+       offset += 2;
+       len -= 2;
+
+       while (len > 0) {
+               int opttype = nh[offset];
+               int optlen;
+
+               if (opttype == type)
+                       return offset;
+
+               switch (opttype) {
+               case IPV6_TLV_PAD1:
+                       optlen = 1;
+                       break;
+               default:
+                       optlen = nh[offset + 1] + 2;
+                       if (optlen > len)
+                               goto bad;
+                       break;
+               }
+               offset += optlen;
+               len -= optlen;
+       }
+       /* not_found */
+ bad:
+       return -1;
+}
+EXPORT_SYMBOL_GPL(ipv6_find_tlv);
+
+/*
+ * find the offset to specified header or the protocol number of last header
+ * if target < 0. "last header" is transport protocol header, ESP, or
+ * "No next header".
+ *
+ * Note that *offset is used as input/output parameter. an if it is not zero,
+ * then it must be a valid offset to an inner IPv6 header. This can be used
+ * to explore inner IPv6 header, eg. ICMPv6 error messages.
+ *
+ * If target header is found, its offset is set in *offset and return protocol
+ * number. Otherwise, return -1.
+ *
+ * If the first fragment doesn't contain the final protocol header or
+ * NEXTHDR_NONE it is considered invalid.
+ *
+ * Note that non-1st fragment is special case that "the protocol number
+ * of last header" is "next header" field in Fragment header. In this case,
+ * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
+ * isn't NULL.
+ *
+ * if flags is not NULL and it's a fragment, then the frag flag
+ * IP6_FH_F_FRAG will be set. If it's an AH header, the
+ * IP6_FH_F_AUTH flag is set and target < 0, then this function will
+ * stop at the AH header. If IP6_FH_F_SKIP_RH flag was passed, then this
+ * function will skip all those routing headers, where segements_left was 0.
+ */
+int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+                 int target, unsigned short *fragoff, int *flags)
+{
+       unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
+       u8 nexthdr = ipv6_hdr(skb)->nexthdr;
+       unsigned int len;
+       bool found;
+
+       if (fragoff)
+               *fragoff = 0;
+
+       if (*offset) {
+               struct ipv6hdr _ip6, *ip6;
+
+               ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
+               if (!ip6 || (ip6->version != 6)) {
+                       printk(KERN_ERR "IPv6 header not found\n");
+                       return -EBADMSG;
+               }
+               start = *offset + sizeof(struct ipv6hdr);
+               nexthdr = ip6->nexthdr;
+       }
+       len = skb->len - start;
+
+       do {
+               struct ipv6_opt_hdr _hdr, *hp;
+               unsigned int hdrlen;
+               found = (nexthdr == target);
+
+               if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
+                       if (target < 0)
+                               break;
+                       return -ENOENT;
+               }
+
+               hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
+               if (hp == NULL)
+                       return -EBADMSG;
+
+               if (nexthdr == NEXTHDR_ROUTING) {
+                       struct ipv6_rt_hdr _rh, *rh;
+
+                       rh = skb_header_pointer(skb, start, sizeof(_rh),
+                                               &_rh);
+                       if (rh == NULL)
+                               return -EBADMSG;
+
+                       if (flags && (*flags & IP6_FH_F_SKIP_RH) &&
+                           rh->segments_left == 0)
+                               found = false;
+               }
+
+               if (nexthdr == NEXTHDR_FRAGMENT) {
+                       unsigned short _frag_off;
+                       __be16 *fp;
+
+                       if (flags)      /* Indicate that this is a fragment */
+                               *flags |= IP6_FH_F_FRAG;
+                       fp = skb_header_pointer(skb,
+                                               start+offsetof(struct frag_hdr,
+                                                              frag_off),
+                                               sizeof(_frag_off),
+                                               &_frag_off);
+                       if (fp == NULL)
+                               return -EBADMSG;
+
+                       _frag_off = ntohs(*fp) & ~0x7;
+                       if (_frag_off) {
+                               if (target < 0 &&
+                                   ((!ipv6_ext_hdr(hp->nexthdr)) ||
+                                    hp->nexthdr == NEXTHDR_NONE)) {
+                                       if (fragoff)
+                                               *fragoff = _frag_off;
+                                       return hp->nexthdr;
+                               }
+                               return -ENOENT;
+                       }
+                       hdrlen = 8;
+               } else if (nexthdr == NEXTHDR_AUTH) {
+                       if (flags && (*flags & IP6_FH_F_AUTH) && (target < 0))
+                               break;
+                       hdrlen = (hp->hdrlen + 2) << 2;
+               } else
+                       hdrlen = ipv6_optlen(hp);
+
+               if (!found) {
+                       nexthdr = hp->nexthdr;
+                       len -= hdrlen;
+                       start += hdrlen;
+               }
+       } while (!found);
+
+       *offset = start;
+       return nexthdr;
+}
+EXPORT_SYMBOL(ipv6_find_hdr);
+
diff --git a/net/ipv6/exthdrs_offload.c b/net/ipv6/exthdrs_offload.c
new file mode 100644 (file)
index 0000000..cf77f3a
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *     IPV6 GSO/GRO offload support
+ *     Linux INET6 implementation
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      IPV6 Extension Header GSO/GRO support
+ */
+#include <net/protocol.h>
+#include "ip6_offload.h"
+
+static const struct net_offload rthdr_offload = {
+       .flags          =       INET6_PROTO_GSO_EXTHDR,
+};
+
+static const struct net_offload dstopt_offload = {
+       .flags          =       INET6_PROTO_GSO_EXTHDR,
+};
+
+int __init ipv6_exthdrs_offload_init(void)
+{
+       int ret;
+
+       ret = inet6_add_offload(&rthdr_offload, IPPROTO_ROUTING);
+       if (!ret)
+               goto out;
+
+       ret = inet6_add_offload(&dstopt_offload, IPPROTO_DSTOPTS);
+       if (!ret)
+               goto out_rt;
+
+out:
+       return ret;
+
+out_rt:
+       inet_del_offload(&rthdr_offload, IPPROTO_ROUTING);
+       goto out;
+}
index d9fb9110f607e8c587667147739979f34d52bc0a..2e1a432867c0897f4e0d4439f9c6fd5d3f4c66cb 100644 (file)
@@ -100,7 +100,7 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
                goto out;
        }
 again:
-       dst_release(&rt->dst);
+       ip6_rt_put(rt);
        rt = NULL;
        goto out;
 
index 24d69dbca4d68e2f1d1444796cb3d5c33b0a1fe2..b4a9fd51dae74bd8143b2d32e791e089f1d8562f 100644 (file)
@@ -280,7 +280,7 @@ static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, st
        return 0;
 }
 
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
 static void mip6_addr_swap(struct sk_buff *skb)
 {
        struct ipv6hdr *iph = ipv6_hdr(skb);
index c4f934176cabd92ebfb4bba774335427b9f8932a..30647857a375bce469c50071636b5aef6c5a33d7 100644 (file)
@@ -252,6 +252,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu)
                return NULL;
        dst->ops->update_pmtu(dst, sk, NULL, mtu);
 
-       return inet6_csk_route_socket(sk, &fl6);
+       dst = inet6_csk_route_socket(sk, &fl6);
+       return IS_ERR(dst) ? NULL : dst;
 }
 EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu);
index 73f1a00a96afcd194e5567c36e2d1956a62018ca..dea17fd28e5037295d56cf517671b479a1bca825 100644 (file)
@@ -87,11 +87,13 @@ struct sock *__inet6_lookup_established(struct net *net,
        rcu_read_lock();
 begin:
        sk_nulls_for_each_rcu(sk, node, &head->chain) {
-               /* For IPV6 do the cheaper port and family tests first. */
-               if (INET6_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
+               if (sk->sk_hash != hash)
+                       continue;
+               if (likely(INET6_MATCH(sk, net, saddr, daddr, ports, dif))) {
                        if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt)))
                                goto begintw;
-                       if (!INET6_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
+                       if (unlikely(!INET6_MATCH(sk, net, saddr, daddr,
+                                                 ports, dif))) {
                                sock_put(sk);
                                goto begin;
                        }
@@ -104,12 +106,16 @@ begin:
 begintw:
        /* Must check for a TIME_WAIT'er before going to listener hash. */
        sk_nulls_for_each_rcu(sk, node, &head->twchain) {
-               if (INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
+               if (sk->sk_hash != hash)
+                       continue;
+               if (likely(INET6_TW_MATCH(sk, net, saddr, daddr,
+                                         ports, dif))) {
                        if (unlikely(!atomic_inc_not_zero(&sk->sk_refcnt))) {
                                sk = NULL;
                                goto out;
                        }
-                       if (!INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) {
+                       if (unlikely(!INET6_TW_MATCH(sk, net, saddr, daddr,
+                                                    ports, dif))) {
                                sock_put(sk);
                                goto begintw;
                        }
@@ -236,9 +242,12 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
 
        /* Check TIME-WAIT sockets first. */
        sk_nulls_for_each(sk2, node, &head->twchain) {
-               tw = inet_twsk(sk2);
+               if (sk2->sk_hash != hash)
+                       continue;
 
-               if (INET6_TW_MATCH(sk2, net, hash, saddr, daddr, ports, dif)) {
+               if (likely(INET6_TW_MATCH(sk2, net, saddr, daddr,
+                                         ports, dif))) {
+                       tw = inet_twsk(sk2);
                        if (twsk_unique(sk, sk2, twp))
                                goto unique;
                        else
@@ -249,7 +258,9 @@ static int __inet6_check_established(struct inet_timewait_death_row *death_row,
 
        /* And established part... */
        sk_nulls_for_each(sk2, node, &head->chain) {
-               if (INET6_MATCH(sk2, net, hash, saddr, daddr, ports, dif))
+               if (sk2->sk_hash != hash)
+                       continue;
+               if (likely(INET6_MATCH(sk2, net, saddr, daddr, ports, dif)))
                        goto not_unique;
        }
 
index 24995a93ef8c94b22224dd344a9d474a72d28cc1..710cafd2e1a9f7a7308ffc4fa82a02abec431523 100644 (file)
@@ -672,6 +672,8 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                            iter->rt6i_idev == rt->rt6i_idev &&
                            ipv6_addr_equal(&iter->rt6i_gateway,
                                            &rt->rt6i_gateway)) {
+                               if (rt->rt6i_nsiblings)
+                                       rt->rt6i_nsiblings = 0;
                                if (!(iter->rt6i_flags & RTF_EXPIRES))
                                        return -EEXIST;
                                if (!(rt->rt6i_flags & RTF_EXPIRES))
@@ -680,6 +682,21 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
                                        rt6_set_expires(iter, rt->dst.expires);
                                return -EEXIST;
                        }
+                       /* If we have the same destination and the same metric,
+                        * but not the same gateway, then the route we try to
+                        * add is sibling to this route, increment our counter
+                        * of siblings, and later we will add our route to the
+                        * list.
+                        * Only static routes (which don't have flag
+                        * RTF_EXPIRES) are used for ECMPv6.
+                        *
+                        * To avoid long list, we only had siblings if the
+                        * route have a gateway.
+                        */
+                       if (rt->rt6i_flags & RTF_GATEWAY &&
+                           !(rt->rt6i_flags & RTF_EXPIRES) &&
+                           !(iter->rt6i_flags & RTF_EXPIRES))
+                               rt->rt6i_nsiblings++;
                }
 
                if (iter->rt6i_metric > rt->rt6i_metric)
@@ -692,6 +709,35 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt,
        if (ins == &fn->leaf)
                fn->rr_ptr = NULL;
 
+       /* Link this route to others same route. */
+       if (rt->rt6i_nsiblings) {
+               unsigned int rt6i_nsiblings;
+               struct rt6_info *sibling, *temp_sibling;
+
+               /* Find the first route that have the same metric */
+               sibling = fn->leaf;
+               while (sibling) {
+                       if (sibling->rt6i_metric == rt->rt6i_metric) {
+                               list_add_tail(&rt->rt6i_siblings,
+                                             &sibling->rt6i_siblings);
+                               break;
+                       }
+                       sibling = sibling->dst.rt6_next;
+               }
+               /* For each sibling in the list, increment the counter of
+                * siblings. BUG() if counters does not match, list of siblings
+                * is broken!
+                */
+               rt6i_nsiblings = 0;
+               list_for_each_entry_safe(sibling, temp_sibling,
+                                        &rt->rt6i_siblings, rt6i_siblings) {
+                       sibling->rt6i_nsiblings++;
+                       BUG_ON(sibling->rt6i_nsiblings != rt->rt6i_nsiblings);
+                       rt6i_nsiblings++;
+               }
+               BUG_ON(rt6i_nsiblings != rt->rt6i_nsiblings);
+       }
+
        /*
         *      insert node
         */
@@ -1193,6 +1239,17 @@ static void fib6_del_route(struct fib6_node *fn, struct rt6_info **rtp,
        if (fn->rr_ptr == rt)
                fn->rr_ptr = NULL;
 
+       /* Remove this entry from other siblings */
+       if (rt->rt6i_nsiblings) {
+               struct rt6_info *sibling, *next_sibling;
+
+               list_for_each_entry_safe(sibling, next_sibling,
+                                        &rt->rt6i_siblings, rt6i_siblings)
+                       sibling->rt6i_nsiblings--;
+               rt->rt6i_nsiblings = 0;
+               list_del_init(&rt->rt6i_siblings);
+       }
+
        /* Adjust walkers */
        read_lock(&fib6_walker_lock);
        FOR_WALKERS(w) {
index 90bbefb579435d3f3c4117f738d38366d0421b33..29124b7a04c8dfb335df69014b5348e22b3fb6ab 100644 (file)
@@ -519,7 +519,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
                }
                read_unlock_bh(&ip6_sk_fl_lock);
 
-               if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) {
+               if (freq.flr_share == IPV6_FL_S_NONE &&
+                   ns_capable(net->user_ns, CAP_NET_ADMIN)) {
                        fl = fl_lookup(net, freq.flr_label);
                        if (fl) {
                                err = fl6_renew(fl, freq.flr_linger, freq.flr_expires);
index 0185679c5f536c1fa98d71ac90a2c24cd6481d8f..867466c96aac053c6bf39c956160171a099ff304 100644 (file)
@@ -109,21 +109,6 @@ static u32 HASH_ADDR(const struct in6_addr *addr)
 #define tunnels_r      tunnels[2]
 #define tunnels_l      tunnels[1]
 #define tunnels_wc     tunnels[0]
-/*
- * Locking : hash tables are protected by RCU and RTNL
- */
-
-#define for_each_ip_tunnel_rcu(start) \
-       for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
-       u64     rx_packets;
-       u64     rx_bytes;
-       u64     tx_packets;
-       u64     tx_bytes;
-       struct u64_stats_sync   syncp;
-};
 
 static struct rtnl_link_stats64 *ip6gre_get_stats64(struct net_device *dev,
                struct rtnl_link_stats64 *tot)
@@ -181,7 +166,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
                       ARPHRD_ETHER : ARPHRD_IP6GRE;
        int score, cand_score = 4;
 
-       for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) {
+       for_each_ip_tunnel_rcu(t, ign->tunnels_r_l[h0 ^ h1]) {
                if (!ipv6_addr_equal(local, &t->parms.laddr) ||
                    !ipv6_addr_equal(remote, &t->parms.raddr) ||
                    key != t->parms.i_key ||
@@ -206,7 +191,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
                }
        }
 
-       for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) {
+       for_each_ip_tunnel_rcu(t, ign->tunnels_r[h0 ^ h1]) {
                if (!ipv6_addr_equal(remote, &t->parms.raddr) ||
                    key != t->parms.i_key ||
                    !(t->dev->flags & IFF_UP))
@@ -230,7 +215,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
                }
        }
 
-       for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) {
+       for_each_ip_tunnel_rcu(t, ign->tunnels_l[h1]) {
                if ((!ipv6_addr_equal(local, &t->parms.laddr) &&
                          (!ipv6_addr_equal(local, &t->parms.raddr) ||
                                 !ipv6_addr_is_multicast(local))) ||
@@ -256,7 +241,7 @@ static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev,
                }
        }
 
-       for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) {
+       for_each_ip_tunnel_rcu(t, ign->tunnels_wc[h1]) {
                if (t->parms.i_key != key ||
                    !(t->dev->flags & IFF_UP))
                        continue;
@@ -1069,7 +1054,7 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu)
                                        dev->mtu = IPV6_MIN_MTU;
                        }
                }
-               dst_release(&rt->dst);
+               ip6_rt_put(rt);
        }
 
        t->hlen = addend;
@@ -1161,7 +1146,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
        case SIOCADDTUNNEL:
        case SIOCCHGTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                err = -EFAULT;
@@ -1209,7 +1194,7 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
 
        case SIOCDELTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                if (dev == ign->fb_tunnel_dev) {
@@ -1633,9 +1618,9 @@ static size_t ip6gre_get_size(const struct net_device *dev)
                /* IFLA_GRE_OKEY */
                nla_total_size(4) +
                /* IFLA_GRE_LOCAL */
-               nla_total_size(4) +
+               nla_total_size(sizeof(struct in6_addr)) +
                /* IFLA_GRE_REMOTE */
-               nla_total_size(4) +
+               nla_total_size(sizeof(struct in6_addr)) +
                /* IFLA_GRE_TTL */
                nla_total_size(1) +
                /* IFLA_GRE_TOS */
@@ -1659,8 +1644,8 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
            nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
-           nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->raddr) ||
-           nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->laddr) ||
+           nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->laddr) ||
+           nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->raddr) ||
            nla_put_u8(skb, IFLA_GRE_TTL, p->hop_limit) ||
            /*nla_put_u8(skb, IFLA_GRE_TOS, t->priority) ||*/
            nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) ||
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
new file mode 100644 (file)
index 0000000..f26f0da
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ *     IPV6 GSO/GRO offload support
+ *     Linux INET6 implementation
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/socket.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/printk.h>
+
+#include <net/protocol.h>
+#include <net/ipv6.h>
+
+#include "ip6_offload.h"
+
+static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
+{
+       const struct net_offload *ops = NULL;
+
+       for (;;) {
+               struct ipv6_opt_hdr *opth;
+               int len;
+
+               if (proto != NEXTHDR_HOP) {
+                       ops = rcu_dereference(inet6_offloads[proto]);
+
+                       if (unlikely(!ops))
+                               break;
+
+                       if (!(ops->flags & INET6_PROTO_GSO_EXTHDR))
+                               break;
+               }
+
+               if (unlikely(!pskb_may_pull(skb, 8)))
+                       break;
+
+               opth = (void *)skb->data;
+               len = ipv6_optlen(opth);
+
+               if (unlikely(!pskb_may_pull(skb, len)))
+                       break;
+
+               proto = opth->nexthdr;
+               __skb_pull(skb, len);
+       }
+
+       return proto;
+}
+
+static int ipv6_gso_send_check(struct sk_buff *skb)
+{
+       const struct ipv6hdr *ipv6h;
+       const struct net_offload *ops;
+       int err = -EINVAL;
+
+       if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+               goto out;
+
+       ipv6h = ipv6_hdr(skb);
+       __skb_pull(skb, sizeof(*ipv6h));
+       err = -EPROTONOSUPPORT;
+
+       rcu_read_lock();
+       ops = rcu_dereference(inet6_offloads[
+               ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr)]);
+
+       if (likely(ops && ops->callbacks.gso_send_check)) {
+               skb_reset_transport_header(skb);
+               err = ops->callbacks.gso_send_check(skb);
+       }
+       rcu_read_unlock();
+
+out:
+       return err;
+}
+
+static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
+       netdev_features_t features)
+{
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+       struct ipv6hdr *ipv6h;
+       const struct net_offload *ops;
+       int proto;
+       struct frag_hdr *fptr;
+       unsigned int unfrag_ip6hlen;
+       u8 *prevhdr;
+       int offset = 0;
+
+       if (!(features & NETIF_F_V6_CSUM))
+               features &= ~NETIF_F_SG;
+
+       if (unlikely(skb_shinfo(skb)->gso_type &
+                    ~(SKB_GSO_UDP |
+                      SKB_GSO_DODGY |
+                      SKB_GSO_TCP_ECN |
+                      SKB_GSO_TCPV6 |
+                      0)))
+               goto out;
+
+       if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
+               goto out;
+
+       ipv6h = ipv6_hdr(skb);
+       __skb_pull(skb, sizeof(*ipv6h));
+       segs = ERR_PTR(-EPROTONOSUPPORT);
+
+       proto = ipv6_gso_pull_exthdrs(skb, ipv6h->nexthdr);
+       rcu_read_lock();
+       ops = rcu_dereference(inet6_offloads[proto]);
+       if (likely(ops && ops->callbacks.gso_segment)) {
+               skb_reset_transport_header(skb);
+               segs = ops->callbacks.gso_segment(skb, features);
+       }
+       rcu_read_unlock();
+
+       if (IS_ERR(segs))
+               goto out;
+
+       for (skb = segs; skb; skb = skb->next) {
+               ipv6h = ipv6_hdr(skb);
+               ipv6h->payload_len = htons(skb->len - skb->mac_len -
+                                          sizeof(*ipv6h));
+               if (proto == IPPROTO_UDP) {
+                       unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+                       fptr = (struct frag_hdr *)(skb_network_header(skb) +
+                               unfrag_ip6hlen);
+                       fptr->frag_off = htons(offset);
+                       if (skb->next != NULL)
+                               fptr->frag_off |= htons(IP6_MF);
+                       offset += (ntohs(ipv6h->payload_len) -
+                                  sizeof(struct frag_hdr));
+               }
+       }
+
+out:
+       return segs;
+}
+
+static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
+                                        struct sk_buff *skb)
+{
+       const struct net_offload *ops;
+       struct sk_buff **pp = NULL;
+       struct sk_buff *p;
+       struct ipv6hdr *iph;
+       unsigned int nlen;
+       unsigned int hlen;
+       unsigned int off;
+       int flush = 1;
+       int proto;
+       __wsum csum;
+
+       off = skb_gro_offset(skb);
+       hlen = off + sizeof(*iph);
+       iph = skb_gro_header_fast(skb, off);
+       if (skb_gro_header_hard(skb, hlen)) {
+               iph = skb_gro_header_slow(skb, hlen, off);
+               if (unlikely(!iph))
+                       goto out;
+       }
+
+       skb_gro_pull(skb, sizeof(*iph));
+       skb_set_transport_header(skb, skb_gro_offset(skb));
+
+       flush += ntohs(iph->payload_len) != skb_gro_len(skb);
+
+       rcu_read_lock();
+       proto = iph->nexthdr;
+       ops = rcu_dereference(inet6_offloads[proto]);
+       if (!ops || !ops->callbacks.gro_receive) {
+               __pskb_pull(skb, skb_gro_offset(skb));
+               proto = ipv6_gso_pull_exthdrs(skb, proto);
+               skb_gro_pull(skb, -skb_transport_offset(skb));
+               skb_reset_transport_header(skb);
+               __skb_push(skb, skb_gro_offset(skb));
+
+               ops = rcu_dereference(inet6_offloads[proto]);
+               if (!ops || !ops->callbacks.gro_receive)
+                       goto out_unlock;
+
+               iph = ipv6_hdr(skb);
+       }
+
+       NAPI_GRO_CB(skb)->proto = proto;
+
+       flush--;
+       nlen = skb_network_header_len(skb);
+
+       for (p = *head; p; p = p->next) {
+               const struct ipv6hdr *iph2;
+               __be32 first_word; /* <Version:4><Traffic_Class:8><Flow_Label:20> */
+
+               if (!NAPI_GRO_CB(p)->same_flow)
+                       continue;
+
+               iph2 = ipv6_hdr(p);
+               first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ;
+
+               /* All fields must match except length and Traffic Class. */
+               if (nlen != skb_network_header_len(p) ||
+                   (first_word & htonl(0xF00FFFFF)) ||
+                   memcmp(&iph->nexthdr, &iph2->nexthdr,
+                          nlen - offsetof(struct ipv6hdr, nexthdr))) {
+                       NAPI_GRO_CB(p)->same_flow = 0;
+                       continue;
+               }
+               /* flush if Traffic Class fields are different */
+               NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
+               NAPI_GRO_CB(p)->flush |= flush;
+       }
+
+       NAPI_GRO_CB(skb)->flush |= flush;
+
+       csum = skb->csum;
+       skb_postpull_rcsum(skb, iph, skb_network_header_len(skb));
+
+       pp = ops->callbacks.gro_receive(head, skb);
+
+       skb->csum = csum;
+
+out_unlock:
+       rcu_read_unlock();
+
+out:
+       NAPI_GRO_CB(skb)->flush |= flush;
+
+       return pp;
+}
+
+static int ipv6_gro_complete(struct sk_buff *skb)
+{
+       const struct net_offload *ops;
+       struct ipv6hdr *iph = ipv6_hdr(skb);
+       int err = -ENOSYS;
+
+       iph->payload_len = htons(skb->len - skb_network_offset(skb) -
+                                sizeof(*iph));
+
+       rcu_read_lock();
+       ops = rcu_dereference(inet6_offloads[NAPI_GRO_CB(skb)->proto]);
+       if (WARN_ON(!ops || !ops->callbacks.gro_complete))
+               goto out_unlock;
+
+       err = ops->callbacks.gro_complete(skb);
+
+out_unlock:
+       rcu_read_unlock();
+
+       return err;
+}
+
+static struct packet_offload ipv6_packet_offload __read_mostly = {
+       .type = cpu_to_be16(ETH_P_IPV6),
+       .callbacks = {
+               .gso_send_check = ipv6_gso_send_check,
+               .gso_segment = ipv6_gso_segment,
+               .gro_receive = ipv6_gro_receive,
+               .gro_complete = ipv6_gro_complete,
+       },
+};
+
+static int __init ipv6_offload_init(void)
+{
+
+       if (tcpv6_offload_init() < 0)
+               pr_crit("%s: Cannot add TCP protocol offload\n", __func__);
+       if (udp_offload_init() < 0)
+               pr_crit("%s: Cannot add UDP protocol offload\n", __func__);
+       if (ipv6_exthdrs_offload_init() < 0)
+               pr_crit("%s: Cannot add EXTHDRS protocol offload\n", __func__);
+
+       dev_add_offload(&ipv6_packet_offload);
+       return 0;
+}
+
+fs_initcall(ipv6_offload_init);
diff --git a/net/ipv6/ip6_offload.h b/net/ipv6/ip6_offload.h
new file mode 100644 (file)
index 0000000..2e155c6
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ *     IPV6 GSO/GRO offload support
+ *     Linux INET6 implementation
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __ip6_offload_h
+#define __ip6_offload_h
+
+int ipv6_exthdrs_offload_init(void);
+int udp_offload_init(void);
+int tcpv6_offload_init(void);
+
+#endif
index aece3e792f84ad4cfcc88ada01817c70242b396d..5552d13ae92f8554c04ec912b82317dfeef065a5 100644 (file)
@@ -538,78 +538,12 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
        to->tc_index = from->tc_index;
 #endif
        nf_copy(to, from);
-#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
-    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
        to->nf_trace = from->nf_trace;
 #endif
        skb_copy_secmark(to, from);
 }
 
-int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
-{
-       u16 offset = sizeof(struct ipv6hdr);
-       struct ipv6_opt_hdr *exthdr =
-                               (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
-       unsigned int packet_len = skb->tail - skb->network_header;
-       int found_rhdr = 0;
-       *nexthdr = &ipv6_hdr(skb)->nexthdr;
-
-       while (offset + 1 <= packet_len) {
-
-               switch (**nexthdr) {
-
-               case NEXTHDR_HOP:
-                       break;
-               case NEXTHDR_ROUTING:
-                       found_rhdr = 1;
-                       break;
-               case NEXTHDR_DEST:
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
-                       if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
-                               break;
-#endif
-                       if (found_rhdr)
-                               return offset;
-                       break;
-               default :
-                       return offset;
-               }
-
-               offset += ipv6_optlen(exthdr);
-               *nexthdr = &exthdr->nexthdr;
-               exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
-                                                offset);
-       }
-
-       return offset;
-}
-
-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
-{
-       static atomic_t ipv6_fragmentation_id;
-       int old, new;
-
-       if (rt && !(rt->dst.flags & DST_NOPEER)) {
-               struct inet_peer *peer;
-               struct net *net;
-
-               net = dev_net(rt->dst.dev);
-               peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
-               if (peer) {
-                       fhdr->identification = htonl(inet_getid(peer, 0));
-                       inet_putpeer(peer);
-                       return;
-               }
-       }
-       do {
-               old = atomic_read(&ipv6_fragmentation_id);
-               new = old + 1;
-               if (!new)
-                       new = 1;
-       } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
-       fhdr->identification = htonl(new);
-}
-
 int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
        struct sk_buff *frag;
@@ -756,7 +690,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
                if (err == 0) {
                        IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
                                      IPSTATS_MIB_FRAGOKS);
-                       dst_release(&rt->dst);
+                       ip6_rt_put(rt);
                        return 0;
                }
 
@@ -768,7 +702,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 
                IP6_INC_STATS(net, ip6_dst_idev(&rt->dst),
                              IPSTATS_MIB_FRAGFAILS);
-               dst_release(&rt->dst);
+               ip6_rt_put(rt);
                return err;
 
 slow_path_clean:
index cb7e2ded6f08cce17f8fb11a7e7e119e8564d661..a14f28b280f57a040e3d499955419f6c949c5c93 100644 (file)
@@ -74,6 +74,10 @@ MODULE_ALIAS_NETDEV("ip6tnl0");
 #define HASH_SIZE_SHIFT  5
 #define HASH_SIZE (1 << HASH_SIZE_SHIFT)
 
+static bool log_ecn_error = true;
+module_param(log_ecn_error, bool, 0644);
+MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
+
 static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2)
 {
        u32 hash = ipv6_addr_hash(addr1) ^ ipv6_addr_hash(addr2);
@@ -83,6 +87,7 @@ static u32 HASH(const struct in6_addr *addr1, const struct in6_addr *addr2)
 
 static int ip6_tnl_dev_init(struct net_device *dev);
 static void ip6_tnl_dev_setup(struct net_device *dev);
+static struct rtnl_link_ops ip6_link_ops __read_mostly;
 
 static int ip6_tnl_net_id __read_mostly;
 struct ip6_tnl_net {
@@ -94,14 +99,6 @@ struct ip6_tnl_net {
        struct ip6_tnl __rcu **tnls[2];
 };
 
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
-       unsigned long   rx_packets;
-       unsigned long   rx_bytes;
-       unsigned long   tx_packets;
-       unsigned long   tx_bytes;
-} __attribute__((aligned(4*sizeof(unsigned long))));
-
 static struct net_device_stats *ip6_get_stats(struct net_device *dev)
 {
        struct pcpu_tstats sum = { 0 };
@@ -258,6 +255,33 @@ static void ip6_dev_free(struct net_device *dev)
        free_netdev(dev);
 }
 
+static int ip6_tnl_create2(struct net_device *dev)
+{
+       struct ip6_tnl *t = netdev_priv(dev);
+       struct net *net = dev_net(dev);
+       struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+       int err;
+
+       t = netdev_priv(dev);
+       err = ip6_tnl_dev_init(dev);
+       if (err < 0)
+               goto out;
+
+       err = register_netdevice(dev);
+       if (err < 0)
+               goto out;
+
+       strcpy(t->parms.name, dev->name);
+       dev->rtnl_link_ops = &ip6_link_ops;
+
+       dev_hold(dev);
+       ip6_tnl_link(ip6n, t);
+       return 0;
+
+out:
+       return err;
+}
+
 /**
  * ip6_tnl_create - create a new tunnel
  *   @p: tunnel parameters
@@ -276,7 +300,6 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
        struct ip6_tnl *t;
        char name[IFNAMSIZ];
        int err;
-       struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
 
        if (p->name[0])
                strlcpy(name, p->name, IFNAMSIZ);
@@ -291,17 +314,10 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
 
        t = netdev_priv(dev);
        t->parms = *p;
-       err = ip6_tnl_dev_init(dev);
+       err = ip6_tnl_create2(dev);
        if (err < 0)
                goto failed_free;
 
-       if ((err = register_netdevice(dev)) < 0)
-               goto failed_free;
-
-       strcpy(t->parms.name, dev->name);
-
-       dev_hold(dev);
-       ip6_tnl_link(ip6n, t);
        return t;
 
 failed_free:
@@ -663,8 +679,7 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
                icmpv6_send(skb2, rel_type, rel_code, rel_info);
 
-               if (rt)
-                       dst_release(&rt->dst);
+               ip6_rt_put(rt);
 
                kfree_skb(skb2);
        }
@@ -672,28 +687,26 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        return 0;
 }
 
-static void ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t,
-                                       const struct ipv6hdr *ipv6h,
-                                       struct sk_buff *skb)
+static int ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t,
+                                      const struct ipv6hdr *ipv6h,
+                                      struct sk_buff *skb)
 {
        __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK;
 
        if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
                ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield);
 
-       if (INET_ECN_is_ce(dsfield))
-               IP_ECN_set_ce(ip_hdr(skb));
+       return IP6_ECN_decapsulate(ipv6h, skb);
 }
 
-static void ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t,
-                                       const struct ipv6hdr *ipv6h,
-                                       struct sk_buff *skb)
+static int ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t,
+                                      const struct ipv6hdr *ipv6h,
+                                      struct sk_buff *skb)
 {
        if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY)
                ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb));
 
-       if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6h)))
-               IP6_ECN_set_ce(ipv6_hdr(skb));
+       return IP6_ECN_decapsulate(ipv6h, skb);
 }
 
 __u32 ip6_tnl_get_cap(struct ip6_tnl *t,
@@ -757,12 +770,13 @@ EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl);
 
 static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
                       __u8 ipproto,
-                      void (*dscp_ecn_decapsulate)(const struct ip6_tnl *t,
-                                                   const struct ipv6hdr *ipv6h,
-                                                   struct sk_buff *skb))
+                      int (*dscp_ecn_decapsulate)(const struct ip6_tnl *t,
+                                                  const struct ipv6hdr *ipv6h,
+                                                  struct sk_buff *skb))
 {
        struct ip6_tnl *t;
        const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+       int err;
 
        rcu_read_lock();
 
@@ -792,14 +806,26 @@ static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol,
                skb->pkt_type = PACKET_HOST;
                memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
 
+               __skb_tunnel_rx(skb, t->dev);
+
+               err = dscp_ecn_decapsulate(t, ipv6h, skb);
+               if (unlikely(err)) {
+                       if (log_ecn_error)
+                               net_info_ratelimited("non-ECT from %pI6 with dsfield=%#x\n",
+                                                    &ipv6h->saddr,
+                                                    ipv6_get_dsfield(ipv6h));
+                       if (err > 1) {
+                               ++t->dev->stats.rx_frame_errors;
+                               ++t->dev->stats.rx_errors;
+                               rcu_read_unlock();
+                               goto discard;
+                       }
+               }
+
                tstats = this_cpu_ptr(t->dev->tstats);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
 
-               __skb_tunnel_rx(skb, t->dev);
-
-               dscp_ecn_decapsulate(t, ipv6h, skb);
-
                netif_rx(skb);
 
                rcu_read_unlock();
@@ -1208,7 +1234,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
                        if (dev->mtu < IPV6_MIN_MTU)
                                dev->mtu = IPV6_MIN_MTU;
                }
-               dst_release(&rt->dst);
+               ip6_rt_put(rt);
        }
 }
 
@@ -1237,6 +1263,20 @@ ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p)
        return 0;
 }
 
+static int ip6_tnl_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p)
+{
+       struct net *net = dev_net(t->dev);
+       struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+       int err;
+
+       ip6_tnl_unlink(ip6n, t);
+       synchronize_net();
+       err = ip6_tnl_change(t, p);
+       ip6_tnl_link(ip6n, t);
+       netdev_state_change(t->dev);
+       return err;
+}
+
 static void
 ip6_tnl_parm_from_user(struct __ip6_tnl_parm *p, const struct ip6_tnl_parm *u)
 {
@@ -1325,7 +1365,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCADDTUNNEL:
        case SIOCCHGTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
                err = -EFAULT;
                if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p)))
@@ -1345,11 +1385,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                        } else
                                t = netdev_priv(dev);
 
-                       ip6_tnl_unlink(ip6n, t);
-                       synchronize_net();
-                       err = ip6_tnl_change(t, &p1);
-                       ip6_tnl_link(ip6n, t);
-                       netdev_state_change(dev);
+                       err = ip6_tnl_update(t, &p1);
                }
                if (t) {
                        err = 0;
@@ -1362,7 +1398,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
                break;
        case SIOCDELTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
 
                if (dev == ip6n->fb_tnl_dev) {
@@ -1505,6 +1541,164 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev)
        return 0;
 }
 
+static int ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+       u8 proto;
+
+       if (!data)
+               return 0;
+
+       proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+       if (proto != IPPROTO_IPV6 &&
+           proto != IPPROTO_IPIP &&
+           proto != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static void ip6_tnl_netlink_parms(struct nlattr *data[],
+                                 struct __ip6_tnl_parm *parms)
+{
+       memset(parms, 0, sizeof(*parms));
+
+       if (!data)
+               return;
+
+       if (data[IFLA_IPTUN_LINK])
+               parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
+
+       if (data[IFLA_IPTUN_LOCAL])
+               nla_memcpy(&parms->laddr, data[IFLA_IPTUN_LOCAL],
+                          sizeof(struct in6_addr));
+
+       if (data[IFLA_IPTUN_REMOTE])
+               nla_memcpy(&parms->raddr, data[IFLA_IPTUN_REMOTE],
+                          sizeof(struct in6_addr));
+
+       if (data[IFLA_IPTUN_TTL])
+               parms->hop_limit = nla_get_u8(data[IFLA_IPTUN_TTL]);
+
+       if (data[IFLA_IPTUN_ENCAP_LIMIT])
+               parms->encap_limit = nla_get_u8(data[IFLA_IPTUN_ENCAP_LIMIT]);
+
+       if (data[IFLA_IPTUN_FLOWINFO])
+               parms->flowinfo = nla_get_be32(data[IFLA_IPTUN_FLOWINFO]);
+
+       if (data[IFLA_IPTUN_FLAGS])
+               parms->flags = nla_get_u32(data[IFLA_IPTUN_FLAGS]);
+
+       if (data[IFLA_IPTUN_PROTO])
+               parms->proto = nla_get_u8(data[IFLA_IPTUN_PROTO]);
+}
+
+static int ip6_tnl_newlink(struct net *src_net, struct net_device *dev,
+                          struct nlattr *tb[], struct nlattr *data[])
+{
+       struct net *net = dev_net(dev);
+       struct ip6_tnl *nt;
+
+       nt = netdev_priv(dev);
+       ip6_tnl_netlink_parms(data, &nt->parms);
+
+       if (ip6_tnl_locate(net, &nt->parms, 0))
+               return -EEXIST;
+
+       return ip6_tnl_create2(dev);
+}
+
+static int ip6_tnl_changelink(struct net_device *dev, struct nlattr *tb[],
+                             struct nlattr *data[])
+{
+       struct ip6_tnl *t;
+       struct __ip6_tnl_parm p;
+       struct net *net = dev_net(dev);
+       struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+
+       if (dev == ip6n->fb_tnl_dev)
+               return -EINVAL;
+
+       ip6_tnl_netlink_parms(data, &p);
+
+       t = ip6_tnl_locate(net, &p, 0);
+
+       if (t) {
+               if (t->dev != dev)
+                       return -EEXIST;
+       } else
+               t = netdev_priv(dev);
+
+       return ip6_tnl_update(t, &p);
+}
+
+static size_t ip6_tnl_get_size(const struct net_device *dev)
+{
+       return
+               /* IFLA_IPTUN_LINK */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_LOCAL */
+               nla_total_size(sizeof(struct in6_addr)) +
+               /* IFLA_IPTUN_REMOTE */
+               nla_total_size(sizeof(struct in6_addr)) +
+               /* IFLA_IPTUN_TTL */
+               nla_total_size(1) +
+               /* IFLA_IPTUN_ENCAP_LIMIT */
+               nla_total_size(1) +
+               /* IFLA_IPTUN_FLOWINFO */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_FLAGS */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_PROTO */
+               nla_total_size(1) +
+               0;
+}
+
+static int ip6_tnl_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct ip6_tnl *tunnel = netdev_priv(dev);
+       struct __ip6_tnl_parm *parm = &tunnel->parms;
+
+       if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
+           nla_put(skb, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr),
+                   &parm->raddr) ||
+           nla_put(skb, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr),
+                   &parm->laddr) ||
+           nla_put_u8(skb, IFLA_IPTUN_TTL, parm->hop_limit) ||
+           nla_put_u8(skb, IFLA_IPTUN_ENCAP_LIMIT, parm->encap_limit) ||
+           nla_put_be32(skb, IFLA_IPTUN_FLOWINFO, parm->flowinfo) ||
+           nla_put_u32(skb, IFLA_IPTUN_FLAGS, parm->flags) ||
+           nla_put_u8(skb, IFLA_IPTUN_PROTO, parm->proto))
+               goto nla_put_failure;
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
+static const struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = {
+       [IFLA_IPTUN_LINK]               = { .type = NLA_U32 },
+       [IFLA_IPTUN_LOCAL]              = { .len = sizeof(struct in6_addr) },
+       [IFLA_IPTUN_REMOTE]             = { .len = sizeof(struct in6_addr) },
+       [IFLA_IPTUN_TTL]                = { .type = NLA_U8 },
+       [IFLA_IPTUN_ENCAP_LIMIT]        = { .type = NLA_U8 },
+       [IFLA_IPTUN_FLOWINFO]           = { .type = NLA_U32 },
+       [IFLA_IPTUN_FLAGS]              = { .type = NLA_U32 },
+       [IFLA_IPTUN_PROTO]              = { .type = NLA_U8 },
+};
+
+static struct rtnl_link_ops ip6_link_ops __read_mostly = {
+       .kind           = "ip6tnl",
+       .maxtype        = IFLA_IPTUN_MAX,
+       .policy         = ip6_tnl_policy,
+       .priv_size      = sizeof(struct ip6_tnl),
+       .setup          = ip6_tnl_dev_setup,
+       .validate       = ip6_tnl_validate,
+       .newlink        = ip6_tnl_newlink,
+       .changelink     = ip6_tnl_changelink,
+       .get_size       = ip6_tnl_get_size,
+       .fill_info      = ip6_tnl_fill_info,
+};
+
 static struct xfrm6_tunnel ip4ip6_handler __read_mostly = {
        .handler        = ip4ip6_rcv,
        .err_handler    = ip4ip6_err,
@@ -1613,9 +1807,14 @@ static int __init ip6_tunnel_init(void)
                pr_err("%s: can't register ip6ip6\n", __func__);
                goto out_ip6ip6;
        }
+       err = rtnl_link_register(&ip6_link_ops);
+       if (err < 0)
+               goto rtnl_link_failed;
 
        return 0;
 
+rtnl_link_failed:
+       xfrm6_tunnel_deregister(&ip6ip6_handler, AF_INET6);
 out_ip6ip6:
        xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET);
 out_ip4ip6:
@@ -1630,6 +1829,7 @@ out_pernet:
 
 static void __exit ip6_tunnel_cleanup(void)
 {
+       rtnl_link_unregister(&ip6_link_ops);
        if (xfrm6_tunnel_deregister(&ip4ip6_handler, AF_INET))
                pr_info("%s: can't deregister ip4ip6\n", __func__);
 
index f7c7c6319720246f67f3cdbf09daea76634df0ba..26dcdec9e3a5f6cbbe799402c39bb5d09c9d561d 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/netfilter_ipv6.h>
 #include <linux/export.h>
 #include <net/ip6_checksum.h>
+#include <linux/netconf.h>
 
 struct mr6_table {
        struct list_head        list;
@@ -66,8 +67,8 @@ struct mr6_table {
        struct mif_device       vif6_table[MAXMIFS];
        int                     maxvif;
        atomic_t                cache_resolve_queue_len;
-       int                     mroute_do_assert;
-       int                     mroute_do_pim;
+       bool                    mroute_do_assert;
+       bool                    mroute_do_pim;
 #ifdef CONFIG_IPV6_PIMSM_V2
        int                     mroute_reg_vif_num;
 #endif
@@ -115,6 +116,8 @@ static int ip6mr_cache_report(struct mr6_table *mrt, struct sk_buff *pkt,
                              mifi_t mifi, int assert);
 static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
                               struct mfc6_cache *c, struct rtmsg *rtm);
+static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
+                             int cmd);
 static int ip6mr_rtm_dumproute(struct sk_buff *skb,
                               struct netlink_callback *cb);
 static void mroute_clean_tables(struct mr6_table *mrt);
@@ -805,8 +808,12 @@ static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
        dev_set_allmulti(dev, -1);
 
        in6_dev = __in6_dev_get(dev);
-       if (in6_dev)
+       if (in6_dev) {
                in6_dev->cnf.mc_forwarding--;
+               inet6_netconf_notify_devconf(dev_net(dev),
+                                            NETCONFA_MC_FORWARDING,
+                                            dev->ifindex, &in6_dev->cnf);
+       }
 
        if (v->flags & MIFF_REGISTER)
                unregister_netdevice_queue(dev, head);
@@ -865,6 +872,7 @@ static void ipmr_do_expire_process(struct mr6_table *mrt)
                }
 
                list_del(&c->list);
+               mr6_netlink_event(mrt, c, RTM_DELROUTE);
                ip6mr_destroy_unres(mrt, c);
        }
 
@@ -958,8 +966,12 @@ static int mif6_add(struct net *net, struct mr6_table *mrt,
        }
 
        in6_dev = __in6_dev_get(dev);
-       if (in6_dev)
+       if (in6_dev) {
                in6_dev->cnf.mc_forwarding++;
+               inet6_netconf_notify_devconf(dev_net(dev),
+                                            NETCONFA_MC_FORWARDING,
+                                            dev->ifindex, &in6_dev->cnf);
+       }
 
        /*
         *      Fill in the VIF structures
@@ -1211,6 +1223,7 @@ ip6mr_cache_unresolved(struct mr6_table *mrt, mifi_t mifi, struct sk_buff *skb)
 
                atomic_inc(&mrt->cache_resolve_queue_len);
                list_add(&c->list, &mrt->mfc6_unres_queue);
+               mr6_netlink_event(mrt, c, RTM_NEWROUTE);
 
                ipmr_do_expire_process(mrt);
        }
@@ -1248,6 +1261,7 @@ static int ip6mr_mfc_delete(struct mr6_table *mrt, struct mf6cctl *mfc)
                        list_del(&c->list);
                        write_unlock_bh(&mrt_lock);
 
+                       mr6_netlink_event(mrt, c, RTM_DELROUTE);
                        ip6mr_cache_free(c);
                        return 0;
                }
@@ -1412,6 +1426,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
                if (!mrtsock)
                        c->mfc_flags |= MFC_STATIC;
                write_unlock_bh(&mrt_lock);
+               mr6_netlink_event(mrt, c, RTM_NEWROUTE);
                return 0;
        }
 
@@ -1456,6 +1471,7 @@ static int ip6mr_mfc_add(struct net *net, struct mr6_table *mrt,
                ip6mr_cache_resolve(net, mrt, uc, c);
                ip6mr_cache_free(uc);
        }
+       mr6_netlink_event(mrt, c, RTM_NEWROUTE);
        return 0;
 }
 
@@ -1489,6 +1505,7 @@ static void mroute_clean_tables(struct mr6_table *mrt)
                        list_del(&c->list);
                        write_unlock_bh(&mrt_lock);
 
+                       mr6_netlink_event(mrt, c, RTM_DELROUTE);
                        ip6mr_cache_free(c);
                }
        }
@@ -1497,6 +1514,7 @@ static void mroute_clean_tables(struct mr6_table *mrt)
                spin_lock_bh(&mfc_unres_lock);
                list_for_each_entry_safe(c, next, &mrt->mfc6_unres_queue, list) {
                        list_del(&c->list);
+                       mr6_netlink_event(mrt, c, RTM_DELROUTE);
                        ip6mr_destroy_unres(mrt, c);
                }
                spin_unlock_bh(&mfc_unres_lock);
@@ -1513,6 +1531,9 @@ static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk)
        if (likely(mrt->mroute6_sk == NULL)) {
                mrt->mroute6_sk = sk;
                net->ipv6.devconf_all->mc_forwarding++;
+               inet6_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+                                            NETCONFA_IFINDEX_ALL,
+                                            net->ipv6.devconf_all);
        }
        else
                err = -EADDRINUSE;
@@ -1535,6 +1556,10 @@ int ip6mr_sk_done(struct sock *sk)
                        write_lock_bh(&mrt_lock);
                        mrt->mroute6_sk = NULL;
                        net->ipv6.devconf_all->mc_forwarding--;
+                       inet6_netconf_notify_devconf(net,
+                                                    NETCONFA_MC_FORWARDING,
+                                                    NETCONFA_IFINDEX_ALL,
+                                                    net->ipv6.devconf_all);
                        write_unlock_bh(&mrt_lock);
 
                        mroute_clean_tables(mrt);
@@ -1583,7 +1608,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
                return -ENOENT;
 
        if (optname != MRT6_INIT) {
-               if (sk != mrt->mroute6_sk && !capable(CAP_NET_ADMIN))
+               if (sk != mrt->mroute6_sk && !ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EACCES;
        }
 
@@ -1646,9 +1671,12 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
        case MRT6_ASSERT:
        {
                int v;
+
+               if (optlen != sizeof(v))
+                       return -EINVAL;
                if (get_user(v, (int __user *)optval))
                        return -EFAULT;
-               mrt->mroute_do_assert = !!v;
+               mrt->mroute_do_assert = v;
                return 0;
        }
 
@@ -1656,6 +1684,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
        case MRT6_PIM:
        {
                int v;
+
+               if (optlen != sizeof(v))
+                       return -EINVAL;
                if (get_user(v, (int __user *)optval))
                        return -EFAULT;
                v = !!v;
@@ -2097,8 +2128,8 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
 {
        int ct;
        struct rtnexthop *nhp;
-       u8 *b = skb_tail_pointer(skb);
-       struct rtattr *mp_head;
+       struct nlattr *mp_attr;
+       struct rta_mfc_stats mfcs;
 
        /* If cache is unresolved, don't try to parse IIF and OIF */
        if (c->mf6c_parent >= MAXMIFS)
@@ -2107,28 +2138,35 @@ static int __ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
        if (MIF_EXISTS(mrt, c->mf6c_parent) &&
            nla_put_u32(skb, RTA_IIF, mrt->vif6_table[c->mf6c_parent].dev->ifindex) < 0)
                return -EMSGSIZE;
-
-       mp_head = (struct rtattr *)skb_put(skb, RTA_LENGTH(0));
+       mp_attr = nla_nest_start(skb, RTA_MULTIPATH);
+       if (mp_attr == NULL)
+               return -EMSGSIZE;
 
        for (ct = c->mfc_un.res.minvif; ct < c->mfc_un.res.maxvif; ct++) {
                if (MIF_EXISTS(mrt, ct) && c->mfc_un.res.ttls[ct] < 255) {
-                       if (skb_tailroom(skb) < RTA_ALIGN(RTA_ALIGN(sizeof(*nhp)) + 4))
-                               goto rtattr_failure;
-                       nhp = (struct rtnexthop *)skb_put(skb, RTA_ALIGN(sizeof(*nhp)));
+                       nhp = nla_reserve_nohdr(skb, sizeof(*nhp));
+                       if (nhp == NULL) {
+                               nla_nest_cancel(skb, mp_attr);
+                               return -EMSGSIZE;
+                       }
+
                        nhp->rtnh_flags = 0;
                        nhp->rtnh_hops = c->mfc_un.res.ttls[ct];
                        nhp->rtnh_ifindex = mrt->vif6_table[ct].dev->ifindex;
                        nhp->rtnh_len = sizeof(*nhp);
                }
        }
-       mp_head->rta_type = RTA_MULTIPATH;
-       mp_head->rta_len = skb_tail_pointer(skb) - (u8 *)mp_head;
+
+       nla_nest_end(skb, mp_attr);
+
+       mfcs.mfcs_packets = c->mfc_un.res.pkt;
+       mfcs.mfcs_bytes = c->mfc_un.res.bytes;
+       mfcs.mfcs_wrong_if = c->mfc_un.res.wrong_if;
+       if (nla_put(skb, RTA_MFC_STATS, sizeof(mfcs), &mfcs) < 0)
+               return -EMSGSIZE;
+
        rtm->rtm_type = RTN_MULTICAST;
        return 1;
-
-rtattr_failure:
-       nlmsg_trim(skb, b);
-       return -EMSGSIZE;
 }
 
 int ip6mr_get_route(struct net *net,
@@ -2202,31 +2240,38 @@ int ip6mr_get_route(struct net *net,
 }
 
 static int ip6mr_fill_mroute(struct mr6_table *mrt, struct sk_buff *skb,
-                            u32 portid, u32 seq, struct mfc6_cache *c)
+                            u32 portid, u32 seq, struct mfc6_cache *c, int cmd)
 {
        struct nlmsghdr *nlh;
        struct rtmsg *rtm;
+       int err;
 
-       nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*rtm), NLM_F_MULTI);
+       nlh = nlmsg_put(skb, portid, seq, cmd, sizeof(*rtm), NLM_F_MULTI);
        if (nlh == NULL)
                return -EMSGSIZE;
 
        rtm = nlmsg_data(nlh);
-       rtm->rtm_family   = RTNL_FAMILY_IPMR;
+       rtm->rtm_family   = RTNL_FAMILY_IP6MR;
        rtm->rtm_dst_len  = 128;
        rtm->rtm_src_len  = 128;
        rtm->rtm_tos      = 0;
        rtm->rtm_table    = mrt->id;
        if (nla_put_u32(skb, RTA_TABLE, mrt->id))
                goto nla_put_failure;
+       rtm->rtm_type = RTN_MULTICAST;
        rtm->rtm_scope    = RT_SCOPE_UNIVERSE;
-       rtm->rtm_protocol = RTPROT_UNSPEC;
+       if (c->mfc_flags & MFC_STATIC)
+               rtm->rtm_protocol = RTPROT_STATIC;
+       else
+               rtm->rtm_protocol = RTPROT_MROUTED;
        rtm->rtm_flags    = 0;
 
        if (nla_put(skb, RTA_SRC, 16, &c->mf6c_origin) ||
            nla_put(skb, RTA_DST, 16, &c->mf6c_mcastgrp))
                goto nla_put_failure;
-       if (__ip6mr_fill_mroute(mrt, skb, c, rtm) < 0)
+       err = __ip6mr_fill_mroute(mrt, skb, c, rtm);
+       /* do not break the dump if cache is unresolved */
+       if (err < 0 && err != -ENOENT)
                goto nla_put_failure;
 
        return nlmsg_end(skb, nlh);
@@ -2236,6 +2281,52 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
+static int mr6_msgsize(bool unresolved, int maxvif)
+{
+       size_t len =
+               NLMSG_ALIGN(sizeof(struct rtmsg))
+               + nla_total_size(4)     /* RTA_TABLE */
+               + nla_total_size(sizeof(struct in6_addr))       /* RTA_SRC */
+               + nla_total_size(sizeof(struct in6_addr))       /* RTA_DST */
+               ;
+
+       if (!unresolved)
+               len = len
+                     + nla_total_size(4)       /* RTA_IIF */
+                     + nla_total_size(0)       /* RTA_MULTIPATH */
+                     + maxvif * NLA_ALIGN(sizeof(struct rtnexthop))
+                                               /* RTA_MFC_STATS */
+                     + nla_total_size(sizeof(struct rta_mfc_stats))
+               ;
+
+       return len;
+}
+
+static void mr6_netlink_event(struct mr6_table *mrt, struct mfc6_cache *mfc,
+                             int cmd)
+{
+       struct net *net = read_pnet(&mrt->net);
+       struct sk_buff *skb;
+       int err = -ENOBUFS;
+
+       skb = nlmsg_new(mr6_msgsize(mfc->mf6c_parent >= MAXMIFS, mrt->maxvif),
+                       GFP_ATOMIC);
+       if (skb == NULL)
+               goto errout;
+
+       err = ip6mr_fill_mroute(mrt, skb, 0, 0, mfc, cmd);
+       if (err < 0)
+               goto errout;
+
+       rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MROUTE, NULL, GFP_ATOMIC);
+       return;
+
+errout:
+       kfree_skb(skb);
+       if (err < 0)
+               rtnl_set_sk_err(net, RTNLGRP_IPV6_MROUTE, err);
+}
+
 static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
 {
        struct net *net = sock_net(skb->sk);
@@ -2262,13 +2353,29 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
                                if (ip6mr_fill_mroute(mrt, skb,
                                                      NETLINK_CB(cb->skb).portid,
                                                      cb->nlh->nlmsg_seq,
-                                                     mfc) < 0)
+                                                     mfc, RTM_NEWROUTE) < 0)
                                        goto done;
 next_entry:
                                e++;
                        }
                        e = s_e = 0;
                }
+               spin_lock_bh(&mfc_unres_lock);
+               list_for_each_entry(mfc, &mrt->mfc6_unres_queue, list) {
+                       if (e < s_e)
+                               goto next_entry2;
+                       if (ip6mr_fill_mroute(mrt, skb,
+                                             NETLINK_CB(cb->skb).portid,
+                                             cb->nlh->nlmsg_seq,
+                                             mfc, RTM_NEWROUTE) < 0) {
+                               spin_unlock_bh(&mfc_unres_lock);
+                               goto done;
+                       }
+next_entry2:
+                       e++;
+               }
+               spin_unlock_bh(&mfc_unres_lock);
+               e = s_e = 0;
                s_h = 0;
 next_table:
                t++;
index ba6d13d1f1e162254fa4e4421e82e4a204a9785c..ee94d31c9d4d494cdfe2dce1ac812e4e094fe65f 100644 (file)
@@ -343,7 +343,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                break;
 
        case IPV6_TRANSPARENT:
-               if (valbool && !capable(CAP_NET_ADMIN) && !capable(CAP_NET_RAW)) {
+               if (valbool && !ns_capable(net->user_ns, CAP_NET_ADMIN) &&
+                   !ns_capable(net->user_ns, CAP_NET_RAW)) {
                        retv = -EPERM;
                        break;
                }
@@ -381,7 +382,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
 
                /* hop-by-hop / destination options are privileged option */
                retv = -EPERM;
-               if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
+               if (optname != IPV6_RTHDR && !ns_capable(net->user_ns, CAP_NET_RAW))
                        break;
 
                opt = ipv6_renew_options(sk, np->opt, optname,
@@ -397,7 +398,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
                if (optname == IPV6_RTHDR && opt && opt->srcrt) {
                        struct ipv6_rt_hdr *rthdr = opt->srcrt;
                        switch (rthdr->type) {
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                        case IPV6_SRCRT_TYPE_2:
                                if (rthdr->hdrlen != 2 ||
                                    rthdr->segments_left != 1)
@@ -754,7 +755,7 @@ done:
        case IPV6_IPSEC_POLICY:
        case IPV6_XFRM_POLICY:
                retv = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        break;
                retv = xfrm_user_policy(sk, optname, optval, optlen);
                break;
@@ -827,6 +828,7 @@ pref_skip_coa:
                if (val < 0 || val > 255)
                        goto e_inval;
                np->min_hopcount = val;
+               retv = 0;
                break;
        case IPV6_DONTFRAG:
                np->dontfrag = valbool;
index 92f8e48e4ba4e63606412e317c28d2153eddccb0..28dfa5f3801febb37cfd4ab17e010be4cc936e24 100644 (file)
@@ -163,7 +163,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
                rt = rt6_lookup(net, addr, NULL, 0, 0);
                if (rt) {
                        dev = rt->dst.dev;
-                       dst_release(&rt->dst);
+                       ip6_rt_put(rt);
                }
        } else
                dev = dev_get_by_index_rcu(net, ifindex);
@@ -260,7 +260,7 @@ static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net,
 
                if (rt) {
                        dev = rt->dst.dev;
-                       dst_release(&rt->dst);
+                       ip6_rt_put(rt);
                }
        } else
                dev = dev_get_by_index_rcu(net, ifindex);
@@ -284,6 +284,9 @@ void ipv6_sock_mc_close(struct sock *sk)
        struct ipv6_mc_socklist *mc_lst;
        struct net *net = sock_net(sk);
 
+       if (!rcu_access_pointer(np->ipv6_mc_list))
+               return;
+
        spin_lock(&ipv6_sk_mc_lock);
        while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list,
                                lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) {
index ff36194a71aa7dd0fe0f707cff80afd83e40102e..cf43b6550f5b062ddfaa67964b4502460566c642 100644 (file)
@@ -535,7 +535,6 @@ static void ndisc_send_unsol_na(struct net_device *dev)
 {
        struct inet6_dev *idev;
        struct inet6_ifaddr *ifa;
-       struct in6_addr mcaddr;
 
        idev = in6_dev_get(dev);
        if (!idev)
@@ -543,8 +542,7 @@ static void ndisc_send_unsol_na(struct net_device *dev)
 
        read_lock_bh(&idev->lock);
        list_for_each_entry(ifa, &idev->addr_list, if_list) {
-               addrconf_addr_solict_mult(&ifa->addr, &mcaddr);
-               ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr,
+               ndisc_send_na(dev, NULL, &in6addr_linklocal_allnodes, &ifa->addr,
                              /*router=*/ !!idev->cnf.forwarding,
                              /*solicited=*/ false, /*override=*/ true,
                              /*inc_opt=*/ true);
@@ -906,7 +904,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
                if (lladdr && !memcmp(lladdr, dev->dev_addr, dev->addr_len) &&
                    net->ipv6.devconf_all->forwarding && net->ipv6.devconf_all->proxy_ndp &&
                    pneigh_lookup(&nd_tbl, net, &msg->target, dev, 0)) {
-                       /* XXX: idev->cnf.prixy_ndp */
+                       /* XXX: idev->cnf.proxy_ndp */
                        goto out;
                }
 
@@ -1034,18 +1032,6 @@ errout:
        rtnl_set_sk_err(net, RTNLGRP_ND_USEROPT, err);
 }
 
-static inline int accept_ra(struct inet6_dev *in6_dev)
-{
-       /*
-        * If forwarding is enabled, RA are not accepted unless the special
-        * hybrid mode (accept_ra=2) is enabled.
-        */
-       if (in6_dev->cnf.forwarding && in6_dev->cnf.accept_ra < 2)
-               return 0;
-
-       return in6_dev->cnf.accept_ra;
-}
-
 static void ndisc_router_discovery(struct sk_buff *skb)
 {
        struct ra_msg *ra_msg = (struct ra_msg *)skb_transport_header(skb);
@@ -1093,7 +1079,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                return;
        }
 
-       if (!accept_ra(in6_dev))
+       if (!ipv6_accept_ra(in6_dev))
                goto skip_linkparms;
 
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
@@ -1145,7 +1131,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                        ND_PRINTK(0, err,
                                  "RA: %s got default router without neighbour\n",
                                  __func__);
-                       dst_release(&rt->dst);
+                       ip6_rt_put(rt);
                        return;
                }
        }
@@ -1170,7 +1156,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                        ND_PRINTK(0, err,
                                  "RA: %s got default router without neighbour\n",
                                  __func__);
-                       dst_release(&rt->dst);
+                       ip6_rt_put(rt);
                        return;
                }
                neigh->flags |= NTF_ROUTER;
@@ -1249,7 +1235,7 @@ skip_linkparms:
                             NEIGH_UPDATE_F_ISROUTER);
        }
 
-       if (!accept_ra(in6_dev))
+       if (!ipv6_accept_ra(in6_dev))
                goto out;
 
 #ifdef CONFIG_IPV6_ROUTE_INFO
@@ -1326,8 +1312,7 @@ skip_routeinfo:
                ND_PRINTK(2, warn, "RA: invalid RA options\n");
        }
 out:
-       if (rt)
-               dst_release(&rt->dst);
+       ip6_rt_put(rt);
        if (neigh)
                neigh_release(neigh);
 }
@@ -1575,11 +1560,18 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = ptr;
        struct net *net = dev_net(dev);
+       struct inet6_dev *idev;
 
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&nd_tbl, dev);
                fib6_run_gc(~0UL, net);
+               idev = in6_dev_get(dev);
+               if (!idev)
+                       break;
+               if (idev->cnf.ndisc_notify)
+                       ndisc_send_unsol_na(dev);
+               in6_dev_put(idev);
                break;
        case NETDEV_DOWN:
                neigh_ifdown(&nd_tbl, dev);
index d7cb04506c3dac8266780c30a74e1a3fa1320ade..125a90d6a795967f13fcdfd19b3c24e24ce02504 100644 (file)
@@ -207,8 +207,7 @@ ip6t_get_target_c(const struct ip6t_entry *e)
        return ip6t_get_target((struct ip6t_entry *)e);
 }
 
-#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
-    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
 /* This cries for unification! */
 static const char *const hooknames[] = {
        [NF_INET_PRE_ROUTING]           = "PREROUTING",
@@ -381,8 +380,7 @@ ip6t_do_table(struct sk_buff *skb,
                t = ip6t_get_target_c(e);
                IP_NF_ASSERT(t->u.kernel.target);
 
-#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
-    defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
                /* The packet is traced: log it */
                if (unlikely(skb->nf_trace))
                        trace_packet(skb, hook, in, out,
@@ -1856,7 +1854,7 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -1971,7 +1969,7 @@ compat_do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -1993,7 +1991,7 @@ do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -2018,7 +2016,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
 {
        int ret;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        switch (cmd) {
@@ -2273,112 +2271,9 @@ static void __exit ip6_tables_fini(void)
        unregister_pernet_subsys(&ip6_tables_net_ops);
 }
 
-/*
- * find the offset to specified header or the protocol number of last header
- * if target < 0. "last header" is transport protocol header, ESP, or
- * "No next header".
- *
- * Note that *offset is used as input/output parameter. an if it is not zero,
- * then it must be a valid offset to an inner IPv6 header. This can be used
- * to explore inner IPv6 header, eg. ICMPv6 error messages.
- *
- * If target header is found, its offset is set in *offset and return protocol
- * number. Otherwise, return -1.
- *
- * If the first fragment doesn't contain the final protocol header or
- * NEXTHDR_NONE it is considered invalid.
- *
- * Note that non-1st fragment is special case that "the protocol number
- * of last header" is "next header" field in Fragment header. In this case,
- * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
- * isn't NULL.
- *
- * if flags is not NULL and it's a fragment, then the frag flag IP6T_FH_F_FRAG
- * will be set. If it's an AH header, the IP6T_FH_F_AUTH flag is set and
- * target < 0, then this function will stop at the AH header.
- */
-int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
-                 int target, unsigned short *fragoff, int *flags)
-{
-       unsigned int start = skb_network_offset(skb) + sizeof(struct ipv6hdr);
-       u8 nexthdr = ipv6_hdr(skb)->nexthdr;
-       unsigned int len;
-
-       if (fragoff)
-               *fragoff = 0;
-
-       if (*offset) {
-               struct ipv6hdr _ip6, *ip6;
-
-               ip6 = skb_header_pointer(skb, *offset, sizeof(_ip6), &_ip6);
-               if (!ip6 || (ip6->version != 6)) {
-                       printk(KERN_ERR "IPv6 header not found\n");
-                       return -EBADMSG;
-               }
-               start = *offset + sizeof(struct ipv6hdr);
-               nexthdr = ip6->nexthdr;
-       }
-       len = skb->len - start;
-
-       while (nexthdr != target) {
-               struct ipv6_opt_hdr _hdr, *hp;
-               unsigned int hdrlen;
-
-               if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
-                       if (target < 0)
-                               break;
-                       return -ENOENT;
-               }
-
-               hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
-               if (hp == NULL)
-                       return -EBADMSG;
-               if (nexthdr == NEXTHDR_FRAGMENT) {
-                       unsigned short _frag_off;
-                       __be16 *fp;
-
-                       if (flags)      /* Indicate that this is a fragment */
-                               *flags |= IP6T_FH_F_FRAG;
-                       fp = skb_header_pointer(skb,
-                                               start+offsetof(struct frag_hdr,
-                                                              frag_off),
-                                               sizeof(_frag_off),
-                                               &_frag_off);
-                       if (fp == NULL)
-                               return -EBADMSG;
-
-                       _frag_off = ntohs(*fp) & ~0x7;
-                       if (_frag_off) {
-                               if (target < 0 &&
-                                   ((!ipv6_ext_hdr(hp->nexthdr)) ||
-                                    hp->nexthdr == NEXTHDR_NONE)) {
-                                       if (fragoff)
-                                               *fragoff = _frag_off;
-                                       return hp->nexthdr;
-                               }
-                               return -ENOENT;
-                       }
-                       hdrlen = 8;
-               } else if (nexthdr == NEXTHDR_AUTH) {
-                       if (flags && (*flags & IP6T_FH_F_AUTH) && (target < 0))
-                               break;
-                       hdrlen = (hp->hdrlen + 2) << 2;
-               } else
-                       hdrlen = ipv6_optlen(hp);
-
-               nexthdr = hp->nexthdr;
-               len -= hdrlen;
-               start += hdrlen;
-       }
-
-       *offset = start;
-       return nexthdr;
-}
-
 EXPORT_SYMBOL(ip6t_register_table);
 EXPORT_SYMBOL(ip6t_unregister_table);
 EXPORT_SYMBOL(ip6t_do_table);
-EXPORT_SYMBOL(ipv6_find_hdr);
 
 module_init(ip6_tables_init);
 module_exit(ip6_tables_fini);
index 5d1d8b04d6943df82a68da781a475b8eb506cde3..5060d54199abbc180d7dc87ba072bace2bc167f7 100644 (file)
@@ -67,7 +67,7 @@ static bool rpfilter_lookup_reverse6(const struct sk_buff *skb,
        if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE))
                ret = true;
  out:
-       dst_release(&rt->dst);
+       ip6_rt_put(rt);
        return ret;
 }
 
index e418bd6350a405c9912f09207b876d1151961551..6c8ae24b85eb15f525e2e43a1b0e7f93068e8d85 100644 (file)
@@ -137,6 +137,10 @@ nf_nat_ipv6_fn(unsigned int hooknum,
                /* ESTABLISHED */
                NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
                             ctinfo == IP_CT_ESTABLISHED_REPLY);
+               if (nf_nat_oif_changed(hooknum, ctinfo, nat, out)) {
+                       nf_ct_kill_acct(ct, ctinfo, skb);
+                       return NF_DROP;
+               }
        }
 
        return nf_nat_packet(ct, ctinfo, hooknum, skb);
@@ -186,7 +190,8 @@ nf_nat_ipv6_out(unsigned int hooknum,
 
                if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
                                      &ct->tuplehash[!dir].tuple.dst.u3) ||
-                   (ct->tuplehash[dir].tuple.src.u.all !=
+                   (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
+                    ct->tuplehash[dir].tuple.src.u.all !=
                     ct->tuplehash[!dir].tuple.dst.u.all))
                        if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
                                ret = NF_DROP;
@@ -222,6 +227,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,
                }
 #ifdef CONFIG_XFRM
                else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
+                        ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
                         ct->tuplehash[dir].tuple.dst.u.all !=
                         ct->tuplehash[!dir].tuple.src.u.all)
                        if (nf_xfrm_me_harder(skb, AF_INET6))
@@ -275,9 +281,7 @@ static int __net_init ip6table_nat_net_init(struct net *net)
                return -ENOMEM;
        net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
        kfree(repl);
-       if (IS_ERR(net->ipv6.ip6table_nat))
-               return PTR_ERR(net->ipv6.ip6table_nat);
-       return 0;
+       return PTR_RET(net->ipv6.ip6table_nat);
 }
 
 static void __net_exit ip6table_nat_net_exit(struct net *net)
index 8860d23e61cfff646e3e034da7fe4c985fbb5575..00ee17c3e8939b1076ae2c2026ed6dfa1b3f68de 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <linux/netfilter_bridge.h>
 #include <linux/netfilter_ipv6.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -295,7 +296,56 @@ static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
        },
 };
 
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+static int
+ipv6_getorigdst(struct sock *sk, int optval, void __user *user, int *len)
+{
+       const struct inet_sock *inet = inet_sk(sk);
+       const struct ipv6_pinfo *inet6 = inet6_sk(sk);
+       const struct nf_conntrack_tuple_hash *h;
+       struct sockaddr_in6 sin6;
+       struct nf_conntrack_tuple tuple = { .src.l3num = NFPROTO_IPV6 };
+       struct nf_conn *ct;
+
+       tuple.src.u3.in6 = inet6->rcv_saddr;
+       tuple.src.u.tcp.port = inet->inet_sport;
+       tuple.dst.u3.in6 = inet6->daddr;
+       tuple.dst.u.tcp.port = inet->inet_dport;
+       tuple.dst.protonum = sk->sk_protocol;
+
+       if (sk->sk_protocol != IPPROTO_TCP && sk->sk_protocol != IPPROTO_SCTP)
+               return -ENOPROTOOPT;
+
+       if (*len < 0 || (unsigned int) *len < sizeof(sin6))
+               return -EINVAL;
+
+       h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple);
+       if (!h) {
+               pr_debug("IP6T_SO_ORIGINAL_DST: Can't find %pI6c/%u-%pI6c/%u.\n",
+                        &tuple.src.u3.ip6, ntohs(tuple.src.u.tcp.port),
+                        &tuple.dst.u3.ip6, ntohs(tuple.dst.u.tcp.port));
+               return -ENOENT;
+       }
+
+       ct = nf_ct_tuplehash_to_ctrack(h);
+
+       sin6.sin6_family = AF_INET6;
+       sin6.sin6_port = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u.tcp.port;
+       sin6.sin6_flowinfo = inet6->flow_label & IPV6_FLOWINFO_MASK;
+       memcpy(&sin6.sin6_addr,
+               &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.in6,
+                                       sizeof(sin6.sin6_addr));
+
+       nf_ct_put(ct);
+
+       if (ipv6_addr_type(&sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
+               sin6.sin6_scope_id = sk->sk_bound_dev_if;
+       else
+               sin6.sin6_scope_id = 0;
+
+       return copy_to_user(user, &sin6, sizeof(sin6)) ? -EFAULT : 0;
+}
+
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
@@ -346,7 +396,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6 __read_mostly = {
        .invert_tuple           = ipv6_invert_tuple,
        .print_tuple            = ipv6_print_tuple,
        .get_l4proto            = ipv6_get_l4proto,
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
        .tuple_to_nlattr        = ipv6_tuple_to_nlattr,
        .nlattr_tuple_size      = ipv6_nlattr_tuple_size,
        .nlattr_to_tuple        = ipv6_nlattr_to_tuple,
@@ -359,6 +409,14 @@ MODULE_ALIAS("nf_conntrack-" __stringify(AF_INET6));
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Yasuyuki KOZAKAI @USAGI <yasuyuki.kozakai@toshiba.co.jp>");
 
+static struct nf_sockopt_ops so_getorigdst6 = {
+       .pf             = NFPROTO_IPV6,
+       .get_optmin     = IP6T_SO_ORIGINAL_DST,
+       .get_optmax     = IP6T_SO_ORIGINAL_DST + 1,
+       .get            = ipv6_getorigdst,
+       .owner          = THIS_MODULE,
+};
+
 static int ipv6_net_init(struct net *net)
 {
        int ret = 0;
@@ -425,6 +483,12 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
        need_conntrack();
        nf_defrag_ipv6_enable();
 
+       ret = nf_register_sockopt(&so_getorigdst6);
+       if (ret < 0) {
+               pr_err("Unable to register netfilter socket option\n");
+               return ret;
+       }
+
        ret = register_pernet_subsys(&ipv6_net_ops);
        if (ret < 0)
                goto cleanup_pernet;
@@ -440,6 +504,7 @@ static int __init nf_conntrack_l3proto_ipv6_init(void)
  cleanup_ipv6:
        unregister_pernet_subsys(&ipv6_net_ops);
  cleanup_pernet:
+       nf_unregister_sockopt(&so_getorigdst6);
        return ret;
 }
 
@@ -448,6 +513,7 @@ static void __exit nf_conntrack_l3proto_ipv6_fini(void)
        synchronize_net();
        nf_unregister_hooks(ipv6_conntrack_ops, ARRAY_SIZE(ipv6_conntrack_ops));
        unregister_pernet_subsys(&ipv6_net_ops);
+       nf_unregister_sockopt(&so_getorigdst6);
 }
 
 module_init(nf_conntrack_l3proto_ipv6_init);
index 2d54b2061d68ef3e947168b82a5b041f84ffea50..24df3dde0076bc58d6081f306832c73d568d72a9 100644 (file)
@@ -232,7 +232,7 @@ icmpv6_error(struct net *net, struct nf_conn *tmpl,
        return icmpv6_error_message(net, tmpl, skb, dataoff, ctinfo, hooknum);
 }
 
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
 
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nfnetlink_conntrack.h>
@@ -375,7 +375,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
        .get_timeouts           = icmpv6_get_timeouts,
        .new                    = icmpv6_new,
        .error                  = icmpv6_error,
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
        .tuple_to_nlattr        = icmpv6_tuple_to_nlattr,
        .nlattr_tuple_size      = icmpv6_nlattr_tuple_size,
        .nlattr_to_tuple        = icmpv6_nlattr_to_tuple,
index 18bd9bbbd1c6c0f50d8bf74c947c05f91a4f20cd..22c8ea9511852e963b982ad68ed7066bda262ad2 100644 (file)
@@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
        { }
 };
 
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        struct ctl_table *table;
        struct ctl_table_header *hdr;
@@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
 }
 
 #else
-static int __net_init nf_ct_frag6_sysctl_register(struct net *net)
+static int nf_ct_frag6_sysctl_register(struct net *net)
 {
        return 0;
 }
index cdd6d045e42e7ff2098adebe149640811ad109e0..aacd121fe8c54365607f49e40679d7fd08dcd8e8 100644 (file)
@@ -19,7 +19,7 @@
 
 #include <linux/netfilter_ipv6.h>
 #include <linux/netfilter_bridge.h>
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
 #include <net/netfilter/nf_conntrack.h>
 #include <net/netfilter/nf_conntrack_helper.h>
 #include <net/netfilter/nf_conntrack_l4proto.h>
@@ -35,7 +35,7 @@ static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
 {
        u16 zone = NF_CT_DEFAULT_ZONE;
 
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
        if (skb->nfct)
                zone = nf_ct_zone((struct nf_conn *)skb->nfct);
 #endif
@@ -60,7 +60,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
 {
        struct sk_buff *reasm;
 
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
        /* Previously seen (loopback)?  */
        if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
                return NF_ACCEPT;
index 5d6da784305bb26bee73f21f4cc6f2b2f8d4ea17..61aaf70f376e9eafee55cae3cb3b909916d0554e 100644 (file)
@@ -84,7 +84,7 @@ const struct nf_nat_l4proto nf_nat_l4proto_icmpv6 = {
        .manip_pkt              = icmpv6_manip_pkt,
        .in_range               = icmpv6_in_range,
        .unique_tuple           = icmpv6_unique_tuple,
-#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
+#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
        .nlattr_to_range        = nf_nat_l4proto_nlattr_to_range,
 #endif
 };
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
new file mode 100644 (file)
index 0000000..c2e73e6
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * IPv6 library code, needed by static components when full IPv6 support is
+ * not configured or static.  These functions are needed by GSO/GRO implementation.
+ */
+#include <linux/export.h>
+#include <net/ipv6.h>
+#include <net/ip6_fib.h>
+
+void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
+{
+       static atomic_t ipv6_fragmentation_id;
+       int old, new;
+
+#if IS_ENABLED(CONFIG_IPV6)
+       if (rt && !(rt->dst.flags & DST_NOPEER)) {
+               struct inet_peer *peer;
+               struct net *net;
+
+               net = dev_net(rt->dst.dev);
+               peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1);
+               if (peer) {
+                       fhdr->identification = htonl(inet_getid(peer, 0));
+                       inet_putpeer(peer);
+                       return;
+               }
+       }
+#endif
+       do {
+               old = atomic_read(&ipv6_fragmentation_id);
+               new = old + 1;
+               if (!new)
+                       new = 1;
+       } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
+       fhdr->identification = htonl(new);
+}
+EXPORT_SYMBOL(ipv6_select_ident);
+
+int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
+{
+       u16 offset = sizeof(struct ipv6hdr);
+       struct ipv6_opt_hdr *exthdr =
+                               (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
+       unsigned int packet_len = skb->tail - skb->network_header;
+       int found_rhdr = 0;
+       *nexthdr = &ipv6_hdr(skb)->nexthdr;
+
+       while (offset + 1 <= packet_len) {
+
+               switch (**nexthdr) {
+
+               case NEXTHDR_HOP:
+                       break;
+               case NEXTHDR_ROUTING:
+                       found_rhdr = 1;
+                       break;
+               case NEXTHDR_DEST:
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
+                       if (ipv6_find_tlv(skb, offset, IPV6_TLV_HAO) >= 0)
+                               break;
+#endif
+                       if (found_rhdr)
+                               return offset;
+                       break;
+               default :
+                       return offset;
+               }
+
+               offset += ipv6_optlen(exthdr);
+               *nexthdr = &exthdr->nexthdr;
+               exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
+                                                offset);
+       }
+
+       return offset;
+}
+EXPORT_SYMBOL(ip6_find_1stfragopt);
index 053082dfc93e1f9d0c98e26e9c083fc384ed06d5..22d1bd4670dab741b2417051b45370b4a75b42a3 100644 (file)
@@ -25,7 +25,9 @@
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 
+#if IS_ENABLED(CONFIG_IPV6)
 const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS] __read_mostly;
+EXPORT_SYMBOL(inet6_protos);
 
 int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
 {
@@ -50,3 +52,26 @@ int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol
        return ret;
 }
 EXPORT_SYMBOL(inet6_del_protocol);
+#endif
+
+const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS] __read_mostly;
+
+int inet6_add_offload(const struct net_offload *prot, unsigned char protocol)
+{
+       return !cmpxchg((const struct net_offload **)&inet6_offloads[protocol],
+                       NULL, prot) ? 0 : -1;
+}
+EXPORT_SYMBOL(inet6_add_offload);
+
+int inet6_del_offload(const struct net_offload *prot, unsigned char protocol)
+{
+       int ret;
+
+       ret = (cmpxchg((const struct net_offload **)&inet6_offloads[protocol],
+                      prot, NULL) == prot) ? 0 : -1;
+
+       synchronize_net();
+
+       return ret;
+}
+EXPORT_SYMBOL(inet6_del_offload);
index d8e95c77db99e5bac5b7cab803c82a731e14a697..6cd29b1e8b926e26a7bc0df5b5c5263fc2e23d84 100644 (file)
@@ -50,7 +50,7 @@
 #include <net/udp.h>
 #include <net/inet_common.h>
 #include <net/tcp_states.h>
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
 #include <net/mip6.h>
 #endif
 #include <linux/mroute6.h>
@@ -123,7 +123,7 @@ static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
        return 1;
 }
 
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
 typedef int mh_filter_t(struct sock *sock, struct sk_buff *skb);
 
 static mh_filter_t __rcu *mh_filter __read_mostly;
@@ -184,7 +184,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr)
                        filtered = icmpv6_filter(sk, skb);
                        break;
 
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                case IPPROTO_MH:
                {
                        /* XXX: To validate MH only once for each packet,
index da8a4e301b1b04ec5d8d0d7aa042a328c986e1d9..e5253ec9e0fcd8b80e506956e68b29407b0be3c6 100644 (file)
@@ -616,6 +616,10 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net)
                table[0].data = &net->ipv6.frags.high_thresh;
                table[1].data = &net->ipv6.frags.low_thresh;
                table[2].data = &net->ipv6.frags.timeout;
+
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       table[0].procname = NULL;
        }
 
        hdr = register_net_sysctl(net, "net/ipv6", table);
index 7c7e963260e1792be01a329d4298dc1123c8f738..e229a3bc345dc4138a188282c4ab4f1717882832 100644 (file)
@@ -57,6 +57,7 @@
 #include <net/xfrm.h>
 #include <net/netevent.h>
 #include <net/netlink.h>
+#include <net/nexthop.h>
 
 #include <asm/uaccess.h>
 
@@ -219,7 +220,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
 };
 
 static const u32 ip6_template_metrics[RTAX_MAX] = {
-       [RTAX_HOPLIMIT - 1] = 255,
+       [RTAX_HOPLIMIT - 1] = 0,
 };
 
 static const struct rt6_info ip6_null_entry_template = {
@@ -289,6 +290,8 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
                memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
                rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
                rt->rt6i_genid = rt_genid(net);
+               INIT_LIST_HEAD(&rt->rt6i_siblings);
+               rt->rt6i_nsiblings = 0;
        }
        return rt;
 }
@@ -318,13 +321,6 @@ static void ip6_dst_destroy(struct dst_entry *dst)
        }
 }
 
-static atomic_t __rt6_peer_genid = ATOMIC_INIT(0);
-
-static u32 rt6_peer_genid(void)
-{
-       return atomic_read(&__rt6_peer_genid);
-}
-
 void rt6_bind_peer(struct rt6_info *rt, int create)
 {
        struct inet_peer_base *base;
@@ -338,8 +334,6 @@ void rt6_bind_peer(struct rt6_info *rt, int create)
        if (peer) {
                if (!rt6_set_peer(rt, peer))
                        inet_putpeer(peer);
-               else
-                       rt->rt6i_peer_genid = rt6_peer_genid();
        }
 }
 
@@ -385,6 +379,69 @@ static bool rt6_need_strict(const struct in6_addr *daddr)
                (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
 }
 
+/* Multipath route selection:
+ *   Hash based function using packet header and flowlabel.
+ * Adapted from fib_info_hashfn()
+ */
+static int rt6_info_hash_nhsfn(unsigned int candidate_count,
+                              const struct flowi6 *fl6)
+{
+       unsigned int val = fl6->flowi6_proto;
+
+       val ^= (__force u32)fl6->daddr.s6_addr32[0];
+       val ^= (__force u32)fl6->daddr.s6_addr32[1];
+       val ^= (__force u32)fl6->daddr.s6_addr32[2];
+       val ^= (__force u32)fl6->daddr.s6_addr32[3];
+
+       val ^= (__force u32)fl6->saddr.s6_addr32[0];
+       val ^= (__force u32)fl6->saddr.s6_addr32[1];
+       val ^= (__force u32)fl6->saddr.s6_addr32[2];
+       val ^= (__force u32)fl6->saddr.s6_addr32[3];
+
+       /* Work only if this not encapsulated */
+       switch (fl6->flowi6_proto) {
+       case IPPROTO_UDP:
+       case IPPROTO_TCP:
+       case IPPROTO_SCTP:
+               val ^= (__force u16)fl6->fl6_sport;
+               val ^= (__force u16)fl6->fl6_dport;
+               break;
+
+       case IPPROTO_ICMPV6:
+               val ^= (__force u16)fl6->fl6_icmp_type;
+               val ^= (__force u16)fl6->fl6_icmp_code;
+               break;
+       }
+       /* RFC6438 recommands to use flowlabel */
+       val ^= (__force u32)fl6->flowlabel;
+
+       /* Perhaps, we need to tune, this function? */
+       val = val ^ (val >> 7) ^ (val >> 12);
+       return val % candidate_count;
+}
+
+static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
+                                            struct flowi6 *fl6)
+{
+       struct rt6_info *sibling, *next_sibling;
+       int route_choosen;
+
+       route_choosen = rt6_info_hash_nhsfn(match->rt6i_nsiblings + 1, fl6);
+       /* Don't change the route, if route_choosen == 0
+        * (siblings does not include ourself)
+        */
+       if (route_choosen)
+               list_for_each_entry_safe(sibling, next_sibling,
+                               &match->rt6i_siblings, rt6i_siblings) {
+                       route_choosen--;
+                       if (route_choosen == 0) {
+                               match = sibling;
+                               break;
+                       }
+               }
+       return match;
+}
+
 /*
  *     Route lookup. Any table->tb6_lock is implied.
  */
@@ -487,35 +544,32 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
        return 0;
 }
 
-static inline int rt6_check_neigh(struct rt6_info *rt)
+static inline bool rt6_check_neigh(struct rt6_info *rt)
 {
        struct neighbour *neigh;
-       int m;
+       bool ret = false;
 
        neigh = rt->n;
        if (rt->rt6i_flags & RTF_NONEXTHOP ||
            !(rt->rt6i_flags & RTF_GATEWAY))
-               m = 1;
+               ret = true;
        else if (neigh) {
                read_lock_bh(&neigh->lock);
                if (neigh->nud_state & NUD_VALID)
-                       m = 2;
+                       ret = true;
 #ifdef CONFIG_IPV6_ROUTER_PREF
-               else if (neigh->nud_state & NUD_FAILED)
-                       m = 0;
+               else if (!(neigh->nud_state & NUD_FAILED))
+                       ret = true;
 #endif
-               else
-                       m = 1;
                read_unlock_bh(&neigh->lock);
-       } else
-               m = 0;
-       return m;
+       }
+       return ret;
 }
 
 static int rt6_score_route(struct rt6_info *rt, int oif,
                           int strict)
 {
-       int m, n;
+       int m;
 
        m = rt6_check_dev(rt, oif);
        if (!m && (strict & RT6_LOOKUP_F_IFACE))
@@ -523,8 +577,7 @@ static int rt6_score_route(struct rt6_info *rt, int oif,
 #ifdef CONFIG_IPV6_ROUTER_PREF
        m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
 #endif
-       n = rt6_check_neigh(rt);
-       if (!n && (strict & RT6_LOOKUP_F_REACHABLE))
+       if (!rt6_check_neigh(rt) && (strict & RT6_LOOKUP_F_REACHABLE))
                return -1;
        return m;
 }
@@ -666,7 +719,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
                else
                        rt6_set_expires(rt, jiffies + HZ * lifetime);
 
-               dst_release(&rt->dst);
+               ip6_rt_put(rt);
        }
        return 0;
 }
@@ -702,6 +755,8 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 restart:
        rt = fn->leaf;
        rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
+       if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
+               rt = rt6_multipath_select(rt, fl6);
        BACKTRACK(net, &fl6->saddr);
 out:
        dst_use(&rt->dst, jiffies);
@@ -863,7 +918,8 @@ restart_2:
 
 restart:
        rt = rt6_select(fn, oif, strict | reachable);
-
+       if (rt->rt6i_nsiblings && oif == 0)
+               rt = rt6_multipath_select(rt, fl6);
        BACKTRACK(net, &fl6->saddr);
        if (rt == net->ipv6.ip6_null_entry ||
            rt->rt6i_flags & RTF_CACHE)
@@ -879,7 +935,7 @@ restart:
        else
                goto out2;
 
-       dst_release(&rt->dst);
+       ip6_rt_put(rt);
        rt = nrt ? : net->ipv6.ip6_null_entry;
 
        dst_hold(&rt->dst);
@@ -896,7 +952,7 @@ restart:
         * Race condition! In the gap, when table->tb6_lock was
         * released someone could insert this route.  Relookup.
         */
-       dst_release(&rt->dst);
+       ip6_rt_put(rt);
        goto relookup;
 
 out:
@@ -1030,14 +1086,9 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
        if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
                return NULL;
 
-       if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
-               if (rt->rt6i_peer_genid != rt6_peer_genid()) {
-                       if (!rt6_has_peer(rt))
-                               rt6_bind_peer(rt, 0);
-                       rt->rt6i_peer_genid = rt6_peer_genid();
-               }
+       if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
                return dst;
-       }
+
        return NULL;
 }
 
@@ -1232,7 +1283,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
        rt->rt6i_dst.addr = fl6->daddr;
        rt->rt6i_dst.plen = 128;
        rt->rt6i_idev     = idev;
-       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
+       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
 
        spin_lock_bh(&icmp6_dst_lock);
        rt->dst.next = icmp6_dst_gc_list;
@@ -1316,12 +1367,6 @@ out:
        return entries > rt_max_size;
 }
 
-/* Clean host part of a prefix. Not necessary in radix tree,
-   but results in cleaner routing tables.
-
-   Remove it only when all the things will work!
- */
-
 int ip6_dst_hoplimit(struct dst_entry *dst)
 {
        int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
@@ -1507,7 +1552,7 @@ int ip6_route_add(struct fib6_config *cfg)
                                goto out;
                        if (dev) {
                                if (dev != grt->dst.dev) {
-                                       dst_release(&grt->dst);
+                                       ip6_rt_put(grt);
                                        goto out;
                                }
                        } else {
@@ -1518,7 +1563,7 @@ int ip6_route_add(struct fib6_config *cfg)
                        }
                        if (!(grt->rt6i_flags & RTF_GATEWAY))
                                err = 0;
-                       dst_release(&grt->dst);
+                       ip6_rt_put(grt);
 
                        if (err)
                                goto out;
@@ -1604,7 +1649,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
        write_unlock_bh(&table->tb6_lock);
 
 out:
-       dst_release(&rt->dst);
+       ip6_rt_put(rt);
        return err;
 }
 
@@ -1987,7 +2032,7 @@ int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        switch(cmd) {
        case SIOCADDRT:         /* Add a route */
        case SIOCDELRT:         /* Delete a route */
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
                err = copy_from_user(&rtmsg, arg,
                                     sizeof(struct in6_rtmsg));
@@ -2249,6 +2294,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
        [RTA_IIF]               = { .type = NLA_U32 },
        [RTA_PRIORITY]          = { .type = NLA_U32 },
        [RTA_METRICS]           = { .type = NLA_NESTED },
+       [RTA_MULTIPATH]         = { .len = sizeof(struct rtnexthop) },
 };
 
 static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2326,11 +2372,71 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (tb[RTA_TABLE])
                cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
 
+       if (tb[RTA_MULTIPATH]) {
+               cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
+               cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
+       }
+
        err = 0;
 errout:
        return err;
 }
 
+static int ip6_route_multipath(struct fib6_config *cfg, int add)
+{
+       struct fib6_config r_cfg;
+       struct rtnexthop *rtnh;
+       int remaining;
+       int attrlen;
+       int err = 0, last_err = 0;
+
+beginning:
+       rtnh = (struct rtnexthop *)cfg->fc_mp;
+       remaining = cfg->fc_mp_len;
+
+       /* Parse a Multipath Entry */
+       while (rtnh_ok(rtnh, remaining)) {
+               memcpy(&r_cfg, cfg, sizeof(*cfg));
+               if (rtnh->rtnh_ifindex)
+                       r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
+
+               attrlen = rtnh_attrlen(rtnh);
+               if (attrlen > 0) {
+                       struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
+
+                       nla = nla_find(attrs, attrlen, RTA_GATEWAY);
+                       if (nla) {
+                               nla_memcpy(&r_cfg.fc_gateway, nla, 16);
+                               r_cfg.fc_flags |= RTF_GATEWAY;
+                       }
+               }
+               err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
+               if (err) {
+                       last_err = err;
+                       /* If we are trying to remove a route, do not stop the
+                        * loop when ip6_route_del() fails (because next hop is
+                        * already gone), we should try to remove all next hops.
+                        */
+                       if (add) {
+                               /* If add fails, we should try to delete all
+                                * next hops that have been already added.
+                                */
+                               add = 0;
+                               goto beginning;
+                       }
+               }
+               /* Because each route is added like a single route we remove
+                * this flag after the first nexthop (if there is a collision,
+                * we have already fail to add the first nexthop:
+                * fib6_add_rt2node() has reject it).
+                */
+               cfg->fc_nlinfo.nlh->nlmsg_flags &= ~NLM_F_EXCL;
+               rtnh = rtnh_next(rtnh, &remaining);
+       }
+
+       return last_err;
+}
+
 static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 {
        struct fib6_config cfg;
@@ -2340,7 +2446,10 @@ static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
        if (err < 0)
                return err;
 
-       return ip6_route_del(&cfg);
+       if (cfg.fc_mp)
+               return ip6_route_multipath(&cfg, 0);
+       else
+               return ip6_route_del(&cfg);
 }
 
 static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
@@ -2352,7 +2461,10 @@ static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *a
        if (err < 0)
                return err;
 
-       return ip6_route_add(&cfg);
+       if (cfg.fc_mp)
+               return ip6_route_multipath(&cfg, 1);
+       else
+               return ip6_route_add(&cfg);
 }
 
 static inline size_t rt6_nlmsg_size(void)
@@ -2596,7 +2708,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
 
        skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
        if (!skb) {
-               dst_release(&rt->dst);
+               ip6_rt_put(rt);
                err = -ENOBUFS;
                goto errout;
        }
@@ -2873,6 +2985,10 @@ struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net)
                table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
                table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
                table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
+
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       table[0].procname = NULL;
        }
 
        return table;
index 3ed54ffd8d50dfa1ccf5b4b539c5461fae29c4fb..cfba99b2c2a4958144ff4c2a2faa1d98192d7310 100644 (file)
 #define HASH_SIZE  16
 #define HASH(addr) (((__force u32)addr^((__force u32)addr>>4))&0xF)
 
+static bool log_ecn_error = true;
+module_param(log_ecn_error, bool, 0644);
+MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");
+
 static int ipip6_tunnel_init(struct net_device *dev);
 static void ipip6_tunnel_setup(struct net_device *dev);
 static void ipip6_dev_free(struct net_device *dev);
+static struct rtnl_link_ops sit_link_ops __read_mostly;
 
 static int sit_net_id __read_mostly;
 struct sit_net {
@@ -80,22 +85,6 @@ struct sit_net {
        struct net_device *fb_tunnel_dev;
 };
 
-/*
- * Locking : hash tables are protected by RCU and RTNL
- */
-
-#define for_each_ip_tunnel_rcu(start) \
-       for (t = rcu_dereference(start); t; t = rcu_dereference(t->next))
-
-/* often modified stats are per cpu, other are shared (netdev->stats) */
-struct pcpu_tstats {
-       u64     rx_packets;
-       u64     rx_bytes;
-       u64     tx_packets;
-       u64     tx_bytes;
-       struct u64_stats_sync   syncp;
-};
-
 static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev,
                                                   struct rtnl_link_stats64 *tot)
 {
@@ -121,6 +110,7 @@ static struct rtnl_link_stats64 *ipip6_get_stats64(struct net_device *dev,
        }
 
        tot->rx_errors = dev->stats.rx_errors;
+       tot->rx_frame_errors = dev->stats.rx_frame_errors;
        tot->tx_fifo_errors = dev->stats.tx_fifo_errors;
        tot->tx_carrier_errors = dev->stats.tx_carrier_errors;
        tot->tx_dropped = dev->stats.tx_dropped;
@@ -141,20 +131,20 @@ static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net,
        struct ip_tunnel *t;
        struct sit_net *sitn = net_generic(net, sit_net_id);
 
-       for_each_ip_tunnel_rcu(sitn->tunnels_r_l[h0 ^ h1]) {
+       for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) {
                if (local == t->parms.iph.saddr &&
                    remote == t->parms.iph.daddr &&
                    (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
                    (t->dev->flags & IFF_UP))
                        return t;
        }
-       for_each_ip_tunnel_rcu(sitn->tunnels_r[h0]) {
+       for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) {
                if (remote == t->parms.iph.daddr &&
                    (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
                    (t->dev->flags & IFF_UP))
                        return t;
        }
-       for_each_ip_tunnel_rcu(sitn->tunnels_l[h1]) {
+       for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) {
                if (local == t->parms.iph.saddr &&
                    (!dev || !t->parms.link || dev->iflink == t->parms.link) &&
                    (t->dev->flags & IFF_UP))
@@ -231,6 +221,37 @@ static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn)
 #endif
 }
 
+static int ipip6_tunnel_create(struct net_device *dev)
+{
+       struct ip_tunnel *t = netdev_priv(dev);
+       struct net *net = dev_net(dev);
+       struct sit_net *sitn = net_generic(net, sit_net_id);
+       int err;
+
+       err = ipip6_tunnel_init(dev);
+       if (err < 0)
+               goto out;
+       ipip6_tunnel_clone_6rd(dev, sitn);
+
+       if ((__force u16)t->parms.i_flags & SIT_ISATAP)
+               dev->priv_flags |= IFF_ISATAP;
+
+       err = register_netdevice(dev);
+       if (err < 0)
+               goto out;
+
+       strcpy(t->parms.name, dev->name);
+       dev->rtnl_link_ops = &sit_link_ops;
+
+       dev_hold(dev);
+
+       ipip6_tunnel_link(sitn, t);
+       return 0;
+
+out:
+       return err;
+}
+
 static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
                struct ip_tunnel_parm *parms, int create)
 {
@@ -271,21 +292,9 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
        nt = netdev_priv(dev);
 
        nt->parms = *parms;
-       if (ipip6_tunnel_init(dev) < 0)
+       if (ipip6_tunnel_create(dev) < 0)
                goto failed_free;
-       ipip6_tunnel_clone_6rd(dev, sitn);
 
-       if (parms->i_flags & SIT_ISATAP)
-               dev->priv_flags |= IFF_ISATAP;
-
-       if (register_netdevice(dev) < 0)
-               goto failed_free;
-
-       strcpy(nt->parms.name, dev->name);
-
-       dev_hold(dev);
-
-       ipip6_tunnel_link(sitn, nt);
        return nt;
 
 failed_free:
@@ -581,16 +590,11 @@ out:
        return err;
 }
 
-static inline void ipip6_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb)
-{
-       if (INET_ECN_is_ce(iph->tos))
-               IP6_ECN_set_ce(ipv6_hdr(skb));
-}
-
 static int ipip6_rcv(struct sk_buff *skb)
 {
        const struct iphdr *iph;
        struct ip_tunnel *tunnel;
+       int err;
 
        if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
                goto out;
@@ -612,18 +616,27 @@ static int ipip6_rcv(struct sk_buff *skb)
                if ((tunnel->dev->priv_flags & IFF_ISATAP) &&
                    !isatap_chksrc(skb, iph, tunnel)) {
                        tunnel->dev->stats.rx_errors++;
-                       kfree_skb(skb);
-                       return 0;
+                       goto out;
+               }
+
+               __skb_tunnel_rx(skb, tunnel->dev);
+
+               err = IP_ECN_decapsulate(iph, skb);
+               if (unlikely(err)) {
+                       if (log_ecn_error)
+                               net_info_ratelimited("non-ECT from %pI4 with TOS=%#x\n",
+                                                    &iph->saddr, iph->tos);
+                       if (err > 1) {
+                               ++tunnel->dev->stats.rx_frame_errors;
+                               ++tunnel->dev->stats.rx_errors;
+                               goto out;
+                       }
                }
 
                tstats = this_cpu_ptr(tunnel->dev->tstats);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
 
-               __skb_tunnel_rx(skb, tunnel->dev);
-
-               ipip6_ecn_decapsulate(iph, skb);
-
                netif_rx(skb);
 
                return 0;
@@ -683,7 +696,6 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                                     struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
-       struct pcpu_tstats *tstats;
        const struct iphdr  *tiph = &tunnel->parms.iph;
        const struct ipv6hdr *iph6 = ipv6_hdr(skb);
        u8     tos = tunnel->parms.iph.tos;
@@ -864,9 +876,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
        if ((iph->ttl = tiph->ttl) == 0)
                iph->ttl        =       iph6->hop_limit;
 
-       nf_reset(skb);
-       tstats = this_cpu_ptr(dev->tstats);
-       __IPTUNNEL_XMIT(tstats, &dev->stats);
+       iptunnel_xmit(skb, dev);
        return NETDEV_TX_OK;
 
 tx_error_icmp:
@@ -914,6 +924,59 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev)
        dev->iflink = tunnel->parms.link;
 }
 
+static void ipip6_tunnel_update(struct ip_tunnel *t, struct ip_tunnel_parm *p)
+{
+       struct net *net = dev_net(t->dev);
+       struct sit_net *sitn = net_generic(net, sit_net_id);
+
+       ipip6_tunnel_unlink(sitn, t);
+       synchronize_net();
+       t->parms.iph.saddr = p->iph.saddr;
+       t->parms.iph.daddr = p->iph.daddr;
+       memcpy(t->dev->dev_addr, &p->iph.saddr, 4);
+       memcpy(t->dev->broadcast, &p->iph.daddr, 4);
+       ipip6_tunnel_link(sitn, t);
+       t->parms.iph.ttl = p->iph.ttl;
+       t->parms.iph.tos = p->iph.tos;
+       if (t->parms.link != p->link) {
+               t->parms.link = p->link;
+               ipip6_tunnel_bind_dev(t->dev);
+       }
+       netdev_state_change(t->dev);
+}
+
+#ifdef CONFIG_IPV6_SIT_6RD
+static int ipip6_tunnel_update_6rd(struct ip_tunnel *t,
+                                  struct ip_tunnel_6rd *ip6rd)
+{
+       struct in6_addr prefix;
+       __be32 relay_prefix;
+
+       if (ip6rd->relay_prefixlen > 32 ||
+           ip6rd->prefixlen + (32 - ip6rd->relay_prefixlen) > 64)
+               return -EINVAL;
+
+       ipv6_addr_prefix(&prefix, &ip6rd->prefix, ip6rd->prefixlen);
+       if (!ipv6_addr_equal(&prefix, &ip6rd->prefix))
+               return -EINVAL;
+       if (ip6rd->relay_prefixlen)
+               relay_prefix = ip6rd->relay_prefix &
+                              htonl(0xffffffffUL <<
+                                    (32 - ip6rd->relay_prefixlen));
+       else
+               relay_prefix = 0;
+       if (relay_prefix != ip6rd->relay_prefix)
+               return -EINVAL;
+
+       t->ip6rd.prefix = prefix;
+       t->ip6rd.relay_prefix = relay_prefix;
+       t->ip6rd.prefixlen = ip6rd->prefixlen;
+       t->ip6rd.relay_prefixlen = ip6rd->relay_prefixlen;
+       netdev_state_change(t->dev);
+       return 0;
+}
+#endif
+
 static int
 ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 {
@@ -966,7 +1029,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCADDTUNNEL:
        case SIOCCHGTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                err = -EFAULT;
@@ -995,28 +1058,13 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
                                        break;
                                }
                                t = netdev_priv(dev);
-                               ipip6_tunnel_unlink(sitn, t);
-                               synchronize_net();
-                               t->parms.iph.saddr = p.iph.saddr;
-                               t->parms.iph.daddr = p.iph.daddr;
-                               memcpy(dev->dev_addr, &p.iph.saddr, 4);
-                               memcpy(dev->broadcast, &p.iph.daddr, 4);
-                               ipip6_tunnel_link(sitn, t);
-                               netdev_state_change(dev);
                        }
+
+                       ipip6_tunnel_update(t, &p);
                }
 
                if (t) {
                        err = 0;
-                       if (cmd == SIOCCHGTUNNEL) {
-                               t->parms.iph.ttl = p.iph.ttl;
-                               t->parms.iph.tos = p.iph.tos;
-                               if (t->parms.link != p.link) {
-                                       t->parms.link = p.link;
-                                       ipip6_tunnel_bind_dev(dev);
-                                       netdev_state_change(dev);
-                               }
-                       }
                        if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof(p)))
                                err = -EFAULT;
                } else
@@ -1025,7 +1073,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
 
        case SIOCDELTUNNEL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                if (dev == sitn->fb_tunnel_dev) {
@@ -1058,7 +1106,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCDELPRL:
        case SIOCCHGPRL:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
                err = -EINVAL;
                if (dev == sitn->fb_tunnel_dev)
@@ -1087,7 +1135,7 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCCHG6RD:
        case SIOCDEL6RD:
                err = -EPERM;
-               if (!capable(CAP_NET_ADMIN))
+               if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        goto done;
 
                err = -EFAULT;
@@ -1098,31 +1146,9 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
                t = netdev_priv(dev);
 
                if (cmd != SIOCDEL6RD) {
-                       struct in6_addr prefix;
-                       __be32 relay_prefix;
-
-                       err = -EINVAL;
-                       if (ip6rd.relay_prefixlen > 32 ||
-                           ip6rd.prefixlen + (32 - ip6rd.relay_prefixlen) > 64)
-                               goto done;
-
-                       ipv6_addr_prefix(&prefix, &ip6rd.prefix,
-                                        ip6rd.prefixlen);
-                       if (!ipv6_addr_equal(&prefix, &ip6rd.prefix))
-                               goto done;
-                       if (ip6rd.relay_prefixlen)
-                               relay_prefix = ip6rd.relay_prefix &
-                                              htonl(0xffffffffUL <<
-                                                    (32 - ip6rd.relay_prefixlen));
-                       else
-                               relay_prefix = 0;
-                       if (relay_prefix != ip6rd.relay_prefix)
+                       err = ipip6_tunnel_update_6rd(t, &ip6rd);
+                       if (err < 0)
                                goto done;
-
-                       t->ip6rd.prefix = prefix;
-                       t->ip6rd.relay_prefix = relay_prefix;
-                       t->ip6rd.prefixlen = ip6rd.prefixlen;
-                       t->ip6rd.relay_prefixlen = ip6rd.relay_prefixlen;
                } else
                        ipip6_tunnel_clone_6rd(dev, sitn);
 
@@ -1216,6 +1242,239 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev)
        return 0;
 }
 
+static void ipip6_netlink_parms(struct nlattr *data[],
+                               struct ip_tunnel_parm *parms)
+{
+       memset(parms, 0, sizeof(*parms));
+
+       parms->iph.version = 4;
+       parms->iph.protocol = IPPROTO_IPV6;
+       parms->iph.ihl = 5;
+       parms->iph.ttl = 64;
+
+       if (!data)
+               return;
+
+       if (data[IFLA_IPTUN_LINK])
+               parms->link = nla_get_u32(data[IFLA_IPTUN_LINK]);
+
+       if (data[IFLA_IPTUN_LOCAL])
+               parms->iph.saddr = nla_get_be32(data[IFLA_IPTUN_LOCAL]);
+
+       if (data[IFLA_IPTUN_REMOTE])
+               parms->iph.daddr = nla_get_be32(data[IFLA_IPTUN_REMOTE]);
+
+       if (data[IFLA_IPTUN_TTL]) {
+               parms->iph.ttl = nla_get_u8(data[IFLA_IPTUN_TTL]);
+               if (parms->iph.ttl)
+                       parms->iph.frag_off = htons(IP_DF);
+       }
+
+       if (data[IFLA_IPTUN_TOS])
+               parms->iph.tos = nla_get_u8(data[IFLA_IPTUN_TOS]);
+
+       if (!data[IFLA_IPTUN_PMTUDISC] || nla_get_u8(data[IFLA_IPTUN_PMTUDISC]))
+               parms->iph.frag_off = htons(IP_DF);
+
+       if (data[IFLA_IPTUN_FLAGS])
+               parms->i_flags = nla_get_be16(data[IFLA_IPTUN_FLAGS]);
+}
+
+#ifdef CONFIG_IPV6_SIT_6RD
+/* This function returns true when 6RD attributes are present in the nl msg */
+static bool ipip6_netlink_6rd_parms(struct nlattr *data[],
+                                   struct ip_tunnel_6rd *ip6rd)
+{
+       bool ret = false;
+       memset(ip6rd, 0, sizeof(*ip6rd));
+
+       if (!data)
+               return ret;
+
+       if (data[IFLA_IPTUN_6RD_PREFIX]) {
+               ret = true;
+               nla_memcpy(&ip6rd->prefix, data[IFLA_IPTUN_6RD_PREFIX],
+                          sizeof(struct in6_addr));
+       }
+
+       if (data[IFLA_IPTUN_6RD_RELAY_PREFIX]) {
+               ret = true;
+               ip6rd->relay_prefix =
+                       nla_get_be32(data[IFLA_IPTUN_6RD_RELAY_PREFIX]);
+       }
+
+       if (data[IFLA_IPTUN_6RD_PREFIXLEN]) {
+               ret = true;
+               ip6rd->prefixlen = nla_get_u16(data[IFLA_IPTUN_6RD_PREFIXLEN]);
+       }
+
+       if (data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) {
+               ret = true;
+               ip6rd->relay_prefixlen =
+                       nla_get_u16(data[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
+       }
+
+       return ret;
+}
+#endif
+
+static int ipip6_newlink(struct net *src_net, struct net_device *dev,
+                        struct nlattr *tb[], struct nlattr *data[])
+{
+       struct net *net = dev_net(dev);
+       struct ip_tunnel *nt;
+#ifdef CONFIG_IPV6_SIT_6RD
+       struct ip_tunnel_6rd ip6rd;
+#endif
+       int err;
+
+       nt = netdev_priv(dev);
+       ipip6_netlink_parms(data, &nt->parms);
+
+       if (ipip6_tunnel_locate(net, &nt->parms, 0))
+               return -EEXIST;
+
+       err = ipip6_tunnel_create(dev);
+       if (err < 0)
+               return err;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+       if (ipip6_netlink_6rd_parms(data, &ip6rd))
+               err = ipip6_tunnel_update_6rd(nt, &ip6rd);
+#endif
+
+       return err;
+}
+
+static int ipip6_changelink(struct net_device *dev, struct nlattr *tb[],
+                         struct nlattr *data[])
+{
+       struct ip_tunnel *t;
+       struct ip_tunnel_parm p;
+       struct net *net = dev_net(dev);
+       struct sit_net *sitn = net_generic(net, sit_net_id);
+#ifdef CONFIG_IPV6_SIT_6RD
+       struct ip_tunnel_6rd ip6rd;
+#endif
+
+       if (dev == sitn->fb_tunnel_dev)
+               return -EINVAL;
+
+       ipip6_netlink_parms(data, &p);
+
+       if (((dev->flags & IFF_POINTOPOINT) && !p.iph.daddr) ||
+           (!(dev->flags & IFF_POINTOPOINT) && p.iph.daddr))
+               return -EINVAL;
+
+       t = ipip6_tunnel_locate(net, &p, 0);
+
+       if (t) {
+               if (t->dev != dev)
+                       return -EEXIST;
+       } else
+               t = netdev_priv(dev);
+
+       ipip6_tunnel_update(t, &p);
+
+#ifdef CONFIG_IPV6_SIT_6RD
+       if (ipip6_netlink_6rd_parms(data, &ip6rd))
+               return ipip6_tunnel_update_6rd(t, &ip6rd);
+#endif
+
+       return 0;
+}
+
+static size_t ipip6_get_size(const struct net_device *dev)
+{
+       return
+               /* IFLA_IPTUN_LINK */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_LOCAL */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_REMOTE */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_TTL */
+               nla_total_size(1) +
+               /* IFLA_IPTUN_TOS */
+               nla_total_size(1) +
+               /* IFLA_IPTUN_PMTUDISC */
+               nla_total_size(1) +
+               /* IFLA_IPTUN_FLAGS */
+               nla_total_size(2) +
+#ifdef CONFIG_IPV6_SIT_6RD
+               /* IFLA_IPTUN_6RD_PREFIX */
+               nla_total_size(sizeof(struct in6_addr)) +
+               /* IFLA_IPTUN_6RD_RELAY_PREFIX */
+               nla_total_size(4) +
+               /* IFLA_IPTUN_6RD_PREFIXLEN */
+               nla_total_size(2) +
+               /* IFLA_IPTUN_6RD_RELAY_PREFIXLEN */
+               nla_total_size(2) +
+#endif
+               0;
+}
+
+static int ipip6_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+       struct ip_tunnel *tunnel = netdev_priv(dev);
+       struct ip_tunnel_parm *parm = &tunnel->parms;
+
+       if (nla_put_u32(skb, IFLA_IPTUN_LINK, parm->link) ||
+           nla_put_be32(skb, IFLA_IPTUN_LOCAL, parm->iph.saddr) ||
+           nla_put_be32(skb, IFLA_IPTUN_REMOTE, parm->iph.daddr) ||
+           nla_put_u8(skb, IFLA_IPTUN_TTL, parm->iph.ttl) ||
+           nla_put_u8(skb, IFLA_IPTUN_TOS, parm->iph.tos) ||
+           nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
+                      !!(parm->iph.frag_off & htons(IP_DF))) ||
+           nla_put_be16(skb, IFLA_IPTUN_FLAGS, parm->i_flags))
+               goto nla_put_failure;
+
+#ifdef CONFIG_IPV6_SIT_6RD
+       if (nla_put(skb, IFLA_IPTUN_6RD_PREFIX, sizeof(struct in6_addr),
+                   &tunnel->ip6rd.prefix) ||
+           nla_put_be32(skb, IFLA_IPTUN_6RD_RELAY_PREFIX,
+                        tunnel->ip6rd.relay_prefix) ||
+           nla_put_u16(skb, IFLA_IPTUN_6RD_PREFIXLEN,
+                       tunnel->ip6rd.prefixlen) ||
+           nla_put_u16(skb, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+                       tunnel->ip6rd.relay_prefixlen))
+               goto nla_put_failure;
+#endif
+
+       return 0;
+
+nla_put_failure:
+       return -EMSGSIZE;
+}
+
+static const struct nla_policy ipip6_policy[IFLA_IPTUN_MAX + 1] = {
+       [IFLA_IPTUN_LINK]               = { .type = NLA_U32 },
+       [IFLA_IPTUN_LOCAL]              = { .type = NLA_U32 },
+       [IFLA_IPTUN_REMOTE]             = { .type = NLA_U32 },
+       [IFLA_IPTUN_TTL]                = { .type = NLA_U8 },
+       [IFLA_IPTUN_TOS]                = { .type = NLA_U8 },
+       [IFLA_IPTUN_PMTUDISC]           = { .type = NLA_U8 },
+       [IFLA_IPTUN_FLAGS]              = { .type = NLA_U16 },
+#ifdef CONFIG_IPV6_SIT_6RD
+       [IFLA_IPTUN_6RD_PREFIX]         = { .len = sizeof(struct in6_addr) },
+       [IFLA_IPTUN_6RD_RELAY_PREFIX]   = { .type = NLA_U32 },
+       [IFLA_IPTUN_6RD_PREFIXLEN]      = { .type = NLA_U16 },
+       [IFLA_IPTUN_6RD_RELAY_PREFIXLEN] = { .type = NLA_U16 },
+#endif
+};
+
+static struct rtnl_link_ops sit_link_ops __read_mostly = {
+       .kind           = "sit",
+       .maxtype        = IFLA_IPTUN_MAX,
+       .policy         = ipip6_policy,
+       .priv_size      = sizeof(struct ip_tunnel),
+       .setup          = ipip6_tunnel_setup,
+       .newlink        = ipip6_newlink,
+       .changelink     = ipip6_changelink,
+       .get_size       = ipip6_get_size,
+       .fill_info      = ipip6_fill_info,
+};
+
 static struct xfrm_tunnel sit_handler __read_mostly = {
        .handler        =       ipip6_rcv,
        .err_handler    =       ipip6_err,
@@ -1302,6 +1561,7 @@ static struct pernet_operations sit_net_ops = {
 
 static void __exit sit_cleanup(void)
 {
+       rtnl_link_unregister(&sit_link_ops);
        xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
 
        unregister_pernet_device(&sit_net_ops);
@@ -1319,10 +1579,21 @@ static int __init sit_init(void)
                return err;
        err = xfrm4_tunnel_register(&sit_handler, AF_INET6);
        if (err < 0) {
-               unregister_pernet_device(&sit_net_ops);
                pr_info("%s: can't add protocol\n", __func__);
+               goto xfrm_tunnel_failed;
        }
+       err = rtnl_link_register(&sit_link_ops);
+       if (err < 0)
+               goto rtnl_link_failed;
+
+out:
        return err;
+
+rtnl_link_failed:
+       xfrm4_tunnel_deregister(&sit_handler, AF_INET6);
+xfrm_tunnel_failed:
+       unregister_pernet_device(&sit_net_ops);
+       goto out;
 }
 
 module_init(sit_init);
index 182ab9a85d6cb5c0ad88e89bab6f5c0d22c380e8..40161977f7cf0b69ecc488d87427e03c88d61598 100644 (file)
@@ -214,7 +214,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
                ireq6->iif = inet6_iif(skb);
 
        req->expires = 0UL;
-       req->retrans = 0;
+       req->num_retrans = 0;
        ireq->ecn_ok            = ecn_ok;
        ireq->snd_wscale        = tcp_opt.snd_wscale;
        ireq->sack_ok           = tcp_opt.sack_ok;
index 26175bffbaa060ad8da6357330ff596a5391cef6..6565cf55eb1e80f9109502995319655147bd1fd7 100644 (file)
@@ -77,9 +77,6 @@ static void   tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
                                      struct request_sock *req);
 
 static int     tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
-static void    __tcp_v6_send_check(struct sk_buff *skb,
-                                   const struct in6_addr *saddr,
-                                   const struct in6_addr *daddr);
 
 static const struct inet_connection_sock_af_ops ipv6_mapped;
 static const struct inet_connection_sock_af_ops ipv6_specific;
@@ -119,14 +116,6 @@ static void tcp_v6_hash(struct sock *sk)
        }
 }
 
-static __inline__ __sum16 tcp_v6_check(int len,
-                                  const struct in6_addr *saddr,
-                                  const struct in6_addr *daddr,
-                                  __wsum base)
-{
-       return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
-}
-
 static __u32 tcp_v6_init_sequence(const struct sk_buff *skb)
 {
        return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32,
@@ -306,7 +295,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        if (err)
                goto late_failure;
 
-       if (!tp->write_seq)
+       if (!tp->write_seq && likely(!tp->repair))
                tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
                                                             np->daddr.s6_addr32,
                                                             inet->inet_sport,
@@ -495,9 +484,12 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req,
                             struct request_values *rvp)
 {
        struct flowi6 fl6;
+       int res;
 
-       TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
-       return tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
+       res = tcp_v6_send_synack(sk, NULL, &fl6, req, rvp, 0);
+       if (!res)
+               TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS);
+       return res;
 }
 
 static void tcp_v6_reqsk_destructor(struct request_sock *req)
@@ -719,94 +711,6 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
 };
 #endif
 
-static void __tcp_v6_send_check(struct sk_buff *skb,
-                               const struct in6_addr *saddr, const struct in6_addr *daddr)
-{
-       struct tcphdr *th = tcp_hdr(skb);
-
-       if (skb->ip_summed == CHECKSUM_PARTIAL) {
-               th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
-               skb->csum_start = skb_transport_header(skb) - skb->head;
-               skb->csum_offset = offsetof(struct tcphdr, check);
-       } else {
-               th->check = tcp_v6_check(skb->len, saddr, daddr,
-                                        csum_partial(th, th->doff << 2,
-                                                     skb->csum));
-       }
-}
-
-static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
-{
-       struct ipv6_pinfo *np = inet6_sk(sk);
-
-       __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
-}
-
-static int tcp_v6_gso_send_check(struct sk_buff *skb)
-{
-       const struct ipv6hdr *ipv6h;
-       struct tcphdr *th;
-
-       if (!pskb_may_pull(skb, sizeof(*th)))
-               return -EINVAL;
-
-       ipv6h = ipv6_hdr(skb);
-       th = tcp_hdr(skb);
-
-       th->check = 0;
-       skb->ip_summed = CHECKSUM_PARTIAL;
-       __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
-       return 0;
-}
-
-static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
-                                        struct sk_buff *skb)
-{
-       const struct ipv6hdr *iph = skb_gro_network_header(skb);
-       __wsum wsum;
-       __sum16 sum;
-
-       switch (skb->ip_summed) {
-       case CHECKSUM_COMPLETE:
-               if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
-                                 skb->csum)) {
-                       skb->ip_summed = CHECKSUM_UNNECESSARY;
-                       break;
-               }
-flush:
-               NAPI_GRO_CB(skb)->flush = 1;
-               return NULL;
-
-       case CHECKSUM_NONE:
-               wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
-                                                   skb_gro_len(skb),
-                                                   IPPROTO_TCP, 0));
-               sum = csum_fold(skb_checksum(skb,
-                                            skb_gro_offset(skb),
-                                            skb_gro_len(skb),
-                                            wsum));
-               if (sum)
-                       goto flush;
-
-               skb->ip_summed = CHECKSUM_UNNECESSARY;
-               break;
-       }
-
-       return tcp_gro_receive(head, skb);
-}
-
-static int tcp6_gro_complete(struct sk_buff *skb)
-{
-       const struct ipv6hdr *iph = ipv6_hdr(skb);
-       struct tcphdr *th = tcp_hdr(skb);
-
-       th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb),
-                                 &iph->saddr, &iph->daddr, 0);
-       skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
-
-       return tcp_gro_complete(skb);
-}
-
 static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
                                 u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass)
 {
@@ -1364,7 +1268,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
 
        tcp_initialize_rcv_mss(newsk);
        tcp_synack_rtt_meas(newsk, req);
-       newtp->total_retrans = req->retrans;
+       newtp->total_retrans = req->num_retrans;
 
        newinet->inet_daddr = newinet->inet_saddr = LOOPBACK4_IPV6;
        newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
@@ -1741,11 +1645,11 @@ static void tcp_v6_early_demux(struct sk_buff *skb)
                skb->destructor = sock_edemux;
                if (sk->sk_state != TCP_TIME_WAIT) {
                        struct dst_entry *dst = sk->sk_rx_dst;
-                       struct inet_sock *icsk = inet_sk(sk);
+
                        if (dst)
                                dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);
                        if (dst &&
-                           icsk->rx_dst_ifindex == skb->skb_iif)
+                           inet_sk(sk)->rx_dst_ifindex == skb->skb_iif)
                                skb_dst_set_noref(skb, dst);
                }
        }
@@ -1866,7 +1770,7 @@ static void get_openreq6(struct seq_file *seq,
                   0,0, /* could print option size, but that is af dependent. */
                   1,   /* timers active (only the expire timer) */
                   jiffies_to_clock_t(ttd),
-                  req->retrans,
+                  req->num_timeout,
                   from_kuid_munged(seq_user_ns(seq), uid),
                   0,  /* non standard timer */
                   0, /* open_requests have no inode */
@@ -2063,10 +1967,6 @@ static const struct inet6_protocol tcpv6_protocol = {
        .early_demux    =       tcp_v6_early_demux,
        .handler        =       tcp_v6_rcv,
        .err_handler    =       tcp_v6_err,
-       .gso_send_check =       tcp_v6_gso_send_check,
-       .gso_segment    =       tcp_tso_segment,
-       .gro_receive    =       tcp6_gro_receive,
-       .gro_complete   =       tcp6_gro_complete,
        .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
@@ -2121,10 +2021,10 @@ int __init tcpv6_init(void)
 out:
        return ret;
 
-out_tcpv6_protocol:
-       inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
 out_tcpv6_protosw:
        inet6_unregister_protosw(&tcpv6_protosw);
+out_tcpv6_protocol:
+       inet6_del_protocol(&tcpv6_protocol, IPPROTO_TCP);
        goto out;
 }
 
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c
new file mode 100644 (file)
index 0000000..2ec6bf6
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ *     IPV6 GSO/GRO offload support
+ *     Linux INET6 implementation
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      TCPv6 GSO/GRO support
+ */
+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/tcp.h>
+#include <net/ip6_checksum.h>
+#include "ip6_offload.h"
+
+static int tcp_v6_gso_send_check(struct sk_buff *skb)
+{
+       const struct ipv6hdr *ipv6h;
+       struct tcphdr *th;
+
+       if (!pskb_may_pull(skb, sizeof(*th)))
+               return -EINVAL;
+
+       ipv6h = ipv6_hdr(skb);
+       th = tcp_hdr(skb);
+
+       th->check = 0;
+       skb->ip_summed = CHECKSUM_PARTIAL;
+       __tcp_v6_send_check(skb, &ipv6h->saddr, &ipv6h->daddr);
+       return 0;
+}
+
+static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
+                                        struct sk_buff *skb)
+{
+       const struct ipv6hdr *iph = skb_gro_network_header(skb);
+       __wsum wsum;
+       __sum16 sum;
+
+       switch (skb->ip_summed) {
+       case CHECKSUM_COMPLETE:
+               if (!tcp_v6_check(skb_gro_len(skb), &iph->saddr, &iph->daddr,
+                                 skb->csum)) {
+                       skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       break;
+               }
+flush:
+               NAPI_GRO_CB(skb)->flush = 1;
+               return NULL;
+
+       case CHECKSUM_NONE:
+               wsum = ~csum_unfold(csum_ipv6_magic(&iph->saddr, &iph->daddr,
+                                                   skb_gro_len(skb),
+                                                   IPPROTO_TCP, 0));
+               sum = csum_fold(skb_checksum(skb,
+                                            skb_gro_offset(skb),
+                                            skb_gro_len(skb),
+                                            wsum));
+               if (sum)
+                       goto flush;
+
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+               break;
+       }
+
+       return tcp_gro_receive(head, skb);
+}
+
+static int tcp6_gro_complete(struct sk_buff *skb)
+{
+       const struct ipv6hdr *iph = ipv6_hdr(skb);
+       struct tcphdr *th = tcp_hdr(skb);
+
+       th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb),
+                                 &iph->saddr, &iph->daddr, 0);
+       skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+
+       return tcp_gro_complete(skb);
+}
+
+static const struct net_offload tcpv6_offload = {
+       .callbacks = {
+               .gso_send_check =       tcp_v6_gso_send_check,
+               .gso_segment    =       tcp_tso_segment,
+               .gro_receive    =       tcp6_gro_receive,
+               .gro_complete   =       tcp6_gro_complete,
+       },
+};
+
+int __init tcpv6_offload_init(void)
+{
+       return inet6_add_offload(&tcpv6_offload, IPPROTO_TCP);
+}
index fc9997260a6bc5b841aafc4f3b57cf11ff7ec404..dfaa29b8b2939c03fef13fa416f6fdaef031bf5d 100644 (file)
@@ -1343,103 +1343,9 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
 }
 #endif
 
-static int udp6_ufo_send_check(struct sk_buff *skb)
-{
-       const struct ipv6hdr *ipv6h;
-       struct udphdr *uh;
-
-       if (!pskb_may_pull(skb, sizeof(*uh)))
-               return -EINVAL;
-
-       ipv6h = ipv6_hdr(skb);
-       uh = udp_hdr(skb);
-
-       uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
-                                    IPPROTO_UDP, 0);
-       skb->csum_start = skb_transport_header(skb) - skb->head;
-       skb->csum_offset = offsetof(struct udphdr, check);
-       skb->ip_summed = CHECKSUM_PARTIAL;
-       return 0;
-}
-
-static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
-       netdev_features_t features)
-{
-       struct sk_buff *segs = ERR_PTR(-EINVAL);
-       unsigned int mss;
-       unsigned int unfrag_ip6hlen, unfrag_len;
-       struct frag_hdr *fptr;
-       u8 *mac_start, *prevhdr;
-       u8 nexthdr;
-       u8 frag_hdr_sz = sizeof(struct frag_hdr);
-       int offset;
-       __wsum csum;
-
-       mss = skb_shinfo(skb)->gso_size;
-       if (unlikely(skb->len <= mss))
-               goto out;
-
-       if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
-               /* Packet is from an untrusted source, reset gso_segs. */
-               int type = skb_shinfo(skb)->gso_type;
-
-               if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
-                            !(type & (SKB_GSO_UDP))))
-                       goto out;
-
-               skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
-
-               segs = NULL;
-               goto out;
-       }
-
-       /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
-        * do checksum of UDP packets sent as multiple IP fragments.
-        */
-       offset = skb_checksum_start_offset(skb);
-       csum = skb_checksum(skb, offset, skb->len - offset, 0);
-       offset += skb->csum_offset;
-       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
-       skb->ip_summed = CHECKSUM_NONE;
-
-       /* Check if there is enough headroom to insert fragment header. */
-       if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
-           pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
-               goto out;
-
-       /* Find the unfragmentable header and shift it left by frag_hdr_sz
-        * bytes to insert fragment header.
-        */
-       unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
-       nexthdr = *prevhdr;
-       *prevhdr = NEXTHDR_FRAGMENT;
-       unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
-                    unfrag_ip6hlen;
-       mac_start = skb_mac_header(skb);
-       memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
-
-       skb->mac_header -= frag_hdr_sz;
-       skb->network_header -= frag_hdr_sz;
-
-       fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
-       fptr->nexthdr = nexthdr;
-       fptr->reserved = 0;
-       ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
-
-       /* Fragment the skb. ipv6 header and the remaining fields of the
-        * fragment header are updated in ipv6_gso_segment()
-        */
-       segs = skb_segment(skb, features);
-
-out:
-       return segs;
-}
-
 static const struct inet6_protocol udpv6_protocol = {
        .handler        =       udpv6_rcv,
        .err_handler    =       udpv6_err,
-       .gso_send_check =       udp6_ufo_send_check,
-       .gso_segment    =       udp6_ufo_fragment,
        .flags          =       INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
new file mode 100644 (file)
index 0000000..0c8934a
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ *     IPV6 GSO/GRO offload support
+ *     Linux INET6 implementation
+ *
+ *     This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ *
+ *      UDPv6 GSO support
+ */
+#include <linux/skbuff.h>
+#include <net/protocol.h>
+#include <net/ipv6.h>
+#include <net/udp.h>
+#include <net/ip6_checksum.h>
+#include "ip6_offload.h"
+
+static int udp6_ufo_send_check(struct sk_buff *skb)
+{
+       const struct ipv6hdr *ipv6h;
+       struct udphdr *uh;
+
+       if (!pskb_may_pull(skb, sizeof(*uh)))
+               return -EINVAL;
+
+       ipv6h = ipv6_hdr(skb);
+       uh = udp_hdr(skb);
+
+       uh->check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, skb->len,
+                                    IPPROTO_UDP, 0);
+       skb->csum_start = skb_transport_header(skb) - skb->head;
+       skb->csum_offset = offsetof(struct udphdr, check);
+       skb->ip_summed = CHECKSUM_PARTIAL;
+       return 0;
+}
+
+static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
+       netdev_features_t features)
+{
+       struct sk_buff *segs = ERR_PTR(-EINVAL);
+       unsigned int mss;
+       unsigned int unfrag_ip6hlen, unfrag_len;
+       struct frag_hdr *fptr;
+       u8 *mac_start, *prevhdr;
+       u8 nexthdr;
+       u8 frag_hdr_sz = sizeof(struct frag_hdr);
+       int offset;
+       __wsum csum;
+
+       mss = skb_shinfo(skb)->gso_size;
+       if (unlikely(skb->len <= mss))
+               goto out;
+
+       if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+               /* Packet is from an untrusted source, reset gso_segs. */
+               int type = skb_shinfo(skb)->gso_type;
+
+               if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY) ||
+                            !(type & (SKB_GSO_UDP))))
+                       goto out;
+
+               skb_shinfo(skb)->gso_segs = DIV_ROUND_UP(skb->len, mss);
+
+               segs = NULL;
+               goto out;
+       }
+
+       /* Do software UFO. Complete and fill in the UDP checksum as HW cannot
+        * do checksum of UDP packets sent as multiple IP fragments.
+        */
+       offset = skb_checksum_start_offset(skb);
+       csum = skb_checksum(skb, offset, skb->len - offset, 0);
+       offset += skb->csum_offset;
+       *(__sum16 *)(skb->data + offset) = csum_fold(csum);
+       skb->ip_summed = CHECKSUM_NONE;
+
+       /* Check if there is enough headroom to insert fragment header. */
+       if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
+           pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
+               goto out;
+
+       /* Find the unfragmentable header and shift it left by frag_hdr_sz
+        * bytes to insert fragment header.
+        */
+       unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+       nexthdr = *prevhdr;
+       *prevhdr = NEXTHDR_FRAGMENT;
+       unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
+                    unfrag_ip6hlen;
+       mac_start = skb_mac_header(skb);
+       memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
+
+       skb->mac_header -= frag_hdr_sz;
+       skb->network_header -= frag_hdr_sz;
+
+       fptr = (struct frag_hdr *)(skb_network_header(skb) + unfrag_ip6hlen);
+       fptr->nexthdr = nexthdr;
+       fptr->reserved = 0;
+       ipv6_select_ident(fptr, (struct rt6_info *)skb_dst(skb));
+
+       /* Fragment the skb. ipv6 header and the remaining fields of the
+        * fragment header are updated in ipv6_gso_segment()
+        */
+       segs = skb_segment(skb, features);
+
+out:
+       return segs;
+}
+static const struct net_offload udpv6_offload = {
+       .callbacks = {
+               .gso_send_check =       udp6_ufo_send_check,
+               .gso_segment    =       udp6_ufo_fragment,
+       },
+};
+
+int __init udp_offload_init(void)
+{
+       return inet6_add_offload(&udpv6_offload, IPPROTO_UDP);
+}
index f8c4c08ffb609d2840adb721e395fcbe99a636d7..c9844135c9caea041bd9a680e39da7bba4cf0997 100644 (file)
@@ -20,7 +20,7 @@
 #include <net/ip.h>
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
 #include <net/mip6.h>
 #endif
 
@@ -182,7 +182,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
                        fl6->flowi6_proto = nexthdr;
                        return;
 
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
                case IPPROTO_MH:
                        if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) {
                                struct ip6_mh *mh;
@@ -327,21 +327,7 @@ static struct ctl_table_header *sysctl_hdr;
 int __init xfrm6_init(void)
 {
        int ret;
-       unsigned int gc_thresh;
-
-       /*
-        * We need a good default value for the xfrm6 gc threshold.
-        * In ipv4 we set it to the route hash table size * 8, which
-        * is half the size of the maximaum route cache for ipv4.  It
-        * would be good to do the same thing for v6, except the table is
-        * constructed differently here.  Here each table for a net namespace
-        * can have FIB_TABLE_HASHSZ entries, so lets go with the same
-        * computation that we used for ipv4 here.  Also, lets keep the initial
-        * gc_thresh to a minimum of 1024, since, the ipv6 route cache defaults
-        * to that as a minimum as well
-        */
-       gc_thresh = FIB6_TABLE_HASHSZ * 8;
-       xfrm6_dst_ops.gc_thresh = (gc_thresh < 1024) ? 1024 : gc_thresh;
+
        dst_entries_init(&xfrm6_dst_ops);
 
        ret = xfrm6_policy_init();
@@ -370,7 +356,6 @@ void xfrm6_fini(void)
        if (sysctl_hdr)
                unregister_net_sysctl_table(sysctl_hdr);
 #endif
-       //xfrm6_input_fini();
        xfrm6_policy_fini();
        xfrm6_state_fini();
        dst_entries_destroy(&xfrm6_dst_ops);
index 3f2f7c4ab7210d5948c22a6e417bc0046b1631b0..d8c70b8efc24231358ab50a32f354b69064f7860 100644 (file)
@@ -101,7 +101,7 @@ static int __xfrm6_state_sort_cmp(void *p)
                        return 1;
                else
                        return 3;
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
        case XFRM_MODE_ROUTEOPTIMIZATION:
        case XFRM_MODE_IN_TRIGGER:
                return 2;
@@ -134,7 +134,7 @@ static int __xfrm6_tmpl_sort_cmp(void *p)
        switch (v->mode) {
        case XFRM_MODE_TRANSPORT:
                return 1;
-#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6_MIP6)
        case XFRM_MODE_ROUTEOPTIMIZATION:
        case XFRM_MODE_IN_TRIGGER:
                return 2;
index 95a3a7a336ba86a0b8b3790a7ce8e722f17db1a2..496ce2cebcd7316f7a1eab1051758e2f90b22263 100644 (file)
@@ -421,6 +421,8 @@ static int ircomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
                hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL);
        }
 
+       tty->driver_data = self;
+
        return tty_port_install(&self->port, driver, tty);
 }
 
index 1002e3396f7287049b41c53e4aaa5cdc285a73e6..ae43c62f9045ba94ced0f025a9ecacb3bf145af1 100644 (file)
@@ -441,6 +441,7 @@ struct tsap_cb *irttp_open_tsap(__u8 stsap_sel, int credit, notify_t *notify)
        lsap = irlmp_open_lsap(stsap_sel, &ttp_notify, 0);
        if (lsap == NULL) {
                IRDA_DEBUG(0, "%s: unable to allocate LSAP!!\n", __func__);
+               __irttp_close_tsap(self);
                return NULL;
        }
 
index 08897a3c7ec764550d518777811fa8e3179a9492..5b426a6465447f954a4b4728f72a6c00966c91ee 100644 (file)
@@ -141,7 +141,7 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol,
        struct sock *sk;
        int err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
        if (sock->type != SOCK_RAW)
                return -ESOCKTNOSUPPORT;
index 37b8b8ba31f7395001cd2f36e234d82878bc22c7..76125c57ee6dddd2396a8a0bef4f19e7720e43ed 100644 (file)
@@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p
 
 out_del_dev:
        free_netdev(dev);
+       spriv->dev = NULL;
 out_del_session:
        l2tp_session_delete(session);
 out:
index 6c4cc12c7414f90341513a29da3097f4c9f9ecb4..bbba3a19e94457378fad759edbe04392f93c1256 100644 (file)
@@ -632,7 +632,7 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl
             nla_put_u16(skb, L2TP_ATTR_MRU, session->mru)))
                goto nla_put_failure;
 
-       if ((session->ifname && session->ifname[0] &&
+       if ((session->ifname[0] &&
             nla_put_string(skb, L2TP_ATTR_IFNAME, session->ifname)) ||
            (session->cookie_len &&
             nla_put(skb, L2TP_ATTR_COOKIE, session->cookie_len,
index c2190005a11410e2f95141fb841dadc051157a8b..88709882c4641f7d147fbeaa9f48323cfc8637eb 100644 (file)
@@ -160,7 +160,7 @@ static int llc_ui_create(struct net *net, struct socket *sock, int protocol,
        struct sock *sk;
        int rc = -ESOCKTNOSUPPORT;
 
-       if (!capable(CAP_NET_RAW))
+       if (!ns_capable(net->user_ns, CAP_NET_RAW))
                return -EPERM;
 
        if (!net_eq(net, &init_net))
index 49a1c70bbd706232cc66b688391dbaf7a908b6d6..6fb1168b9f16dabb5f35f8315f28ee8d10d4820c 100644 (file)
@@ -220,7 +220,9 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
        } else
                return -EINVAL;
 
-       tid = simple_strtoul(buf, NULL, 0);
+       ret = kstrtoul(buf, 0, &tid);
+       if (ret)
+               return ret;
 
        if (tid >= IEEE80211_NUM_TIDS)
                return -EINVAL;
index 1a4df39c722e3d0b871105ea0ff30099a1ed37a1..4e09d070995a129a065b33eb15c0c729913b4365 100644 (file)
@@ -85,6 +85,7 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
 
        if (!(priv->phy->channels_supported[page] & (1 << chan))) {
                WARN_ON(1);
+               kfree_skb(skb);
                return NETDEV_TX_OK;
        }
 
@@ -98,13 +99,15 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
        }
 
        if (skb_cow_head(skb, priv->hw.extra_tx_headroom)) {
-               dev_kfree_skb(skb);
+               kfree_skb(skb);
                return NETDEV_TX_OK;
        }
 
        work = kzalloc(sizeof(struct xmit_work), GFP_ATOMIC);
-       if (!work)
+       if (!work) {
+               kfree_skb(skb);
                return NETDEV_TX_BUSY;
+       }
 
        INIT_WORK(&work->work, mac802154_xmit_worker);
        work->skb = skb;
index f30f6d4beea178ed46750131e5840decd8c5238a..1191039c2b1bc38bda25402dd395d7e3b1bbe7b4 100644 (file)
@@ -327,8 +327,10 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (chan == MAC802154_CHAN_NONE ||
            page >= WPAN_NUM_PAGES ||
-           chan >= WPAN_NUM_CHANNELS)
+           chan >= WPAN_NUM_CHANNELS) {
+               kfree_skb(skb);
                return NETDEV_TX_OK;
+       }
 
        skb->skb_iif = dev->ifindex;
        dev->stats.tx_packets++;
index 68912dadf13d15c0354bec108039176b9659c75a..a9c488b6c50d446e1c9e5276553728af83281fad 100644 (file)
@@ -295,8 +295,6 @@ void __init netfilter_init(void)
                panic("cannot create netfilter proc entry");
 #endif
 
-       if (netfilter_queue_init() < 0)
-               panic("cannot initialize nf_queue");
        if (netfilter_log_init() < 0)
                panic("cannot initialize nf_log");
 }
index 778465f217fa975c39af6fb3d7429214dbfe2a51..6d6d8f2b033e0505f88648b9646d3963d3aa10e0 100644 (file)
@@ -28,9 +28,10 @@ static LIST_HEAD(ip_set_type_list);          /* all registered set types */
 static DEFINE_MUTEX(ip_set_type_mutex);                /* protects ip_set_type_list */
 static DEFINE_RWLOCK(ip_set_ref_lock);         /* protects the set refs */
 
-static struct ip_set **ip_set_list;            /* all individual sets */
+static struct ip_set * __rcu *ip_set_list;     /* all individual sets */
 static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */
 
+#define IP_SET_INC     64
 #define STREQ(a, b)    (strncmp(a, b, IPSET_MAXNAMELEN) == 0)
 
 static unsigned int max_sets;
@@ -42,6 +43,12 @@ MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
 MODULE_DESCRIPTION("core IP set support");
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
 
+/* When the nfnl mutex is held: */
+#define nfnl_dereference(p)            \
+       rcu_dereference_protected(p, 1)
+#define nfnl_set(id)                   \
+       nfnl_dereference(ip_set_list)[id]
+
 /*
  * The set types are implemented in modules and registered set types
  * can be found in ip_set_type_list. Adding/deleting types is
@@ -321,19 +328,19 @@ EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
  */
 
 static inline void
-__ip_set_get(ip_set_id_t index)
+__ip_set_get(struct ip_set *set)
 {
        write_lock_bh(&ip_set_ref_lock);
-       ip_set_list[index]->ref++;
+       set->ref++;
        write_unlock_bh(&ip_set_ref_lock);
 }
 
 static inline void
-__ip_set_put(ip_set_id_t index)
+__ip_set_put(struct ip_set *set)
 {
        write_lock_bh(&ip_set_ref_lock);
-       BUG_ON(ip_set_list[index]->ref == 0);
-       ip_set_list[index]->ref--;
+       BUG_ON(set->ref == 0);
+       set->ref--;
        write_unlock_bh(&ip_set_ref_lock);
 }
 
@@ -344,12 +351,25 @@ __ip_set_put(ip_set_id_t index)
  * so it can't be destroyed (or changed) under our foot.
  */
 
+static inline struct ip_set *
+ip_set_rcu_get(ip_set_id_t index)
+{
+       struct ip_set *set;
+
+       rcu_read_lock();
+       /* ip_set_list itself needs to be protected */
+       set = rcu_dereference(ip_set_list)[index];
+       rcu_read_unlock();
+
+       return set;
+}
+
 int
 ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
            const struct xt_action_param *par,
            const struct ip_set_adt_opt *opt)
 {
-       struct ip_set *set = ip_set_list[index];
+       struct ip_set *set = ip_set_rcu_get(index);
        int ret = 0;
 
        BUG_ON(set == NULL);
@@ -388,7 +408,7 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
           const struct xt_action_param *par,
           const struct ip_set_adt_opt *opt)
 {
-       struct ip_set *set = ip_set_list[index];
+       struct ip_set *set = ip_set_rcu_get(index);
        int ret;
 
        BUG_ON(set == NULL);
@@ -411,7 +431,7 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
           const struct xt_action_param *par,
           const struct ip_set_adt_opt *opt)
 {
-       struct ip_set *set = ip_set_list[index];
+       struct ip_set *set = ip_set_rcu_get(index);
        int ret = 0;
 
        BUG_ON(set == NULL);
@@ -440,14 +460,17 @@ ip_set_get_byname(const char *name, struct ip_set **set)
        ip_set_id_t i, index = IPSET_INVALID_ID;
        struct ip_set *s;
 
+       rcu_read_lock();
        for (i = 0; i < ip_set_max; i++) {
-               s = ip_set_list[i];
+               s = rcu_dereference(ip_set_list)[i];
                if (s != NULL && STREQ(s->name, name)) {
-                       __ip_set_get(i);
+                       __ip_set_get(s);
                        index = i;
                        *set = s;
+                       break;
                }
        }
+       rcu_read_unlock();
 
        return index;
 }
@@ -462,8 +485,13 @@ EXPORT_SYMBOL_GPL(ip_set_get_byname);
 void
 ip_set_put_byindex(ip_set_id_t index)
 {
-       if (ip_set_list[index] != NULL)
-               __ip_set_put(index);
+       struct ip_set *set;
+
+       rcu_read_lock();
+       set = rcu_dereference(ip_set_list)[index];
+       if (set != NULL)
+               __ip_set_put(set);
+       rcu_read_unlock();
 }
 EXPORT_SYMBOL_GPL(ip_set_put_byindex);
 
@@ -477,7 +505,7 @@ EXPORT_SYMBOL_GPL(ip_set_put_byindex);
 const char *
 ip_set_name_byindex(ip_set_id_t index)
 {
-       const struct ip_set *set = ip_set_list[index];
+       const struct ip_set *set = ip_set_rcu_get(index);
 
        BUG_ON(set == NULL);
        BUG_ON(set->ref == 0);
@@ -501,11 +529,18 @@ EXPORT_SYMBOL_GPL(ip_set_name_byindex);
 ip_set_id_t
 ip_set_nfnl_get(const char *name)
 {
+       ip_set_id_t i, index = IPSET_INVALID_ID;
        struct ip_set *s;
-       ip_set_id_t index;
 
        nfnl_lock();
-       index = ip_set_get_byname(name, &s);
+       for (i = 0; i < ip_set_max; i++) {
+               s = nfnl_set(i);
+               if (s != NULL && STREQ(s->name, name)) {
+                       __ip_set_get(s);
+                       index = i;
+                       break;
+               }
+       }
        nfnl_unlock();
 
        return index;
@@ -521,12 +556,15 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_get);
 ip_set_id_t
 ip_set_nfnl_get_byindex(ip_set_id_t index)
 {
+       struct ip_set *set;
+
        if (index > ip_set_max)
                return IPSET_INVALID_ID;
 
        nfnl_lock();
-       if (ip_set_list[index])
-               __ip_set_get(index);
+       set = nfnl_set(index);
+       if (set)
+               __ip_set_get(set);
        else
                index = IPSET_INVALID_ID;
        nfnl_unlock();
@@ -545,8 +583,11 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
 void
 ip_set_nfnl_put(ip_set_id_t index)
 {
+       struct ip_set *set;
        nfnl_lock();
-       ip_set_put_byindex(index);
+       set = nfnl_set(index);
+       if (set != NULL)
+               __ip_set_put(set);
        nfnl_unlock();
 }
 EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
@@ -603,41 +644,46 @@ static const struct nla_policy ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] = {
        [IPSET_ATTR_DATA]       = { .type = NLA_NESTED },
 };
 
-static ip_set_id_t
-find_set_id(const char *name)
+static struct ip_set *
+find_set_and_id(const char *name, ip_set_id_t *id)
 {
-       ip_set_id_t i, index = IPSET_INVALID_ID;
-       const struct ip_set *set;
+       struct ip_set *set = NULL;
+       ip_set_id_t i;
 
-       for (i = 0; index == IPSET_INVALID_ID && i < ip_set_max; i++) {
-               set = ip_set_list[i];
-               if (set != NULL && STREQ(set->name, name))
-                       index = i;
+       *id = IPSET_INVALID_ID;
+       for (i = 0; i < ip_set_max; i++) {
+               set = nfnl_set(i);
+               if (set != NULL && STREQ(set->name, name)) {
+                       *id = i;
+                       break;
+               }
        }
-       return index;
+       return (*id == IPSET_INVALID_ID ? NULL : set);
 }
 
 static inline struct ip_set *
 find_set(const char *name)
 {
-       ip_set_id_t index = find_set_id(name);
+       ip_set_id_t id;
 
-       return index == IPSET_INVALID_ID ? NULL : ip_set_list[index];
+       return find_set_and_id(name, &id);
 }
 
 static int
 find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set)
 {
+       struct ip_set *s;
        ip_set_id_t i;
 
        *index = IPSET_INVALID_ID;
        for (i = 0;  i < ip_set_max; i++) {
-               if (ip_set_list[i] == NULL) {
+               s = nfnl_set(i);
+               if (s == NULL) {
                        if (*index == IPSET_INVALID_ID)
                                *index = i;
-               } else if (STREQ(name, ip_set_list[i]->name)) {
+               } else if (STREQ(name, s->name)) {
                        /* Name clash */
-                       *set = ip_set_list[i];
+                       *set = s;
                        return -EEXIST;
                }
        }
@@ -730,10 +776,9 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
         * and check clashing.
         */
        ret = find_free_id(set->name, &index, &clash);
-       if (ret != 0) {
+       if (ret == -EEXIST) {
                /* If this is the same set and requested, ignore error */
-               if (ret == -EEXIST &&
-                   (flags & IPSET_FLAG_EXIST) &&
+               if ((flags & IPSET_FLAG_EXIST) &&
                    STREQ(set->type->name, clash->type->name) &&
                    set->type->family == clash->type->family &&
                    set->type->revision_min == clash->type->revision_min &&
@@ -741,13 +786,36 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
                    set->variant->same_set(set, clash))
                        ret = 0;
                goto cleanup;
-       }
+       } else if (ret == -IPSET_ERR_MAX_SETS) {
+               struct ip_set **list, **tmp;
+               ip_set_id_t i = ip_set_max + IP_SET_INC;
+
+               if (i < ip_set_max || i == IPSET_INVALID_ID)
+                       /* Wraparound */
+                       goto cleanup;
+
+               list = kzalloc(sizeof(struct ip_set *) * i, GFP_KERNEL);
+               if (!list)
+                       goto cleanup;
+               /* nfnl mutex is held, both lists are valid */
+               tmp = nfnl_dereference(ip_set_list);
+               memcpy(list, tmp, sizeof(struct ip_set *) * ip_set_max);
+               rcu_assign_pointer(ip_set_list, list);
+               /* Make sure all current packets have passed through */
+               synchronize_net();
+               /* Use new list */
+               index = ip_set_max;
+               ip_set_max = i;
+               kfree(tmp);
+               ret = 0;
+       } else if (ret)
+               goto cleanup;
 
        /*
         * Finally! Add our shiny new set to the list, and be done.
         */
        pr_debug("create: '%s' created with index %u!\n", set->name, index);
-       ip_set_list[index] = set;
+       nfnl_set(index) = set;
 
        return ret;
 
@@ -772,10 +840,10 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
 static void
 ip_set_destroy_set(ip_set_id_t index)
 {
-       struct ip_set *set = ip_set_list[index];
+       struct ip_set *set = nfnl_set(index);
 
        pr_debug("set: %s\n",  set->name);
-       ip_set_list[index] = NULL;
+       nfnl_set(index) = NULL;
 
        /* Must call it without holding any lock */
        set->variant->destroy(set);
@@ -788,6 +856,7 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
               const struct nlmsghdr *nlh,
               const struct nlattr * const attr[])
 {
+       struct ip_set *s;
        ip_set_id_t i;
        int ret = 0;
 
@@ -807,22 +876,24 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
        read_lock_bh(&ip_set_ref_lock);
        if (!attr[IPSET_ATTR_SETNAME]) {
                for (i = 0; i < ip_set_max; i++) {
-                       if (ip_set_list[i] != NULL && ip_set_list[i]->ref) {
+                       s = nfnl_set(i);
+                       if (s != NULL && s->ref) {
                                ret = -IPSET_ERR_BUSY;
                                goto out;
                        }
                }
                read_unlock_bh(&ip_set_ref_lock);
                for (i = 0; i < ip_set_max; i++) {
-                       if (ip_set_list[i] != NULL)
+                       s = nfnl_set(i);
+                       if (s != NULL)
                                ip_set_destroy_set(i);
                }
        } else {
-               i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
-               if (i == IPSET_INVALID_ID) {
+               s = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME]), &i);
+               if (s == NULL) {
                        ret = -ENOENT;
                        goto out;
-               } else if (ip_set_list[i]->ref) {
+               } else if (s->ref) {
                        ret = -IPSET_ERR_BUSY;
                        goto out;
                }
@@ -853,21 +924,24 @@ ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
             const struct nlmsghdr *nlh,
             const struct nlattr * const attr[])
 {
+       struct ip_set *s;
        ip_set_id_t i;
 
        if (unlikely(protocol_failed(attr)))
                return -IPSET_ERR_PROTOCOL;
 
        if (!attr[IPSET_ATTR_SETNAME]) {
-               for (i = 0; i < ip_set_max; i++)
-                       if (ip_set_list[i] != NULL)
-                               ip_set_flush_set(ip_set_list[i]);
+               for (i = 0; i < ip_set_max; i++) {
+                       s = nfnl_set(i);
+                       if (s != NULL)
+                               ip_set_flush_set(s);
+               }
        } else {
-               i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
-               if (i == IPSET_INVALID_ID)
+               s = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
+               if (s == NULL)
                        return -ENOENT;
 
-               ip_set_flush_set(ip_set_list[i]);
+               ip_set_flush_set(s);
        }
 
        return 0;
@@ -889,7 +963,7 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
              const struct nlmsghdr *nlh,
              const struct nlattr * const attr[])
 {
-       struct ip_set *set;
+       struct ip_set *set, *s;
        const char *name2;
        ip_set_id_t i;
        int ret = 0;
@@ -911,8 +985,8 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
 
        name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
        for (i = 0; i < ip_set_max; i++) {
-               if (ip_set_list[i] != NULL &&
-                   STREQ(ip_set_list[i]->name, name2)) {
+               s = nfnl_set(i);
+               if (s != NULL && STREQ(s->name, name2)) {
                        ret = -IPSET_ERR_EXIST_SETNAME2;
                        goto out;
                }
@@ -947,17 +1021,14 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
                     attr[IPSET_ATTR_SETNAME2] == NULL))
                return -IPSET_ERR_PROTOCOL;
 
-       from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
-       if (from_id == IPSET_INVALID_ID)
+       from = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME]), &from_id);
+       if (from == NULL)
                return -ENOENT;
 
-       to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2]));
-       if (to_id == IPSET_INVALID_ID)
+       to = find_set_and_id(nla_data(attr[IPSET_ATTR_SETNAME2]), &to_id);
+       if (to == NULL)
                return -IPSET_ERR_EXIST_SETNAME2;
 
-       from = ip_set_list[from_id];
-       to = ip_set_list[to_id];
-
        /* Features must not change.
         * Not an artificial restriction anymore, as we must prevent
         * possible loops created by swapping in setlist type of sets. */
@@ -971,8 +1042,8 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
 
        write_lock_bh(&ip_set_ref_lock);
        swap(from->ref, to->ref);
-       ip_set_list[from_id] = to;
-       ip_set_list[to_id] = from;
+       nfnl_set(from_id) = to;
+       nfnl_set(to_id) = from;
        write_unlock_bh(&ip_set_ref_lock);
 
        return 0;
@@ -992,7 +1063,7 @@ static int
 ip_set_dump_done(struct netlink_callback *cb)
 {
        if (cb->args[2]) {
-               pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name);
+               pr_debug("release set %s\n", nfnl_set(cb->args[1])->name);
                ip_set_put_byindex((ip_set_id_t) cb->args[1]);
        }
        return 0;
@@ -1030,8 +1101,11 @@ dump_init(struct netlink_callback *cb)
         */
 
        if (cda[IPSET_ATTR_SETNAME]) {
-               index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
-               if (index == IPSET_INVALID_ID)
+               struct ip_set *set;
+
+               set = find_set_and_id(nla_data(cda[IPSET_ATTR_SETNAME]),
+                                     &index);
+               if (set == NULL)
                        return -ENOENT;
 
                dump_type = DUMP_ONE;
@@ -1081,7 +1155,7 @@ dump_last:
                 dump_type, dump_flags, cb->args[1]);
        for (; cb->args[1] < max; cb->args[1]++) {
                index = (ip_set_id_t) cb->args[1];
-               set = ip_set_list[index];
+               set = nfnl_set(index);
                if (set == NULL) {
                        if (dump_type == DUMP_ONE) {
                                ret = -ENOENT;
@@ -1100,7 +1174,7 @@ dump_last:
                if (!cb->args[2]) {
                        /* Start listing: make sure set won't be destroyed */
                        pr_debug("reference set\n");
-                       __ip_set_get(index);
+                       __ip_set_get(set);
                }
                nlh = start_msg(skb, NETLINK_CB(cb->skb).portid,
                                cb->nlh->nlmsg_seq, flags,
@@ -1159,7 +1233,7 @@ next_set:
 release_refcount:
        /* If there was an error or set is done, release set */
        if (ret || !cb->args[2]) {
-               pr_debug("release set %s\n", ip_set_list[index]->name);
+               pr_debug("release set %s\n", nfnl_set(index)->name);
                ip_set_put_byindex(index);
                cb->args[2] = 0;
        }
@@ -1409,17 +1483,15 @@ ip_set_header(struct sock *ctnl, struct sk_buff *skb,
        const struct ip_set *set;
        struct sk_buff *skb2;
        struct nlmsghdr *nlh2;
-       ip_set_id_t index;
        int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
                     attr[IPSET_ATTR_SETNAME] == NULL))
                return -IPSET_ERR_PROTOCOL;
 
-       index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
-       if (index == IPSET_INVALID_ID)
+       set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
+       if (set == NULL)
                return -ENOENT;
-       set = ip_set_list[index];
 
        skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (skb2 == NULL)
@@ -1643,7 +1715,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
        void *data;
        int copylen = *len, ret = 0;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
        if (optval != SO_IP_SET)
                return -EBADF;
@@ -1684,6 +1756,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
        }
        case IP_SET_OP_GET_BYNAME: {
                struct ip_set_req_get_set *req_get = data;
+               ip_set_id_t id;
 
                if (*len != sizeof(struct ip_set_req_get_set)) {
                        ret = -EINVAL;
@@ -1691,12 +1764,14 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
                }
                req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
                nfnl_lock();
-               req_get->set.index = find_set_id(req_get->set.name);
+               find_set_and_id(req_get->set.name, &id);
+               req_get->set.index = id;
                nfnl_unlock();
                goto copy;
        }
        case IP_SET_OP_GET_BYINDEX: {
                struct ip_set_req_get_set *req_get = data;
+               struct ip_set *set;
 
                if (*len != sizeof(struct ip_set_req_get_set) ||
                    req_get->set.index >= ip_set_max) {
@@ -1704,9 +1779,8 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
                        goto done;
                }
                nfnl_lock();
-               strncpy(req_get->set.name,
-                       ip_set_list[req_get->set.index]
-                               ? ip_set_list[req_get->set.index]->name : "",
+               set = nfnl_set(req_get->set.index);
+               strncpy(req_get->set.name, set ? set->name : "",
                        IPSET_MAXNAMELEN);
                nfnl_unlock();
                goto copy;
@@ -1737,6 +1811,7 @@ static struct nf_sockopt_ops so_set __read_mostly = {
 static int __init
 ip_set_init(void)
 {
+       struct ip_set **list;
        int ret;
 
        if (max_sets)
@@ -1744,22 +1819,22 @@ ip_set_init(void)
        if (ip_set_max >= IPSET_INVALID_ID)
                ip_set_max = IPSET_INVALID_ID - 1;
 
-       ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max,
-                             GFP_KERNEL);
-       if (!ip_set_list)
+       list = kzalloc(sizeof(struct ip_set *) * ip_set_max, GFP_KERNEL);
+       if (!list)
                return -ENOMEM;
 
+       rcu_assign_pointer(ip_set_list, list);
        ret = nfnetlink_subsys_register(&ip_set_netlink_subsys);
        if (ret != 0) {
                pr_err("ip_set: cannot register with nfnetlink.\n");
-               kfree(ip_set_list);
+               kfree(list);
                return ret;
        }
        ret = nf_register_sockopt(&so_set);
        if (ret != 0) {
                pr_err("SO_SET registry failed: %d\n", ret);
                nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
-               kfree(ip_set_list);
+               kfree(list);
                return ret;
        }
 
@@ -1770,10 +1845,12 @@ ip_set_init(void)
 static void __exit
 ip_set_fini(void)
 {
+       struct ip_set **list = rcu_dereference_protected(ip_set_list, 1);
+
        /* There can't be any existing set */
        nf_unregister_sockopt(&so_set);
        nfnetlink_subsys_unregister(&ip_set_netlink_subsys);
-       kfree(ip_set_list);
+       kfree(list);
        pr_debug("these are the famous last words\n");
 }
 
index ec3dba5dcd62f081c1749fb60f2aa71cd31d11ad..5c0b78528e55b1af2288aa2e1a398202131413d5 100644 (file)
@@ -173,6 +173,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                return adtfn(set, &nip, timeout, flags);
        }
 
+       ip_to = ip;
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -185,8 +186,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
index 0171f7502fa58d035fcda2361a6c4968acf09b7b..6283351f4eebee920c2939613ff05676b16f91ad 100644 (file)
@@ -162,7 +162,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipport4_elem data = { };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -210,7 +210,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
-       ip = ntohl(data.ip);
+       ip_to = ip = ntohl(data.ip);
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -223,8 +223,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        port_to = port = ntohs(data.port);
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
index 6344ef551ec811208b79ddc54c89a1270c2419cd..6a21271c8d5a9f5da822c9789d55b761924d6da5 100644 (file)
@@ -166,7 +166,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportip4_elem data = { };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -218,7 +218,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
-       ip = ntohl(data.ip);
+       ip_to = ip = ntohl(data.ip);
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -231,8 +231,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        port_to = port = ntohs(data.port);
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
index cb71f9a774e7d50d67998aaaadc199a563f43f40..2d5cd4ee30eb4d5872b4aa9be7199a3d8999f6c7 100644 (file)
@@ -215,8 +215,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
-       u32 ip2_from = 0, ip2_to, ip2_last, ip2;
+       u32 ip, ip_to, p = 0, port, port_to;
+       u32 ip2_from, ip2_to, ip2_last, ip2;
        u32 timeout = h->timeout;
        bool with_ports = false;
        u8 cidr;
@@ -286,6 +286,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
+       ip_to = ip;
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -306,6 +307,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (port > port_to)
                        swap(port, port_to);
        }
+
+       ip2_to = ip2_from;
        if (tb[IPSET_ATTR_IP2_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
                if (ret)
index b9a63381e34998e08ab5271f7d82cca9058a76d8..45a101439bc5dc62798e62b1516b78a9d8096272 100644 (file)
@@ -793,7 +793,7 @@ static struct ip_set_type hash_netiface_type __read_mostly = {
                [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
                [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
                [IPSET_ATTR_IFACE]      = { .type = NLA_NUL_STRING,
-                                           .len = IPSET_MAXNAMELEN - 1 },
+                                           .len  = IFNAMSIZ - 1 },
                [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
                [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
                [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
index 8b2cffdfdd9985e7397a0b800d5e2c28af20a4b7..0c3b1670b0d164cddf2e80717a89737821fd2b3b 100644 (file)
@@ -28,12 +28,11 @@ if IP_VS
 config IP_VS_IPV6
        bool "IPv6 support for IPVS"
        depends on IPV6 = y || IP_VS = IPV6
+       select IP6_NF_IPTABLES
        ---help---
-         Add IPv6 support to IPVS. This is incomplete and might be dangerous.
+         Add IPv6 support to IPVS.
 
-         See http://www.mindbasket.com/ipvs for more information.
-
-         Say N if unsure.
+         Say Y if unsure.
 
 config IP_VS_DEBUG
        bool "IP virtual server debugging"
index 1548df9a7524af0f61b0ed65bd6e1cc3d4731d09..30e764ad021f75bea322afa2799f434bb97833fa 100644 (file)
@@ -308,13 +308,12 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct ip_vs_conn_param *p)
 static int
 ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
                            const struct ip_vs_iphdr *iph,
-                           unsigned int proto_off, int inverse,
-                           struct ip_vs_conn_param *p)
+                           int inverse, struct ip_vs_conn_param *p)
 {
        __be16 _ports[2], *pptr;
        struct net *net = skb_net(skb);
 
-       pptr = skb_header_pointer(skb, proto_off, sizeof(_ports), _ports);
+       pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
        if (pptr == NULL)
                return 1;
 
@@ -329,12 +328,11 @@ ip_vs_conn_fill_param_proto(int af, const struct sk_buff *skb,
 
 struct ip_vs_conn *
 ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
-                       const struct ip_vs_iphdr *iph,
-                       unsigned int proto_off, int inverse)
+                       const struct ip_vs_iphdr *iph, int inverse)
 {
        struct ip_vs_conn_param p;
 
-       if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
+       if (ip_vs_conn_fill_param_proto(af, skb, iph, inverse, &p))
                return NULL;
 
        return ip_vs_conn_in_get(&p);
@@ -432,12 +430,11 @@ struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p)
 
 struct ip_vs_conn *
 ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
-                        const struct ip_vs_iphdr *iph,
-                        unsigned int proto_off, int inverse)
+                        const struct ip_vs_iphdr *iph, int inverse)
 {
        struct ip_vs_conn_param p;
 
-       if (ip_vs_conn_fill_param_proto(af, skb, iph, proto_off, inverse, &p))
+       if (ip_vs_conn_fill_param_proto(af, skb, iph, inverse, &p))
                return NULL;
 
        return ip_vs_conn_out_get(&p);
index 58918e20f9d5b038c2181b893b0e0458dbd3a8f2..47edf5a40a5939d2401dc11baa89142b9bcd64b6 100644 (file)
@@ -222,11 +222,10 @@ ip_vs_conn_fill_param_persist(const struct ip_vs_service *svc,
  */
 static struct ip_vs_conn *
 ip_vs_sched_persist(struct ip_vs_service *svc,
-                   struct sk_buff *skb,
-                   __be16 src_port, __be16 dst_port, int *ignored)
+                   struct sk_buff *skb, __be16 src_port, __be16 dst_port,
+                   int *ignored, struct ip_vs_iphdr *iph)
 {
        struct ip_vs_conn *cp = NULL;
-       struct ip_vs_iphdr iph;
        struct ip_vs_dest *dest;
        struct ip_vs_conn *ct;
        __be16 dport = 0;               /* destination port to forward */
@@ -236,20 +235,18 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
        union nf_inet_addr snet;        /* source network of the client,
                                           after masking */
 
-       ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
-
        /* Mask saddr with the netmask to adjust template granularity */
 #ifdef CONFIG_IP_VS_IPV6
        if (svc->af == AF_INET6)
-               ipv6_addr_prefix(&snet.in6, &iph.saddr.in6, svc->netmask);
+               ipv6_addr_prefix(&snet.in6, &iph->saddr.in6, svc->netmask);
        else
 #endif
-               snet.ip = iph.saddr.ip & svc->netmask;
+               snet.ip = iph->saddr.ip & svc->netmask;
 
        IP_VS_DBG_BUF(6, "p-schedule: src %s:%u dest %s:%u "
                      "mnet %s\n",
-                     IP_VS_DBG_ADDR(svc->af, &iph.saddr), ntohs(src_port),
-                     IP_VS_DBG_ADDR(svc->af, &iph.daddr), ntohs(dst_port),
+                     IP_VS_DBG_ADDR(svc->af, &iph->saddr), ntohs(src_port),
+                     IP_VS_DBG_ADDR(svc->af, &iph->daddr), ntohs(dst_port),
                      IP_VS_DBG_ADDR(svc->af, &snet));
 
        /*
@@ -266,8 +263,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
         * is created for other persistent services.
         */
        {
-               int protocol = iph.protocol;
-               const union nf_inet_addr *vaddr = &iph.daddr;
+               int protocol = iph->protocol;
+               const union nf_inet_addr *vaddr = &iph->daddr;
                __be16 vport = 0;
 
                if (dst_port == svc->port) {
@@ -342,14 +339,14 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
                dport = dest->port;
 
        flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
-                && iph.protocol == IPPROTO_UDP)?
+                && iph->protocol == IPPROTO_UDP) ?
                IP_VS_CONN_F_ONE_PACKET : 0;
 
        /*
         *    Create a new connection according to the template
         */
-       ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol, &iph.saddr,
-                             src_port, &iph.daddr, dst_port, &param);
+       ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr,
+                             src_port, &iph->daddr, dst_port, &param);
 
        cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest, skb->mark);
        if (cp == NULL) {
@@ -392,18 +389,20 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
  */
 struct ip_vs_conn *
 ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
-              struct ip_vs_proto_data *pd, int *ignored)
+              struct ip_vs_proto_data *pd, int *ignored,
+              struct ip_vs_iphdr *iph)
 {
        struct ip_vs_protocol *pp = pd->pp;
        struct ip_vs_conn *cp = NULL;
-       struct ip_vs_iphdr iph;
        struct ip_vs_dest *dest;
        __be16 _ports[2], *pptr;
        unsigned int flags;
 
        *ignored = 1;
-       ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
-       pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
+       /*
+        * IPv6 frags, only the first hit here.
+        */
+       pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
        if (pptr == NULL)
                return NULL;
 
@@ -423,7 +422,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
         *    Do not schedule replies from local real server.
         */
        if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
-           (cp = pp->conn_in_get(svc->af, skb, &iph, iph.len, 1))) {
+           (cp = pp->conn_in_get(svc->af, skb, iph, 1))) {
                IP_VS_DBG_PKT(12, svc->af, pp, skb, 0,
                              "Not scheduling reply for existing connection");
                __ip_vs_conn_put(cp);
@@ -434,7 +433,8 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
         *    Persistent service
         */
        if (svc->flags & IP_VS_SVC_F_PERSISTENT)
-               return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored);
+               return ip_vs_sched_persist(svc, skb, pptr[0], pptr[1], ignored,
+                                          iph);
 
        *ignored = 0;
 
@@ -456,7 +456,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
        }
 
        flags = (svc->flags & IP_VS_SVC_F_ONEPACKET
-                && iph.protocol == IPPROTO_UDP)?
+                && iph->protocol == IPPROTO_UDP) ?
                IP_VS_CONN_F_ONE_PACKET : 0;
 
        /*
@@ -465,9 +465,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
        {
                struct ip_vs_conn_param p;
 
-               ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol,
-                                     &iph.saddr, pptr[0], &iph.daddr, pptr[1],
-                                     &p);
+               ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
+                                     &iph->saddr, pptr[0], &iph->daddr,
+                                     pptr[1], &p);
                cp = ip_vs_conn_new(&p, &dest->addr,
                                    dest->port ? dest->port : pptr[1],
                                    flags, dest, skb->mark);
@@ -496,19 +496,16 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
  *  no destination is available for a new connection.
  */
 int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
-               struct ip_vs_proto_data *pd)
+               struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph)
 {
        __be16 _ports[2], *pptr;
-       struct ip_vs_iphdr iph;
 #ifdef CONFIG_SYSCTL
        struct net *net;
        struct netns_ipvs *ipvs;
        int unicast;
 #endif
 
-       ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
-
-       pptr = skb_header_pointer(skb, iph.len, sizeof(_ports), _ports);
+       pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
        if (pptr == NULL) {
                ip_vs_service_put(svc);
                return NF_DROP;
@@ -519,10 +516,10 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
 
 #ifdef CONFIG_IP_VS_IPV6
        if (svc->af == AF_INET6)
-               unicast = ipv6_addr_type(&iph.daddr.in6) & IPV6_ADDR_UNICAST;
+               unicast = ipv6_addr_type(&iph->daddr.in6) & IPV6_ADDR_UNICAST;
        else
 #endif
-               unicast = (inet_addr_type(net, iph.daddr.ip) == RTN_UNICAST);
+               unicast = (inet_addr_type(net, iph->daddr.ip) == RTN_UNICAST);
 
        /* if it is fwmark-based service, the cache_bypass sysctl is up
           and the destination is a non-local unicast, then create
@@ -532,7 +529,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
                int ret;
                struct ip_vs_conn *cp;
                unsigned int flags = (svc->flags & IP_VS_SVC_F_ONEPACKET &&
-                                     iph.protocol == IPPROTO_UDP)?
+                                     iph->protocol == IPPROTO_UDP) ?
                                      IP_VS_CONN_F_ONE_PACKET : 0;
                union nf_inet_addr daddr =  { .all = { 0, 0, 0, 0 } };
 
@@ -542,9 +539,9 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
                IP_VS_DBG(6, "%s(): create a cache_bypass entry\n", __func__);
                {
                        struct ip_vs_conn_param p;
-                       ip_vs_conn_fill_param(svc->net, svc->af, iph.protocol,
-                                             &iph.saddr, pptr[0],
-                                             &iph.daddr, pptr[1], &p);
+                       ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
+                                             &iph->saddr, pptr[0],
+                                             &iph->daddr, pptr[1], &p);
                        cp = ip_vs_conn_new(&p, &daddr, 0,
                                            IP_VS_CONN_F_BYPASS | flags,
                                            NULL, skb->mark);
@@ -559,7 +556,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
                ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
 
                /* transmit the first SYN packet */
-               ret = cp->packet_xmit(skb, cp, pd->pp);
+               ret = cp->packet_xmit(skb, cp, pd->pp, iph);
                /* do not touch skb anymore */
 
                atomic_inc(&cp->in_pkts);
@@ -654,14 +651,6 @@ static inline int ip_vs_gather_frags(struct sk_buff *skb, u_int32_t user)
        return err;
 }
 
-#ifdef CONFIG_IP_VS_IPV6
-static inline int ip_vs_gather_frags_v6(struct sk_buff *skb, u_int32_t user)
-{
-       /* TODO IPv6: Find out what to do here for IPv6 */
-       return 0;
-}
-#endif
-
 static int ip_vs_route_me_harder(int af, struct sk_buff *skb)
 {
 #ifdef CONFIG_IP_VS_IPV6
@@ -732,10 +721,19 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
                    struct ip_vs_conn *cp, int inout)
 {
        struct ipv6hdr *iph      = ipv6_hdr(skb);
-       unsigned int icmp_offset = sizeof(struct ipv6hdr);
-       struct icmp6hdr *icmph   = (struct icmp6hdr *)(skb_network_header(skb) +
-                                                     icmp_offset);
-       struct ipv6hdr *ciph     = (struct ipv6hdr *)(icmph + 1);
+       unsigned int icmp_offset = 0;
+       unsigned int offs        = 0; /* header offset*/
+       int protocol;
+       struct icmp6hdr *icmph;
+       struct ipv6hdr *ciph;
+       unsigned short fragoffs;
+
+       ipv6_find_hdr(skb, &icmp_offset, IPPROTO_ICMPV6, &fragoffs, NULL);
+       icmph = (struct icmp6hdr *)(skb_network_header(skb) + icmp_offset);
+       offs = icmp_offset + sizeof(struct icmp6hdr);
+       ciph = (struct ipv6hdr *)(skb_network_header(skb) + offs);
+
+       protocol = ipv6_find_hdr(skb, &offs, -1, &fragoffs, NULL);
 
        if (inout) {
                iph->saddr = cp->vaddr.in6;
@@ -746,10 +744,13 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp,
        }
 
        /* the TCP/UDP/SCTP port */
-       if (IPPROTO_TCP == ciph->nexthdr || IPPROTO_UDP == ciph->nexthdr ||
-           IPPROTO_SCTP == ciph->nexthdr) {
-               __be16 *ports = (void *)ciph + sizeof(struct ipv6hdr);
+       if (!fragoffs && (IPPROTO_TCP == protocol || IPPROTO_UDP == protocol ||
+                         IPPROTO_SCTP == protocol)) {
+               __be16 *ports = (void *)(skb_network_header(skb) + offs);
 
+               IP_VS_DBG(11, "%s() changed port %d to %d\n", __func__,
+                             ntohs(inout ? ports[1] : ports[0]),
+                             ntohs(inout ? cp->vport : cp->dport));
                if (inout)
                        ports[1] = cp->vport;
                else
@@ -898,51 +899,35 @@ static int ip_vs_out_icmp(struct sk_buff *skb, int *related,
        IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset,
                      "Checking outgoing ICMP for");
 
-       offset += cih->ihl * 4;
-
-       ip_vs_fill_iphdr(AF_INET, cih, &ciph);
+       ip_vs_fill_ip4hdr(cih, &ciph);
+       ciph.len += offset;
        /* The embedded headers contain source and dest in reverse order */
-       cp = pp->conn_out_get(AF_INET, skb, &ciph, offset, 1);
+       cp = pp->conn_out_get(AF_INET, skb, &ciph, 1);
        if (!cp)
                return NF_ACCEPT;
 
        snet.ip = iph->saddr;
        return handle_response_icmp(AF_INET, skb, &snet, cih->protocol, cp,
-                                   pp, offset, ihl);
+                                   pp, ciph.len, ihl);
 }
 
 #ifdef CONFIG_IP_VS_IPV6
 static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
-                            unsigned int hooknum)
+                            unsigned int hooknum, struct ip_vs_iphdr *ipvsh)
 {
-       struct ipv6hdr *iph;
        struct icmp6hdr _icmph, *ic;
-       struct ipv6hdr  _ciph, *cih;    /* The ip header contained
-                                          within the ICMP */
-       struct ip_vs_iphdr ciph;
+       struct ipv6hdr _ip6h, *ip6h; /* The ip header contained within ICMP */
+       struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */
        struct ip_vs_conn *cp;
        struct ip_vs_protocol *pp;
-       unsigned int offset;
        union nf_inet_addr snet;
+       unsigned int writable;
 
        *related = 1;
-
-       /* reassemble IP fragments */
-       if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
-               if (ip_vs_gather_frags_v6(skb, ip_vs_defrag_user(hooknum)))
-                       return NF_STOLEN;
-       }
-
-       iph = ipv6_hdr(skb);
-       offset = sizeof(struct ipv6hdr);
-       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       ic = frag_safe_skb_hp(skb, ipvsh->len, sizeof(_icmph), &_icmph, ipvsh);
        if (ic == NULL)
                return NF_DROP;
 
-       IP_VS_DBG(12, "Outgoing ICMPv6 (%d,%d) %pI6->%pI6\n",
-                 ic->icmp6_type, ntohs(icmpv6_id(ic)),
-                 &iph->saddr, &iph->daddr);
-
        /*
         * Work through seeing if this is for us.
         * These checks are supposed to be in an order that means easy
@@ -950,42 +935,45 @@ static int ip_vs_out_icmp_v6(struct sk_buff *skb, int *related,
         * this means that some packets will manage to get a long way
         * down this stack and then be rejected, but that's life.
         */
-       if ((ic->icmp6_type != ICMPV6_DEST_UNREACH) &&
-           (ic->icmp6_type != ICMPV6_PKT_TOOBIG) &&
-           (ic->icmp6_type != ICMPV6_TIME_EXCEED)) {
+       if (ic->icmp6_type & ICMPV6_INFOMSG_MASK) {
                *related = 0;
                return NF_ACCEPT;
        }
+       /* Fragment header that is before ICMP header tells us that:
+        * it's not an error message since they can't be fragmented.
+        */
+       if (ipvsh->flags & IP6_FH_F_FRAG)
+               return NF_DROP;
+
+       IP_VS_DBG(8, "Outgoing ICMPv6 (%d,%d) %pI6c->%pI6c\n",
+                 ic->icmp6_type, ntohs(icmpv6_id(ic)),
+                 &ipvsh->saddr, &ipvsh->daddr);
 
        /* Now find the contained IP header */
-       offset += sizeof(_icmph);
-       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
-       if (cih == NULL)
+       ciph.len = ipvsh->len + sizeof(_icmph);
+       ip6h = skb_header_pointer(skb, ciph.len, sizeof(_ip6h), &_ip6h);
+       if (ip6h == NULL)
                return NF_ACCEPT; /* The packet looks wrong, ignore */
-
-       pp = ip_vs_proto_get(cih->nexthdr);
+       ciph.saddr.in6 = ip6h->saddr; /* conn_out_get() handles reverse order */
+       ciph.daddr.in6 = ip6h->daddr;
+       /* skip possible IPv6 exthdrs of contained IPv6 packet */
+       ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs, NULL);
+       if (ciph.protocol < 0)
+               return NF_ACCEPT; /* Contained IPv6 hdr looks wrong, ignore */
+
+       pp = ip_vs_proto_get(ciph.protocol);
        if (!pp)
                return NF_ACCEPT;
 
-       /* Is the embedded protocol header present? */
-       /* TODO: we don't support fragmentation at the moment anyways */
-       if (unlikely(cih->nexthdr == IPPROTO_FRAGMENT && pp->dont_defrag))
-               return NF_ACCEPT;
-
-       IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
-                     "Checking outgoing ICMPv6 for");
-
-       offset += sizeof(struct ipv6hdr);
-
-       ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
        /* The embedded headers contain source and dest in reverse order */
-       cp = pp->conn_out_get(AF_INET6, skb, &ciph, offset, 1);
+       cp = pp->conn_out_get(AF_INET6, skb, &ciph, 1);
        if (!cp)
                return NF_ACCEPT;
 
-       snet.in6 = iph->saddr;
-       return handle_response_icmp(AF_INET6, skb, &snet, cih->nexthdr, cp,
-                                   pp, offset, sizeof(struct ipv6hdr));
+       snet.in6 = ciph.saddr.in6;
+       writable = ciph.len;
+       return handle_response_icmp(AF_INET6, skb, &snet, ciph.protocol, cp,
+                                   pp, writable, sizeof(struct ipv6hdr));
 }
 #endif
 
@@ -1018,17 +1006,17 @@ static inline int is_tcp_reset(const struct sk_buff *skb, int nh_len)
  */
 static unsigned int
 handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
-               struct ip_vs_conn *cp, int ihl)
+               struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
 {
        struct ip_vs_protocol *pp = pd->pp;
 
        IP_VS_DBG_PKT(11, af, pp, skb, 0, "Outgoing packet");
 
-       if (!skb_make_writable(skb, ihl))
+       if (!skb_make_writable(skb, iph->len))
                goto drop;
 
        /* mangle the packet */
-       if (pp->snat_handler && !pp->snat_handler(skb, pp, cp))
+       if (pp->snat_handler && !pp->snat_handler(skb, pp, cp, iph))
                goto drop;
 
 #ifdef CONFIG_IP_VS_IPV6
@@ -1115,17 +1103,22 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
        if (!net_ipvs(net)->enable)
                return NF_ACCEPT;
 
-       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+       ip_vs_fill_iph_skb(af, skb, &iph);
 #ifdef CONFIG_IP_VS_IPV6
        if (af == AF_INET6) {
+               if (!iph.fragoffs && skb_nfct_reasm(skb)) {
+                       struct sk_buff *reasm = skb_nfct_reasm(skb);
+                       /* Save fw mark for coming frags */
+                       reasm->ipvs_property = 1;
+                       reasm->mark = skb->mark;
+               }
                if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
                        int related;
                        int verdict = ip_vs_out_icmp_v6(skb, &related,
-                                                       hooknum);
+                                                       hooknum, &iph);
 
                        if (related)
                                return verdict;
-                       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
                }
        } else
 #endif
@@ -1135,7 +1128,6 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 
                        if (related)
                                return verdict;
-                       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
                }
 
        pd = ip_vs_proto_data_get(net, iph.protocol);
@@ -1145,39 +1137,31 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af)
 
        /* reassemble IP fragments */
 #ifdef CONFIG_IP_VS_IPV6
-       if (af == AF_INET6) {
-               if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
-                       if (ip_vs_gather_frags_v6(skb,
-                                                 ip_vs_defrag_user(hooknum)))
-                               return NF_STOLEN;
-               }
-
-               ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
-       } else
+       if (af == AF_INET)
 #endif
                if (unlikely(ip_is_fragment(ip_hdr(skb)) && !pp->dont_defrag)) {
                        if (ip_vs_gather_frags(skb,
                                               ip_vs_defrag_user(hooknum)))
                                return NF_STOLEN;
 
-                       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+                       ip_vs_fill_ip4hdr(skb_network_header(skb), &iph);
                }
 
        /*
         * Check if the packet belongs to an existing entry
         */
-       cp = pp->conn_out_get(af, skb, &iph, iph.len, 0);
+       cp = pp->conn_out_get(af, skb, &iph, 0);
 
        if (likely(cp))
-               return handle_response(af, skb, pd, cp, iph.len);
+               return handle_response(af, skb, pd, cp, &iph);
        if (sysctl_nat_icmp_send(net) &&
            (pp->protocol == IPPROTO_TCP ||
             pp->protocol == IPPROTO_UDP ||
             pp->protocol == IPPROTO_SCTP)) {
                __be16 _ports[2], *pptr;
 
-               pptr = skb_header_pointer(skb, iph.len,
-                                         sizeof(_ports), _ports);
+               pptr = frag_safe_skb_hp(skb, iph.len,
+                                        sizeof(_ports), _ports, &iph);
                if (pptr == NULL)
                        return NF_ACCEPT;       /* Not for me */
                if (ip_vs_lookup_real_service(net, af, iph.protocol,
@@ -1375,13 +1359,13 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
                      "Checking incoming ICMP for");
 
        offset2 = offset;
-       offset += cih->ihl * 4;
-
-       ip_vs_fill_iphdr(AF_INET, cih, &ciph);
+       ip_vs_fill_ip4hdr(cih, &ciph);
+       ciph.len += offset;
+       offset = ciph.len;
        /* The embedded headers contain source and dest in reverse order.
         * For IPIP this is error for request, not for reply.
         */
-       cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, ipip ? 0 : 1);
+       cp = pp->conn_in_get(AF_INET, skb, &ciph, ipip ? 0 : 1);
        if (!cp)
                return NF_ACCEPT;
 
@@ -1450,7 +1434,7 @@ ignore_ipip:
        ip_vs_in_stats(cp, skb);
        if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol)
                offset += 2 * sizeof(__u16);
-       verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum);
+       verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum, &ciph);
 
 out:
        __ip_vs_conn_put(cp);
@@ -1459,38 +1443,24 @@ out:
 }
 
 #ifdef CONFIG_IP_VS_IPV6
-static int
-ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
+static int ip_vs_in_icmp_v6(struct sk_buff *skb, int *related,
+                           unsigned int hooknum, struct ip_vs_iphdr *iph)
 {
        struct net *net = NULL;
-       struct ipv6hdr *iph;
+       struct ipv6hdr _ip6h, *ip6h;
        struct icmp6hdr _icmph, *ic;
-       struct ipv6hdr  _ciph, *cih;    /* The ip header contained
-                                          within the ICMP */
-       struct ip_vs_iphdr ciph;
+       struct ip_vs_iphdr ciph = {.flags = 0, .fragoffs = 0};/*Contained IP */
        struct ip_vs_conn *cp;
        struct ip_vs_protocol *pp;
        struct ip_vs_proto_data *pd;
-       unsigned int offset, verdict;
+       unsigned int offs_ciph, writable, verdict;
 
        *related = 1;
 
-       /* reassemble IP fragments */
-       if (ipv6_hdr(skb)->nexthdr == IPPROTO_FRAGMENT) {
-               if (ip_vs_gather_frags_v6(skb, ip_vs_defrag_user(hooknum)))
-                       return NF_STOLEN;
-       }
-
-       iph = ipv6_hdr(skb);
-       offset = sizeof(struct ipv6hdr);
-       ic = skb_header_pointer(skb, offset, sizeof(_icmph), &_icmph);
+       ic = frag_safe_skb_hp(skb, iph->len, sizeof(_icmph), &_icmph, iph);
        if (ic == NULL)
                return NF_DROP;
 
-       IP_VS_DBG(12, "Incoming ICMPv6 (%d,%d) %pI6->%pI6\n",
-                 ic->icmp6_type, ntohs(icmpv6_id(ic)),
-                 &iph->saddr, &iph->daddr);
-
        /*
         * Work through seeing if this is for us.
         * These checks are supposed to be in an order that means easy
@@ -1498,47 +1468,71 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum)
         * this means that some packets will manage to get a long way
         * down this stack and then be rejected, but that's life.
         */
-       if ((ic->icmp6_type != ICMPV6_DEST_UNREACH) &&
-           (ic->icmp6_type != ICMPV6_PKT_TOOBIG) &&
-           (ic->icmp6_type != ICMPV6_TIME_EXCEED)) {
+       if (ic->icmp6_type & ICMPV6_INFOMSG_MASK) {
                *related = 0;
                return NF_ACCEPT;
        }
+       /* Fragment header that is before ICMP header tells us that:
+        * it's not an error message since they can't be fragmented.
+        */
+       if (iph->flags & IP6_FH_F_FRAG)
+               return NF_DROP;
+
+       IP_VS_DBG(8, "Incoming ICMPv6 (%d,%d) %pI6c->%pI6c\n",
+                 ic->icmp6_type, ntohs(icmpv6_id(ic)),
+                 &iph->saddr, &iph->daddr);
 
        /* Now find the contained IP header */
-       offset += sizeof(_icmph);
-       cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph);
-       if (cih == NULL)
+       ciph.len = iph->len + sizeof(_icmph);
+       offs_ciph = ciph.len; /* Save ip header offset */
+       ip6h = skb_header_pointer(skb, ciph.len, sizeof(_ip6h), &_ip6h);
+       if (ip6h == NULL)
                return NF_ACCEPT; /* The packet looks wrong, ignore */
+       ciph.saddr.in6 = ip6h->saddr; /* conn_in_get() handles reverse order */
+       ciph.daddr.in6 = ip6h->daddr;
+       /* skip possible IPv6 exthdrs of contained IPv6 packet */
+       ciph.protocol = ipv6_find_hdr(skb, &ciph.len, -1, &ciph.fragoffs, NULL);
+       if (ciph.protocol < 0)
+               return NF_ACCEPT; /* Contained IPv6 hdr looks wrong, ignore */
 
        net = skb_net(skb);
-       pd = ip_vs_proto_data_get(net, cih->nexthdr);
+       pd = ip_vs_proto_data_get(net, ciph.protocol);
        if (!pd)
                return NF_ACCEPT;
        pp = pd->pp;
 
-       /* Is the embedded protocol header present? */
-       /* TODO: we don't support fragmentation at the moment anyways */
-       if (unlikely(cih->nexthdr == IPPROTO_FRAGMENT && pp->dont_defrag))
+       /* Cannot handle fragmented embedded protocol */
+       if (ciph.fragoffs)
                return NF_ACCEPT;
 
-       IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offset,
+       IP_VS_DBG_PKT(11, AF_INET6, pp, skb, offs_ciph,
                      "Checking incoming ICMPv6 for");
 
-       offset += sizeof(struct ipv6hdr);
+       /* The embedded headers contain source and dest in reverse order
+        * if not from localhost
+        */
+       cp = pp->conn_in_get(AF_INET6, skb, &ciph,
+                            (hooknum == NF_INET_LOCAL_OUT) ? 0 : 1);
 
-       ip_vs_fill_iphdr(AF_INET6, cih, &ciph);
-       /* The embedded headers contain source and dest in reverse order */
-       cp = pp->conn_in_get(AF_INET6, skb, &ciph, offset, 1);
        if (!cp)
                return NF_ACCEPT;
+       /* VS/TUN, VS/DR and LOCALNODE just let it go */
+       if ((hooknum == NF_INET_LOCAL_OUT) &&
+           (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)) {
+               __ip_vs_conn_put(cp);
+               return NF_ACCEPT;
+       }
 
        /* do the statistics and put it back */
        ip_vs_in_stats(cp, skb);
-       if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr ||
-           IPPROTO_SCTP == cih->nexthdr)
-               offset += 2 * sizeof(__u16);
-       verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum);
+
+       /* Need to mangle contained IPv6 header in ICMPv6 packet */
+       writable = ciph.len;
+       if (IPPROTO_TCP == ciph.protocol || IPPROTO_UDP == ciph.protocol ||
+           IPPROTO_SCTP == ciph.protocol)
+               writable += 2 * sizeof(__u16); /* Also mangle ports */
+
+       verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, writable, hooknum, &ciph);
 
        __ip_vs_conn_put(cp);
 
@@ -1574,7 +1568,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
        if (unlikely((skb->pkt_type != PACKET_HOST &&
                      hooknum != NF_INET_LOCAL_OUT) ||
                     !skb_dst(skb))) {
-               ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+               ip_vs_fill_iph_skb(af, skb, &iph);
                IP_VS_DBG_BUF(12, "packet type=%d proto=%d daddr=%s"
                              " ignored in hook %u\n",
                              skb->pkt_type, iph.protocol,
@@ -1586,7 +1580,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
        if (!net_ipvs(net)->enable)
                return NF_ACCEPT;
 
-       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
+       ip_vs_fill_iph_skb(af, skb, &iph);
 
        /* Bad... Do not break raw sockets */
        if (unlikely(skb->sk != NULL && hooknum == NF_INET_LOCAL_OUT &&
@@ -1600,13 +1594,19 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
 
 #ifdef CONFIG_IP_VS_IPV6
        if (af == AF_INET6) {
+               if (!iph.fragoffs && skb_nfct_reasm(skb)) {
+                       struct sk_buff *reasm = skb_nfct_reasm(skb);
+                       /* Save fw mark for coming frags. */
+                       reasm->ipvs_property = 1;
+                       reasm->mark = skb->mark;
+               }
                if (unlikely(iph.protocol == IPPROTO_ICMPV6)) {
                        int related;
-                       int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum);
+                       int verdict = ip_vs_in_icmp_v6(skb, &related, hooknum,
+                                                      &iph);
 
                        if (related)
                                return verdict;
-                       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
                }
        } else
 #endif
@@ -1616,7 +1616,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
 
                        if (related)
                                return verdict;
-                       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
                }
 
        /* Protocol supported? */
@@ -1627,12 +1626,15 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
        /*
         * Check if the packet belongs to an existing connection entry
         */
-       cp = pp->conn_in_get(af, skb, &iph, iph.len, 0);
-
-       if (unlikely(!cp)) {
+       cp = pp->conn_in_get(af, skb, &iph, 0);
+       if (unlikely(!cp) && !iph.fragoffs) {
+               /* No (second) fragments need to enter here, as nf_defrag_ipv6
+                * replayed fragment zero will already have created the cp
+                */
                int v;
 
-               if (!pp->conn_schedule(af, skb, pd, &v, &cp))
+               /* Schedule and create new connection entry into &cp */
+               if (!pp->conn_schedule(af, skb, pd, &v, &cp, &iph))
                        return v;
        }
 
@@ -1640,6 +1642,14 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
                /* sorry, all this trouble for a no-hit :) */
                IP_VS_DBG_PKT(12, af, pp, skb, 0,
                              "ip_vs_in: packet continues traversal as normal");
+               if (iph.fragoffs && !skb_nfct_reasm(skb)) {
+                       /* Fragment that couldn't be mapped to a conn entry
+                        * and don't have any pointer to a reasm skb
+                        * is missing module nf_defrag_ipv6
+                        */
+                       IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
+                       IP_VS_DBG_PKT(7, af, pp, skb, 0, "unhandled fragment");
+               }
                return NF_ACCEPT;
        }
 
@@ -1662,7 +1672,7 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
        ip_vs_in_stats(cp, skb);
        ip_vs_set_state(cp, IP_VS_DIR_INPUT, skb, pd);
        if (cp->packet_xmit)
-               ret = cp->packet_xmit(skb, cp, pp);
+               ret = cp->packet_xmit(skb, cp, pp, &iph);
                /* do not touch skb anymore */
        else {
                IP_VS_DBG_RL("warning: packet_xmit is null");
@@ -1723,6 +1733,38 @@ ip_vs_local_request4(unsigned int hooknum, struct sk_buff *skb,
 
 #ifdef CONFIG_IP_VS_IPV6
 
+/*
+ * AF_INET6 fragment handling
+ * Copy info from first fragment, to the rest of them.
+ */
+static unsigned int
+ip_vs_preroute_frag6(unsigned int hooknum, struct sk_buff *skb,
+                    const struct net_device *in,
+                    const struct net_device *out,
+                    int (*okfn)(struct sk_buff *))
+{
+       struct sk_buff *reasm = skb_nfct_reasm(skb);
+       struct net *net;
+
+       /* Skip if not a "replay" from nf_ct_frag6_output or first fragment.
+        * ipvs_property is set when checking first fragment
+        * in ip_vs_in() and ip_vs_out().
+        */
+       if (reasm)
+               IP_VS_DBG(2, "Fragment recv prop:%d\n", reasm->ipvs_property);
+       if (!reasm || !reasm->ipvs_property)
+               return NF_ACCEPT;
+
+       net = skb_net(skb);
+       if (!net_ipvs(net)->enable)
+               return NF_ACCEPT;
+
+       /* Copy stored fw mark, saved in ip_vs_{in,out} */
+       skb->mark = reasm->mark;
+
+       return NF_ACCEPT;
+}
+
 /*
  *     AF_INET6 handler in NF_INET_LOCAL_IN chain
  *     Schedule and forward packets from remote clients
@@ -1793,8 +1835,10 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
 {
        int r;
        struct net *net;
+       struct ip_vs_iphdr iphdr;
 
-       if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6)
+       ip_vs_fill_iph_skb(AF_INET6, skb, &iphdr);
+       if (iphdr.protocol != IPPROTO_ICMPV6)
                return NF_ACCEPT;
 
        /* ipvs enabled in this netns ? */
@@ -1802,7 +1846,7 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
        if (!net_ipvs(net)->enable)
                return NF_ACCEPT;
 
-       return ip_vs_in_icmp_v6(skb, &r, hooknum);
+       return ip_vs_in_icmp_v6(skb, &r, hooknum, &iphdr);
 }
 #endif
 
@@ -1860,6 +1904,14 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = {
                .priority       = 100,
        },
 #ifdef CONFIG_IP_VS_IPV6
+       /* After mangle & nat fetch 2:nd fragment and following */
+       {
+               .hook           = ip_vs_preroute_frag6,
+               .owner          = THIS_MODULE,
+               .pf             = NFPROTO_IPV6,
+               .hooknum        = NF_INET_PRE_ROUTING,
+               .priority       = NF_IP6_PRI_NAT_DST + 1,
+       },
        /* After packet filtering, change source only for VS/NAT */
        {
                .hook           = ip_vs_reply6,
index 7e7198b51c068a7ea10446af4d390a9e6e2044f4..ec664cbb119f658991fd1e18134305ec08b4d5d8 100644 (file)
@@ -2339,7 +2339,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
        struct ip_vs_dest_user_kern udest;
        struct netns_ipvs *ipvs = net_ipvs(net);
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        if (cmd < IP_VS_BASE_CTL || cmd > IP_VS_SO_SET_MAX)
@@ -2589,6 +2589,8 @@ __ip_vs_get_timeouts(struct net *net, struct ip_vs_timeout_user *u)
        struct ip_vs_proto_data *pd;
 #endif
 
+       memset(u, 0, sizeof (*u));
+
 #ifdef CONFIG_IP_VS_PROTO_TCP
        pd = ip_vs_proto_data_get(net, IPPROTO_TCP);
        u->tcp_timeout = pd->timeout_table[IP_VS_TCP_S_ESTABLISHED] / HZ;
@@ -2630,7 +2632,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
        struct netns_ipvs *ipvs = net_ipvs(net);
 
        BUG_ON(!net);
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        if (cmd < IP_VS_BASE_CTL || cmd > IP_VS_SO_GET_MAX)
@@ -2766,7 +2768,6 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
        {
                struct ip_vs_timeout_user t;
 
-               memset(&t, 0, sizeof(t));
                __ip_vs_get_timeouts(net, &t);
                if (copy_to_user(user, &t, sizeof(t)) != 0)
                        ret = -EFAULT;
@@ -3698,6 +3699,10 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
                tbl = kmemdup(vs_vars, sizeof(vs_vars), GFP_KERNEL);
                if (tbl == NULL)
                        return -ENOMEM;
+
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       tbl[0].procname = NULL;
        } else
                tbl = vs_vars;
        /* Initialize sysctl defaults */
index 8b7dca9ea4222d34476015ed8bbbb9d7ca98166b..7f3b0cc00b7add352264752cd9db38aa9adda21a 100644 (file)
@@ -215,7 +215,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
        struct ip_vs_dh_bucket *tbl;
        struct ip_vs_iphdr iph;
 
-       ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+       ip_vs_fill_iph_addr_only(svc->af, skb, &iph);
 
        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
 
index df646ccf08a744af9fb1a7f5d16385bd541b22ae..fdd89b9564ea6e537d70cb79fdcb4f58dbd1ce34 100644 (file)
@@ -479,7 +479,7 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
        struct ip_vs_dest *dest = NULL;
        struct ip_vs_lblc_entry *en;
 
-       ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+       ip_vs_fill_iph_addr_only(svc->af, skb, &iph);
 
        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
 
@@ -560,6 +560,11 @@ static int __net_init __ip_vs_lblc_init(struct net *net)
                                                GFP_KERNEL);
                if (ipvs->lblc_ctl_table == NULL)
                        return -ENOMEM;
+
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       ipvs->lblc_ctl_table[0].procname = NULL;
+
        } else
                ipvs->lblc_ctl_table = vs_vars_table;
        ipvs->sysctl_lblc_expiration = DEFAULT_EXPIRATION;
index 570e31ea427a1b5017fb2e926d9d47d0ac8ad014..c03b6a3ade2f90a4c9d96f8a3a11dceb1b3df130 100644 (file)
@@ -649,7 +649,7 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
        struct ip_vs_dest *dest = NULL;
        struct ip_vs_lblcr_entry *en;
 
-       ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+       ip_vs_fill_iph_addr_only(svc->af, skb, &iph);
 
        IP_VS_DBG(6, "%s(): Scheduling...\n", __func__);
 
@@ -754,6 +754,10 @@ static int __net_init __ip_vs_lblcr_init(struct net *net)
                                                GFP_KERNEL);
                if (ipvs->lblcr_ctl_table == NULL)
                        return -ENOMEM;
+
+               /* Don't export sysctls to unprivileged users */
+               if (net->user_ns != &init_user_ns)
+                       ipvs->lblcr_ctl_table[0].procname = NULL;
        } else
                ipvs->lblcr_ctl_table = vs_vars_table;
        ipvs->sysctl_lblcr_expiration = DEFAULT_EXPIRATION;
index 022e77e1e766450136340710a0e6c4b063e9a212..c8beafd401aa283f0befa0494e02649359bab83f 100644 (file)
@@ -82,7 +82,7 @@ void
 ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
 {
        enum ip_conntrack_info ctinfo;
-       struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+       struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
        struct nf_conntrack_tuple new_tuple;
 
        if (ct == NULL || nf_ct_is_confirmed(ct) || nf_ct_is_untracked(ct) ||
index 1aa5cac748c4ad5ee32cc6c2acb44ce2e9f5e78a..12475ef88dafe571bbc2e031af50890c08d91a54 100644 (file)
@@ -68,23 +68,31 @@ static int get_callid(const char *dptr, unsigned int dataoff,
 static int
 ip_vs_sip_fill_param(struct ip_vs_conn_param *p, struct sk_buff *skb)
 {
+       struct sk_buff *reasm = skb_nfct_reasm(skb);
        struct ip_vs_iphdr iph;
        unsigned int dataoff, datalen, matchoff, matchlen;
        const char *dptr;
        int retc;
 
-       ip_vs_fill_iphdr(p->af, skb_network_header(skb), &iph);
+       ip_vs_fill_iph_skb(p->af, skb, &iph);
 
        /* Only useful with UDP */
        if (iph.protocol != IPPROTO_UDP)
                return -EINVAL;
+       /* todo: IPv6 fragments:
+        *       I think this only should be done for the first fragment. /HS
+        */
+       if (reasm) {
+               skb = reasm;
+               dataoff = iph.thoff_reasm + sizeof(struct udphdr);
+       } else
+               dataoff = iph.len + sizeof(struct udphdr);
 
-       /* No Data ? */
-       dataoff = iph.len + sizeof(struct udphdr);
        if (dataoff >= skb->len)
                return -EINVAL;
-
-       if ((retc=skb_linearize(skb)) < 0)
+       /* todo: Check if this will mess-up the reasm skb !!! /HS */
+       retc = skb_linearize(skb);
+       if (retc < 0)
                return retc;
        dptr = skb->data + dataoff;
        datalen = skb->len - dataoff;
index 50d82186da87a22da2c46302c3b8cf298350cae2..939f7fbe9b46d832ffab36569e7e4b67f3a0bc68 100644 (file)
@@ -280,17 +280,17 @@ ip_vs_tcpudp_debug_packet_v6(struct ip_vs_protocol *pp,
        if (ih == NULL)
                sprintf(buf, "TRUNCATED");
        else if (ih->nexthdr == IPPROTO_FRAGMENT)
-               sprintf(buf, "%pI6->%pI6 frag", &ih->saddr, &ih->daddr);
+               sprintf(buf, "%pI6c->%pI6c frag", &ih->saddr, &ih->daddr);
        else {
                __be16 _ports[2], *pptr;
 
                pptr = skb_header_pointer(skb, offset + sizeof(struct ipv6hdr),
                                          sizeof(_ports), _ports);
                if (pptr == NULL)
-                       sprintf(buf, "TRUNCATED %pI6->%pI6",
+                       sprintf(buf, "TRUNCATED %pI6c->%pI6c",
                                &ih->saddr, &ih->daddr);
                else
-                       sprintf(buf, "%pI6:%u->%pI6:%u",
+                       sprintf(buf, "%pI6c:%u->%pI6c:%u",
                                &ih->saddr, ntohs(pptr[0]),
                                &ih->daddr, ntohs(pptr[1]));
        }
index 5b8eb8b12c3e6a1155df420f8b101b32c29f6def..5de3dd312c0f77ad787ea037378cf1a9eeb5536a 100644 (file)
@@ -57,7 +57,7 @@ ah_esp_conn_fill_param_proto(struct net *net, int af,
 
 static struct ip_vs_conn *
 ah_esp_conn_in_get(int af, const struct sk_buff *skb,
-                  const struct ip_vs_iphdr *iph, unsigned int proto_off,
+                  const struct ip_vs_iphdr *iph,
                   int inverse)
 {
        struct ip_vs_conn *cp;
@@ -85,9 +85,7 @@ ah_esp_conn_in_get(int af, const struct sk_buff *skb,
 
 static struct ip_vs_conn *
 ah_esp_conn_out_get(int af, const struct sk_buff *skb,
-                   const struct ip_vs_iphdr *iph,
-                   unsigned int proto_off,
-                   int inverse)
+                   const struct ip_vs_iphdr *iph, int inverse)
 {
        struct ip_vs_conn *cp;
        struct ip_vs_conn_param p;
@@ -110,7 +108,8 @@ ah_esp_conn_out_get(int af, const struct sk_buff *skb,
 
 static int
 ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
-                    int *verdict, struct ip_vs_conn **cpp)
+                    int *verdict, struct ip_vs_conn **cpp,
+                    struct ip_vs_iphdr *iph)
 {
        /*
         * AH/ESP is only related traffic. Pass the packet to IP stack.
index 9f3fb751c49154bac37fa4baa84853a2c0dd0c06..746048b13ef3aff9659b7161199d2298960662ec 100644 (file)
 
 static int
 sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
-                  int *verdict, struct ip_vs_conn **cpp)
+                  int *verdict, struct ip_vs_conn **cpp,
+                  struct ip_vs_iphdr *iph)
 {
        struct net *net;
        struct ip_vs_service *svc;
        sctp_chunkhdr_t _schunkh, *sch;
        sctp_sctphdr_t *sh, _sctph;
-       struct ip_vs_iphdr iph;
 
-       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
-
-       sh = skb_header_pointer(skb, iph.len, sizeof(_sctph), &_sctph);
+       sh = skb_header_pointer(skb, iph->len, sizeof(_sctph), &_sctph);
        if (sh == NULL)
                return 0;
 
-       sch = skb_header_pointer(skb, iph.len + sizeof(sctp_sctphdr_t),
+       sch = skb_header_pointer(skb, iph->len + sizeof(sctp_sctphdr_t),
                                 sizeof(_schunkh), &_schunkh);
        if (sch == NULL)
                return 0;
        net = skb_net(skb);
        if ((sch->type == SCTP_CID_INIT) &&
-           (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
-                                    &iph.daddr, sh->dest))) {
+           (svc = ip_vs_service_get(net, af, skb->mark, iph->protocol,
+                                    &iph->daddr, sh->dest))) {
                int ignored;
 
                if (ip_vs_todrop(net_ipvs(net))) {
@@ -47,10 +45,10 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
                 * Let the virtual server select a real server for the
                 * incoming connection, and create a connection entry.
                 */
-               *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+               *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);
                if (!*cpp && ignored <= 0) {
                        if (!ignored)
-                               *verdict = ip_vs_leave(svc, skb, pd);
+                               *verdict = ip_vs_leave(svc, skb, pd, iph);
                        else {
                                ip_vs_service_put(svc);
                                *verdict = NF_DROP;
@@ -64,20 +62,18 @@ sctp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
 }
 
 static int
-sctp_snat_handler(struct sk_buff *skb,
-                 struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                 struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
 {
        sctp_sctphdr_t *sctph;
-       unsigned int sctphoff;
+       unsigned int sctphoff = iph->len;
        struct sk_buff *iter;
        __be32 crc32;
 
 #ifdef CONFIG_IP_VS_IPV6
-       if (cp->af == AF_INET6)
-               sctphoff = sizeof(struct ipv6hdr);
-       else
+       if (cp->af == AF_INET6 && iph->fragoffs)
+               return 1;
 #endif
-               sctphoff = ip_hdrlen(skb);
 
        /* csum_check requires unshared skb */
        if (!skb_make_writable(skb, sctphoff + sizeof(*sctph)))
@@ -108,20 +104,18 @@ sctp_snat_handler(struct sk_buff *skb,
 }
 
 static int
-sctp_dnat_handler(struct sk_buff *skb,
-                 struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                 struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
 {
        sctp_sctphdr_t *sctph;
-       unsigned int sctphoff;
+       unsigned int sctphoff = iph->len;
        struct sk_buff *iter;
        __be32 crc32;
 
 #ifdef CONFIG_IP_VS_IPV6
-       if (cp->af == AF_INET6)
-               sctphoff = sizeof(struct ipv6hdr);
-       else
+       if (cp->af == AF_INET6 && iph->fragoffs)
+               return 1;
 #endif
-               sctphoff = ip_hdrlen(skb);
 
        /* csum_check requires unshared skb */
        if (!skb_make_writable(skb, sctphoff + sizeof(*sctph)))
index cd609cc62721095baf50475d14e80384089f280a..9af653a75825d0568450445ee3f5828622ac997c 100644 (file)
 
 static int
 tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
-                 int *verdict, struct ip_vs_conn **cpp)
+                 int *verdict, struct ip_vs_conn **cpp,
+                 struct ip_vs_iphdr *iph)
 {
        struct net *net;
        struct ip_vs_service *svc;
        struct tcphdr _tcph, *th;
-       struct ip_vs_iphdr iph;
 
-       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
-
-       th = skb_header_pointer(skb, iph.len, sizeof(_tcph), &_tcph);
+       th = skb_header_pointer(skb, iph->len, sizeof(_tcph), &_tcph);
        if (th == NULL) {
                *verdict = NF_DROP;
                return 0;
@@ -50,8 +48,8 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
        net = skb_net(skb);
        /* No !th->ack check to allow scheduling on SYN+ACK for Active FTP */
        if (th->syn &&
-           (svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
-                                    &iph.daddr, th->dest))) {
+           (svc = ip_vs_service_get(net, af, skb->mark, iph->protocol,
+                                    &iph->daddr, th->dest))) {
                int ignored;
 
                if (ip_vs_todrop(net_ipvs(net))) {
@@ -68,10 +66,10 @@ tcp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
                 * Let the virtual server select a real server for the
                 * incoming connection, and create a connection entry.
                 */
-               *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+               *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);
                if (!*cpp && ignored <= 0) {
                        if (!ignored)
-                               *verdict = ip_vs_leave(svc, skb, pd);
+                               *verdict = ip_vs_leave(svc, skb, pd, iph);
                        else {
                                ip_vs_service_put(svc);
                                *verdict = NF_DROP;
@@ -128,20 +126,18 @@ tcp_partial_csum_update(int af, struct tcphdr *tcph,
 
 
 static int
-tcp_snat_handler(struct sk_buff *skb,
-                struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
 {
        struct tcphdr *tcph;
-       unsigned int tcphoff;
+       unsigned int tcphoff = iph->len;
        int oldlen;
        int payload_csum = 0;
 
 #ifdef CONFIG_IP_VS_IPV6
-       if (cp->af == AF_INET6)
-               tcphoff = sizeof(struct ipv6hdr);
-       else
+       if (cp->af == AF_INET6 && iph->fragoffs)
+               return 1;
 #endif
-               tcphoff = ip_hdrlen(skb);
        oldlen = skb->len - tcphoff;
 
        /* csum_check requires unshared skb */
@@ -208,20 +204,18 @@ tcp_snat_handler(struct sk_buff *skb,
 
 
 static int
-tcp_dnat_handler(struct sk_buff *skb,
-                struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
 {
        struct tcphdr *tcph;
-       unsigned int tcphoff;
+       unsigned int tcphoff = iph->len;
        int oldlen;
        int payload_csum = 0;
 
 #ifdef CONFIG_IP_VS_IPV6
-       if (cp->af == AF_INET6)
-               tcphoff = sizeof(struct ipv6hdr);
-       else
+       if (cp->af == AF_INET6 && iph->fragoffs)
+               return 1;
 #endif
-               tcphoff = ip_hdrlen(skb);
        oldlen = skb->len - tcphoff;
 
        /* csum_check requires unshared skb */
index 2fedb2dcb3d1f5e831546b59480eceee14e59a84..503a842c90d271bac3a1c8386db92611f2888502 100644 (file)
 
 static int
 udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
-                 int *verdict, struct ip_vs_conn **cpp)
+                 int *verdict, struct ip_vs_conn **cpp,
+                 struct ip_vs_iphdr *iph)
 {
        struct net *net;
        struct ip_vs_service *svc;
        struct udphdr _udph, *uh;
-       struct ip_vs_iphdr iph;
 
-       ip_vs_fill_iphdr(af, skb_network_header(skb), &iph);
-
-       uh = skb_header_pointer(skb, iph.len, sizeof(_udph), &_udph);
+       /* IPv6 fragments, only first fragment will hit this */
+       uh = skb_header_pointer(skb, iph->len, sizeof(_udph), &_udph);
        if (uh == NULL) {
                *verdict = NF_DROP;
                return 0;
        }
        net = skb_net(skb);
-       svc = ip_vs_service_get(net, af, skb->mark, iph.protocol,
-                               &iph.daddr, uh->dest);
+       svc = ip_vs_service_get(net, af, skb->mark, iph->protocol,
+                               &iph->daddr, uh->dest);
        if (svc) {
                int ignored;
 
@@ -64,10 +63,10 @@ udp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
                 * Let the virtual server select a real server for the
                 * incoming connection, and create a connection entry.
                 */
-               *cpp = ip_vs_schedule(svc, skb, pd, &ignored);
+               *cpp = ip_vs_schedule(svc, skb, pd, &ignored, iph);
                if (!*cpp && ignored <= 0) {
                        if (!ignored)
-                               *verdict = ip_vs_leave(svc, skb, pd);
+                               *verdict = ip_vs_leave(svc, skb, pd, iph);
                        else {
                                ip_vs_service_put(svc);
                                *verdict = NF_DROP;
@@ -125,20 +124,18 @@ udp_partial_csum_update(int af, struct udphdr *uhdr,
 
 
 static int
-udp_snat_handler(struct sk_buff *skb,
-                struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
 {
        struct udphdr *udph;
-       unsigned int udphoff;
+       unsigned int udphoff = iph->len;
        int oldlen;
        int payload_csum = 0;
 
 #ifdef CONFIG_IP_VS_IPV6
-       if (cp->af == AF_INET6)
-               udphoff = sizeof(struct ipv6hdr);
-       else
+       if (cp->af == AF_INET6 && iph->fragoffs)
+               return 1;
 #endif
-               udphoff = ip_hdrlen(skb);
        oldlen = skb->len - udphoff;
 
        /* csum_check requires unshared skb */
@@ -210,20 +207,18 @@ udp_snat_handler(struct sk_buff *skb,
 
 
 static int
-udp_dnat_handler(struct sk_buff *skb,
-                struct ip_vs_protocol *pp, struct ip_vs_conn *cp)
+udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
+                struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
 {
        struct udphdr *udph;
-       unsigned int udphoff;
+       unsigned int udphoff = iph->len;
        int oldlen;
        int payload_csum = 0;
 
 #ifdef CONFIG_IP_VS_IPV6
-       if (cp->af == AF_INET6)
-               udphoff = sizeof(struct ipv6hdr);
-       else
+       if (cp->af == AF_INET6 && iph->fragoffs)
+               return 1;
 #endif
-               udphoff = ip_hdrlen(skb);
        oldlen = skb->len - udphoff;
 
        /* csum_check requires unshared skb */
index 08dbdd5bc18fc5dc9f23562ac86a66e20dafb897..d6bf20d6cdbef724e310ed26aca7b0098bcf9182 100644 (file)
@@ -159,7 +159,7 @@ void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
                             svc->fwmark, msg);
 #ifdef CONFIG_IP_VS_IPV6
        } else if (svc->af == AF_INET6) {
-               IP_VS_ERR_RL("%s: %s [%pI6]:%d - %s\n",
+               IP_VS_ERR_RL("%s: %s [%pI6c]:%d - %s\n",
                             svc->scheduler->name,
                             ip_vs_proto_name(svc->protocol),
                             &svc->addr.in6, ntohs(svc->port), msg);
index 05126521743e54b35cf0bb8dce99bd41f1696962..e331269946287a42faad5c78fb0b985dd3e0dcbf 100644 (file)
@@ -228,7 +228,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb)
        struct ip_vs_sh_bucket *tbl;
        struct ip_vs_iphdr iph;
 
-       ip_vs_fill_iphdr(svc->af, skb_network_header(skb), &iph);
+       ip_vs_fill_iph_addr_only(svc->af, skb, &iph);
 
        IP_VS_DBG(6, "ip_vs_sh_schedule(): Scheduling...\n");
 
index cc4c8095681ad70dd0c40fa1a5459debed396a01..ee6b7a9f1ec24e4f0a0049ff3af4c6fc73a29752 100644 (file)
@@ -338,7 +338,7 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
        local = __ip_vs_is_local_route6(rt);
        if (!((local ? IP_VS_RT_MODE_LOCAL : IP_VS_RT_MODE_NON_LOCAL) &
              rt_mode)) {
-               IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6\n",
+               IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6c\n",
                             local ? "local":"non-local", daddr);
                dst_release(&rt->dst);
                return NULL;
@@ -346,8 +346,8 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
        if (local && !(rt_mode & IP_VS_RT_MODE_RDR) &&
            !((ort = (struct rt6_info *) skb_dst(skb)) &&
              __ip_vs_is_local_route6(ort))) {
-               IP_VS_DBG_RL("Redirect from non-local address %pI6 to local "
-                            "requires NAT method, dest: %pI6\n",
+               IP_VS_DBG_RL("Redirect from non-local address %pI6c to local "
+                            "requires NAT method, dest: %pI6c\n",
                             &ipv6_hdr(skb)->daddr, daddr);
                dst_release(&rt->dst);
                return NULL;
@@ -355,8 +355,8 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
        if (unlikely(!local && (!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
                     ipv6_addr_type(&ipv6_hdr(skb)->saddr) &
                                    IPV6_ADDR_LOOPBACK)) {
-               IP_VS_DBG_RL("Stopping traffic from loopback address %pI6 "
-                            "to non-local address, dest: %pI6\n",
+               IP_VS_DBG_RL("Stopping traffic from loopback address %pI6c "
+                            "to non-local address, dest: %pI6c\n",
                             &ipv6_hdr(skb)->saddr, daddr);
                dst_release(&rt->dst);
                return NULL;
@@ -427,7 +427,7 @@ do {                                                        \
  */
 int
 ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
-               struct ip_vs_protocol *pp)
+               struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
 {
        /* we do not touch skb and do not need pskb ptr */
        IP_VS_XMIT(NFPROTO_IPV4, skb, cp, 1);
@@ -441,7 +441,7 @@ ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
  */
 int
 ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
-                 struct ip_vs_protocol *pp)
+                 struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
 {
        struct rtable *rt;                      /* Route to the other host */
        struct iphdr  *iph = ip_hdr(skb);
@@ -496,16 +496,16 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 #ifdef CONFIG_IP_VS_IPV6
 int
 ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
-                    struct ip_vs_protocol *pp)
+                    struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph)
 {
        struct rt6_info *rt;                    /* Route to the other host */
-       struct ipv6hdr  *iph = ipv6_hdr(skb);
        int    mtu;
 
        EnterFunction(10);
 
-       if (!(rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr, NULL, 0,
-                                        IP_VS_RT_MODE_NON_LOCAL)))
+       rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr.in6, NULL, 0,
+                                  IP_VS_RT_MODE_NON_LOCAL);
+       if (!rt)
                goto tx_error_icmp;
 
        /* MTU checking */
@@ -516,7 +516,9 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
                        skb->dev = net->loopback_dev;
                }
-               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+               /* only send ICMP too big on first fragment */
+               if (!iph->fragoffs)
+                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                dst_release(&rt->dst);
                IP_VS_DBG_RL("%s(): frag needed\n", __func__);
                goto tx_error;
@@ -559,7 +561,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
  */
 int
 ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
-              struct ip_vs_protocol *pp)
+              struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
 {
        struct rtable *rt;              /* Route to the other host */
        int mtu;
@@ -592,7 +594,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
        if (cp->flags & IP_VS_CONN_F_SYNC && local) {
                enum ip_conntrack_info ctinfo;
-               struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+               struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 
                if (ct && !nf_ct_is_untracked(ct)) {
                        IP_VS_DBG_RL_PKT(10, AF_INET, pp, skb, 0,
@@ -629,7 +631,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
                goto tx_error_put;
 
        /* mangle the packet */
-       if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
+       if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp, ipvsh))
                goto tx_error_put;
        ip_hdr(skb)->daddr = cp->daddr.ip;
        ip_send_check(ip_hdr(skb));
@@ -677,7 +679,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 #ifdef CONFIG_IP_VS_IPV6
 int
 ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
-                 struct ip_vs_protocol *pp)
+                 struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph)
 {
        struct rt6_info *rt;            /* Route to the other host */
        int mtu;
@@ -686,10 +688,9 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
        EnterFunction(10);
 
        /* check if it is a connection of no-client-port */
-       if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT)) {
+       if (unlikely(cp->flags & IP_VS_CONN_F_NO_CPORT && !iph->fragoffs)) {
                __be16 _pt, *p;
-               p = skb_header_pointer(skb, sizeof(struct ipv6hdr),
-                                      sizeof(_pt), &_pt);
+               p = skb_header_pointer(skb, iph->len, sizeof(_pt), &_pt);
                if (p == NULL)
                        goto tx_error;
                ip_vs_conn_fill_cport(cp, *p);
@@ -709,7 +710,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
        if (cp->flags & IP_VS_CONN_F_SYNC && local) {
                enum ip_conntrack_info ctinfo;
-               struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+               struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 
                if (ct && !nf_ct_is_untracked(ct)) {
                        IP_VS_DBG_RL_PKT(10, AF_INET6, pp, skb, 0,
@@ -737,7 +738,9 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
                        skb->dev = net->loopback_dev;
                }
-               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+               /* only send ICMP too big on first fragment */
+               if (!iph->fragoffs)
+                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                IP_VS_DBG_RL_PKT(0, AF_INET6, pp, skb, 0,
                                 "ip_vs_nat_xmit_v6(): frag needed for");
                goto tx_error_put;
@@ -751,7 +754,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
                goto tx_error_put;
 
        /* mangle the packet */
-       if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp))
+       if (pp->dnat_handler && !pp->dnat_handler(skb, pp, cp, iph))
                goto tx_error;
        ipv6_hdr(skb)->daddr = cp->daddr.in6;
 
@@ -812,7 +815,7 @@ tx_error_put:
  */
 int
 ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
-                 struct ip_vs_protocol *pp)
+                 struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
 {
        struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
        struct rtable *rt;                      /* Route to the other host */
@@ -932,7 +935,7 @@ tx_error_put:
 #ifdef CONFIG_IP_VS_IPV6
 int
 ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
-                    struct ip_vs_protocol *pp)
+                    struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
 {
        struct rt6_info *rt;            /* Route to the other host */
        struct in6_addr saddr;          /* Source for tunnel */
@@ -972,7 +975,9 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
                        skb->dev = net->loopback_dev;
                }
-               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+               /* only send ICMP too big on first fragment */
+               if (!ipvsh->fragoffs)
+                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                IP_VS_DBG_RL("%s(): frag needed\n", __func__);
                goto tx_error_put;
        }
@@ -1053,7 +1058,7 @@ tx_error_put:
  */
 int
 ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
-             struct ip_vs_protocol *pp)
+             struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh)
 {
        struct rtable *rt;                      /* Route to the other host */
        struct iphdr  *iph = ip_hdr(skb);
@@ -1115,7 +1120,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 #ifdef CONFIG_IP_VS_IPV6
 int
 ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
-                struct ip_vs_protocol *pp)
+                struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph)
 {
        struct rt6_info *rt;                    /* Route to the other host */
        int    mtu;
@@ -1139,7 +1144,9 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
                        skb->dev = net->loopback_dev;
                }
-               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+               /* only send ICMP too big on first fragment */
+               if (!iph->fragoffs)
+                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                dst_release(&rt->dst);
                IP_VS_DBG_RL("%s(): frag needed\n", __func__);
                goto tx_error;
@@ -1183,7 +1190,8 @@ tx_error:
  */
 int
 ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
-               struct ip_vs_protocol *pp, int offset, unsigned int hooknum)
+               struct ip_vs_protocol *pp, int offset, unsigned int hooknum,
+               struct ip_vs_iphdr *iph)
 {
        struct rtable   *rt;    /* Route to the other host */
        int mtu;
@@ -1198,7 +1206,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
           translate address/port back */
        if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
                if (cp->packet_xmit)
-                       rc = cp->packet_xmit(skb, cp, pp);
+                       rc = cp->packet_xmit(skb, cp, pp, iph);
                else
                        rc = NF_ACCEPT;
                /* do not touch skb anymore */
@@ -1227,7 +1235,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
        if (cp->flags & IP_VS_CONN_F_SYNC && local) {
                enum ip_conntrack_info ctinfo;
-               struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+               struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 
                if (ct && !nf_ct_is_untracked(ct)) {
                        IP_VS_DBG(10, "%s(): "
@@ -1304,7 +1312,8 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
 #ifdef CONFIG_IP_VS_IPV6
 int
 ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
-               struct ip_vs_protocol *pp, int offset, unsigned int hooknum)
+               struct ip_vs_protocol *pp, int offset, unsigned int hooknum,
+               struct ip_vs_iphdr *iph)
 {
        struct rt6_info *rt;    /* Route to the other host */
        int mtu;
@@ -1319,7 +1328,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
           translate address/port back */
        if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) {
                if (cp->packet_xmit)
-                       rc = cp->packet_xmit(skb, cp, pp);
+                       rc = cp->packet_xmit(skb, cp, pp, iph);
                else
                        rc = NF_ACCEPT;
                /* do not touch skb anymore */
@@ -1347,7 +1356,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 #if IS_ENABLED(CONFIG_NF_CONNTRACK)
        if (cp->flags & IP_VS_CONN_F_SYNC && local) {
                enum ip_conntrack_info ctinfo;
-               struct nf_conn *ct = ct = nf_ct_get(skb, &ctinfo);
+               struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
 
                if (ct && !nf_ct_is_untracked(ct)) {
                        IP_VS_DBG(10, "%s(): "
@@ -1375,7 +1384,9 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
 
                        skb->dev = net->loopback_dev;
                }
-               icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
+               /* only send ICMP too big on first fragment */
+               if (!iph->fragoffs)
+                       icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
                IP_VS_DBG_RL("%s(): frag needed\n", __func__);
                goto tx_error_put;
        }
index d61e0782a797db1d4f4548ef583108f08272b6f4..7df424e2d10cf6146e7c3b38eaf0bf86a2bb0544 100644 (file)
@@ -69,6 +69,10 @@ static int nf_conntrack_acct_init_sysctl(struct net *net)
 
        table[0].data = &net->ct.sysctl_acct;
 
+       /* Don't export sysctls to unprivileged users */
+       if (net->user_ns != &init_user_ns)
+               table[0].procname = NULL;
+
        net->ct.acct_sysctl_header = register_net_sysctl(net, "net/netfilter",
                                                         table);
        if (!net->ct.acct_sysctl_header) {
index 0f241be28f9eec697ea9216c096657ace6eaefd6..08cdc71d8e8714b75782379929fa6b050dafa7f4 100644 (file)
@@ -221,11 +221,9 @@ destroy_conntrack(struct nf_conntrack *nfct)
         * too. */
        nf_ct_remove_expectations(ct);
 
-       /* We overload first tuple to link into unconfirmed list. */
-       if (!nf_ct_is_confirmed(ct)) {
-               BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
-               hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
-       }
+       /* We overload first tuple to link into unconfirmed or dying list.*/
+       BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode));
+       hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
 
        NF_CT_STAT_INC(net, delete);
        spin_unlock_bh(&nf_conntrack_lock);
@@ -247,6 +245,9 @@ void nf_ct_delete_from_lists(struct nf_conn *ct)
         * Otherwise we can get spurious warnings. */
        NF_CT_STAT_INC(net, delete_list);
        clean_from_lists(ct);
+       /* add this conntrack to the dying list */
+       hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
+                            &net->ct.dying);
        spin_unlock_bh(&nf_conntrack_lock);
 }
 EXPORT_SYMBOL_GPL(nf_ct_delete_from_lists);
@@ -268,31 +269,23 @@ static void death_by_event(unsigned long ul_conntrack)
        }
        /* we've got the event delivered, now it's dying */
        set_bit(IPS_DYING_BIT, &ct->status);
-       spin_lock(&nf_conntrack_lock);
-       hlist_nulls_del(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode);
-       spin_unlock(&nf_conntrack_lock);
        nf_ct_put(ct);
 }
 
-void nf_ct_insert_dying_list(struct nf_conn *ct)
+void nf_ct_dying_timeout(struct nf_conn *ct)
 {
        struct net *net = nf_ct_net(ct);
        struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
 
        BUG_ON(ecache == NULL);
 
-       /* add this conntrack to the dying list */
-       spin_lock_bh(&nf_conntrack_lock);
-       hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
-                            &net->ct.dying);
-       spin_unlock_bh(&nf_conntrack_lock);
        /* set a new timer to retry event delivery */
        setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct);
        ecache->timeout.expires = jiffies +
                (random32() % net->ct.sysctl_events_retry_timeout);
        add_timer(&ecache->timeout);
 }
-EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list);
+EXPORT_SYMBOL_GPL(nf_ct_dying_timeout);
 
 static void death_by_timeout(unsigned long ul_conntrack)
 {
@@ -307,7 +300,7 @@ static void death_by_timeout(unsigned long ul_conntrack)
            unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) {
                /* destroy event was not delivered */
                nf_ct_delete_from_lists(ct);
-               nf_ct_insert_dying_list(ct);
+               nf_ct_dying_timeout(ct);
                return;
        }
        set_bit(IPS_DYING_BIT, &ct->status);
@@ -1416,7 +1409,7 @@ EXPORT_SYMBOL_GPL(nf_ct_alloc_hashtable);
 
 int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
 {
-       int i, bucket;
+       int i, bucket, rc;
        unsigned int hashsize, old_size;
        struct hlist_nulls_head *hash, *old_hash;
        struct nf_conntrack_tuple_hash *h;
@@ -1429,7 +1422,9 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
        if (!nf_conntrack_htable_size)
                return param_set_uint(val, kp);
 
-       hashsize = simple_strtoul(val, NULL, 0);
+       rc = kstrtouint(val, 0, &hashsize);
+       if (rc)
+               return rc;
        if (!hashsize)
                return -EINVAL;
 
index de9781b6464f0940d391555489782bf63f1c956e..faa978f1714b831ff81d81e9ec4732eb3f167fb7 100644 (file)
@@ -196,6 +196,10 @@ static int nf_conntrack_event_init_sysctl(struct net *net)
        table[0].data = &net->ct.sysctl_events;
        table[1].data = &net->ct.sysctl_events_retry_timeout;
 
+       /* Don't export sysctls to unprivileged users */
+       if (net->user_ns != &init_user_ns)
+               table[0].procname = NULL;
+
        net->ct.event_sysctl_header =
                register_net_sysctl(net, "net/netfilter", table);
        if (!net->ct.event_sysctl_header) {
index 1b30b0dee70818c4842b1835964ffc5f59e6b6e3..962795e839ab099ce426a27a1dcd4d887bc56eef 100644 (file)
@@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src,
                                   flowi4_to_flowi(&fl1), false)) {
                        if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
                                           flowi4_to_flowi(&fl2), false)) {
-                               if (rt1->rt_gateway == rt2->rt_gateway &&
+                               if (rt_nexthop(rt1, fl1.daddr) ==
+                                   rt_nexthop(rt2, fl2.daddr) &&
                                    rt1->dst.dev  == rt2->dst.dev)
                                        ret = 1;
                                dst_release(&rt2->dst);
index c4bc637feb76b3e542ac0eaac9c76198e38188cf..884f2b39319a258ffbaa4360736fd7f83b867195 100644 (file)
@@ -64,6 +64,10 @@ static int nf_conntrack_helper_init_sysctl(struct net *net)
 
        table[0].data = &net->ct.sysctl_auto_assign_helper;
 
+       /* Don't export sysctls to unprivileged users */
+       if (net->user_ns != &init_user_ns)
+               table[0].procname = NULL;
+
        net->ct.helper_sysctl_header =
                register_net_sysctl(net, "net/netfilter", table);
 
index 7bbfb3deea305e4d8434c3af9a68ee6e4531c80f..4e078cd84d83c2c15c70ab4270b87a05e590f4ad 100644 (file)
@@ -898,7 +898,8 @@ ctnetlink_parse_zone(const struct nlattr *attr, u16 *zone)
 }
 
 static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = {
-       [CTA_HELP_NAME]         = { .type = NLA_NUL_STRING },
+       [CTA_HELP_NAME]         = { .type = NLA_NUL_STRING,
+                                   .len = NF_CT_HELPER_NAME_LEN - 1 },
 };
 
 static inline int
@@ -932,6 +933,8 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
        [CTA_ID]                = { .type = NLA_U32 },
        [CTA_NAT_DST]           = { .type = NLA_NESTED },
        [CTA_TUPLE_MASTER]      = { .type = NLA_NESTED },
+       [CTA_NAT_SEQ_ADJ_ORIG]  = { .type = NLA_NESTED },
+       [CTA_NAT_SEQ_ADJ_REPLY] = { .type = NLA_NESTED },
        [CTA_ZONE]              = { .type = NLA_U16 },
        [CTA_MARK_MASK]         = { .type = NLA_U32 },
 };
@@ -989,7 +992,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
                                              nlmsg_report(nlh)) < 0) {
                        nf_ct_delete_from_lists(ct);
                        /* we failed to report the event, try later */
-                       nf_ct_insert_dying_list(ct);
+                       nf_ct_dying_timeout(ct);
                        nf_ct_put(ct);
                        return 0;
                }
@@ -1089,6 +1092,112 @@ out:
        return err == -EAGAIN ? -ENOBUFS : err;
 }
 
+static int ctnetlink_done_list(struct netlink_callback *cb)
+{
+       if (cb->args[1])
+               nf_ct_put((struct nf_conn *)cb->args[1]);
+       return 0;
+}
+
+static int
+ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb,
+                   struct hlist_nulls_head *list)
+{
+       struct nf_conn *ct, *last;
+       struct nf_conntrack_tuple_hash *h;
+       struct hlist_nulls_node *n;
+       struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
+       u_int8_t l3proto = nfmsg->nfgen_family;
+       int res;
+
+       if (cb->args[2])
+               return 0;
+
+       spin_lock_bh(&nf_conntrack_lock);
+       last = (struct nf_conn *)cb->args[1];
+restart:
+       hlist_nulls_for_each_entry(h, n, list, hnnode) {
+               ct = nf_ct_tuplehash_to_ctrack(h);
+               if (l3proto && nf_ct_l3num(ct) != l3proto)
+                       continue;
+               if (cb->args[1]) {
+                       if (ct != last)
+                               continue;
+                       cb->args[1] = 0;
+               }
+               rcu_read_lock();
+               res = ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid,
+                                         cb->nlh->nlmsg_seq,
+                                         NFNL_MSG_TYPE(cb->nlh->nlmsg_type),
+                                         ct);
+               rcu_read_unlock();
+               if (res < 0) {
+                       nf_conntrack_get(&ct->ct_general);
+                       cb->args[1] = (unsigned long)ct;
+                       goto out;
+               }
+       }
+       if (cb->args[1]) {
+               cb->args[1] = 0;
+               goto restart;
+       } else
+               cb->args[2] = 1;
+out:
+       spin_unlock_bh(&nf_conntrack_lock);
+       if (last)
+               nf_ct_put(last);
+
+       return skb->len;
+}
+
+static int
+ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct net *net = sock_net(skb->sk);
+
+       return ctnetlink_dump_list(skb, cb, &net->ct.dying);
+}
+
+static int
+ctnetlink_get_ct_dying(struct sock *ctnl, struct sk_buff *skb,
+                      const struct nlmsghdr *nlh,
+                      const struct nlattr * const cda[])
+{
+       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+                       .dump = ctnetlink_dump_dying,
+                       .done = ctnetlink_done_list,
+               };
+               return netlink_dump_start(ctnl, skb, nlh, &c);
+       }
+
+       return -EOPNOTSUPP;
+}
+
+static int
+ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb)
+{
+       struct net *net = sock_net(skb->sk);
+
+       return ctnetlink_dump_list(skb, cb, &net->ct.unconfirmed);
+}
+
+static int
+ctnetlink_get_ct_unconfirmed(struct sock *ctnl, struct sk_buff *skb,
+                            const struct nlmsghdr *nlh,
+                            const struct nlattr * const cda[])
+{
+       if (nlh->nlmsg_flags & NLM_F_DUMP) {
+               struct netlink_dump_control c = {
+                       .dump = ctnetlink_dump_unconfirmed,
+                       .done = ctnetlink_done_list,
+               };
+               return netlink_dump_start(ctnl, skb, nlh, &c);
+       }
+
+       return -EOPNOTSUPP;
+}
+
 #ifdef CONFIG_NF_NAT_NEEDED
 static int
 ctnetlink_parse_nat_setup(struct nf_conn *ct,
@@ -2216,7 +2325,8 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
        [CTA_EXPECT_MASK]       = { .type = NLA_NESTED },
        [CTA_EXPECT_TIMEOUT]    = { .type = NLA_U32 },
        [CTA_EXPECT_ID]         = { .type = NLA_U32 },
-       [CTA_EXPECT_HELP_NAME]  = { .type = NLA_NUL_STRING },
+       [CTA_EXPECT_HELP_NAME]  = { .type = NLA_NUL_STRING,
+                                   .len = NF_CT_HELPER_NAME_LEN - 1 },
        [CTA_EXPECT_ZONE]       = { .type = NLA_U16 },
        [CTA_EXPECT_FLAGS]      = { .type = NLA_U32 },
        [CTA_EXPECT_CLASS]      = { .type = NLA_U32 },
@@ -2712,6 +2822,8 @@ static const struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
                                            .policy = ct_nla_policy },
        [IPCTNL_MSG_CT_GET_STATS_CPU]   = { .call = ctnetlink_stat_ct_cpu },
        [IPCTNL_MSG_CT_GET_STATS]       = { .call = ctnetlink_stat_ct },
+       [IPCTNL_MSG_CT_GET_DYING]       = { .call = ctnetlink_get_ct_dying },
+       [IPCTNL_MSG_CT_GET_UNCONFIRMED] = { .call = ctnetlink_get_ct_unconfirmed },
 };
 
 static const struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_EXP_MAX] = {
index 6535326cf07c773ba9166c6cbba16b9e7f29fb75..a8ae287bc7afe00ec89ed8032f3cbd7ea1c54b7a 100644 (file)
@@ -815,7 +815,7 @@ static struct ctl_table dccp_sysctl_table[] = {
 };
 #endif /* CONFIG_SYSCTL */
 
-static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn,
+static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
                                     struct dccp_net *dn)
 {
 #ifdef CONFIG_SYSCTL
@@ -836,6 +836,10 @@ static int dccp_kmemdup_sysctl_table(struct nf_proto_net *pn,
        pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
        pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
        pn->ctl_table[7].data = &dn->dccp_loose;
+
+       /* Don't export sysctls to unprivileged users */
+       if (net->user_ns != &init_user_ns)
+               pn->ctl_table[0].procname = NULL;
 #endif
        return 0;
 }
@@ -857,7 +861,7 @@ static int dccp_init_net(struct net *net, u_int16_t proto)
                dn->dccp_timeout[CT_DCCP_TIMEWAIT]      = 2 * DCCP_MSL;
        }
 
-       return dccp_kmemdup_sysctl_table(pn, dn);
+       return dccp_kmemdup_sysctl_table(net, pn, dn);
 }
 
 static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
index 61f9285111d19ae5b34c59b5d8f98366d0645086..83876e9877f1457e675dadb65a3d299e71e84165 100644 (file)
@@ -1353,6 +1353,8 @@ static const struct nla_policy tcp_timeout_nla_policy[CTA_TIMEOUT_TCP_MAX+1] = {
        [CTA_TIMEOUT_TCP_TIME_WAIT]     = { .type = NLA_U32 },
        [CTA_TIMEOUT_TCP_CLOSE]         = { .type = NLA_U32 },
        [CTA_TIMEOUT_TCP_SYN_SENT2]     = { .type = NLA_U32 },
+       [CTA_TIMEOUT_TCP_RETRANS]       = { .type = NLA_U32 },
+       [CTA_TIMEOUT_TCP_UNACK]         = { .type = NLA_U32 },
 };
 #endif /* CONFIG_NF_CT_NETLINK_TIMEOUT */
 
index 9b3943252a5e9c0b0dd6d2127606d11ac4e502b9..363285d544a1c7402152e6a7da3a7129d94b83ae 100644 (file)
@@ -489,6 +489,10 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
        table[3].data = &net->ct.sysctl_checksum;
        table[4].data = &net->ct.sysctl_log_invalid;
 
+       /* Don't export sysctls to unprivileged users */
+       if (net->user_ns != &init_user_ns)
+               table[0].procname = NULL;
+
        net->ct.sysctl_header = register_net_sysctl(net, "net/netfilter", table);
        if (!net->ct.sysctl_header)
                goto out_unregister_netfilter;
index dbb364f62d6f03b593b7b804251f48c2dcf7b845..7ea8026f07c9c843698bb54c68eb236840956bf9 100644 (file)
@@ -51,6 +51,10 @@ static int nf_conntrack_tstamp_init_sysctl(struct net *net)
 
        table[0].data = &net->ct.sysctl_tstamp;
 
+       /* Don't export sysctls to unprivileged users */
+       if (net->user_ns != &init_user_ns)
+               table[0].procname = NULL;
+
        net->ct.tstamp_sysctl_header = register_net_sysctl(net, "net/netfilter",
                                                           table);
        if (!net->ct.tstamp_sysctl_header) {
index 8d2cf9ec37a850951648640728ab1ad6d8f53e6d..d812c1235b30372b35f7b2866b113a9878b27147 100644 (file)
 #include "nf_internals.h"
 
 /*
- * A queue handler may be registered for each protocol.  Each is protected by
- * long term mutex.  The handler must provide an an outfn() to accept packets
- * for queueing and must reinject all packets it receives, no matter what.
+ * Hook for nfnetlink_queue to register its queue handler.
+ * We do this so that most of the NFQUEUE code can be modular.
+ *
+ * Once the queue is registered it must reinject all packets it
+ * receives, no matter what.
  */
-static const struct nf_queue_handler __rcu *queue_handler[NFPROTO_NUMPROTO] __read_mostly;
-
-static DEFINE_MUTEX(queue_handler_mutex);
+static const struct nf_queue_handler __rcu *queue_handler __read_mostly;
 
 /* return EBUSY when somebody else is registered, return EEXIST if the
  * same handler is registered, return 0 in case of success. */
-int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
+void nf_register_queue_handler(const struct nf_queue_handler *qh)
 {
-       int ret;
-       const struct nf_queue_handler *old;
-
-       if (pf >= ARRAY_SIZE(queue_handler))
-               return -EINVAL;
-
-       mutex_lock(&queue_handler_mutex);
-       old = rcu_dereference_protected(queue_handler[pf],
-                                       lockdep_is_held(&queue_handler_mutex));
-       if (old == qh)
-               ret = -EEXIST;
-       else if (old)
-               ret = -EBUSY;
-       else {
-               rcu_assign_pointer(queue_handler[pf], qh);
-               ret = 0;
-       }
-       mutex_unlock(&queue_handler_mutex);
-
-       return ret;
+       /* should never happen, we only have one queueing backend in kernel */
+       WARN_ON(rcu_access_pointer(queue_handler));
+       rcu_assign_pointer(queue_handler, qh);
 }
 EXPORT_SYMBOL(nf_register_queue_handler);
 
 /* The caller must flush their queue before this */
-int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
+void nf_unregister_queue_handler(void)
 {
-       const struct nf_queue_handler *old;
-
-       if (pf >= ARRAY_SIZE(queue_handler))
-               return -EINVAL;
-
-       mutex_lock(&queue_handler_mutex);
-       old = rcu_dereference_protected(queue_handler[pf],
-                                       lockdep_is_held(&queue_handler_mutex));
-       if (old && old != qh) {
-               mutex_unlock(&queue_handler_mutex);
-               return -EINVAL;
-       }
-
-       RCU_INIT_POINTER(queue_handler[pf], NULL);
-       mutex_unlock(&queue_handler_mutex);
-
+       RCU_INIT_POINTER(queue_handler, NULL);
        synchronize_rcu();
-
-       return 0;
 }
 EXPORT_SYMBOL(nf_unregister_queue_handler);
 
-void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
-{
-       u_int8_t pf;
-
-       mutex_lock(&queue_handler_mutex);
-       for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++)  {
-               if (rcu_dereference_protected(
-                               queue_handler[pf],
-                               lockdep_is_held(&queue_handler_mutex)
-                               ) == qh)
-                       RCU_INIT_POINTER(queue_handler[pf], NULL);
-       }
-       mutex_unlock(&queue_handler_mutex);
-
-       synchronize_rcu();
-}
-EXPORT_SYMBOL_GPL(nf_unregister_queue_handlers);
-
 static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
 {
        /* Release those devices we held, or Alexey will kill me. */
@@ -137,7 +85,7 @@ static int __nf_queue(struct sk_buff *skb,
        /* QUEUE == DROP if no one is waiting, to be safe. */
        rcu_read_lock();
 
-       qh = rcu_dereference(queue_handler[pf]);
+       qh = rcu_dereference(queue_handler);
        if (!qh) {
                status = -ESRCH;
                goto err_unlock;
@@ -344,77 +292,3 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
        kfree(entry);
 }
 EXPORT_SYMBOL(nf_reinject);
-
-#ifdef CONFIG_PROC_FS
-static void *seq_start(struct seq_file *seq, loff_t *pos)
-{
-       if (*pos >= ARRAY_SIZE(queue_handler))
-               return NULL;
-
-       return pos;
-}
-
-static void *seq_next(struct seq_file *s, void *v, loff_t *pos)
-{
-       (*pos)++;
-
-       if (*pos >= ARRAY_SIZE(queue_handler))
-               return NULL;
-
-       return pos;
-}
-
-static void seq_stop(struct seq_file *s, void *v)
-{
-
-}
-
-static int seq_show(struct seq_file *s, void *v)
-{
-       int ret;
-       loff_t *pos = v;
-       const struct nf_queue_handler *qh;
-
-       rcu_read_lock();
-       qh = rcu_dereference(queue_handler[*pos]);
-       if (!qh)
-               ret = seq_printf(s, "%2lld NONE\n", *pos);
-       else
-               ret = seq_printf(s, "%2lld %s\n", *pos, qh->name);
-       rcu_read_unlock();
-
-       return ret;
-}
-
-static const struct seq_operations nfqueue_seq_ops = {
-       .start  = seq_start,
-       .next   = seq_next,
-       .stop   = seq_stop,
-       .show   = seq_show,
-};
-
-static int nfqueue_open(struct inode *inode, struct file *file)
-{
-       return seq_open(file, &nfqueue_seq_ops);
-}
-
-static const struct file_operations nfqueue_file_ops = {
-       .owner   = THIS_MODULE,
-       .open    = nfqueue_open,
-       .read    = seq_read,
-       .llseek  = seq_lseek,
-       .release = seq_release,
-};
-#endif /* PROC_FS */
-
-
-int __init netfilter_queue_init(void)
-{
-#ifdef CONFIG_PROC_FS
-       if (!proc_create("nf_queue", S_IRUGO,
-                        proc_net_netfilter, &nfqueue_file_ops))
-               return -1;
-#endif
-       return 0;
-}
-
index ffb92c03a358a8ce64c9e824a09db72a823b76d8..58a09b7c3f6d50b4cf95a4c139d637a225421aae 100644 (file)
@@ -138,7 +138,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        const struct nfnetlink_subsystem *ss;
        int type, err;
 
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        /* All the messages must at least contain nfgenmsg */
index 8847b4d8be06b9ad536c2bb32d9bbd3d34a7c289..701c88a20fea4c2a3ca6c9b4b2189521e13f96fe 100644 (file)
@@ -41,7 +41,8 @@ MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tu
 static LIST_HEAD(cttimeout_list);
 
 static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
-       [CTA_TIMEOUT_NAME]      = { .type = NLA_NUL_STRING },
+       [CTA_TIMEOUT_NAME]      = { .type = NLA_NUL_STRING,
+                                   .len  = CTNL_TIMEOUT_NAME_MAX - 1},
        [CTA_TIMEOUT_L3PROTO]   = { .type = NLA_U16 },
        [CTA_TIMEOUT_L4PROTO]   = { .type = NLA_U8 },
        [CTA_TIMEOUT_DATA]      = { .type = NLA_NESTED },
index e12d44e75b21f79f266b3dc580fd283aa81b58f9..3158d87b56a816112ad71bb675d61a5e8c07305b 100644 (file)
@@ -809,7 +809,6 @@ static const struct nla_policy nfqa_cfg_policy[NFQA_CFG_MAX+1] = {
 };
 
 static const struct nf_queue_handler nfqh = {
-       .name   = "nf_queue",
        .outfn  = &nfqnl_enqueue_packet,
 };
 
@@ -827,14 +826,10 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb,
        if (nfqa[NFQA_CFG_CMD]) {
                cmd = nla_data(nfqa[NFQA_CFG_CMD]);
 
-               /* Commands without queue context - might sleep */
+               /* Obsolete commands without queue context */
                switch (cmd->command) {
-               case NFQNL_CFG_CMD_PF_BIND:
-                       return nf_register_queue_handler(ntohs(cmd->pf),
-                                                        &nfqh);
-               case NFQNL_CFG_CMD_PF_UNBIND:
-                       return nf_unregister_queue_handler(ntohs(cmd->pf),
-                                                          &nfqh);
+               case NFQNL_CFG_CMD_PF_BIND: return 0;
+               case NFQNL_CFG_CMD_PF_UNBIND: return 0;
                }
        }
 
@@ -1074,6 +1069,7 @@ static int __init nfnetlink_queue_init(void)
 #endif
 
        register_netdevice_notifier(&nfqnl_dev_notifier);
+       nf_register_queue_handler(&nfqh);
        return status;
 
 #ifdef CONFIG_PROC_FS
@@ -1087,7 +1083,7 @@ cleanup_netlink_notifier:
 
 static void __exit nfnetlink_queue_fini(void)
 {
-       nf_unregister_queue_handlers(&nfqh);
+       nf_unregister_queue_handler();
        unregister_netdevice_notifier(&nfqnl_dev_notifier);
 #ifdef CONFIG_PROC_FS
        remove_proc_entry("nfnetlink_queue", proc_net_netfilter);
index 16c712563860bad8b8ba03041b06cf2c386d43ab..ae7f5daeee4362bff5aee9a30a85347de70a2ccc 100644 (file)
@@ -180,9 +180,9 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        typeof(nf_ct_timeout_find_get_hook) timeout_find_get;
        struct ctnl_timeout *timeout;
        struct nf_conn_timeout *timeout_ext;
-       const struct ipt_entry *e = par->entryinfo;
        struct nf_conntrack_l4proto *l4proto;
        int ret = 0;
+       u8 proto;
 
        rcu_read_lock();
        timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook);
@@ -192,9 +192,11 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
                goto out;
        }
 
-       if (e->ip.invflags & IPT_INV_PROTO) {
+       proto = xt_ct_find_proto(par);
+       if (!proto) {
                ret = -EINVAL;
-               pr_info("You cannot use inversion on L4 protocol\n");
+               pr_info("You must specify a L4 protocol, and not use "
+                       "inversions on it.\n");
                goto out;
        }
 
@@ -214,7 +216,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
        /* Make sure the timeout policy matches any existing protocol tracker,
         * otherwise default to generic.
         */
-       l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto);
+       l4proto = __nf_ct_l4proto_find(par->family, proto);
        if (timeout->l4proto->l4proto != l4proto->l4proto) {
                ret = -EINVAL;
                pr_info("Timeout policy `%s' can only be used by L4 protocol "
index 1686ca1b53a157d8568ae8ac104aeb0f9415d696..73b73f687c580ccfe66648234caab5f0bdc543b9 100644 (file)
@@ -167,7 +167,7 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t,
                          const struct xt_hmark_info *info)
 {
        struct ipv6hdr *ip6, _ip6;
-       int flag = IP6T_FH_F_AUTH;
+       int flag = IP6_FH_F_AUTH;
        unsigned int nhoff = 0;
        u16 fragoff = 0;
        int nexthdr;
@@ -177,7 +177,7 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t,
        if (nexthdr < 0)
                return 0;
        /* No need to check for icmp errors on fragments */
-       if ((flag & IP6T_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
+       if ((flag & IP6_FH_F_FRAG) || (nexthdr != IPPROTO_ICMPV6))
                goto noicmp;
        /* Use inner header in case of ICMP errors */
        if (get_inner6_hdr(skb, &nhoff)) {
@@ -185,7 +185,7 @@ hmark_pkt_set_htuple_ipv6(const struct sk_buff *skb, struct hmark_tuple *t,
                if (ip6 == NULL)
                        return -1;
                /* If AH present, use SPI like in ESP. */
-               flag = IP6T_FH_F_AUTH;
+               flag = IP6_FH_F_AUTH;
                nexthdr = ipv6_find_hdr(skb, &nhoff, -1, &fragoff, &flag);
                if (nexthdr < 0)
                        return -1;
@@ -201,7 +201,7 @@ noicmp:
        if (t->proto == IPPROTO_ICMPV6)
                return 0;
 
-       if (flag & IP6T_FH_F_FRAG)
+       if (flag & IP6_FH_F_FRAG)
                return 0;
 
        hmark_set_tuple_ports(skb, nhoff, t, info);
index ee2e5bc5a8c7b506842b6d143fba3f7aa04f3a8d..bd93e51d30acc4eded7e5e4da0898e0838dd7c43 100644 (file)
@@ -70,6 +70,7 @@ tee_tg_route4(struct sk_buff *skb, const struct xt_tee_tginfo *info)
        fl4.daddr = info->gw.ip;
        fl4.flowi4_tos = RT_TOS(iph->tos);
        fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
+       fl4.flowi4_flags = FLOWI_FLAG_KNOWN_NH;
        rt = ip_route_output_key(net, &fl4);
        if (IS_ERR(rt))
                return false;
index bb10b0717f1bd1472411ce9b0892750722400bab..8d47c3780fda8f98c1a16f6b6b396ec94c2bea34 100644 (file)
@@ -67,7 +67,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
                goto out;
        }
 
-       ip_vs_fill_iphdr(family, skb_network_header(skb), &iph);
+       ip_vs_fill_iph_skb(family, skb, &iph);
 
        if (data->bitmask & XT_IPVS_PROTO)
                if ((iph.protocol == data->l4proto) ^
@@ -85,7 +85,7 @@ ipvs_mt(const struct sk_buff *skb, struct xt_action_param *par)
        /*
         * Check if the packet belongs to an existing entry
         */
-       cp = pp->conn_out_get(family, skb, &iph, iph.len, 1 /* inverse */);
+       cp = pp->conn_out_get(family, skb, &iph, 1 /* inverse */);
        if (unlikely(cp == NULL)) {
                match = false;
                goto out;
index 81aafa8e4fef894e9f24d7c460b627108884bba6..bea7464cc43fd9ced593ece7d073b66ea85d18de 100644 (file)
@@ -111,7 +111,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .family         = NFPROTO_IPV4,
                .table          = "nat",
                .hooks          = (1 << NF_INET_POST_ROUTING) |
-                                 (1 << NF_INET_LOCAL_OUT),
+                                 (1 << NF_INET_LOCAL_IN),
                .me             = THIS_MODULE,
        },
        {
@@ -123,7 +123,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .family         = NFPROTO_IPV4,
                .table          = "nat",
                .hooks          = (1 << NF_INET_PRE_ROUTING) |
-                                 (1 << NF_INET_LOCAL_IN),
+                                 (1 << NF_INET_LOCAL_OUT),
                .me             = THIS_MODULE,
        },
        {
@@ -133,7 +133,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .targetsize     = sizeof(struct nf_nat_range),
                .table          = "nat",
                .hooks          = (1 << NF_INET_POST_ROUTING) |
-                                 (1 << NF_INET_LOCAL_OUT),
+                                 (1 << NF_INET_LOCAL_IN),
                .me             = THIS_MODULE,
        },
        {
@@ -143,7 +143,7 @@ static struct xt_target xt_nat_target_reg[] __read_mostly = {
                .targetsize     = sizeof(struct nf_nat_range),
                .table          = "nat",
                .hooks          = (1 << NF_INET_PRE_ROUTING) |
-                                 (1 << NF_INET_LOCAL_IN),
+                                 (1 << NF_INET_LOCAL_OUT),
                .me             = THIS_MODULE,
        },
 };
index 01e944a017a4db6be96c3d4a8e7adc8d7890b34e..c8a1eb6eca2dea3597ba9c96a01b84656bad5700 100644 (file)
@@ -138,6 +138,8 @@ static int netlink_dump(struct sock *sk);
 static DEFINE_RWLOCK(nl_table_lock);
 static atomic_t nl_table_users = ATOMIC_INIT(0);
 
+#define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock));
+
 static ATOMIC_NOTIFIER_HEAD(netlink_chain);
 
 static inline u32 netlink_group_mask(u32 group)
@@ -345,6 +347,11 @@ netlink_update_listeners(struct sock *sk)
        struct hlist_node *node;
        unsigned long mask;
        unsigned int i;
+       struct listeners *listeners;
+
+       listeners = nl_deref_protected(tbl->listeners);
+       if (!listeners)
+               return;
 
        for (i = 0; i < NLGRPLONGS(tbl->groups); i++) {
                mask = 0;
@@ -352,7 +359,7 @@ netlink_update_listeners(struct sock *sk)
                        if (i < NLGRPLONGS(nlk_sk(sk)->ngroups))
                                mask |= nlk_sk(sk)->groups[i];
                }
-               tbl->listeners->masks[i] = mask;
+               listeners->masks[i] = mask;
        }
        /* this function is only called with the netlink table "grabbed", which
         * makes sure updates are visible before bind or setsockopt return. */
@@ -536,7 +543,11 @@ static int netlink_release(struct socket *sock)
        if (netlink_is_kernel(sk)) {
                BUG_ON(nl_table[sk->sk_protocol].registered == 0);
                if (--nl_table[sk->sk_protocol].registered == 0) {
-                       kfree(nl_table[sk->sk_protocol].listeners);
+                       struct listeners *old;
+
+                       old = nl_deref_protected(nl_table[sk->sk_protocol].listeners);
+                       RCU_INIT_POINTER(nl_table[sk->sk_protocol].listeners, NULL);
+                       kfree_rcu(old, rcu);
                        nl_table[sk->sk_protocol].module = NULL;
                        nl_table[sk->sk_protocol].bind = NULL;
                        nl_table[sk->sk_protocol].flags = 0;
@@ -601,7 +612,7 @@ retry:
 static inline int netlink_capable(const struct socket *sock, unsigned int flag)
 {
        return (nl_table[sock->sk->sk_protocol].flags & flag) ||
-              capable(CAP_NET_ADMIN);
+               ns_capable(sock_net(sock->sk)->user_ns, CAP_NET_ADMIN);
 }
 
 static void
@@ -982,7 +993,7 @@ int netlink_has_listeners(struct sock *sk, unsigned int group)
        rcu_read_lock();
        listeners = rcu_dereference(nl_table[sk->sk_protocol].listeners);
 
-       if (group - 1 < nl_table[sk->sk_protocol].groups)
+       if (listeners && group - 1 < nl_table[sk->sk_protocol].groups)
                res = test_bit(group - 1, listeners->masks);
 
        rcu_read_unlock();
@@ -1625,7 +1636,7 @@ int __netlink_change_ngroups(struct sock *sk, unsigned int groups)
                new = kzalloc(sizeof(*new) + NLGRPSZ(groups), GFP_ATOMIC);
                if (!new)
                        return -ENOMEM;
-               old = rcu_dereference_protected(tbl->listeners, 1);
+               old = nl_deref_protected(tbl->listeners);
                memcpy(new->masks, old->masks, NLGRPSZ(tbl->groups));
                rcu_assign_pointer(tbl->listeners, new);
 
index 08114478cb853256c3e6f0aeb63d791887513cd8..ac2defeeba83ddbbb1ffcacb54deec0714fb85e0 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/if_arp.h>
 #include <linux/if_vlan.h>
 #include <net/ip.h>
+#include <net/ipv6.h>
 #include <net/checksum.h>
 #include <net/dsfield.h>
 
@@ -162,6 +163,53 @@ static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
        *addr = new_addr;
 }
 
+static void update_ipv6_checksum(struct sk_buff *skb, u8 l4_proto,
+                                __be32 addr[4], const __be32 new_addr[4])
+{
+       int transport_len = skb->len - skb_transport_offset(skb);
+
+       if (l4_proto == IPPROTO_TCP) {
+               if (likely(transport_len >= sizeof(struct tcphdr)))
+                       inet_proto_csum_replace16(&tcp_hdr(skb)->check, skb,
+                                                 addr, new_addr, 1);
+       } else if (l4_proto == IPPROTO_UDP) {
+               if (likely(transport_len >= sizeof(struct udphdr))) {
+                       struct udphdr *uh = udp_hdr(skb);
+
+                       if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
+                               inet_proto_csum_replace16(&uh->check, skb,
+                                                         addr, new_addr, 1);
+                               if (!uh->check)
+                                       uh->check = CSUM_MANGLED_0;
+                       }
+               }
+       }
+}
+
+static void set_ipv6_addr(struct sk_buff *skb, u8 l4_proto,
+                         __be32 addr[4], const __be32 new_addr[4],
+                         bool recalculate_csum)
+{
+       if (recalculate_csum)
+               update_ipv6_checksum(skb, l4_proto, addr, new_addr);
+
+       skb->rxhash = 0;
+       memcpy(addr, new_addr, sizeof(__be32[4]));
+}
+
+static void set_ipv6_tc(struct ipv6hdr *nh, u8 tc)
+{
+       nh->priority = tc >> 4;
+       nh->flow_lbl[0] = (nh->flow_lbl[0] & 0x0F) | ((tc & 0x0F) << 4);
+}
+
+static void set_ipv6_fl(struct ipv6hdr *nh, u32 fl)
+{
+       nh->flow_lbl[0] = (nh->flow_lbl[0] & 0xF0) | (fl & 0x000F0000) >> 16;
+       nh->flow_lbl[1] = (fl & 0x0000FF00) >> 8;
+       nh->flow_lbl[2] = fl & 0x000000FF;
+}
+
 static void set_ip_ttl(struct sk_buff *skb, struct iphdr *nh, u8 new_ttl)
 {
        csum_replace2(&nh->check, htons(nh->ttl << 8), htons(new_ttl << 8));
@@ -195,6 +243,47 @@ static int set_ipv4(struct sk_buff *skb, const struct ovs_key_ipv4 *ipv4_key)
        return 0;
 }
 
+static int set_ipv6(struct sk_buff *skb, const struct ovs_key_ipv6 *ipv6_key)
+{
+       struct ipv6hdr *nh;
+       int err;
+       __be32 *saddr;
+       __be32 *daddr;
+
+       err = make_writable(skb, skb_network_offset(skb) +
+                           sizeof(struct ipv6hdr));
+       if (unlikely(err))
+               return err;
+
+       nh = ipv6_hdr(skb);
+       saddr = (__be32 *)&nh->saddr;
+       daddr = (__be32 *)&nh->daddr;
+
+       if (memcmp(ipv6_key->ipv6_src, saddr, sizeof(ipv6_key->ipv6_src)))
+               set_ipv6_addr(skb, ipv6_key->ipv6_proto, saddr,
+                             ipv6_key->ipv6_src, true);
+
+       if (memcmp(ipv6_key->ipv6_dst, daddr, sizeof(ipv6_key->ipv6_dst))) {
+               unsigned int offset = 0;
+               int flags = IP6_FH_F_SKIP_RH;
+               bool recalc_csum = true;
+
+               if (ipv6_ext_hdr(nh->nexthdr))
+                       recalc_csum = ipv6_find_hdr(skb, &offset,
+                                                   NEXTHDR_ROUTING, NULL,
+                                                   &flags) != NEXTHDR_ROUTING;
+
+               set_ipv6_addr(skb, ipv6_key->ipv6_proto, daddr,
+                             ipv6_key->ipv6_dst, recalc_csum);
+       }
+
+       set_ipv6_tc(nh, ipv6_key->ipv6_tclass);
+       set_ipv6_fl(nh, ntohl(ipv6_key->ipv6_label));
+       nh->hop_limit = ipv6_key->ipv6_hlimit;
+
+       return 0;
+}
+
 /* Must follow make_writable() since that can move the skb data. */
 static void set_tp_port(struct sk_buff *skb, __be16 *port,
                         __be16 new_port, __sum16 *check)
@@ -339,6 +428,10 @@ static int execute_set_action(struct sk_buff *skb,
                skb->priority = nla_get_u32(nested_attr);
                break;
 
+       case OVS_KEY_ATTR_SKB_MARK:
+               skb->mark = nla_get_u32(nested_attr);
+               break;
+
        case OVS_KEY_ATTR_ETHERNET:
                err = set_eth_addr(skb, nla_data(nested_attr));
                break;
@@ -347,6 +440,10 @@ static int execute_set_action(struct sk_buff *skb,
                err = set_ipv4(skb, nla_data(nested_attr));
                break;
 
+       case OVS_KEY_ATTR_IPV6:
+               err = set_ipv6(skb, nla_data(nested_attr));
+               break;
+
        case OVS_KEY_ATTR_TCP:
                err = set_tcp(skb, nla_data(nested_attr));
                break;
index 4c4b62ccc7d745bf9ba3298f17c2417b28c563b1..f996db343247aab3b155a27df330252de35761db 100644 (file)
@@ -208,7 +208,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
        int error;
        int key_len;
 
-       stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id());
+       stats = this_cpu_ptr(dp->stats_percpu);
 
        /* Extract flow from 'skb' into 'key'. */
        error = ovs_flow_extract(skb, p->port_no, &key, &key_len);
@@ -282,7 +282,7 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb,
        return 0;
 
 err:
-       stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id());
+       stats = this_cpu_ptr(dp->stats_percpu);
 
        u64_stats_update_begin(&stats->sync);
        stats->n_lost++;
@@ -479,8 +479,10 @@ static int validate_set(const struct nlattr *a,
 
        switch (key_type) {
        const struct ovs_key_ipv4 *ipv4_key;
+       const struct ovs_key_ipv6 *ipv6_key;
 
        case OVS_KEY_ATTR_PRIORITY:
+       case OVS_KEY_ATTR_SKB_MARK:
        case OVS_KEY_ATTR_ETHERNET:
                break;
 
@@ -500,6 +502,25 @@ static int validate_set(const struct nlattr *a,
 
                break;
 
+       case OVS_KEY_ATTR_IPV6:
+               if (flow_key->eth.type != htons(ETH_P_IPV6))
+                       return -EINVAL;
+
+               if (!flow_key->ip.proto)
+                       return -EINVAL;
+
+               ipv6_key = nla_data(ovs_key);
+               if (ipv6_key->ipv6_proto != flow_key->ip.proto)
+                       return -EINVAL;
+
+               if (ipv6_key->ipv6_frag != flow_key->ip.frag)
+                       return -EINVAL;
+
+               if (ntohl(ipv6_key->ipv6_label) & 0xFFF00000)
+                       return -EINVAL;
+
+               break;
+
        case OVS_KEY_ATTR_TCP:
                if (flow_key->ip.proto != IPPROTO_TCP)
                        return -EINVAL;
@@ -675,6 +696,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
                goto err_flow_free;
 
        err = ovs_flow_metadata_from_nlattrs(&flow->key.phy.priority,
+                                            &flow->key.phy.skb_mark,
                                             &flow->key.phy.in_port,
                                             a[OVS_PACKET_ATTR_KEY]);
        if (err)
@@ -694,6 +716,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 
        OVS_CB(packet)->flow = flow;
        packet->priority = flow->key.phy.priority;
+       packet->mark = flow->key.phy.skb_mark;
 
        rcu_read_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
index 98c70630ad06178778dc4f1e04275fa6032facc8..c3294cebc4f2d8bb56182004145eac444fbc2908 100644 (file)
@@ -604,6 +604,7 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
 
        key->phy.priority = skb->priority;
        key->phy.in_port = in_port;
+       key->phy.skb_mark = skb->mark;
 
        skb_reset_mac_header(skb);
 
@@ -689,7 +690,8 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
                        }
                }
 
-       } else if (key->eth.type == htons(ETH_P_ARP) && arphdr_ok(skb)) {
+       } else if ((key->eth.type == htons(ETH_P_ARP) ||
+                  key->eth.type == htons(ETH_P_RARP)) && arphdr_ok(skb)) {
                struct arp_eth_header *arp;
 
                arp = (struct arp_eth_header *)skb_network_header(skb);
@@ -702,15 +704,11 @@ int ovs_flow_extract(struct sk_buff *skb, u16 in_port, struct sw_flow_key *key,
                        /* We only match on the lower 8 bits of the opcode. */
                        if (ntohs(arp->ar_op) <= 0xff)
                                key->ip.proto = ntohs(arp->ar_op);
-
-                       if (key->ip.proto == ARPOP_REQUEST
-                                       || key->ip.proto == ARPOP_REPLY) {
-                               memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
-                               memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
-                               memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
-                               memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
-                               key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
-                       }
+                       memcpy(&key->ipv4.addr.src, arp->ar_sip, sizeof(key->ipv4.addr.src));
+                       memcpy(&key->ipv4.addr.dst, arp->ar_tip, sizeof(key->ipv4.addr.dst));
+                       memcpy(key->ipv4.arp.sha, arp->ar_sha, ETH_ALEN);
+                       memcpy(key->ipv4.arp.tha, arp->ar_tha, ETH_ALEN);
+                       key_len = SW_FLOW_KEY_OFFSET(ipv4.arp);
                }
        } else if (key->eth.type == htons(ETH_P_IPV6)) {
                int nh_len;             /* IPv6 Header + Extensions */
@@ -806,6 +804,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_ENCAP] = -1,
        [OVS_KEY_ATTR_PRIORITY] = sizeof(u32),
        [OVS_KEY_ATTR_IN_PORT] = sizeof(u32),
+       [OVS_KEY_ATTR_SKB_MARK] = sizeof(u32),
        [OVS_KEY_ATTR_ETHERNET] = sizeof(struct ovs_key_ethernet),
        [OVS_KEY_ATTR_VLAN] = sizeof(__be16),
        [OVS_KEY_ATTR_ETHERTYPE] = sizeof(__be16),
@@ -991,6 +990,10 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
        } else {
                swkey->phy.in_port = DP_MAX_PORTS;
        }
+       if (attrs & (1 << OVS_KEY_ATTR_SKB_MARK)) {
+               swkey->phy.skb_mark = nla_get_u32(a[OVS_KEY_ATTR_SKB_MARK]);
+               attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
+       }
 
        /* Data attributes. */
        if (!(attrs & (1 << OVS_KEY_ATTR_ETHERNET)))
@@ -1090,7 +1093,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
                        if (err)
                                return err;
                }
-       } else if (swkey->eth.type == htons(ETH_P_ARP)) {
+       } else if (swkey->eth.type == htons(ETH_P_ARP) ||
+                  swkey->eth.type == htons(ETH_P_RARP)) {
                const struct ovs_key_arp *arp_key;
 
                if (!(attrs & (1 << OVS_KEY_ATTR_ARP)))
@@ -1117,6 +1121,8 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
 
 /**
  * ovs_flow_metadata_from_nlattrs - parses Netlink attributes into a flow key.
+ * @priority: receives the skb priority
+ * @mark: receives the skb mark
  * @in_port: receives the extracted input port.
  * @key: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
  * sequence.
@@ -1126,7 +1132,7 @@ int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
  * get the metadata, that is, the parts of the flow key that cannot be
  * extracted from the packet itself.
  */
-int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
+int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port,
                               const struct nlattr *attr)
 {
        const struct nlattr *nla;
@@ -1134,6 +1140,7 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
 
        *in_port = DP_MAX_PORTS;
        *priority = 0;
+       *mark = 0;
 
        nla_for_each_nested(nla, attr, rem) {
                int type = nla_type(nla);
@@ -1152,6 +1159,10 @@ int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
                                        return -EINVAL;
                                *in_port = nla_get_u32(nla);
                                break;
+
+                       case OVS_KEY_ATTR_SKB_MARK:
+                               *mark = nla_get_u32(nla);
+                               break;
                        }
                }
        }
@@ -1173,6 +1184,10 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
            nla_put_u32(skb, OVS_KEY_ATTR_IN_PORT, swkey->phy.in_port))
                goto nla_put_failure;
 
+       if (swkey->phy.skb_mark &&
+           nla_put_u32(skb, OVS_KEY_ATTR_SKB_MARK, swkey->phy.skb_mark))
+               goto nla_put_failure;
+
        nla = nla_reserve(skb, OVS_KEY_ATTR_ETHERNET, sizeof(*eth_key));
        if (!nla)
                goto nla_put_failure;
@@ -1226,7 +1241,8 @@ int ovs_flow_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb)
                ipv6_key->ipv6_tclass = swkey->ip.tos;
                ipv6_key->ipv6_hlimit = swkey->ip.ttl;
                ipv6_key->ipv6_frag = swkey->ip.frag;
-       } else if (swkey->eth.type == htons(ETH_P_ARP)) {
+       } else if (swkey->eth.type == htons(ETH_P_ARP) ||
+                  swkey->eth.type == htons(ETH_P_RARP)) {
                struct ovs_key_arp *arp_key;
 
                nla = nla_reserve(skb, OVS_KEY_ATTR_ARP, sizeof(*arp_key));
index 14a324eb017b44cca9263701d094f3221a37c9a3..a7bb60ff3b5b6f057c8bf5c7300357a9a926e148 100644 (file)
@@ -43,6 +43,7 @@ struct sw_flow_actions {
 struct sw_flow_key {
        struct {
                u32     priority;       /* Packet QoS priority. */
+               u32     skb_mark;       /* SKB mark. */
                u16     in_port;        /* Input switch port (or DP_MAX_PORTS). */
        } phy;
        struct {
@@ -144,6 +145,7 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
  *                         ------  ---  ------  -----
  *  OVS_KEY_ATTR_PRIORITY      4    --     4      8
  *  OVS_KEY_ATTR_IN_PORT       4    --     4      8
+ *  OVS_KEY_ATTR_SKB_MARK      4    --     4      8
  *  OVS_KEY_ATTR_ETHERNET     12    --     4     16
  *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (outer VLAN ethertype)
  *  OVS_KEY_ATTR_8021Q         4    --     4      8
@@ -153,14 +155,14 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
  *  OVS_KEY_ATTR_ICMPV6        2     2     4      8
  *  OVS_KEY_ATTR_ND           28    --     4     32
  *  -------------------------------------------------
- *  total                                       144
+ *  total                                       152
  */
-#define FLOW_BUFSIZE 144
+#define FLOW_BUFSIZE 152
 
 int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
 int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
                      const struct nlattr *);
-int ovs_flow_metadata_from_nlattrs(u32 *priority, u16 *in_port,
+int ovs_flow_metadata_from_nlattrs(u32 *priority, u32 *mark, u16 *in_port,
                               const struct nlattr *);
 
 #define MAX_ACTIONS_BUFSIZE    (16 * 1024)
index 3c1e58ba714bf9534b597c9f28147cc7c3038b39..a9327e2e48ce8450212feef7085f91e446766faa 100644 (file)
@@ -114,6 +114,15 @@ error:
        return ERR_PTR(err);
 }
 
+static void free_port_rcu(struct rcu_head *rcu)
+{
+       struct netdev_vport *netdev_vport = container_of(rcu,
+                                       struct netdev_vport, rcu);
+
+       dev_put(netdev_vport->dev);
+       ovs_vport_free(vport_from_priv(netdev_vport));
+}
+
 static void netdev_destroy(struct vport *vport)
 {
        struct netdev_vport *netdev_vport = netdev_vport_priv(vport);
@@ -122,10 +131,7 @@ static void netdev_destroy(struct vport *vport)
        netdev_rx_handler_unregister(netdev_vport->dev);
        dev_set_promiscuity(netdev_vport->dev, -1);
 
-       synchronize_rcu();
-
-       dev_put(netdev_vport->dev);
-       ovs_vport_free(vport);
+       call_rcu(&netdev_vport->rcu, free_port_rcu);
 }
 
 const char *ovs_netdev_get_name(const struct vport *vport)
@@ -158,7 +164,7 @@ static int netdev_send(struct vport *vport, struct sk_buff *skb)
 
        if (unlikely(packet_length(skb) > mtu && !skb_is_gso(skb))) {
                net_warn_ratelimited("%s: dropped over-mtu packet: %d > %d\n",
-                                    ovs_dp_name(vport->dp),
+                                    netdev_vport->dev->name,
                                     packet_length(skb), mtu);
                goto error;
        }
index f7072a25c60465a4b71455bd71282f57cf139a0c..6478079b3417fd460c9011048be234d62b3478c2 100644 (file)
 #define VPORT_NETDEV_H 1
 
 #include <linux/netdevice.h>
+#include <linux/rcupdate.h>
 
 #include "vport.h"
 
 struct vport *ovs_netdev_get_vport(struct net_device *dev);
 
 struct netdev_vport {
+       struct rcu_head rcu;
+
        struct net_device *dev;
 };
 
index 03779e8a262289f9a8178e62e0adf5afc16a9ae5..70af0bedbac4db09c08c896ba0173466e29e9b79 100644 (file)
@@ -333,8 +333,7 @@ void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
 {
        struct vport_percpu_stats *stats;
 
-       stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
-
+       stats = this_cpu_ptr(vport->percpu_stats);
        u64_stats_update_begin(&stats->sync);
        stats->rx_packets++;
        stats->rx_bytes += skb->len;
@@ -359,7 +358,7 @@ int ovs_vport_send(struct vport *vport, struct sk_buff *skb)
        if (likely(sent)) {
                struct vport_percpu_stats *stats;
 
-               stats = per_cpu_ptr(vport->percpu_stats, smp_processor_id());
+               stats = this_cpu_ptr(vport->percpu_stats);
 
                u64_stats_update_begin(&stats->sync);
                stats->tx_packets++;
index 94060edbbd706ed11c7609913f1e434e5cec76c1..e639645e8fec8ca365c8fc1bc4fb3650db04b5f4 100644 (file)
@@ -1881,7 +1881,35 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
        skb_reserve(skb, hlen);
        skb_reset_network_header(skb);
 
-       data = ph.raw + po->tp_hdrlen - sizeof(struct sockaddr_ll);
+       if (po->tp_tx_has_off) {
+               int off_min, off_max, off;
+               off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll);
+               off_max = po->tx_ring.frame_size - tp_len;
+               if (sock->type == SOCK_DGRAM) {
+                       switch (po->tp_version) {
+                       case TPACKET_V2:
+                               off = ph.h2->tp_net;
+                               break;
+                       default:
+                               off = ph.h1->tp_net;
+                               break;
+                       }
+               } else {
+                       switch (po->tp_version) {
+                       case TPACKET_V2:
+                               off = ph.h2->tp_mac;
+                               break;
+                       default:
+                               off = ph.h1->tp_mac;
+                               break;
+                       }
+               }
+               if (unlikely((off < off_min) || (off_max < off)))
+                       return -EINVAL;
+               data = ph.raw + off;
+       } else {
+               data = ph.raw + po->tp_hdrlen - sizeof(struct sockaddr_ll);
+       }
        to_write = tp_len;
 
        if (sock->type == SOCK_DGRAM) {
@@ -1907,7 +1935,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
                to_write -= dev->hard_header_len;
        }
 
-       err = -EFAULT;
        offset = offset_in_page(data);
        len_max = PAGE_SIZE - offset;
        len = ((to_write > len_max) ? len_max : to_write);
@@ -1957,7 +1984,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 
        mutex_lock(&po->pg_vec_lock);
 
-       err = -EBUSY;
        if (saddr == NULL) {
                dev = po->prot_hook.dev;
                proto   = po->num;
@@ -2478,7 +2504,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol,
        __be16 proto = (__force __be16)protocol; /* weird, but documented */
        int err;
 
-       if (!capable(CAP_NET_RAW))
+       if (!ns_capable(net->user_ns, CAP_NET_RAW))
                return -EPERM;
        if (sock->type != SOCK_DGRAM && sock->type != SOCK_RAW &&
            sock->type != SOCK_PACKET)
@@ -3111,6 +3137,19 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 
                return fanout_add(sk, val & 0xffff, val >> 16);
        }
+       case PACKET_TX_HAS_OFF:
+       {
+               unsigned int val;
+
+               if (optlen != sizeof(val))
+                       return -EINVAL;
+               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
+                       return -EBUSY;
+               if (copy_from_user(&val, optval, sizeof(val)))
+                       return -EFAULT;
+               po->tp_tx_has_off = !!val;
+               return 0;
+       }
        default:
                return -ENOPROTOOPT;
        }
@@ -3202,6 +3241,9 @@ static int packet_getsockopt(struct socket *sock, int level, int optname,
                        ((u32)po->fanout->type << 16)) :
                       0);
                break;
+       case PACKET_TX_HAS_OFF:
+               val = po->tp_tx_has_off;
+               break;
        default:
                return -ENOPROTOOPT;
        }
index 44945f6b7252c5c42e3fddf265a610824b6a646c..e84cab8cb7a99a6a07fe26daa9f33c03f8bb3bda 100644 (file)
@@ -109,6 +109,7 @@ struct packet_sock {
        unsigned int            tp_hdrlen;
        unsigned int            tp_reserve;
        unsigned int            tp_loss:1;
+       unsigned int            tp_tx_has_off:1;
        unsigned int            tp_tstamp;
        struct packet_type      prot_hook ____cacheline_aligned_in_smp;
 };
index 83a8389619aa7ccc0a490a8f8b664200bee53df9..0193630d306125a62f273db3165e98a306249fc0 100644 (file)
@@ -70,6 +70,9 @@ static int addr_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
        int err;
        u8 pnaddr;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
@@ -230,6 +233,9 @@ static int route_doit(struct sk_buff *skb, struct nlmsghdr *nlh, void *attr)
        int err;
        u8 dst;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
index 8d2b3d5a7c21e5ffb2063621a569e1f6280f52ad..7280ab8810c203ed574131c4c9b8a5ea10cf292b 100644 (file)
@@ -50,7 +50,7 @@ struct rds_ib_cache_head {
 };
 
 struct rds_ib_refill_cache {
-       struct rds_ib_cache_head *percpu;
+       struct rds_ib_cache_head __percpu *percpu;
        struct list_head         *xfer;
        struct list_head         *ready;
 };
index 8d194912c695ba86afc235c5792556c912da71f3..8c5bc857f04d92dd85986f4c292437223a4de557 100644 (file)
@@ -418,20 +418,21 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
                                 struct rds_ib_refill_cache *cache)
 {
        unsigned long flags;
-       struct rds_ib_cache_head *chp;
        struct list_head *old;
+       struct list_head __percpu *chpfirst;
 
        local_irq_save(flags);
 
-       chp = per_cpu_ptr(cache->percpu, smp_processor_id());
-       if (!chp->first)
+       chpfirst = __this_cpu_read(cache->percpu->first);
+       if (!chpfirst)
                INIT_LIST_HEAD(new_item);
        else /* put on front */
-               list_add_tail(new_item, chp->first);
-       chp->first = new_item;
-       chp->count++;
+               list_add_tail(new_item, chpfirst);
 
-       if (chp->count < RDS_IB_RECYCLE_BATCH_COUNT)
+       __this_cpu_write(chpfirst, new_item);
+       __this_cpu_inc(cache->percpu->count);
+
+       if (__this_cpu_read(cache->percpu->count) < RDS_IB_RECYCLE_BATCH_COUNT)
                goto end;
 
        /*
@@ -443,12 +444,13 @@ static void rds_ib_recv_cache_put(struct list_head *new_item,
        do {
                old = xchg(&cache->xfer, NULL);
                if (old)
-                       list_splice_entire_tail(old, chp->first);
-               old = cmpxchg(&cache->xfer, NULL, chp->first);
+                       list_splice_entire_tail(old, chpfirst);
+               old = cmpxchg(&cache->xfer, NULL, chpfirst);
        } while (old);
 
-       chp->first = NULL;
-       chp->count = 0;
+
+       __this_cpu_write(chpfirst, NULL);
+       __this_cpu_write(cache->percpu->count, 0);
 end:
        local_irq_restore(flags);
 }
index 62fb51face8a12a002783ee0dd1f3fea88b4ce9f..235e01acac518ad84d7917b53bb2bd524df8ce05 100644 (file)
@@ -509,7 +509,7 @@ config NET_EMATCH_TEXT
 
 config NET_EMATCH_CANID
        tristate "CAN Identifier"
-       depends on NET_EMATCH && CAN
+       depends on NET_EMATCH && (CAN=y || CAN=m)
        ---help---
          Say Y here if you want to be able to classify CAN frames based
          on CAN Identifier.
index 102761d294cbe7b470de479be5f07b7c5d4d69ed..65d240cbf74b7513e7dc42effdc7f126bb4fff65 100644 (file)
@@ -987,6 +987,9 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
        u32 portid = skb ? NETLINK_CB(skb).portid : 0;
        int ret = 0, ovr = 0;
 
+       if ((n->nlmsg_type != RTM_GETACTION) && !capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ACT_MAX, NULL);
        if (ret < 0)
                return ret;
index 7ae02892437c25bf1e925d6dc756ed23aabff1a3..ff55ed6c49b24115f4dc78b505da368a34e06b6b 100644 (file)
@@ -139,6 +139,8 @@ static int tc_ctl_tfilter(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
        int err;
        int tp_created = 0;
 
+       if ((n->nlmsg_type != RTM_GETTFILTER) && !capable(CAP_NET_ADMIN))
+               return -EPERM;
 replay:
        t = nlmsg_data(n);
        protocol = TC_H_MIN(t->tcm_info);
index 2ecde225ae609af970a39e5acc5c2b3ce797f6b2..709b0fb38a1825f427b189cc49199e3d0a625d87 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/skbuff.h>
 #include <linux/cgroup.h>
 #include <linux/rcupdate.h>
+#include <linux/fdtable.h>
 #include <net/rtnetlink.h>
 #include <net/pkt_cls.h>
 #include <net/sock.h>
@@ -53,6 +54,28 @@ static void cgrp_destroy(struct cgroup *cgrp)
        kfree(cgrp_cls_state(cgrp));
 }
 
+static int update_classid(const void *v, struct file *file, unsigned n)
+{
+       int err;
+       struct socket *sock = sock_from_file(file, &err);
+       if (sock)
+               sock->sk->sk_classid = (u32)(unsigned long)v;
+       return 0;
+}
+
+static void cgrp_attach(struct cgroup *cgrp, struct cgroup_taskset *tset)
+{
+       struct task_struct *p;
+       void *v;
+
+       cgroup_taskset_for_each(p, cgrp, tset) {
+               task_lock(p);
+               v = (void *)(unsigned long)task_cls_classid(p);
+               iterate_fd(p->files, 0, update_classid, v);
+               task_unlock(p);
+       }
+}
+
 static u64 read_classid(struct cgroup *cgrp, struct cftype *cft)
 {
        return cgrp_cls_state(cgrp)->classid;
@@ -77,6 +100,7 @@ struct cgroup_subsys net_cls_subsys = {
        .name           = "net_cls",
        .create         = cgrp_create,
        .destroy        = cgrp_destroy,
+       .attach         = cgrp_attach,
        .subsys_id      = net_cls_subsys_id,
        .base_cftypes   = ss_files,
        .module         = THIS_MODULE,
index a18d975db59cea34eb0558490deb800f24c10d22..4799c4840c1a2e89fd22885a9e6212ae1682b819 100644 (file)
@@ -495,16 +495,15 @@ EXPORT_SYMBOL(qdisc_watchdog_init);
 
 void qdisc_watchdog_schedule(struct qdisc_watchdog *wd, psched_time_t expires)
 {
-       ktime_t time;
-
        if (test_bit(__QDISC_STATE_DEACTIVATED,
                     &qdisc_root_sleeping(wd->qdisc)->state))
                return;
 
        qdisc_throttled(wd->qdisc);
-       time = ktime_set(0, 0);
-       time = ktime_add_ns(time, PSCHED_TICKS2NS(expires));
-       hrtimer_start(&wd->timer, time, HRTIMER_MODE_ABS);
+
+       hrtimer_start(&wd->timer,
+                     ns_to_ktime(PSCHED_TICKS2NS(expires)),
+                     HRTIMER_MODE_ABS);
 }
 EXPORT_SYMBOL(qdisc_watchdog_schedule);
 
@@ -981,6 +980,9 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
        struct Qdisc *p = NULL;
        int err;
 
+       if ((n->nlmsg_type != RTM_GETQDISC) && !capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        dev = __dev_get_by_index(net, tcm->tcm_ifindex);
        if (!dev)
                return -ENODEV;
@@ -1044,6 +1046,9 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
        struct Qdisc *q, *p;
        int err;
 
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
 replay:
        /* Reinit, just in case something touches this. */
        tcm = nlmsg_data(n);
@@ -1380,6 +1385,9 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n, void *arg)
        u32 qid = TC_H_MAJ(clid);
        int err;
 
+       if ((n->nlmsg_type != RTM_GETTCLASS) && !capable(CAP_NET_ADMIN))
+               return -EPERM;
+
        dev = __dev_get_by_index(net, tcm->tcm_ifindex);
        if (!dev)
                return -ENODEV;
index 564b9fc8efd3c8778ef8ba155cf17f79d92a9a80..0e19948470b88ce8dff6c3e1cded52a6121fe7ea 100644 (file)
@@ -509,8 +509,7 @@ static void cbq_ovl_delay(struct cbq_class *cl)
                        cl->cpriority = TC_CBQ_MAXPRIO;
                        q->pmask |= (1<<TC_CBQ_MAXPRIO);
 
-                       expires = ktime_set(0, 0);
-                       expires = ktime_add_ns(expires, PSCHED_TICKS2NS(sched));
+                       expires = ns_to_ktime(PSCHED_TICKS2NS(sched));
                        if (hrtimer_try_to_cancel(&q->delay_timer) &&
                            ktime_to_ns(ktime_sub(
                                        hrtimer_get_expires(&q->delay_timer),
index 9d75b7761313c5789ca51fb47d5f0fe49fec6966..d2922c0ef57a65047e82e9fbf8f1a890dcdbea85 100644 (file)
@@ -71,6 +71,12 @@ enum htb_cmode {
        HTB_CAN_SEND            /* class can send */
 };
 
+struct htb_rate_cfg {
+       u64 rate_bps;
+       u32 mult;
+       u32 shift;
+};
+
 /* interior & leaf nodes; props specific to leaves are marked L: */
 struct htb_class {
        struct Qdisc_class_common common;
@@ -118,11 +124,11 @@ struct htb_class {
        int filter_cnt;
 
        /* token bucket parameters */
-       struct qdisc_rate_table *rate;  /* rate table of the class itself */
-       struct qdisc_rate_table *ceil;  /* ceiling rate (limits borrows too) */
-       long buffer, cbuffer;   /* token bucket depth/rate */
+       struct htb_rate_cfg rate;
+       struct htb_rate_cfg ceil;
+       s64 buffer, cbuffer;    /* token bucket depth/rate */
        psched_tdiff_t mbuffer; /* max wait time */
-       long tokens, ctokens;   /* current number of tokens */
+       s64 tokens, ctokens;    /* current number of tokens */
        psched_time_t t_c;      /* checkpoint time */
 };
 
@@ -162,6 +168,45 @@ struct htb_sched {
        struct work_struct work;
 };
 
+static u64 l2t_ns(struct htb_rate_cfg *r, unsigned int len)
+{
+       return ((u64)len * r->mult) >> r->shift;
+}
+
+static void htb_precompute_ratedata(struct htb_rate_cfg *r)
+{
+       u64 factor;
+       u64 mult;
+       int shift;
+
+       r->shift = 0;
+       r->mult = 1;
+       /*
+        * Calibrate mult, shift so that token counting is accurate
+        * for smallest packet size (64 bytes).  Token (time in ns) is
+        * computed as (bytes * 8) * NSEC_PER_SEC / rate_bps.  It will
+        * work as long as the smallest packet transfer time can be
+        * accurately represented in nanosec.
+        */
+       if (r->rate_bps > 0) {
+               /*
+                * Higher shift gives better accuracy.  Find the largest
+                * shift such that mult fits in 32 bits.
+                */
+               for (shift = 0; shift < 16; shift++) {
+                       r->shift = shift;
+                       factor = 8LLU * NSEC_PER_SEC * (1 << r->shift);
+                       mult = div64_u64(factor, r->rate_bps);
+                       if (mult > UINT_MAX)
+                               break;
+               }
+
+               r->shift = shift - 1;
+               factor = 8LLU * NSEC_PER_SEC * (1 << r->shift);
+               r->mult = div64_u64(factor, r->rate_bps);
+       }
+}
+
 /* find class in global hash table using given handle */
 static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch)
 {
@@ -273,7 +318,7 @@ static void htb_add_to_id_tree(struct rb_root *root,
  * already in the queue.
  */
 static void htb_add_to_wait_tree(struct htb_sched *q,
-                                struct htb_class *cl, long delay)
+                                struct htb_class *cl, s64 delay)
 {
        struct rb_node **p = &q->wait_pq[cl->level].rb_node, *parent = NULL;
 
@@ -441,14 +486,14 @@ static void htb_deactivate_prios(struct htb_sched *q, struct htb_class *cl)
                htb_remove_class_from_row(q, cl, mask);
 }
 
-static inline long htb_lowater(const struct htb_class *cl)
+static inline s64 htb_lowater(const struct htb_class *cl)
 {
        if (htb_hysteresis)
                return cl->cmode != HTB_CANT_SEND ? -cl->cbuffer : 0;
        else
                return 0;
 }
-static inline long htb_hiwater(const struct htb_class *cl)
+static inline s64 htb_hiwater(const struct htb_class *cl)
 {
        if (htb_hysteresis)
                return cl->cmode == HTB_CAN_SEND ? -cl->buffer : 0;
@@ -469,9 +514,9 @@ static inline long htb_hiwater(const struct htb_class *cl)
  * mode transitions per time unit. The speed gain is about 1/6.
  */
 static inline enum htb_cmode
-htb_class_mode(struct htb_class *cl, long *diff)
+htb_class_mode(struct htb_class *cl, s64 *diff)
 {
-       long toks;
+       s64 toks;
 
        if ((toks = (cl->ctokens + *diff)) < htb_lowater(cl)) {
                *diff = -toks;
@@ -495,7 +540,7 @@ htb_class_mode(struct htb_class *cl, long *diff)
  * to mode other than HTB_CAN_SEND (see htb_add_to_wait_tree).
  */
 static void
-htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, long *diff)
+htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff)
 {
        enum htb_cmode new_mode = htb_class_mode(cl, diff);
 
@@ -581,26 +626,26 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        return NET_XMIT_SUCCESS;
 }
 
-static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, long diff)
+static inline void htb_accnt_tokens(struct htb_class *cl, int bytes, s64 diff)
 {
-       long toks = diff + cl->tokens;
+       s64 toks = diff + cl->tokens;
 
        if (toks > cl->buffer)
                toks = cl->buffer;
-       toks -= (long) qdisc_l2t(cl->rate, bytes);
+       toks -= (s64) l2t_ns(&cl->rate, bytes);
        if (toks <= -cl->mbuffer)
                toks = 1 - cl->mbuffer;
 
        cl->tokens = toks;
 }
 
-static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, long diff)
+static inline void htb_accnt_ctokens(struct htb_class *cl, int bytes, s64 diff)
 {
-       long toks = diff + cl->ctokens;
+       s64 toks = diff + cl->ctokens;
 
        if (toks > cl->cbuffer)
                toks = cl->cbuffer;
-       toks -= (long) qdisc_l2t(cl->ceil, bytes);
+       toks -= (s64) l2t_ns(&cl->ceil, bytes);
        if (toks <= -cl->mbuffer)
                toks = 1 - cl->mbuffer;
 
@@ -623,10 +668,10 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
 {
        int bytes = qdisc_pkt_len(skb);
        enum htb_cmode old_mode;
-       long diff;
+       s64 diff;
 
        while (cl) {
-               diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
+               diff = min_t(s64, q->now - cl->t_c, cl->mbuffer);
                if (cl->level >= level) {
                        if (cl->level == level)
                                cl->xstats.lends++;
@@ -673,7 +718,7 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
        unsigned long stop_at = start + 2;
        while (time_before(jiffies, stop_at)) {
                struct htb_class *cl;
-               long diff;
+               s64 diff;
                struct rb_node *p = rb_first(&q->wait_pq[level]);
 
                if (!p)
@@ -684,7 +729,7 @@ static psched_time_t htb_do_events(struct htb_sched *q, int level,
                        return cl->pq_key;
 
                htb_safe_rb_erase(p, q->wait_pq + level);
-               diff = psched_tdiff_bounded(q->now, cl->t_c, cl->mbuffer);
+               diff = min_t(s64, q->now - cl->t_c, cl->mbuffer);
                htb_change_class_mode(q, cl, &diff);
                if (cl->cmode != HTB_CAN_SEND)
                        htb_add_to_wait_tree(q, cl, diff);
@@ -871,10 +916,10 @@ ok:
 
        if (!sch->q.qlen)
                goto fin;
-       q->now = psched_get_time();
+       q->now = ktime_to_ns(ktime_get());
        start_at = jiffies;
 
-       next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
+       next_event = q->now + 5 * NSEC_PER_SEC;
 
        for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
                /* common case optimization - skip event handler quickly */
@@ -884,7 +929,7 @@ ok:
                if (q->now >= q->near_ev_cache[level]) {
                        event = htb_do_events(q, level, start_at);
                        if (!event)
-                               event = q->now + PSCHED_TICKS_PER_SEC;
+                               event = q->now + NSEC_PER_SEC;
                        q->near_ev_cache[level] = event;
                } else
                        event = q->near_ev_cache[level];
@@ -903,10 +948,17 @@ ok:
                }
        }
        sch->qstats.overlimits++;
-       if (likely(next_event > q->now))
-               qdisc_watchdog_schedule(&q->watchdog, next_event);
-       else
+       if (likely(next_event > q->now)) {
+               if (!test_bit(__QDISC_STATE_DEACTIVATED,
+                             &qdisc_root_sleeping(q->watchdog.qdisc)->state)) {
+                       ktime_t time = ns_to_ktime(next_event);
+                       qdisc_throttled(q->watchdog.qdisc);
+                       hrtimer_start(&q->watchdog.timer, time,
+                                     HRTIMER_MODE_ABS);
+               }
+       } else {
                schedule_work(&q->work);
+       }
 fin:
        return skb;
 }
@@ -1082,9 +1134,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg,
 
        memset(&opt, 0, sizeof(opt));
 
-       opt.rate = cl->rate->rate;
+       opt.rate.rate = cl->rate.rate_bps >> 3;
        opt.buffer = cl->buffer;
-       opt.ceil = cl->ceil->rate;
+       opt.ceil.rate = cl->ceil.rate_bps >> 3;
        opt.cbuffer = cl->cbuffer;
        opt.quantum = cl->quantum;
        opt.prio = cl->prio;
@@ -1203,9 +1255,6 @@ static void htb_destroy_class(struct Qdisc *sch, struct htb_class *cl)
                qdisc_destroy(cl->un.leaf.q);
        }
        gen_kill_estimator(&cl->bstats, &cl->rate_est);
-       qdisc_put_rtab(cl->rate);
-       qdisc_put_rtab(cl->ceil);
-
        tcf_destroy_chain(&cl->filter_list);
        kfree(cl);
 }
@@ -1307,7 +1356,6 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = (struct htb_class *)*arg, *parent;
        struct nlattr *opt = tca[TCA_OPTIONS];
-       struct qdisc_rate_table *rtab = NULL, *ctab = NULL;
        struct nlattr *tb[__TCA_HTB_MAX];
        struct tc_htb_opt *hopt;
 
@@ -1326,10 +1374,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
        parent = parentid == TC_H_ROOT ? NULL : htb_find(parentid, sch);
 
        hopt = nla_data(tb[TCA_HTB_PARMS]);
-
-       rtab = qdisc_get_rtab(&hopt->rate, tb[TCA_HTB_RTAB]);
-       ctab = qdisc_get_rtab(&hopt->ceil, tb[TCA_HTB_CTAB]);
-       if (!rtab || !ctab)
+       if (!hopt->rate.rate || !hopt->ceil.rate)
                goto failure;
 
        if (!cl) {              /* new class */
@@ -1439,7 +1484,7 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
         * is really leaf before changing cl->un.leaf !
         */
        if (!cl->level) {
-               cl->quantum = rtab->rate.rate / q->rate2quantum;
+               cl->quantum = hopt->rate.rate / q->rate2quantum;
                if (!hopt->quantum && cl->quantum < 1000) {
                        pr_warning(
                               "HTB: quantum of class %X is small. Consider r2q change.\n",
@@ -1460,12 +1505,16 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
 
        cl->buffer = hopt->buffer;
        cl->cbuffer = hopt->cbuffer;
-       if (cl->rate)
-               qdisc_put_rtab(cl->rate);
-       cl->rate = rtab;
-       if (cl->ceil)
-               qdisc_put_rtab(cl->ceil);
-       cl->ceil = ctab;
+
+       cl->rate.rate_bps = (u64)hopt->rate.rate << 3;
+       cl->ceil.rate_bps = (u64)hopt->ceil.rate << 3;
+
+       htb_precompute_ratedata(&cl->rate);
+       htb_precompute_ratedata(&cl->ceil);
+
+       cl->buffer = hopt->buffer << PSCHED_SHIFT;
+       cl->cbuffer = hopt->buffer << PSCHED_SHIFT;
+
        sch_tree_unlock(sch);
 
        qdisc_class_hash_grow(sch, &q->clhash);
@@ -1474,10 +1523,6 @@ static int htb_change_class(struct Qdisc *sch, u32 classid,
        return 0;
 
 failure:
-       if (rtab)
-               qdisc_put_rtab(rtab);
-       if (ctab)
-               qdisc_put_rtab(ctab);
        return err;
 }
 
index f0dd83cff90652dc870f5bc720f9ae1a404b8931..6ed37652a4c388df5f96dde4f4e865d86e1868f6 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * net/sched/sch_qfq.c         Quick Fair Queueing Scheduler.
+ * net/sched/sch_qfq.c         Quick Fair Queueing Plus Scheduler.
  *
  * Copyright (c) 2009 Fabio Checconi, Luigi Rizzo, and Paolo Valente.
+ * Copyright (c) 2012 Paolo Valente.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #include <net/pkt_cls.h>
 
 
-/*  Quick Fair Queueing
-    ===================
+/*  Quick Fair Queueing Plus
+    ========================
 
     Sources:
 
-    Fabio Checconi, Luigi Rizzo, and Paolo Valente: "QFQ: Efficient
+    [1] Paolo Valente,
+    "Reducing the Execution Time of Fair-Queueing Schedulers."
+    http://algo.ing.unimo.it/people/paolo/agg-sched/agg-sched.pdf
+
+    Sources for QFQ:
+
+    [2] Fabio Checconi, Luigi Rizzo, and Paolo Valente: "QFQ: Efficient
     Packet Scheduling with Tight Bandwidth Distribution Guarantees."
 
     See also:
 
 /*
 
+  QFQ+ divides classes into aggregates of at most MAX_AGG_CLASSES
+  classes. Each aggregate is timestamped with a virtual start time S
+  and a virtual finish time F, and scheduled according to its
+  timestamps. S and F are computed as a function of a system virtual
+  time function V. The classes within each aggregate are instead
+  scheduled with DRR.
+
+  To speed up operations, QFQ+ divides also aggregates into a limited
+  number of groups. Which group a class belongs to depends on the
+  ratio between the maximum packet length for the class and the weight
+  of the class. Groups have their own S and F. In the end, QFQ+
+  schedules groups, then aggregates within groups, then classes within
+  aggregates. See [1] and [2] for a full description.
+
   Virtual time computations.
 
   S, F and V are all computed in fixed point arithmetic with
 #define QFQ_MAX_SLOTS  32
 
 /*
- * Shifts used for class<->group mapping.  We allow class weights that are
- * in the range [1, 2^MAX_WSHIFT], and we try to map each class i to the
+ * Shifts used for aggregate<->group mapping.  We allow class weights that are
+ * in the range [1, 2^MAX_WSHIFT], and we try to map each aggregate i to the
  * group with the smallest index that can support the L_i / r_i configured
- * for the class.
+ * for the classes in the aggregate.
  *
  * grp->index is the index of the group; and grp->slot_shift
  * is the shift for the corresponding (scaled) sigma_i.
  */
-#define QFQ_MAX_INDEX          19
-#define QFQ_MAX_WSHIFT         16
+#define QFQ_MAX_INDEX          24
+#define QFQ_MAX_WSHIFT         10
 
-#define        QFQ_MAX_WEIGHT          (1<<QFQ_MAX_WSHIFT)
-#define QFQ_MAX_WSUM           (2*QFQ_MAX_WEIGHT)
+#define        QFQ_MAX_WEIGHT          (1<<QFQ_MAX_WSHIFT) /* see qfq_slot_insert */
+#define QFQ_MAX_WSUM           (64*QFQ_MAX_WEIGHT)
 
 #define FRAC_BITS              30      /* fixed point arithmetic */
 #define ONE_FP                 (1UL << FRAC_BITS)
 #define IWSUM                  (ONE_FP/QFQ_MAX_WSUM)
 
-#define QFQ_MTU_SHIFT          11
-#define QFQ_MIN_SLOT_SHIFT     (FRAC_BITS + QFQ_MTU_SHIFT - QFQ_MAX_INDEX)
+#define QFQ_MTU_SHIFT          16      /* to support TSO/GSO */
+#define QFQ_MIN_LMAX           512     /* see qfq_slot_insert */
+
+#define QFQ_MAX_AGG_CLASSES    8 /* max num classes per aggregate allowed */
 
 /*
  * Possible group states.  These values are used as indexes for the bitmaps
@@ -105,6 +128,8 @@ enum qfq_state { ER, IR, EB, IB, QFQ_MAX_STATE };
 
 struct qfq_group;
 
+struct qfq_aggregate;
+
 struct qfq_class {
        struct Qdisc_class_common common;
 
@@ -115,7 +140,12 @@ struct qfq_class {
        struct gnet_stats_queue qstats;
        struct gnet_stats_rate_est rate_est;
        struct Qdisc *qdisc;
+       struct list_head alist;         /* Link for active-classes list. */
+       struct qfq_aggregate *agg;      /* Parent aggregate. */
+       int deficit;                    /* DRR deficit counter. */
+};
 
+struct qfq_aggregate {
        struct hlist_node next; /* Link for the slot list. */
        u64 S, F;               /* flow timestamps (exact) */
 
@@ -126,8 +156,18 @@ struct qfq_class {
        struct qfq_group *grp;
 
        /* these are copied from the flowset. */
-       u32     inv_w;          /* ONE_FP/weight */
-       u32     lmax;           /* Max packet size for this flow. */
+       u32     class_weight; /* Weight of each class in this aggregate. */
+       /* Max pkt size for the classes in this aggregate, DRR quantum. */
+       int     lmax;
+
+       u32     inv_w;      /* ONE_FP/(sum of weights of classes in aggr.). */
+       u32     budgetmax;  /* Max budget for this aggregate. */
+       u32     initial_budget, budget;     /* Initial and current budget. */
+
+       int               num_classes;  /* Number of classes in this aggr. */
+       struct list_head  active;       /* DRR queue of active classes. */
+
+       struct hlist_node nonfull_next; /* See nonfull_aggs in qfq_sched. */
 };
 
 struct qfq_group {
@@ -137,7 +177,7 @@ struct qfq_group {
        unsigned int front;             /* Index of the front slot. */
        unsigned long full_slots;       /* non-empty slots */
 
-       /* Array of RR lists of active classes. */
+       /* Array of RR lists of active aggregates. */
        struct hlist_head slots[QFQ_MAX_SLOTS];
 };
 
@@ -145,13 +185,28 @@ struct qfq_sched {
        struct tcf_proto *filter_list;
        struct Qdisc_class_hash clhash;
 
-       u64             V;              /* Precise virtual time. */
-       u32             wsum;           /* weight sum */
+       u64                     oldV, V;        /* Precise virtual times. */
+       struct qfq_aggregate    *in_serv_agg;   /* Aggregate being served. */
+       u32                     num_active_agg; /* Num. of active aggregates */
+       u32                     wsum;           /* weight sum */
 
        unsigned long bitmaps[QFQ_MAX_STATE];       /* Group bitmaps. */
        struct qfq_group groups[QFQ_MAX_INDEX + 1]; /* The groups. */
+       u32 min_slot_shift;     /* Index of the group-0 bit in the bitmaps. */
+
+       u32 max_agg_classes;            /* Max number of classes per aggr. */
+       struct hlist_head nonfull_aggs; /* Aggs with room for more classes. */
 };
 
+/*
+ * Possible reasons why the timestamps of an aggregate are updated
+ * enqueue: the aggregate switches from idle to active and must scheduled
+ *         for service
+ * requeue: the aggregate finishes its budget, so it stops being served and
+ *         must be rescheduled for service
+ */
+enum update_reason {enqueue, requeue};
+
 static struct qfq_class *qfq_find_class(struct Qdisc *sch, u32 classid)
 {
        struct qfq_sched *q = qdisc_priv(sch);
@@ -181,18 +236,18 @@ static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = {
  * index = log_2(maxlen/weight) but we need to apply the scaling.
  * This is used only once at flow creation.
  */
-static int qfq_calc_index(u32 inv_w, unsigned int maxlen)
+static int qfq_calc_index(u32 inv_w, unsigned int maxlen, u32 min_slot_shift)
 {
        u64 slot_size = (u64)maxlen * inv_w;
        unsigned long size_map;
        int index = 0;
 
-       size_map = slot_size >> QFQ_MIN_SLOT_SHIFT;
+       size_map = slot_size >> min_slot_shift;
        if (!size_map)
                goto out;
 
        index = __fls(size_map) + 1;    /* basically a log_2 */
-       index -= !(slot_size - (1ULL << (index + QFQ_MIN_SLOT_SHIFT - 1)));
+       index -= !(slot_size - (1ULL << (index + min_slot_shift - 1)));
 
        if (index < 0)
                index = 0;
@@ -203,32 +258,140 @@ out:
        return index;
 }
 
-/* Length of the next packet (0 if the queue is empty). */
-static unsigned int qdisc_peek_len(struct Qdisc *sch)
+static void qfq_deactivate_agg(struct qfq_sched *, struct qfq_aggregate *);
+static void qfq_activate_agg(struct qfq_sched *, struct qfq_aggregate *,
+                            enum update_reason);
+
+static void qfq_init_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
+                        u32 lmax, u32 weight)
 {
-       struct sk_buff *skb;
+       INIT_LIST_HEAD(&agg->active);
+       hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs);
+
+       agg->lmax = lmax;
+       agg->class_weight = weight;
+}
+
+static struct qfq_aggregate *qfq_find_agg(struct qfq_sched *q,
+                                         u32 lmax, u32 weight)
+{
+       struct qfq_aggregate *agg;
+       struct hlist_node *n;
+
+       hlist_for_each_entry(agg, n, &q->nonfull_aggs, nonfull_next)
+               if (agg->lmax == lmax && agg->class_weight == weight)
+                       return agg;
+
+       return NULL;
+}
+
+
+/* Update aggregate as a function of the new number of classes. */
+static void qfq_update_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
+                          int new_num_classes)
+{
+       u32 new_agg_weight;
 
-       skb = sch->ops->peek(sch);
-       return skb ? qdisc_pkt_len(skb) : 0;
+       if (new_num_classes == q->max_agg_classes)
+               hlist_del_init(&agg->nonfull_next);
+
+       if (agg->num_classes > new_num_classes &&
+           new_num_classes == q->max_agg_classes - 1) /* agg no more full */
+               hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs);
+
+       agg->budgetmax = new_num_classes * agg->lmax;
+       new_agg_weight = agg->class_weight * new_num_classes;
+       agg->inv_w = ONE_FP/new_agg_weight;
+
+       if (agg->grp == NULL) {
+               int i = qfq_calc_index(agg->inv_w, agg->budgetmax,
+                                      q->min_slot_shift);
+               agg->grp = &q->groups[i];
+       }
+
+       q->wsum +=
+               (int) agg->class_weight * (new_num_classes - agg->num_classes);
+
+       agg->num_classes = new_num_classes;
+}
+
+/* Add class to aggregate. */
+static void qfq_add_to_agg(struct qfq_sched *q,
+                          struct qfq_aggregate *agg,
+                          struct qfq_class *cl)
+{
+       cl->agg = agg;
+
+       qfq_update_agg(q, agg, agg->num_classes+1);
+       if (cl->qdisc->q.qlen > 0) { /* adding an active class */
+               list_add_tail(&cl->alist, &agg->active);
+               if (list_first_entry(&agg->active, struct qfq_class, alist) ==
+                   cl && q->in_serv_agg != agg) /* agg was inactive */
+                       qfq_activate_agg(q, agg, enqueue); /* schedule agg */
+       }
+}
+
+static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *);
+
+static void qfq_destroy_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
+{
+       if (!hlist_unhashed(&agg->nonfull_next))
+               hlist_del_init(&agg->nonfull_next);
+       if (q->in_serv_agg == agg)
+               q->in_serv_agg = qfq_choose_next_agg(q);
+       kfree(agg);
 }
 
-static void qfq_deactivate_class(struct qfq_sched *, struct qfq_class *);
-static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
-                              unsigned int len);
+/* Deschedule class from within its parent aggregate. */
+static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl)
+{
+       struct qfq_aggregate *agg = cl->agg;
 
-static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl,
-                                   u32 lmax, u32 inv_w, int delta_w)
+
+       list_del(&cl->alist); /* remove from RR queue of the aggregate */
+       if (list_empty(&agg->active)) /* agg is now inactive */
+               qfq_deactivate_agg(q, agg);
+}
+
+/* Remove class from its parent aggregate. */
+static void qfq_rm_from_agg(struct qfq_sched *q, struct qfq_class *cl)
 {
-       int i;
+       struct qfq_aggregate *agg = cl->agg;
 
-       /* update qfq-specific data */
-       cl->lmax = lmax;
-       cl->inv_w = inv_w;
-       i = qfq_calc_index(cl->inv_w, cl->lmax);
+       cl->agg = NULL;
+       if (agg->num_classes == 1) { /* agg being emptied, destroy it */
+               qfq_destroy_agg(q, agg);
+               return;
+       }
+       qfq_update_agg(q, agg, agg->num_classes-1);
+}
 
-       cl->grp = &q->groups[i];
+/* Deschedule class and remove it from its parent aggregate. */
+static void qfq_deact_rm_from_agg(struct qfq_sched *q, struct qfq_class *cl)
+{
+       if (cl->qdisc->q.qlen > 0) /* class is active */
+               qfq_deactivate_class(q, cl);
 
-       q->wsum += delta_w;
+       qfq_rm_from_agg(q, cl);
+}
+
+/* Move class to a new aggregate, matching the new class weight and/or lmax */
+static int qfq_change_agg(struct Qdisc *sch, struct qfq_class *cl, u32 weight,
+                          u32 lmax)
+{
+       struct qfq_sched *q = qdisc_priv(sch);
+       struct qfq_aggregate *new_agg = qfq_find_agg(q, lmax, weight);
+
+       if (new_agg == NULL) { /* create new aggregate */
+               new_agg = kzalloc(sizeof(*new_agg), GFP_ATOMIC);
+               if (new_agg == NULL)
+                       return -ENOBUFS;
+               qfq_init_agg(q, new_agg, lmax, weight);
+       }
+       qfq_deact_rm_from_agg(q, cl);
+       qfq_add_to_agg(q, new_agg, cl);
+
+       return 0;
 }
 
 static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
@@ -236,9 +399,11 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 {
        struct qfq_sched *q = qdisc_priv(sch);
        struct qfq_class *cl = (struct qfq_class *)*arg;
+       bool existing = false;
        struct nlattr *tb[TCA_QFQ_MAX + 1];
+       struct qfq_aggregate *new_agg = NULL;
        u32 weight, lmax, inv_w;
-       int i, err;
+       int err;
        int delta_w;
 
        if (tca[TCA_OPTIONS] == NULL) {
@@ -259,27 +424,32 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        } else
                weight = 1;
 
-       inv_w = ONE_FP / weight;
-       weight = ONE_FP / inv_w;
-       delta_w = weight - (cl ? ONE_FP / cl->inv_w : 0);
-       if (q->wsum + delta_w > QFQ_MAX_WSUM) {
-               pr_notice("qfq: total weight out of range (%u + %u)\n",
-                         delta_w, q->wsum);
-               return -EINVAL;
-       }
-
        if (tb[TCA_QFQ_LMAX]) {
                lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
-               if (!lmax || lmax > (1UL << QFQ_MTU_SHIFT)) {
+               if (lmax < QFQ_MIN_LMAX || lmax > (1UL << QFQ_MTU_SHIFT)) {
                        pr_notice("qfq: invalid max length %u\n", lmax);
                        return -EINVAL;
                }
        } else
-               lmax = 1UL << QFQ_MTU_SHIFT;
+               lmax = psched_mtu(qdisc_dev(sch));
+
+       inv_w = ONE_FP / weight;
+       weight = ONE_FP / inv_w;
 
-       if (cl != NULL) {
-               bool need_reactivation = false;
+       if (cl != NULL &&
+           lmax == cl->agg->lmax &&
+           weight == cl->agg->class_weight)
+               return 0; /* nothing to change */
 
+       delta_w = weight - (cl ? cl->agg->class_weight : 0);
+
+       if (q->wsum + delta_w > QFQ_MAX_WSUM) {
+               pr_notice("qfq: total weight out of range (%d + %u)\n",
+                         delta_w, q->wsum);
+               return -EINVAL;
+       }
+
+       if (cl != NULL) { /* modify existing class */
                if (tca[TCA_RATE]) {
                        err = gen_replace_estimator(&cl->bstats, &cl->rate_est,
                                                    qdisc_root_sleeping_lock(sch),
@@ -287,41 +457,18 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                        if (err)
                                return err;
                }
-
-               if (lmax == cl->lmax && inv_w == cl->inv_w)
-                       return 0; /* nothing to update */
-
-               i = qfq_calc_index(inv_w, lmax);
-               sch_tree_lock(sch);
-               if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) {
-                       /*
-                        * shift cl->F back, to not charge the
-                        * class for the not-yet-served head
-                        * packet
-                        */
-                       cl->F = cl->S;
-                       /* remove class from its slot in the old group */
-                       qfq_deactivate_class(q, cl);
-                       need_reactivation = true;
-               }
-
-               qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
-
-               if (need_reactivation) /* activate in new group */
-                       qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc));
-               sch_tree_unlock(sch);
-
-               return 0;
+               existing = true;
+               goto set_change_agg;
        }
 
+       /* create and init new class */
        cl = kzalloc(sizeof(struct qfq_class), GFP_KERNEL);
        if (cl == NULL)
                return -ENOBUFS;
 
        cl->refcnt = 1;
        cl->common.classid = classid;
-
-       qfq_update_class_params(q, cl, lmax, inv_w, delta_w);
+       cl->deficit = lmax;
 
        cl->qdisc = qdisc_create_dflt(sch->dev_queue,
                                      &pfifo_qdisc_ops, classid);
@@ -332,11 +479,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
                err = gen_new_estimator(&cl->bstats, &cl->rate_est,
                                        qdisc_root_sleeping_lock(sch),
                                        tca[TCA_RATE]);
-               if (err) {
-                       qdisc_destroy(cl->qdisc);
-                       kfree(cl);
-                       return err;
-               }
+               if (err)
+                       goto destroy_class;
        }
 
        sch_tree_lock(sch);
@@ -345,19 +489,39 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
 
        qdisc_class_hash_grow(sch, &q->clhash);
 
+set_change_agg:
+       sch_tree_lock(sch);
+       new_agg = qfq_find_agg(q, lmax, weight);
+       if (new_agg == NULL) { /* create new aggregate */
+               sch_tree_unlock(sch);
+               new_agg = kzalloc(sizeof(*new_agg), GFP_KERNEL);
+               if (new_agg == NULL) {
+                       err = -ENOBUFS;
+                       gen_kill_estimator(&cl->bstats, &cl->rate_est);
+                       goto destroy_class;
+               }
+               sch_tree_lock(sch);
+               qfq_init_agg(q, new_agg, lmax, weight);
+       }
+       if (existing)
+               qfq_deact_rm_from_agg(q, cl);
+       qfq_add_to_agg(q, new_agg, cl);
+       sch_tree_unlock(sch);
+
        *arg = (unsigned long)cl;
        return 0;
+
+destroy_class:
+       qdisc_destroy(cl->qdisc);
+       kfree(cl);
+       return err;
 }
 
 static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl)
 {
        struct qfq_sched *q = qdisc_priv(sch);
 
-       if (cl->inv_w) {
-               q->wsum -= ONE_FP / cl->inv_w;
-               cl->inv_w = 0;
-       }
-
+       qfq_rm_from_agg(q, cl);
        gen_kill_estimator(&cl->bstats, &cl->rate_est);
        qdisc_destroy(cl->qdisc);
        kfree(cl);
@@ -472,8 +636,8 @@ static int qfq_dump_class(struct Qdisc *sch, unsigned long arg,
        nest = nla_nest_start(skb, TCA_OPTIONS);
        if (nest == NULL)
                goto nla_put_failure;
-       if (nla_put_u32(skb, TCA_QFQ_WEIGHT, ONE_FP/cl->inv_w) ||
-           nla_put_u32(skb, TCA_QFQ_LMAX, cl->lmax))
+       if (nla_put_u32(skb, TCA_QFQ_WEIGHT, cl->agg->class_weight) ||
+           nla_put_u32(skb, TCA_QFQ_LMAX, cl->agg->lmax))
                goto nla_put_failure;
        return nla_nest_end(skb, nest);
 
@@ -491,8 +655,8 @@ static int qfq_dump_class_stats(struct Qdisc *sch, unsigned long arg,
        memset(&xstats, 0, sizeof(xstats));
        cl->qdisc->qstats.qlen = cl->qdisc->q.qlen;
 
-       xstats.weight = ONE_FP/cl->inv_w;
-       xstats.lmax = cl->lmax;
+       xstats.weight = cl->agg->class_weight;
+       xstats.lmax = cl->agg->lmax;
 
        if (gnet_stats_copy_basic(d, &cl->bstats) < 0 ||
            gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 ||
@@ -643,16 +807,16 @@ static void qfq_unblock_groups(struct qfq_sched *q, int index, u64 old_F)
  * perhaps
  *
        old_V ^= q->V;
-       old_V >>= QFQ_MIN_SLOT_SHIFT;
+       old_V >>= q->min_slot_shift;
        if (old_V) {
                ...
        }
  *
  */
-static void qfq_make_eligible(struct qfq_sched *q, u64 old_V)
+static void qfq_make_eligible(struct qfq_sched *q)
 {
-       unsigned long vslot = q->V >> QFQ_MIN_SLOT_SHIFT;
-       unsigned long old_vslot = old_V >> QFQ_MIN_SLOT_SHIFT;
+       unsigned long vslot = q->V >> q->min_slot_shift;
+       unsigned long old_vslot = q->oldV >> q->min_slot_shift;
 
        if (vslot != old_vslot) {
                unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1;
@@ -663,25 +827,62 @@ static void qfq_make_eligible(struct qfq_sched *q, u64 old_V)
 
 
 /*
- * XXX we should make sure that slot becomes less than 32.
- * This is guaranteed by the input values.
- * roundedS is always cl->S rounded on grp->slot_shift bits.
+ * The index of the slot in which the aggregate is to be inserted must
+ * not be higher than QFQ_MAX_SLOTS-2. There is a '-2' and not a '-1'
+ * because the start time of the group may be moved backward by one
+ * slot after the aggregate has been inserted, and this would cause
+ * non-empty slots to be right-shifted by one position.
+ *
+ * If the weight and lmax (max_pkt_size) of the classes do not change,
+ * then QFQ+ does meet the above contraint according to the current
+ * values of its parameters. In fact, if the weight and lmax of the
+ * classes do not change, then, from the theory, QFQ+ guarantees that
+ * the slot index is never higher than
+ * 2 + QFQ_MAX_AGG_CLASSES * ((1<<QFQ_MTU_SHIFT)/QFQ_MIN_LMAX) *
+ * (QFQ_MAX_WEIGHT/QFQ_MAX_WSUM) = 2 + 8 * 128 * (1 / 64) = 18
+ *
+ * When the weight of a class is increased or the lmax of the class is
+ * decreased, a new aggregate with smaller slot size than the original
+ * parent aggregate of the class may happen to be activated. The
+ * activation of this aggregate should be properly delayed to when the
+ * service of the class has finished in the ideal system tracked by
+ * QFQ+. If the activation of the aggregate is not delayed to this
+ * reference time instant, then this aggregate may be unjustly served
+ * before other aggregates waiting for service. This may cause the
+ * above bound to the slot index to be violated for some of these
+ * unlucky aggregates.
+ *
+ * Instead of delaying the activation of the new aggregate, which is
+ * quite complex, the following inaccurate but simple solution is used:
+ * if the slot index is higher than QFQ_MAX_SLOTS-2, then the
+ * timestamps of the aggregate are shifted backward so as to let the
+ * slot index become equal to QFQ_MAX_SLOTS-2.
  */
-static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl,
+static void qfq_slot_insert(struct qfq_group *grp, struct qfq_aggregate *agg,
                            u64 roundedS)
 {
        u64 slot = (roundedS - grp->S) >> grp->slot_shift;
-       unsigned int i = (grp->front + slot) % QFQ_MAX_SLOTS;
+       unsigned int i; /* slot index in the bucket list */
+
+       if (unlikely(slot > QFQ_MAX_SLOTS - 2)) {
+               u64 deltaS = roundedS - grp->S -
+                       ((u64)(QFQ_MAX_SLOTS - 2)<<grp->slot_shift);
+               agg->S -= deltaS;
+               agg->F -= deltaS;
+               slot = QFQ_MAX_SLOTS - 2;
+       }
 
-       hlist_add_head(&cl->next, &grp->slots[i]);
+       i = (grp->front + slot) % QFQ_MAX_SLOTS;
+
+       hlist_add_head(&agg->next, &grp->slots[i]);
        __set_bit(slot, &grp->full_slots);
 }
 
 /* Maybe introduce hlist_first_entry?? */
-static struct qfq_class *qfq_slot_head(struct qfq_group *grp)
+static struct qfq_aggregate *qfq_slot_head(struct qfq_group *grp)
 {
        return hlist_entry(grp->slots[grp->front].first,
-                          struct qfq_class, next);
+                          struct qfq_aggregate, next);
 }
 
 /*
@@ -689,20 +890,20 @@ static struct qfq_class *qfq_slot_head(struct qfq_group *grp)
  */
 static void qfq_front_slot_remove(struct qfq_group *grp)
 {
-       struct qfq_class *cl = qfq_slot_head(grp);
+       struct qfq_aggregate *agg = qfq_slot_head(grp);
 
-       BUG_ON(!cl);
-       hlist_del(&cl->next);
+       BUG_ON(!agg);
+       hlist_del(&agg->next);
        if (hlist_empty(&grp->slots[grp->front]))
                __clear_bit(0, &grp->full_slots);
 }
 
 /*
- * Returns the first full queue in a group. As a side effect,
- * adjust the bucket list so the first non-empty bucket is at
- * position 0 in full_slots.
+ * Returns the first aggregate in the first non-empty bucket of the
+ * group. As a side effect, adjusts the bucket list so the first
+ * non-empty bucket is at position 0 in full_slots.
  */
-static struct qfq_class *qfq_slot_scan(struct qfq_group *grp)
+static struct qfq_aggregate *qfq_slot_scan(struct qfq_group *grp)
 {
        unsigned int i;
 
@@ -738,7 +939,7 @@ static void qfq_slot_rotate(struct qfq_group *grp, u64 roundedS)
        grp->front = (grp->front - i) % QFQ_MAX_SLOTS;
 }
 
-static void qfq_update_eligible(struct qfq_sched *q, u64 old_V)
+static void qfq_update_eligible(struct qfq_sched *q)
 {
        struct qfq_group *grp;
        unsigned long ineligible;
@@ -750,137 +951,226 @@ static void qfq_update_eligible(struct qfq_sched *q, u64 old_V)
                        if (qfq_gt(grp->S, q->V))
                                q->V = grp->S;
                }
-               qfq_make_eligible(q, old_V);
+               qfq_make_eligible(q);
        }
 }
 
-/*
- * Updates the class, returns true if also the group needs to be updated.
- */
-static bool qfq_update_class(struct qfq_group *grp, struct qfq_class *cl)
+/* Dequeue head packet of the head class in the DRR queue of the aggregate. */
+static void agg_dequeue(struct qfq_aggregate *agg,
+                       struct qfq_class *cl, unsigned int len)
 {
-       unsigned int len = qdisc_peek_len(cl->qdisc);
+       qdisc_dequeue_peeked(cl->qdisc);
 
-       cl->S = cl->F;
-       if (!len)
-               qfq_front_slot_remove(grp);     /* queue is empty */
-       else {
-               u64 roundedS;
-
-               cl->F = cl->S + (u64)len * cl->inv_w;
-               roundedS = qfq_round_down(cl->S, grp->slot_shift);
-               if (roundedS == grp->S)
-                       return false;
+       cl->deficit -= (int) len;
 
-               qfq_front_slot_remove(grp);
-               qfq_slot_insert(grp, cl, roundedS);
+       if (cl->qdisc->q.qlen == 0) /* no more packets, remove from list */
+               list_del(&cl->alist);
+       else if (cl->deficit < qdisc_pkt_len(cl->qdisc->ops->peek(cl->qdisc))) {
+               cl->deficit += agg->lmax;
+               list_move_tail(&cl->alist, &agg->active);
        }
+}
 
-       return true;
+static inline struct sk_buff *qfq_peek_skb(struct qfq_aggregate *agg,
+                                          struct qfq_class **cl,
+                                          unsigned int *len)
+{
+       struct sk_buff *skb;
+
+       *cl = list_first_entry(&agg->active, struct qfq_class, alist);
+       skb = (*cl)->qdisc->ops->peek((*cl)->qdisc);
+       if (skb == NULL)
+               WARN_ONCE(1, "qfq_dequeue: non-workconserving leaf\n");
+       else
+               *len = qdisc_pkt_len(skb);
+
+       return skb;
+}
+
+/* Update F according to the actual service received by the aggregate. */
+static inline void charge_actual_service(struct qfq_aggregate *agg)
+{
+       /* compute the service received by the aggregate */
+       u32 service_received = agg->initial_budget - agg->budget;
+
+       agg->F = agg->S + (u64)service_received * agg->inv_w;
 }
 
 static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
 {
        struct qfq_sched *q = qdisc_priv(sch);
-       struct qfq_group *grp;
+       struct qfq_aggregate *in_serv_agg = q->in_serv_agg;
        struct qfq_class *cl;
-       struct sk_buff *skb;
-       unsigned int len;
-       u64 old_V;
+       struct sk_buff *skb = NULL;
+       /* next-packet len, 0 means no more active classes in in-service agg */
+       unsigned int len = 0;
 
-       if (!q->bitmaps[ER])
+       if (in_serv_agg == NULL)
                return NULL;
 
-       grp = qfq_ffs(q, q->bitmaps[ER]);
+       if (!list_empty(&in_serv_agg->active))
+               skb = qfq_peek_skb(in_serv_agg, &cl, &len);
 
-       cl = qfq_slot_head(grp);
-       skb = qdisc_dequeue_peeked(cl->qdisc);
-       if (!skb) {
-               WARN_ONCE(1, "qfq_dequeue: non-workconserving leaf\n");
-               return NULL;
+       /*
+        * If there are no active classes in the in-service aggregate,
+        * or if the aggregate has not enough budget to serve its next
+        * class, then choose the next aggregate to serve.
+        */
+       if (len == 0 || in_serv_agg->budget < len) {
+               charge_actual_service(in_serv_agg);
+
+               /* recharge the budget of the aggregate */
+               in_serv_agg->initial_budget = in_serv_agg->budget =
+                       in_serv_agg->budgetmax;
+
+               if (!list_empty(&in_serv_agg->active))
+                       /*
+                        * Still active: reschedule for
+                        * service. Possible optimization: if no other
+                        * aggregate is active, then there is no point
+                        * in rescheduling this aggregate, and we can
+                        * just keep it as the in-service one. This
+                        * should be however a corner case, and to
+                        * handle it, we would need to maintain an
+                        * extra num_active_aggs field.
+                       */
+                       qfq_activate_agg(q, in_serv_agg, requeue);
+               else if (sch->q.qlen == 0) { /* no aggregate to serve */
+                       q->in_serv_agg = NULL;
+                       return NULL;
+               }
+
+               /*
+                * If we get here, there are other aggregates queued:
+                * choose the new aggregate to serve.
+                */
+               in_serv_agg = q->in_serv_agg = qfq_choose_next_agg(q);
+               skb = qfq_peek_skb(in_serv_agg, &cl, &len);
        }
+       if (!skb)
+               return NULL;
 
        sch->q.qlen--;
        qdisc_bstats_update(sch, skb);
 
-       old_V = q->V;
-       len = qdisc_pkt_len(skb);
+       agg_dequeue(in_serv_agg, cl, len);
+       in_serv_agg->budget -= len;
        q->V += (u64)len * IWSUM;
        pr_debug("qfq dequeue: len %u F %lld now %lld\n",
-                len, (unsigned long long) cl->F, (unsigned long long) q->V);
+                len, (unsigned long long) in_serv_agg->F,
+                (unsigned long long) q->V);
 
-       if (qfq_update_class(grp, cl)) {
-               u64 old_F = grp->F;
+       return skb;
+}
 
-               cl = qfq_slot_scan(grp);
-               if (!cl)
-                       __clear_bit(grp->index, &q->bitmaps[ER]);
-               else {
-                       u64 roundedS = qfq_round_down(cl->S, grp->slot_shift);
-                       unsigned int s;
+static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *q)
+{
+       struct qfq_group *grp;
+       struct qfq_aggregate *agg, *new_front_agg;
+       u64 old_F;
 
-                       if (grp->S == roundedS)
-                               goto skip_unblock;
-                       grp->S = roundedS;
-                       grp->F = roundedS + (2ULL << grp->slot_shift);
-                       __clear_bit(grp->index, &q->bitmaps[ER]);
-                       s = qfq_calc_state(q, grp);
-                       __set_bit(grp->index, &q->bitmaps[s]);
-               }
+       qfq_update_eligible(q);
+       q->oldV = q->V;
 
-               qfq_unblock_groups(q, grp->index, old_F);
+       if (!q->bitmaps[ER])
+               return NULL;
+
+       grp = qfq_ffs(q, q->bitmaps[ER]);
+       old_F = grp->F;
+
+       agg = qfq_slot_head(grp);
+
+       /* agg starts to be served, remove it from schedule */
+       qfq_front_slot_remove(grp);
+
+       new_front_agg = qfq_slot_scan(grp);
+
+       if (new_front_agg == NULL) /* group is now inactive, remove from ER */
+               __clear_bit(grp->index, &q->bitmaps[ER]);
+       else {
+               u64 roundedS = qfq_round_down(new_front_agg->S,
+                                             grp->slot_shift);
+               unsigned int s;
+
+               if (grp->S == roundedS)
+                       return agg;
+               grp->S = roundedS;
+               grp->F = roundedS + (2ULL << grp->slot_shift);
+               __clear_bit(grp->index, &q->bitmaps[ER]);
+               s = qfq_calc_state(q, grp);
+               __set_bit(grp->index, &q->bitmaps[s]);
        }
 
-skip_unblock:
-       qfq_update_eligible(q, old_V);
+       qfq_unblock_groups(q, grp->index, old_F);
 
-       return skb;
+       return agg;
 }
 
 /*
- * Assign a reasonable start time for a new flow k in group i.
+ * Assign a reasonable start time for a new aggregate in group i.
  * Admissible values for \hat(F) are multiples of \sigma_i
  * no greater than V+\sigma_i . Larger values mean that
  * we had a wraparound so we consider the timestamp to be stale.
  *
  * If F is not stale and F >= V then we set S = F.
  * Otherwise we should assign S = V, but this may violate
- * the ordering in ER. So, if we have groups in ER, set S to
- * the F_j of the first group j which would be blocking us.
+ * the ordering in EB (see [2]). So, if we have groups in ER,
+ * set S to the F_j of the first group j which would be blocking us.
  * We are guaranteed not to move S backward because
  * otherwise our group i would still be blocked.
  */
-static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
+static void qfq_update_start(struct qfq_sched *q, struct qfq_aggregate *agg)
 {
        unsigned long mask;
        u64 limit, roundedF;
-       int slot_shift = cl->grp->slot_shift;
+       int slot_shift = agg->grp->slot_shift;
 
-       roundedF = qfq_round_down(cl->F, slot_shift);
+       roundedF = qfq_round_down(agg->F, slot_shift);
        limit = qfq_round_down(q->V, slot_shift) + (1ULL << slot_shift);
 
-       if (!qfq_gt(cl->F, q->V) || qfq_gt(roundedF, limit)) {
+       if (!qfq_gt(agg->F, q->V) || qfq_gt(roundedF, limit)) {
                /* timestamp was stale */
-               mask = mask_from(q->bitmaps[ER], cl->grp->index);
+               mask = mask_from(q->bitmaps[ER], agg->grp->index);
                if (mask) {
                        struct qfq_group *next = qfq_ffs(q, mask);
                        if (qfq_gt(roundedF, next->F)) {
                                if (qfq_gt(limit, next->F))
-                                       cl->S = next->F;
+                                       agg->S = next->F;
                                else /* preserve timestamp correctness */
-                                       cl->S = limit;
+                                       agg->S = limit;
                                return;
                        }
                }
-               cl->S = q->V;
+               agg->S = q->V;
        } else  /* timestamp is not stale */
-               cl->S = cl->F;
+               agg->S = agg->F;
+}
+
+/*
+ * Update the timestamps of agg before scheduling/rescheduling it for
+ * service.  In particular, assign to agg->F its maximum possible
+ * value, i.e., the virtual finish time with which the aggregate
+ * should be labeled if it used all its budget once in service.
+ */
+static inline void
+qfq_update_agg_ts(struct qfq_sched *q,
+                   struct qfq_aggregate *agg, enum update_reason reason)
+{
+       if (reason != requeue)
+               qfq_update_start(q, agg);
+       else /* just charge agg for the service received */
+               agg->S = agg->F;
+
+       agg->F = agg->S + (u64)agg->budgetmax * agg->inv_w;
 }
 
+static void qfq_schedule_agg(struct qfq_sched *, struct qfq_aggregate *);
+
 static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct qfq_sched *q = qdisc_priv(sch);
        struct qfq_class *cl;
+       struct qfq_aggregate *agg;
        int err = 0;
 
        cl = qfq_classify(skb, sch, &err);
@@ -892,6 +1182,15 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        }
        pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
 
+       if (unlikely(cl->agg->lmax < qdisc_pkt_len(skb))) {
+               pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
+                        cl->agg->lmax, qdisc_pkt_len(skb), cl->common.classid);
+               err = qfq_change_agg(sch, cl, cl->agg->class_weight,
+                                    qdisc_pkt_len(skb));
+               if (err)
+                       return err;
+       }
+
        err = qdisc_enqueue(skb, cl->qdisc);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                pr_debug("qfq_enqueue: enqueue failed %d\n", err);
@@ -905,35 +1204,50 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        bstats_update(&cl->bstats, skb);
        ++sch->q.qlen;
 
-       /* If the new skb is not the head of queue, then done here. */
-       if (cl->qdisc->q.qlen != 1)
+       agg = cl->agg;
+       /* if the queue was not empty, then done here */
+       if (cl->qdisc->q.qlen != 1) {
+               if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) &&
+                   list_first_entry(&agg->active, struct qfq_class, alist)
+                   == cl && cl->deficit < qdisc_pkt_len(skb))
+                       list_move_tail(&cl->alist, &agg->active);
+
                return err;
+       }
 
-       /* If reach this point, queue q was idle */
-       qfq_activate_class(q, cl, qdisc_pkt_len(skb));
+       /* schedule class for service within the aggregate */
+       cl->deficit = agg->lmax;
+       list_add_tail(&cl->alist, &agg->active);
+
+       if (list_first_entry(&agg->active, struct qfq_class, alist) != cl)
+               return err; /* aggregate was not empty, nothing else to do */
+
+       /* recharge budget */
+       agg->initial_budget = agg->budget = agg->budgetmax;
+
+       qfq_update_agg_ts(q, agg, enqueue);
+       if (q->in_serv_agg == NULL)
+               q->in_serv_agg = agg;
+       else if (agg != q->in_serv_agg)
+               qfq_schedule_agg(q, agg);
 
        return err;
 }
 
 /*
- * Handle class switch from idle to backlogged.
+ * Schedule aggregate according to its timestamps.
  */
-static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
-                              unsigned int pkt_len)
+static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
 {
-       struct qfq_group *grp = cl->grp;
+       struct qfq_group *grp = agg->grp;
        u64 roundedS;
        int s;
 
-       qfq_update_start(q, cl);
-
-       /* compute new finish time and rounded start. */
-       cl->F = cl->S + (u64)pkt_len * cl->inv_w;
-       roundedS = qfq_round_down(cl->S, grp->slot_shift);
+       roundedS = qfq_round_down(agg->S, grp->slot_shift);
 
        /*
-        * insert cl in the correct bucket.
-        * If cl->S >= grp->S we don't need to adjust the
+        * Insert agg in the correct bucket.
+        * If agg->S >= grp->S we don't need to adjust the
         * bucket list and simply go to the insertion phase.
         * Otherwise grp->S is decreasing, we must make room
         * in the bucket list, and also recompute the group state.
@@ -941,10 +1255,10 @@ static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
         * was in ER make sure to adjust V.
         */
        if (grp->full_slots) {
-               if (!qfq_gt(grp->S, cl->S))
+               if (!qfq_gt(grp->S, agg->S))
                        goto skip_update;
 
-               /* create a slot for this cl->S */
+               /* create a slot for this agg->S */
                qfq_slot_rotate(grp, roundedS);
                /* group was surely ineligible, remove */
                __clear_bit(grp->index, &q->bitmaps[IR]);
@@ -959,46 +1273,61 @@ static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl,
 
        pr_debug("qfq enqueue: new state %d %#lx S %lld F %lld V %lld\n",
                 s, q->bitmaps[s],
-                (unsigned long long) cl->S,
-                (unsigned long long) cl->F,
+                (unsigned long long) agg->S,
+                (unsigned long long) agg->F,
                 (unsigned long long) q->V);
 
 skip_update:
-       qfq_slot_insert(grp, cl, roundedS);
+       qfq_slot_insert(grp, agg, roundedS);
 }
 
 
+/* Update agg ts and schedule agg for service */
+static void qfq_activate_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
+                            enum update_reason reason)
+{
+       qfq_update_agg_ts(q, agg, reason);
+       qfq_schedule_agg(q, agg);
+}
+
 static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp,
-                           struct qfq_class *cl)
+                           struct qfq_aggregate *agg)
 {
        unsigned int i, offset;
        u64 roundedS;
 
-       roundedS = qfq_round_down(cl->S, grp->slot_shift);
+       roundedS = qfq_round_down(agg->S, grp->slot_shift);
        offset = (roundedS - grp->S) >> grp->slot_shift;
+
        i = (grp->front + offset) % QFQ_MAX_SLOTS;
 
-       hlist_del(&cl->next);
+       hlist_del(&agg->next);
        if (hlist_empty(&grp->slots[i]))
                __clear_bit(offset, &grp->full_slots);
 }
 
 /*
- * called to forcibly destroy a queue.
- * If the queue is not in the front bucket, or if it has
- * other queues in the front bucket, we can simply remove
- * the queue with no other side effects.
+ * Called to forcibly deschedule an aggregate.  If the aggregate is
+ * not in the front bucket, or if the latter has other aggregates in
+ * the front bucket, we can simply remove the aggregate with no other
+ * side effects.
  * Otherwise we must propagate the event up.
  */
-static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl)
+static void qfq_deactivate_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
 {
-       struct qfq_group *grp = cl->grp;
+       struct qfq_group *grp = agg->grp;
        unsigned long mask;
        u64 roundedS;
        int s;
 
-       cl->F = cl->S;
-       qfq_slot_remove(q, grp, cl);
+       if (agg == q->in_serv_agg) {
+               charge_actual_service(agg);
+               q->in_serv_agg = qfq_choose_next_agg(q);
+               return;
+       }
+
+       agg->F = agg->S;
+       qfq_slot_remove(q, grp, agg);
 
        if (!grp->full_slots) {
                __clear_bit(grp->index, &q->bitmaps[IR]);
@@ -1017,8 +1346,8 @@ static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl)
                }
                __clear_bit(grp->index, &q->bitmaps[ER]);
        } else if (hlist_empty(&grp->slots[grp->front])) {
-               cl = qfq_slot_scan(grp);
-               roundedS = qfq_round_down(cl->S, grp->slot_shift);
+               agg = qfq_slot_scan(grp);
+               roundedS = qfq_round_down(agg->S, grp->slot_shift);
                if (grp->S != roundedS) {
                        __clear_bit(grp->index, &q->bitmaps[ER]);
                        __clear_bit(grp->index, &q->bitmaps[IR]);
@@ -1031,7 +1360,7 @@ static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl)
                }
        }
 
-       qfq_update_eligible(q, q->V);
+       qfq_update_eligible(q);
 }
 
 static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
@@ -1043,6 +1372,32 @@ static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
                qfq_deactivate_class(q, cl);
 }
 
+static unsigned int qfq_drop_from_slot(struct qfq_sched *q,
+                                      struct hlist_head *slot)
+{
+       struct qfq_aggregate *agg;
+       struct hlist_node *n;
+       struct qfq_class *cl;
+       unsigned int len;
+
+       hlist_for_each_entry(agg, n, slot, next) {
+               list_for_each_entry(cl, &agg->active, alist) {
+
+                       if (!cl->qdisc->ops->drop)
+                               continue;
+
+                       len = cl->qdisc->ops->drop(cl->qdisc);
+                       if (len > 0) {
+                               if (cl->qdisc->q.qlen == 0)
+                                       qfq_deactivate_class(q, cl);
+
+                               return len;
+                       }
+               }
+       }
+       return 0;
+}
+
 static unsigned int qfq_drop(struct Qdisc *sch)
 {
        struct qfq_sched *q = qdisc_priv(sch);
@@ -1052,24 +1407,13 @@ static unsigned int qfq_drop(struct Qdisc *sch)
        for (i = 0; i <= QFQ_MAX_INDEX; i++) {
                grp = &q->groups[i];
                for (j = 0; j < QFQ_MAX_SLOTS; j++) {
-                       struct qfq_class *cl;
-                       struct hlist_node *n;
-
-                       hlist_for_each_entry(cl, n, &grp->slots[j], next) {
-
-                               if (!cl->qdisc->ops->drop)
-                                       continue;
-
-                               len = cl->qdisc->ops->drop(cl->qdisc);
-                               if (len > 0) {
-                                       sch->q.qlen--;
-                                       if (!cl->qdisc->q.qlen)
-                                               qfq_deactivate_class(q, cl);
-
-                                       return len;
-                               }
+                       len = qfq_drop_from_slot(q, &grp->slots[j]);
+                       if (len > 0) {
+                               sch->q.qlen--;
+                               return len;
                        }
                }
+
        }
 
        return 0;
@@ -1080,44 +1424,51 @@ static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt)
        struct qfq_sched *q = qdisc_priv(sch);
        struct qfq_group *grp;
        int i, j, err;
+       u32 max_cl_shift, maxbudg_shift, max_classes;
 
        err = qdisc_class_hash_init(&q->clhash);
        if (err < 0)
                return err;
 
+       if (qdisc_dev(sch)->tx_queue_len + 1 > QFQ_MAX_AGG_CLASSES)
+               max_classes = QFQ_MAX_AGG_CLASSES;
+       else
+               max_classes = qdisc_dev(sch)->tx_queue_len + 1;
+       /* max_cl_shift = floor(log_2(max_classes)) */
+       max_cl_shift = __fls(max_classes);
+       q->max_agg_classes = 1<<max_cl_shift;
+
+       /* maxbudg_shift = log2(max_len * max_classes_per_agg) */
+       maxbudg_shift = QFQ_MTU_SHIFT + max_cl_shift;
+       q->min_slot_shift = FRAC_BITS + maxbudg_shift - QFQ_MAX_INDEX;
+
        for (i = 0; i <= QFQ_MAX_INDEX; i++) {
                grp = &q->groups[i];
                grp->index = i;
-               grp->slot_shift = QFQ_MTU_SHIFT + FRAC_BITS
-                                  - (QFQ_MAX_INDEX - i);
+               grp->slot_shift = q->min_slot_shift + i;
                for (j = 0; j < QFQ_MAX_SLOTS; j++)
                        INIT_HLIST_HEAD(&grp->slots[j]);
        }
 
+       INIT_HLIST_HEAD(&q->nonfull_aggs);
+
        return 0;
 }
 
 static void qfq_reset_qdisc(struct Qdisc *sch)
 {
        struct qfq_sched *q = qdisc_priv(sch);
-       struct qfq_group *grp;
        struct qfq_class *cl;
-       struct hlist_node *n, *tmp;
-       unsigned int i, j;
+       struct hlist_node *n;
+       unsigned int i;
 
-       for (i = 0; i <= QFQ_MAX_INDEX; i++) {
-               grp = &q->groups[i];
-               for (j = 0; j < QFQ_MAX_SLOTS; j++) {
-                       hlist_for_each_entry_safe(cl, n, tmp,
-                                                 &grp->slots[j], next) {
+       for (i = 0; i < q->clhash.hashsize; i++) {
+               hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) {
+                       if (cl->qdisc->q.qlen > 0)
                                qfq_deactivate_class(q, cl);
-                       }
-               }
-       }
 
-       for (i = 0; i < q->clhash.hashsize; i++) {
-               hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode)
                        qdisc_reset(cl->qdisc);
+               }
        }
        sch->q.qlen = 0;
 }
index 126b014eb79b495dff682943bb49e151a3faf677..a9edd2e205f4eabaeb842ec06406d0e61ec83127 100644 (file)
@@ -9,7 +9,6 @@ menuconfig IP_SCTP
        select CRYPTO
        select CRYPTO_HMAC
        select CRYPTO_SHA1
-       select CRYPTO_MD5 if SCTP_HMAC_MD5
        select LIBCRC32C
        ---help---
          Stream Control Transmission Protocol
@@ -68,33 +67,21 @@ config SCTP_DBG_OBJCNT
 
          If unsure, say N
 
-choice
-       prompt "SCTP: Cookie HMAC Algorithm"
-       default SCTP_HMAC_MD5
+config SCTP_COOKIE_HMAC_MD5
+       bool "Enable optional MD5 hmac cookie generation"
        help
-         HMAC algorithm to be used during association initialization.  It
-         is strongly recommended to use HMAC-SHA1 or HMAC-MD5.  See 
-         configuration for Cryptographic API and enable those algorithms
-          to make usable by SCTP. 
-
-config SCTP_HMAC_NONE
-       bool "None"
-       help 
-         Choosing this disables the use of an HMAC during association 
-         establishment.  It is advised to use either HMAC-MD5 or HMAC-SHA1.
-
-config SCTP_HMAC_SHA1
-       bool "HMAC-SHA1"
-       help 
-         Enable the use of HMAC-SHA1 during association establishment.  It 
-         is advised to use either HMAC-MD5 or HMAC-SHA1.
-
-config SCTP_HMAC_MD5
-       bool "HMAC-MD5"
+         Enable optional MD5 hmac based SCTP cookie generation
+       default y
+       select CRYPTO_HMAC if SCTP_COOKIE_HMAC_MD5
+       select CRYPTO_MD5 if SCTP_COOKIE_HMAC_MD5
+
+config SCTP_COOKIE_HMAC_SHA1
+       bool "Enable optional SHA1 hmac cookie generation"
        help
-         Enable the use of HMAC-MD5 during association establishment.  It is 
-         advised to use either HMAC-MD5 or HMAC-SHA1.
+         Enable optional SHA1 hmac based SCTP cookie generation
+       default y
+       select CRYPTO_HMAC if SCTP_COOKIE_HMAC_SHA1
+       select CRYPTO_SHA1 if SCTP_COOKIE_HMAC_SHA1
 
-endchoice
 
 endif # IP_SCTP
index b1ef3bc301a5ad424fb041c0f6f37c010098bcc3..b45ed1f96921285bf75badfeaa5caf922118bb4d 100644 (file)
@@ -321,6 +321,9 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
        asoc->default_timetolive = sp->default_timetolive;
        asoc->default_rcv_context = sp->default_rcv_context;
 
+       /* SCTP_GET_ASSOC_STATS COUNTERS */
+       memset(&asoc->stats, 0, sizeof(struct sctp_priv_assoc_stats));
+
        /* AUTH related initializations */
        INIT_LIST_HEAD(&asoc->endpoint_shared_keys);
        err = sctp_auth_asoc_copy_shkeys(ep, asoc, gfp);
@@ -445,7 +448,7 @@ void sctp_association_free(struct sctp_association *asoc)
        /* Release the transport structures. */
        list_for_each_safe(pos, temp, &asoc->peer.transport_addr_list) {
                transport = list_entry(pos, struct sctp_transport, transports);
-               list_del(pos);
+               list_del_rcu(pos);
                sctp_transport_free(transport);
        }
 
@@ -565,7 +568,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
                sctp_assoc_update_retran_path(asoc);
 
        /* Remove this peer from the list. */
-       list_del(&peer->transports);
+       list_del_rcu(&peer->transports);
 
        /* Get the first transport of asoc. */
        pos = asoc->peer.transport_addr_list.next;
@@ -760,12 +763,13 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 
        /* Set the transport's RTO.initial value */
        peer->rto = asoc->rto_initial;
+       sctp_max_rto(asoc, peer);
 
        /* Set the peer's active state. */
        peer->state = peer_state;
 
        /* Attach the remote transport to our asoc.  */
-       list_add_tail(&peer->transports, &asoc->peer.transport_addr_list);
+       list_add_tail_rcu(&peer->transports, &asoc->peer.transport_addr_list);
        asoc->peer.transport_count++;
 
        /* If we do not yet have a primary path, set one.  */
@@ -1152,8 +1156,12 @@ static void sctp_assoc_bh_rcv(struct work_struct *work)
                 */
                if (sctp_chunk_is_data(chunk))
                        asoc->peer.last_data_from = chunk->transport;
-               else
+               else {
                        SCTP_INC_STATS(net, SCTP_MIB_INCTRLCHUNKS);
+                       asoc->stats.ictrlchunks++;
+                       if (chunk->chunk_hdr->type == SCTP_CID_SACK)
+                               asoc->stats.isacks++;
+               }
 
                if (chunk->transport)
                        chunk->transport->last_time_heard = jiffies;
index 7c2df9c33df37a588c426e7945cd71233edd4577..69ce21e3716f89fbfc78b050ffc3943455906d27 100644 (file)
@@ -183,7 +183,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
 
        msg = sctp_datamsg_new(GFP_KERNEL);
        if (!msg)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        /* Note: Calculate this outside of the loop, so that all fragments
         * have the same expiration.
@@ -280,11 +280,14 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
 
                chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
 
-               if (!chunk)
+               if (!chunk) {
+                       err = -ENOMEM;
                        goto errout;
+               }
+
                err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
                if (err < 0)
-                       goto errout;
+                       goto errout_chunk_free;
 
                offset += len;
 
@@ -315,8 +318,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
 
                chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
 
-               if (!chunk)
+               if (!chunk) {
+                       err = -ENOMEM;
                        goto errout;
+               }
 
                err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
 
@@ -324,7 +329,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
                __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
                           - (__u8 *)chunk->skb->data);
                if (err < 0)
-                       goto errout;
+                       goto errout_chunk_free;
 
                sctp_datamsg_assign(msg, chunk);
                list_add_tail(&chunk->frag_list, &msg->chunks);
@@ -332,6 +337,9 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
 
        return msg;
 
+errout_chunk_free:
+       sctp_chunk_free(chunk);
+
 errout:
        list_for_each_safe(pos, temp, &msg->chunks) {
                list_del_init(pos);
@@ -339,7 +347,7 @@ errout:
                sctp_chunk_free(chunk);
        }
        sctp_datamsg_put(msg);
-       return NULL;
+       return ERR_PTR(err);
 }
 
 /* Check whether this message has expired. */
index 1859e2bc83d113d1a14d01f904475b01099e0626..32ab55b18281e7e614b7226c5029c10356ca854c 100644 (file)
@@ -480,8 +480,11 @@ normal:
                 */
                if (asoc && sctp_chunk_is_data(chunk))
                        asoc->peer.last_data_from = chunk->transport;
-               else
+               else {
                        SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS);
+                       if (asoc)
+                               asoc->stats.ictrlchunks++;
+               }
 
                if (chunk->transport)
                        chunk->transport->last_time_heard = jiffies;
index 397296fb156fd094169db1cacb0f940d936c6bc6..2d5ad280de388d07f3949a578ce6bbdf9cf6ae5f 100644 (file)
@@ -104,6 +104,8 @@ void sctp_inq_push(struct sctp_inq *q, struct sctp_chunk *chunk)
         * on the BH related data structures.
         */
        list_add_tail(&chunk->list, &q->in_chunk_list);
+       if (chunk->asoc)
+               chunk->asoc->stats.ipackets++;
        q->immediate.func(&q->immediate);
 }
 
index ea14cb44529528124e2bdd24988a59f1cacc2569..f3f0f4dc31dd3adf33033e071e02cb891b982719 100644 (file)
@@ -345,7 +345,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        }
 
 out:
-       if (!IS_ERR(dst)) {
+       if (!IS_ERR_OR_NULL(dst)) {
                struct rt6_info *rt;
                rt = (struct rt6_info *)dst;
                t->dst = dst;
index 4e90188bf4895b95f89cdcd9ca0f024c31bbe08a..f5200a2ad852e0ac9e14593a070fac3ad6e66558 100644 (file)
@@ -311,6 +311,8 @@ static sctp_xmit_t __sctp_packet_append_chunk(struct sctp_packet *packet,
 
            case SCTP_CID_SACK:
                packet->has_sack = 1;
+               if (chunk->asoc)
+                       chunk->asoc->stats.osacks++;
                break;
 
            case SCTP_CID_AUTH:
@@ -584,11 +586,13 @@ int sctp_packet_transmit(struct sctp_packet *packet)
         */
 
        /* Dump that on IP!  */
-       if (asoc && asoc->peer.last_sent_to != tp) {
-               /* Considering the multiple CPU scenario, this is a
-                * "correcter" place for last_sent_to.  --xguo
-                */
-               asoc->peer.last_sent_to = tp;
+       if (asoc) {
+               asoc->stats.opackets++;
+               if (asoc->peer.last_sent_to != tp)
+                       /* Considering the multiple CPU scenario, this is a
+                        * "correcter" place for last_sent_to.  --xguo
+                        */
+                       asoc->peer.last_sent_to = tp;
        }
 
        if (has_data) {
index 1b4a7f8ec3fd9186fdb6f6fd7cbfb1e9956c29cb..379c81dee9d1256b3a1af84b84bc23b28092f12b 100644 (file)
@@ -667,6 +667,7 @@ redo:
                                chunk->fast_retransmit = SCTP_DONT_FRTX;
 
                        q->empty = 0;
+                       q->asoc->stats.rtxchunks++;
                        break;
                }
 
@@ -876,12 +877,14 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
                        if (status  != SCTP_XMIT_OK) {
                                /* put the chunk back */
                                list_add(&chunk->list, &q->control_chunk_list);
-                       } else if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN) {
+                       } else {
+                               asoc->stats.octrlchunks++;
                                /* PR-SCTP C5) If a FORWARD TSN is sent, the
                                 * sender MUST assure that at least one T3-rtx
                                 * timer is running.
                                 */
-                               sctp_transport_reset_timers(transport);
+                               if (chunk->chunk_hdr->type == SCTP_CID_FWD_TSN)
+                                       sctp_transport_reset_timers(transport);
                        }
                        break;
 
@@ -1055,6 +1058,10 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout)
                                 */
                                if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING)
                                        chunk->chunk_hdr->flags |= SCTP_DATA_SACK_IMM;
+                               if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
+                                       asoc->stats.ouodchunks++;
+                               else
+                                       asoc->stats.oodchunks++;
 
                                break;
 
@@ -1162,6 +1169,7 @@ int sctp_outq_sack(struct sctp_outq *q, struct sctp_chunk *chunk)
 
        sack_ctsn = ntohl(sack->cum_tsn_ack);
        gap_ack_blocks = ntohs(sack->num_gap_ack_blocks);
+       asoc->stats.gapcnt += gap_ack_blocks;
        /*
         * SFR-CACC algorithm:
         * On receipt of a SACK the sender SHOULD execute the
index c3bea269faf4e6228143f70c6422046842922177..8c19e97262caf78fae564c09dd679dfc31e252f6 100644 (file)
@@ -102,7 +102,7 @@ static const struct file_operations sctp_snmp_seq_fops = {
        .open    = sctp_snmp_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = single_release,
+       .release = single_release_net,
 };
 
 /* Set up the proc fs entry for 'snmp' object. */
@@ -139,7 +139,11 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
            primary = &peer->saddr;
        }
 
-       list_for_each_entry(laddr, &epb->bind_addr.address_list, list) {
+       rcu_read_lock();
+       list_for_each_entry_rcu(laddr, &epb->bind_addr.address_list, list) {
+               if (!laddr->valid)
+                       continue;
+
                addr = &laddr->a;
                af = sctp_get_af_specific(addr->sa.sa_family);
                if (primary && af->cmp_addr(addr, primary)) {
@@ -147,6 +151,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
                }
                af->seq_dump_addr(seq, addr);
        }
+       rcu_read_unlock();
 }
 
 /* Dump remote addresses of an association. */
@@ -157,15 +162,20 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
        struct sctp_af *af;
 
        primary = &assoc->peer.primary_addr;
-       list_for_each_entry(transport, &assoc->peer.transport_addr_list,
+       rcu_read_lock();
+       list_for_each_entry_rcu(transport, &assoc->peer.transport_addr_list,
                        transports) {
                addr = &transport->ipaddr;
+               if (transport->dead)
+                       continue;
+
                af = sctp_get_af_specific(addr->sa.sa_family);
                if (af->cmp_addr(addr, primary)) {
                        seq_printf(seq, "*");
                }
                af->seq_dump_addr(seq, addr);
        }
+       rcu_read_unlock();
 }
 
 static void * sctp_eps_seq_start(struct seq_file *seq, loff_t *pos)
@@ -251,7 +261,7 @@ static const struct file_operations sctp_eps_seq_fops = {
        .open    = sctp_eps_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 /* Set up the proc fs entry for 'eps' object. */
@@ -372,7 +382,7 @@ static const struct file_operations sctp_assocs_seq_fops = {
        .open    = sctp_assocs_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 /* Set up the proc fs entry for 'assocs' object. */
@@ -436,12 +446,16 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
        head = &sctp_assoc_hashtable[hash];
        sctp_local_bh_disable();
        read_lock(&head->lock);
+       rcu_read_lock();
        sctp_for_each_hentry(epb, node, &head->chain) {
                if (!net_eq(sock_net(epb->sk), seq_file_net(seq)))
                        continue;
                assoc = sctp_assoc(epb);
-               list_for_each_entry(tsp, &assoc->peer.transport_addr_list,
+               list_for_each_entry_rcu(tsp, &assoc->peer.transport_addr_list,
                                        transports) {
+                       if (tsp->dead)
+                               continue;
+
                        /*
                         * The remote address (ADDR)
                         */
@@ -487,6 +501,7 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
                }
        }
 
+       rcu_read_unlock();
        read_unlock(&head->lock);
        sctp_local_bh_enable();
 
@@ -517,7 +532,7 @@ static const struct file_operations sctp_remaddr_seq_fops = {
        .open = sctp_remaddr_seq_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 int __net_init sctp_remaddr_proc_init(struct net *net)
index 2d518425d5984bf954c6ebba3d7db0abb7ef5dc7..2c7785bacf744491524ee60dae73e5924099ad99 100644 (file)
@@ -86,7 +86,7 @@ int sysctl_sctp_rmem[3];
 int sysctl_sctp_wmem[3];
 
 /* Set up the proc fs entry for the SCTP protocol. */
-static __net_init int sctp_proc_init(struct net *net)
+static int __net_init sctp_proc_init(struct net *net)
 {
 #ifdef CONFIG_PROC_FS
        net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net);
@@ -1165,7 +1165,7 @@ static void sctp_v4_del_protocol(void)
        unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
 }
 
-static int sctp_net_init(struct net *net)
+static int __net_init sctp_net_init(struct net *net)
 {
        int status;
 
@@ -1190,6 +1190,15 @@ static int sctp_net_init(struct net *net)
        /* Whether Cookie Preservative is enabled(1) or not(0) */
        net->sctp.cookie_preserve_enable        = 1;
 
+       /* Default sctp sockets to use md5 as their hmac alg */
+#if defined (CONFIG_CRYPTO_MD5)
+       net->sctp.sctp_hmac_alg                 = "md5";
+#elif defined (CONFIG_CRYPTO_SHA1)
+       net->sctp.sctp_hmac_alg                 = "sha1";
+#else
+       net->sctp.sctp_hmac_alg                 = NULL;
+#endif
+
        /* Max.Burst                - 4 */
        net->sctp.max_burst                     = SCTP_DEFAULT_MAX_BURST;
 
@@ -1281,7 +1290,7 @@ err_sysctl_register:
        return status;
 }
 
-static void sctp_net_exit(struct net *net)
+static void __net_exit sctp_net_exit(struct net *net)
 {
        /* Free the local address list */
        sctp_free_addr_wq(net);
index fbe1636309a75ac054de225fe4d1cf245a3923d2..e1c5fc2be6b8f2f245c091c54a927d1440abc1ee 100644 (file)
@@ -804,10 +804,11 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc)
                                 gabs);
 
        /* Add the duplicate TSN information.  */
-       if (num_dup_tsns)
+       if (num_dup_tsns) {
+               aptr->stats.idupchunks += num_dup_tsns;
                sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns,
                                 sctp_tsnmap_get_dups(map));
-
+       }
        /* Once we have a sack generated, check to see what our sack
         * generation is, if its 0, reset the transports to 0, and reset
         * the association generation to 1
@@ -1090,6 +1091,25 @@ nodata:
        return retval;
 }
 
+struct sctp_chunk *sctp_make_violation_max_retrans(
+       const struct sctp_association *asoc,
+       const struct sctp_chunk *chunk)
+{
+       struct sctp_chunk *retval;
+       static const char error[] = "Association exceeded its max_retans count";
+       size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t);
+
+       retval = sctp_make_abort(asoc, chunk, payload_len);
+       if (!retval)
+               goto nodata;
+
+       sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, sizeof(error));
+       sctp_addto_chunk(retval, sizeof(error), error);
+
+nodata:
+       return retval;
+}
+
 /* Make a HEARTBEAT chunk.  */
 struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc,
                                  const struct sctp_transport *transport)
index 57f7de839b038b8a6ae626820dd4a63e4ef0b384..c9577754a70825cd00da2a24854a441c93dac09a 100644 (file)
@@ -542,6 +542,7 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
         */
        if (!is_hb || transport->hb_sent) {
                transport->rto = min((transport->rto * 2), transport->asoc->rto_max);
+               sctp_max_rto(asoc, transport);
        }
 }
 
@@ -577,7 +578,7 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
                                  unsigned int error)
 {
        struct sctp_ulpevent *event;
-
+       struct sctp_chunk *abort;
        /* Cancel any partial delivery in progress. */
        sctp_ulpq_abort_pd(&asoc->ulpq, GFP_ATOMIC);
 
@@ -593,6 +594,13 @@ static void sctp_cmd_assoc_failed(sctp_cmd_seq_t *commands,
                sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP,
                                SCTP_ULPEVENT(event));
 
+       if (asoc->overall_error_count >= asoc->max_retrans) {
+               abort = sctp_make_violation_max_retrans(asoc, chunk);
+               if (abort)
+                       sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+                                       SCTP_CHUNK(abort));
+       }
+
        sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
                        SCTP_STATE(SCTP_STATE_CLOSED));
 
@@ -1268,14 +1276,14 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                sctp_outq_uncork(&asoc->outqueue);
                                local_cork = 0;
                        }
-                       asoc = cmd->obj.ptr;
+                       asoc = cmd->obj.asoc;
                        /* Register with the endpoint.  */
                        sctp_endpoint_add_asoc(ep, asoc);
                        sctp_hash_established(asoc);
                        break;
 
                case SCTP_CMD_UPDATE_ASSOC:
-                      sctp_assoc_update(asoc, cmd->obj.ptr);
+                      sctp_assoc_update(asoc, cmd->obj.asoc);
                       break;
 
                case SCTP_CMD_PURGE_OUTQUEUE:
@@ -1315,7 +1323,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                        break;
 
                case SCTP_CMD_PROCESS_FWDTSN:
-                       sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.ptr);
+                       sctp_cmd_process_fwdtsn(&asoc->ulpq, cmd->obj.chunk);
                        break;
 
                case SCTP_CMD_GEN_SACK:
@@ -1331,7 +1339,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                case SCTP_CMD_PROCESS_SACK:
                        /* Process an inbound SACK.  */
                        error = sctp_cmd_process_sack(commands, asoc,
-                                                     cmd->obj.ptr);
+                                                     cmd->obj.chunk);
                        break;
 
                case SCTP_CMD_GEN_INIT_ACK:
@@ -1352,15 +1360,15 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                         * layer which will bail.
                         */
                        error = sctp_cmd_process_init(commands, asoc, chunk,
-                                                     cmd->obj.ptr, gfp);
+                                                     cmd->obj.init, gfp);
                        break;
 
                case SCTP_CMD_GEN_COOKIE_ECHO:
                        /* Generate a COOKIE ECHO chunk.  */
                        new_obj = sctp_make_cookie_echo(asoc, chunk);
                        if (!new_obj) {
-                               if (cmd->obj.ptr)
-                                       sctp_chunk_free(cmd->obj.ptr);
+                               if (cmd->obj.chunk)
+                                       sctp_chunk_free(cmd->obj.chunk);
                                goto nomem;
                        }
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
@@ -1369,9 +1377,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                        /* If there is an ERROR chunk to be sent along with
                         * the COOKIE_ECHO, send it, too.
                         */
-                       if (cmd->obj.ptr)
+                       if (cmd->obj.chunk)
                                sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-                                               SCTP_CHUNK(cmd->obj.ptr));
+                                               SCTP_CHUNK(cmd->obj.chunk));
 
                        if (new_obj->transport) {
                                new_obj->transport->init_sent_count++;
@@ -1417,18 +1425,18 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                case SCTP_CMD_CHUNK_ULP:
                        /* Send a chunk to the sockets layer.  */
                        SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",
-                                         "chunk_up:", cmd->obj.ptr,
+                                         "chunk_up:", cmd->obj.chunk,
                                          "ulpq:", &asoc->ulpq);
-                       sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.ptr,
+                       sctp_ulpq_tail_data(&asoc->ulpq, cmd->obj.chunk,
                                            GFP_ATOMIC);
                        break;
 
                case SCTP_CMD_EVENT_ULP:
                        /* Send a notification to the sockets layer.  */
                        SCTP_DEBUG_PRINTK("sm_sideff: %s %p, %s %p.\n",
-                                         "event_up:",cmd->obj.ptr,
+                                         "event_up:",cmd->obj.ulpevent,
                                          "ulpq:",&asoc->ulpq);
-                       sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ptr);
+                       sctp_ulpq_tail_event(&asoc->ulpq, cmd->obj.ulpevent);
                        break;
 
                case SCTP_CMD_REPLY:
@@ -1438,12 +1446,12 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                local_cork = 1;
                        }
                        /* Send a chunk to our peer.  */
-                       error = sctp_outq_tail(&asoc->outqueue, cmd->obj.ptr);
+                       error = sctp_outq_tail(&asoc->outqueue, cmd->obj.chunk);
                        break;
 
                case SCTP_CMD_SEND_PKT:
                        /* Send a full packet to our peer.  */
-                       packet = cmd->obj.ptr;
+                       packet = cmd->obj.packet;
                        sctp_packet_transmit(packet);
                        sctp_ootb_pkt_free(packet);
                        break;
@@ -1480,7 +1488,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                        break;
 
                case SCTP_CMD_SETUP_T2:
-                       sctp_cmd_setup_t2(commands, asoc, cmd->obj.ptr);
+                       sctp_cmd_setup_t2(commands, asoc, cmd->obj.chunk);
                        break;
 
                case SCTP_CMD_TIMER_START_ONCE:
@@ -1514,7 +1522,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                        break;
 
                case SCTP_CMD_INIT_CHOOSE_TRANSPORT:
-                       chunk = cmd->obj.ptr;
+                       chunk = cmd->obj.chunk;
                        t = sctp_assoc_choose_alter_transport(asoc,
                                                asoc->init_last_sent_to);
                        asoc->init_last_sent_to = t;
@@ -1642,8 +1650,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                                        asoc->outqueue.outstanding_bytes;
                        sackh.num_gap_ack_blocks = 0;
                        sackh.num_dup_tsns = 0;
+                       chunk->subh.sack_hdr = &sackh;
                        sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK,
-                                       SCTP_SACKH(&sackh));
+                                       SCTP_CHUNK(chunk));
                        break;
 
                case SCTP_CMD_DISCARD_PACKET:
@@ -1664,17 +1673,16 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                        break;
 
                case SCTP_CMD_PART_DELIVER:
-                       sctp_ulpq_partial_delivery(&asoc->ulpq, cmd->obj.ptr,
-                                                  GFP_ATOMIC);
+                       sctp_ulpq_partial_delivery(&asoc->ulpq, GFP_ATOMIC);
                        break;
 
                case SCTP_CMD_RENEGE:
-                       sctp_ulpq_renege(&asoc->ulpq, cmd->obj.ptr,
+                       sctp_ulpq_renege(&asoc->ulpq, cmd->obj.chunk,
                                         GFP_ATOMIC);
                        break;
 
                case SCTP_CMD_SETUP_T4:
-                       sctp_cmd_setup_t4(commands, asoc, cmd->obj.ptr);
+                       sctp_cmd_setup_t4(commands, asoc, cmd->obj.chunk);
                        break;
 
                case SCTP_CMD_PROCESS_OPERR:
@@ -1733,8 +1741,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type,
                        break;
 
                default:
-                       pr_warn("Impossible command: %u, %p\n",
-                               cmd->verb, cmd->obj.ptr);
+                       pr_warn("Impossible command: %u\n",
+                               cmd->verb);
                        break;
                }
 
index b6adef8a1e938d22b5cab026597e6f82c917794d..ebcd1eedb1151d050d51c5a5043e720f4797a33a 100644 (file)
@@ -1055,6 +1055,7 @@ sctp_disposition_t sctp_sf_beat_8_3(struct net *net,
                                    void *arg,
                                    sctp_cmd_seq_t *commands)
 {
+       sctp_paramhdr_t *param_hdr;
        struct sctp_chunk *chunk = arg;
        struct sctp_chunk *reply;
        size_t paylen = 0;
@@ -1072,12 +1073,17 @@ sctp_disposition_t sctp_sf_beat_8_3(struct net *net,
         * Information field copied from the received HEARTBEAT chunk.
         */
        chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data;
+       param_hdr = (sctp_paramhdr_t *) chunk->subh.hb_hdr;
        paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
+
+       if (ntohs(param_hdr->length) > paylen)
+               return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
+                                                 param_hdr, commands);
+
        if (!pskb_pull(chunk->skb, paylen))
                goto nomem;
 
-       reply = sctp_make_heartbeat_ack(asoc, chunk,
-                                       chunk->subh.hb_hdr, paylen);
+       reply = sctp_make_heartbeat_ack(asoc, chunk, param_hdr, paylen);
        if (!reply)
                goto nomem;
 
@@ -6127,6 +6133,8 @@ static int sctp_eat_data(const struct sctp_association *asoc,
                /* The TSN is too high--silently discard the chunk and
                 * count on it getting retransmitted later.
                 */
+               if (chunk->asoc)
+                       chunk->asoc->stats.outofseqtsns++;
                return SCTP_IERROR_HIGH_TSN;
        } else if (tmp > 0) {
                /* This is a duplicate.  Record it.  */
@@ -6226,10 +6234,14 @@ static int sctp_eat_data(const struct sctp_association *asoc,
        /* Note: Some chunks may get overcounted (if we drop) or overcounted
         * if we renege and the chunk arrives again.
         */
-       if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED)
+       if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) {
                SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS);
-       else {
+               if (chunk->asoc)
+                       chunk->asoc->stats.iuodchunks++;
+       } else {
                SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS);
+               if (chunk->asoc)
+                       chunk->asoc->stats.iodchunks++;
                ordered = 1;
        }
 
index 59d16ea927f0f83d706d3a59c79d13be0a95c1e8..9e65758cb03814f9372eafbf86c4821af124be00 100644 (file)
@@ -110,7 +110,6 @@ static int sctp_do_bind(struct sock *, union sctp_addr *, int);
 static int sctp_autobind(struct sock *sk);
 static void sctp_sock_migrate(struct sock *, struct sock *,
                              struct sctp_association *, sctp_socket_type_t);
-static char *sctp_hmac_alg = SCTP_COOKIE_HMAC_ALG;
 
 extern struct kmem_cache *sctp_bucket_cachep;
 extern long sysctl_sctp_mem[3];
@@ -336,6 +335,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
 /* Bind a local address either to an endpoint or to an association.  */
 SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
 {
+       struct net *net = sock_net(sk);
        struct sctp_sock *sp = sctp_sk(sk);
        struct sctp_endpoint *ep = sp->ep;
        struct sctp_bind_addr *bp = &ep->base.bind_addr;
@@ -379,7 +379,8 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
                }
        }
 
-       if (snum && snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
+       if (snum && snum < PROT_SOCK &&
+           !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE))
                return -EACCES;
 
        /* See if the address matches any of the addresses we may have
@@ -610,6 +611,7 @@ static int sctp_send_asconf_add_ip(struct sock              *sk,
                                    2*asoc->pathmtu, 4380));
                                trans->ssthresh = asoc->peer.i.a_rwnd;
                                trans->rto = asoc->rto_initial;
+                               sctp_max_rto(asoc, trans);
                                trans->rtt = trans->srtt = trans->rttvar = 0;
                                sctp_transport_route(trans, NULL,
                                    sctp_sk(asoc->base.sk));
@@ -974,7 +976,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,
        void *addr_buf;
        struct sctp_af *af;
 
-       SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p"
+       SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p"
                          " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);
 
        if (unlikely(addrs_size <= 0))
@@ -1162,7 +1164,7 @@ static int __sctp_connect(struct sock* sk,
                                 * be permitted to open new associations.
                                 */
                                if (ep->base.bind_addr.port < PROT_SOCK &&
-                                   !capable(CAP_NET_BIND_SERVICE)) {
+                                   !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) {
                                        err = -EACCES;
                                        goto out_free;
                                }
@@ -1791,7 +1793,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
                         * associations.
                         */
                        if (ep->base.bind_addr.port < PROT_SOCK &&
-                           !capable(CAP_NET_BIND_SERVICE)) {
+                           !ns_capable(net->user_ns, CAP_NET_BIND_SERVICE)) {
                                err = -EACCES;
                                goto out_unlock;
                        }
@@ -1915,8 +1917,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 
        /* Break the message into multiple chunks of maximum size. */
        datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
-       if (!datamsg) {
-               err = -ENOMEM;
+       if (IS_ERR(datamsg)) {
+               err = PTR_ERR(datamsg);
                goto out_free;
        }
 
@@ -3890,6 +3892,8 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk)
        sp->default_rcv_context = 0;
        sp->max_burst = net->sctp.max_burst;
 
+       sp->sctp_hmac_alg = net->sctp.sctp_hmac_alg;
+
        /* Initialize default setup parameters. These parameters
         * can be modified with the SCTP_INITMSG socket option or
         * overridden by the SCTP_INIT CMSG.
@@ -5632,6 +5636,71 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
        return 0;
 }
 
+/*
+ * SCTP_GET_ASSOC_STATS
+ *
+ * This option retrieves local per endpoint statistics. It is modeled
+ * after OpenSolaris' implementation
+ */
+static int sctp_getsockopt_assoc_stats(struct sock *sk, int len,
+                                      char __user *optval,
+                                      int __user *optlen)
+{
+       struct sctp_assoc_stats sas;
+       struct sctp_association *asoc = NULL;
+
+       /* User must provide at least the assoc id */
+       if (len < sizeof(sctp_assoc_t))
+               return -EINVAL;
+
+       if (copy_from_user(&sas, optval, len))
+               return -EFAULT;
+
+       asoc = sctp_id2assoc(sk, sas.sas_assoc_id);
+       if (!asoc)
+               return -EINVAL;
+
+       sas.sas_rtxchunks = asoc->stats.rtxchunks;
+       sas.sas_gapcnt = asoc->stats.gapcnt;
+       sas.sas_outofseqtsns = asoc->stats.outofseqtsns;
+       sas.sas_osacks = asoc->stats.osacks;
+       sas.sas_isacks = asoc->stats.isacks;
+       sas.sas_octrlchunks = asoc->stats.octrlchunks;
+       sas.sas_ictrlchunks = asoc->stats.ictrlchunks;
+       sas.sas_oodchunks = asoc->stats.oodchunks;
+       sas.sas_iodchunks = asoc->stats.iodchunks;
+       sas.sas_ouodchunks = asoc->stats.ouodchunks;
+       sas.sas_iuodchunks = asoc->stats.iuodchunks;
+       sas.sas_idupchunks = asoc->stats.idupchunks;
+       sas.sas_opackets = asoc->stats.opackets;
+       sas.sas_ipackets = asoc->stats.ipackets;
+
+       /* New high max rto observed, will return 0 if not a single
+        * RTO update took place. obs_rto_ipaddr will be bogus
+        * in such a case
+        */
+       sas.sas_maxrto = asoc->stats.max_obs_rto;
+       memcpy(&sas.sas_obs_rto_ipaddr, &asoc->stats.obs_rto_ipaddr,
+               sizeof(struct sockaddr_storage));
+
+       /* Mark beginning of a new observation period */
+       asoc->stats.max_obs_rto = asoc->rto_min;
+
+       /* Allow the struct to grow and fill in as much as possible */
+       len = min_t(size_t, len, sizeof(sas));
+
+       if (put_user(len, optlen))
+               return -EFAULT;
+
+       SCTP_DEBUG_PRINTK("sctp_getsockopt_assoc_stat(%d): %d\n",
+                         len, sas.sas_assoc_id);
+
+       if (copy_to_user(optval, &sas, len))
+               return -EFAULT;
+
+       return 0;
+}
+
 SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
                                char __user *optval, int __user *optlen)
 {
@@ -5773,6 +5842,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname,
        case SCTP_PEER_ADDR_THLDS:
                retval = sctp_getsockopt_paddr_thresholds(sk, optval, len, optlen);
                break;
+       case SCTP_GET_ASSOC_STATS:
+               retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen);
+               break;
        default:
                retval = -ENOPROTOOPT;
                break;
@@ -5981,13 +6053,15 @@ SCTP_STATIC int sctp_listen_start(struct sock *sk, int backlog)
        struct sctp_sock *sp = sctp_sk(sk);
        struct sctp_endpoint *ep = sp->ep;
        struct crypto_hash *tfm = NULL;
+       char alg[32];
 
        /* Allocate HMAC for generating cookie. */
-       if (!sctp_sk(sk)->hmac && sctp_hmac_alg) {
-               tfm = crypto_alloc_hash(sctp_hmac_alg, 0, CRYPTO_ALG_ASYNC);
+       if (!sp->hmac && sp->sctp_hmac_alg) {
+               sprintf(alg, "hmac(%s)", sp->sctp_hmac_alg);
+               tfm = crypto_alloc_hash(alg, 0, CRYPTO_ALG_ASYNC);
                if (IS_ERR(tfm)) {
                        net_info_ratelimited("failed to load transform for %s: %ld\n",
-                                            sctp_hmac_alg, PTR_ERR(tfm));
+                                            sp->sctp_hmac_alg, PTR_ERR(tfm));
                        return -ENOSYS;
                }
                sctp_sk(sk)->hmac = tfm;
index 70e3ba5cb50b319319e60c7bfa6fae69bc5c1fed..043889ac86c0419b3d368481b202864077034efa 100644 (file)
@@ -62,6 +62,11 @@ extern long sysctl_sctp_mem[3];
 extern int sysctl_sctp_rmem[3];
 extern int sysctl_sctp_wmem[3];
 
+static int proc_sctp_do_hmac_alg(ctl_table *ctl,
+                               int write,
+                               void __user *buffer, size_t *lenp,
+
+                               loff_t *ppos);
 static ctl_table sctp_table[] = {
        {
                .procname       = "sctp_mem",
@@ -146,6 +151,12 @@ static ctl_table sctp_net_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+       {
+               .procname       = "cookie_hmac_alg",
+               .maxlen         = 8,
+               .mode           = 0644,
+               .proc_handler   = proc_sctp_do_hmac_alg,
+       },
        {
                .procname       = "valid_cookie_life",
                .data           = &init_net.sctp.valid_cookie_life,
@@ -289,6 +300,54 @@ static ctl_table sctp_net_table[] = {
        { /* sentinel */ }
 };
 
+static int proc_sctp_do_hmac_alg(ctl_table *ctl,
+                               int write,
+                               void __user *buffer, size_t *lenp,
+                               loff_t *ppos)
+{
+       struct net *net = current->nsproxy->net_ns;
+       char tmp[8];
+       ctl_table tbl;
+       int ret;
+       int changed = 0;
+       char *none = "none";
+
+       memset(&tbl, 0, sizeof(struct ctl_table));
+
+       if (write) {
+               tbl.data = tmp;
+               tbl.maxlen = 8;
+       } else {
+               tbl.data = net->sctp.sctp_hmac_alg ? : none;
+               tbl.maxlen = strlen(tbl.data);
+       }
+               ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
+
+       if (write) {
+#ifdef CONFIG_CRYPTO_MD5
+               if (!strncmp(tmp, "md5", 3)) {
+                       net->sctp.sctp_hmac_alg = "md5";
+                       changed = 1;
+               }
+#endif
+#ifdef CONFIG_CRYPTO_SHA1
+               if (!strncmp(tmp, "sha1", 4)) {
+                       net->sctp.sctp_hmac_alg = "sha1";
+                       changed = 1;
+               }
+#endif
+               if (!strncmp(tmp, "none", 4)) {
+                       net->sctp.sctp_hmac_alg = NULL;
+                       changed = 1;
+               }
+
+               if (!changed)
+                       ret = -EINVAL;
+       }
+
+       return ret;
+}
+
 int sctp_sysctl_net_register(struct net *net)
 {
        struct ctl_table *table;
index 953c21e4af977a752362187976e84b578bdb085c..4e45bb68aef0c7abca77a476f52ac0a9fcfd1f94 100644 (file)
@@ -163,13 +163,11 @@ void sctp_transport_free(struct sctp_transport *transport)
        sctp_transport_put(transport);
 }
 
-/* Destroy the transport data structure.
- * Assumes there are no more users of this structure.
- */
-static void sctp_transport_destroy(struct sctp_transport *transport)
+static void sctp_transport_destroy_rcu(struct rcu_head *head)
 {
-       SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+       struct sctp_transport *transport;
 
+       transport = container_of(head, struct sctp_transport, rcu);
        if (transport->asoc)
                sctp_association_put(transport->asoc);
 
@@ -180,6 +178,16 @@ static void sctp_transport_destroy(struct sctp_transport *transport)
        SCTP_DBG_OBJCNT_DEC(transport);
 }
 
+/* Destroy the transport data structure.
+ * Assumes there are no more users of this structure.
+ */
+static void sctp_transport_destroy(struct sctp_transport *transport)
+{
+       SCTP_ASSERT(transport->dead, "Transport is not dead", return);
+
+       call_rcu(&transport->rcu, sctp_transport_destroy_rcu);
+}
+
 /* Start T3_rtx timer if it is not already running and update the heartbeat
  * timer.  This routine is called every time a DATA chunk is sent.
  */
@@ -331,7 +339,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
                 * 1/8, rto_alpha would be expressed as 3.
                 */
                tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta)
-                       + ((abs(tp->srtt - rtt)) >> net->sctp.rto_beta);
+                       + (((__u32)abs64((__s64)tp->srtt - (__s64)rtt)) >> net->sctp.rto_beta);
                tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha)
                        + (rtt >> net->sctp.rto_alpha);
        } else {
@@ -363,6 +371,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt)
        if (tp->rto > tp->asoc->rto_max)
                tp->rto = tp->asoc->rto_max;
 
+       sctp_max_rto(tp->asoc, tp);
        tp->rtt = rtt;
 
        /* Reset rto_pending so that a new RTT measurement is started when a
@@ -620,6 +629,7 @@ void sctp_transport_reset(struct sctp_transport *t)
        t->burst_limited = 0;
        t->ssthresh = asoc->peer.i.a_rwnd;
        t->rto = asoc->rto_initial;
+       sctp_max_rto(asoc, t);
        t->rtt = 0;
        t->srtt = 0;
        t->rttvar = 0;
index b5fb7c409023ff8adea81d41e68ace60781febae..5f25e0c92c31e48460536cd2bb0fc29549172b93 100644 (file)
@@ -272,7 +272,7 @@ __u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)
        __u32 max_tsn = map->max_tsn_seen;
        __u32 base_tsn = map->base_tsn;
        __u16 pending_data;
-       u32 gap, i;
+       u32 gap;
 
        pending_data = max_tsn - cum_tsn;
        gap = max_tsn - base_tsn;
@@ -280,11 +280,7 @@ __u16 sctp_tsnmap_pending(struct sctp_tsnmap *map)
        if (gap == 0 || gap >= map->len)
                goto out;
 
-       for (i = 0; i < gap+1; i++) {
-               if (test_bit(i, map->tsn_map))
-                       pending_data--;
-       }
-
+       pending_data -= bitmap_weight(map->tsn_map, gap + 1);
 out:
        return pending_data;
 }
index 360d8697b95c33408d6a4913b9b1d497d27e5ee7..ada17464b65bf23a089c036fba47989a2a1d4b8b 100644 (file)
@@ -997,7 +997,6 @@ static __u16 sctp_ulpq_renege_frags(struct sctp_ulpq *ulpq, __u16 needed)
 
 /* Partial deliver the first message as there is pressure on rwnd. */
 void sctp_ulpq_partial_delivery(struct sctp_ulpq *ulpq,
-                               struct sctp_chunk *chunk,
                                gfp_t gfp)
 {
        struct sctp_ulpevent *event;
@@ -1060,7 +1059,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk,
                sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport);
                sctp_ulpq_tail_data(ulpq, chunk, gfp);
 
-               sctp_ulpq_partial_delivery(ulpq, chunk, gfp);
+               sctp_ulpq_partial_delivery(ulpq, gfp);
        }
 
        sk_mem_reclaim(asoc->base.sk);
index d92c490e66fa84e432f11086642c091f5831da65..2ca51c719ef984cdadef749008456cf7bd5e1ae4 100644 (file)
@@ -620,8 +620,6 @@ static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock,
 {
        struct sock_iocb *si = kiocb_to_siocb(iocb);
 
-       sock_update_classid(sock->sk);
-
        si->sock = sock;
        si->scm = NULL;
        si->msg = msg;
@@ -784,8 +782,6 @@ static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
 {
        struct sock_iocb *si = kiocb_to_siocb(iocb);
 
-       sock_update_classid(sock->sk);
-
        si->sock = sock;
        si->scm = NULL;
        si->msg = msg;
@@ -896,8 +892,6 @@ static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
        if (unlikely(!sock->ops->splice_read))
                return -EINVAL;
 
-       sock_update_classid(sock->sk);
-
        return sock->ops->splice_read(sock, ppos, pipe, len, flags);
 }
 
@@ -3437,8 +3431,6 @@ EXPORT_SYMBOL(kernel_setsockopt);
 int kernel_sendpage(struct socket *sock, struct page *page, int offset,
                    size_t size, int flags)
 {
-       sock_update_classid(sock->sk);
-
        if (sock->ops->sendpage)
                return sock->ops->sendpage(sock, page, offset, size, flags);
 
index 5a3d675d2f2f9f3971b4707474cc511ad328ac2a..a9c0bbccad6bfb787b4ff1630a1eb7a28918e634 100644 (file)
@@ -172,7 +172,7 @@ out_free:
                xprt_free_allocation(req);
 
        dprintk("RPC:       setup backchannel transport failed\n");
-       return -1;
+       return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(xprt_setup_backchannel);
 
index 2a68bb3db772a4d6001716e28af4385bb9c066bb..fc2f7aa4dca7aa04b3e7bc45cd39d47b744a1da4 100644 (file)
@@ -1409,11 +1409,11 @@ static ssize_t read_flush(struct file *file, char __user *buf,
                          size_t count, loff_t *ppos,
                          struct cache_detail *cd)
 {
-       char tbuf[20];
+       char tbuf[22];
        unsigned long p = *ppos;
        size_t len;
 
-       sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time));
+       snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time));
        len = strlen(tbuf);
        if (p >= len)
                return 0;
index aaaadfbe36e9525a42a86e1f649bf66e59eb7274..75853cabf4c97b153873eda4ce67cd228581fd15 100644 (file)
@@ -254,7 +254,6 @@ struct sock_xprt {
        void                    (*old_data_ready)(struct sock *, int);
        void                    (*old_state_change)(struct sock *);
        void                    (*old_write_space)(struct sock *);
-       void                    (*old_error_report)(struct sock *);
 };
 
 /*
@@ -737,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task)
                dprintk("RPC:       sendmsg returned unrecognized error %d\n",
                        -status);
        case -ECONNRESET:
-       case -EPIPE:
                xs_tcp_shutdown(xprt);
        case -ECONNREFUSED:
        case -ENOTCONN:
+       case -EPIPE:
                clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
        }
 
@@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
        transport->old_data_ready = sk->sk_data_ready;
        transport->old_state_change = sk->sk_state_change;
        transport->old_write_space = sk->sk_write_space;
-       transport->old_error_report = sk->sk_error_report;
 }
 
 static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
@@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s
        sk->sk_data_ready = transport->old_data_ready;
        sk->sk_state_change = transport->old_state_change;
        sk->sk_write_space = transport->old_write_space;
-       sk->sk_error_report = transport->old_error_report;
 }
 
 static void xs_reset_transport(struct sock_xprt *transport)
@@ -1453,7 +1450,7 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt)
        xprt_clear_connecting(xprt);
 }
 
-static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt)
 {
        smp_mb__before_clear_bit();
        clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
@@ -1461,6 +1458,11 @@ static void xs_sock_mark_closed(struct rpc_xprt *xprt)
        clear_bit(XPRT_CLOSE_WAIT, &xprt->state);
        clear_bit(XPRT_CLOSING, &xprt->state);
        smp_mb__after_clear_bit();
+}
+
+static void xs_sock_mark_closed(struct rpc_xprt *xprt)
+{
+       xs_sock_reset_connection_flags(xprt);
        /* Mark transport as closed and wake up all pending tasks */
        xprt_disconnect_done(xprt);
 }
@@ -1516,6 +1518,7 @@ static void xs_tcp_state_change(struct sock *sk)
        case TCP_CLOSE_WAIT:
                /* The server initiated a shutdown of the socket */
                xprt->connect_cookie++;
+               clear_bit(XPRT_CONNECTED, &xprt->state);
                xs_tcp_force_close(xprt);
        case TCP_CLOSING:
                /*
@@ -1540,25 +1543,6 @@ static void xs_tcp_state_change(struct sock *sk)
        read_unlock_bh(&sk->sk_callback_lock);
 }
 
-/**
- * xs_error_report - callback mainly for catching socket errors
- * @sk: socket
- */
-static void xs_error_report(struct sock *sk)
-{
-       struct rpc_xprt *xprt;
-
-       read_lock_bh(&sk->sk_callback_lock);
-       if (!(xprt = xprt_from_sock(sk)))
-               goto out;
-       dprintk("RPC:       %s client %p...\n"
-                       "RPC:       error %d\n",
-                       __func__, xprt, sk->sk_err);
-       xprt_wake_pending_tasks(xprt, -EAGAIN);
-out:
-       read_unlock_bh(&sk->sk_callback_lock);
-}
-
 static void xs_write_space(struct sock *sk)
 {
        struct socket *sock;
@@ -1858,7 +1842,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt,
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_local_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                xprt_clear_connected(xprt);
@@ -1983,7 +1966,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_user_data = xprt;
                sk->sk_data_ready = xs_udp_data_ready;
                sk->sk_write_space = xs_udp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_no_check = UDP_CSUM_NORCV;
                sk->sk_allocation = GFP_ATOMIC;
 
@@ -2050,10 +2032,8 @@ static void xs_abort_connection(struct sock_xprt *transport)
        any.sa_family = AF_UNSPEC;
        result = kernel_connect(transport->sock, &any, sizeof(any), 0);
        if (!result)
-               xs_sock_mark_closed(&transport->xprt);
-       else
-               dprintk("RPC:       AF_UNSPEC connect return code %d\n",
-                               result);
+               xs_sock_reset_connection_flags(&transport->xprt);
+       dprintk("RPC:       AF_UNSPEC connect return code %d\n", result);
 }
 
 static void xs_tcp_reuse_connection(struct sock_xprt *transport)
@@ -2098,7 +2078,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
                sk->sk_data_ready = xs_tcp_data_ready;
                sk->sk_state_change = xs_tcp_state_change;
                sk->sk_write_space = xs_tcp_write_space;
-               sk->sk_error_report = xs_error_report;
                sk->sk_allocation = GFP_ATOMIC;
 
                /* socket options */
index e3a6e37cd1c536cc93d5caa850219e4104bb646b..9bc6db04be3ea7cd998f41187ff40b19baa9c920 100644 (file)
@@ -38,15 +38,24 @@ static int is_seen(struct ctl_table_set *set)
 }
 
 /* Return standard mode bits for table entry. */
-static int net_ctl_permissions(struct ctl_table_root *root,
-                              struct nsproxy *nsproxy,
+static int net_ctl_permissions(struct ctl_table_header *head,
                               struct ctl_table *table)
 {
+       struct net *net = container_of(head->set, struct net, sysctls);
+       kuid_t root_uid = make_kuid(net->user_ns, 0);
+       kgid_t root_gid = make_kgid(net->user_ns, 0);
+
        /* Allow network administrator to have same access as root. */
-       if (capable(CAP_NET_ADMIN)) {
+       if (ns_capable(net->user_ns, CAP_NET_ADMIN) ||
+           uid_eq(root_uid, current_uid())) {
                int mode = (table->mode >> 6) & 7;
                return (mode << 6) | (mode << 3) | mode;
        }
+       /* Allow netns root group to have the same access as the root group */
+       if (gid_eq(root_gid, current_gid())) {
+               int mode = (table->mode >> 3) & 7;
+               return (mode << 3) | mode;
+       }
        return table->mode;
 }
 
index 585460180ffb22df0ac0ae966ecc49cf87dcb8cc..bc41bd31eadc064a112fddb3066a9ee9d3405b9d 100644 (file)
@@ -20,18 +20,9 @@ menuconfig TIPC
 
          If in doubt, say N.
 
-if TIPC
-
-config TIPC_ADVANCED
-       bool "Advanced TIPC configuration"
-       default n
-       help
-         Saying Y here will open some advanced configuration for TIPC.
-         Most users do not need to bother; if unsure, just say N.
-
 config TIPC_PORTS
        int "Maximum number of ports in a node"
-       depends on TIPC_ADVANCED
+       depends on TIPC
        range 127 65535
        default "8191"
        help
@@ -40,5 +31,3 @@ config TIPC_PORTS
 
          Setting this to a smaller value saves some memory,
          setting it to higher allows for more ports.
-
-endif # TIPC
index e4e6d8cd47e6fb8ec63c2cd6893c663b79f3bb0c..54f89f90ac33e2b795c9e48c01e625c8248f4d18 100644 (file)
@@ -347,7 +347,7 @@ static void bclink_peek_nack(struct tipc_msg *msg)
 
        tipc_node_lock(n_ptr);
 
-       if (n_ptr->bclink.supported &&
+       if (n_ptr->bclink.recv_permitted &&
            (n_ptr->bclink.last_in != n_ptr->bclink.last_sent) &&
            (n_ptr->bclink.last_in == msg_bcgap_after(msg)))
                n_ptr->bclink.oos_state = 2;
@@ -429,7 +429,7 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf)
                goto exit;
 
        tipc_node_lock(node);
-       if (unlikely(!node->bclink.supported))
+       if (unlikely(!node->bclink.recv_permitted))
                goto unlock;
 
        /* Handle broadcast protocol message */
@@ -564,7 +564,7 @@ exit:
 
 u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr)
 {
-       return (n_ptr->bclink.supported &&
+       return (n_ptr->bclink.recv_permitted &&
                (tipc_bclink_get_last_sent() != n_ptr->bclink.acked));
 }
 
@@ -619,16 +619,14 @@ static int tipc_bcbearer_send(struct sk_buff *buf,
                if (bcbearer->remains_new.count == bcbearer->remains.count)
                        continue;       /* bearer pair doesn't add anything */
 
-               if (p->blocked ||
-                   p->media->send_msg(buf, p, &p->media->bcast_addr)) {
+               if (!tipc_bearer_blocked(p))
+                       tipc_bearer_send(p, buf, &p->media->bcast_addr);
+               else if (s && !tipc_bearer_blocked(s))
                        /* unable to send on primary bearer */
-                       if (!s || s->blocked ||
-                           s->media->send_msg(buf, s,
-                                              &s->media->bcast_addr)) {
-                               /* unable to send on either bearer */
-                               continue;
-                       }
-               }
+                       tipc_bearer_send(s, buf, &s->media->bcast_addr);
+               else
+                       /* unable to send on either bearer */
+                       continue;
 
                if (s) {
                        bcbearer->bpairs[bp_index].primary = s;
@@ -731,8 +729,8 @@ int tipc_bclink_stats(char *buf, const u32 buf_size)
                             "  TX naks:%u acks:%u dups:%u\n",
                             s->sent_nacks, s->sent_acks, s->retransmitted);
        ret += tipc_snprintf(buf + ret, buf_size - ret,
-                            "  Congestion bearer:%u link:%u  Send queue max:%u avg:%u\n",
-                            s->bearer_congs, s->link_congs, s->max_queue_sz,
+                            "  Congestion link:%u  Send queue max:%u avg:%u\n",
+                            s->link_congs, s->max_queue_sz,
                             s->queue_sz_counts ?
                             (s->accu_queue_sz / s->queue_sz_counts) : 0);
 
@@ -766,7 +764,6 @@ int tipc_bclink_set_queue_limits(u32 limit)
 
 void tipc_bclink_init(void)
 {
-       INIT_LIST_HEAD(&bcbearer->bearer.cong_links);
        bcbearer->bearer.media = &bcbearer->media;
        bcbearer->media.send_msg = tipc_bcbearer_send;
        sprintf(bcbearer->media.name, "tipc-broadcast");
index 4ec5c80e8a7ca0b20c7291db9641636f4dc0a3a6..aa62f93a91275b355b994c66318fddb8b42e1af6 100644 (file)
@@ -279,115 +279,30 @@ void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest)
 }
 
 /*
- * bearer_push(): Resolve bearer congestion. Force the waiting
- * links to push out their unsent packets, one packet per link
- * per iteration, until all packets are gone or congestion reoccurs.
- * 'tipc_net_lock' is read_locked when this function is called
- * bearer.lock must be taken before calling
- * Returns binary true(1) ore false(0)
- */
-static int bearer_push(struct tipc_bearer *b_ptr)
-{
-       u32 res = 0;
-       struct tipc_link *ln, *tln;
-
-       if (b_ptr->blocked)
-               return 0;
-
-       while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
-               list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
-                       res = tipc_link_push_packet(ln);
-                       if (res == PUSH_FAILED)
-                               break;
-                       if (res == PUSH_FINISHED)
-                               list_move_tail(&ln->link_list, &b_ptr->links);
-               }
-       }
-       return list_empty(&b_ptr->cong_links);
-}
-
-void tipc_bearer_lock_push(struct tipc_bearer *b_ptr)
-{
-       spin_lock_bh(&b_ptr->lock);
-       bearer_push(b_ptr);
-       spin_unlock_bh(&b_ptr->lock);
-}
-
-
-/*
- * Interrupt enabling new requests after bearer congestion or blocking:
+ * Interrupt enabling new requests after bearer blocking:
  * See bearer_send().
  */
-void tipc_continue(struct tipc_bearer *b_ptr)
+void tipc_continue(struct tipc_bearer *b)
 {
-       spin_lock_bh(&b_ptr->lock);
-       if (!list_empty(&b_ptr->cong_links))
-               tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
-       b_ptr->blocked = 0;
-       spin_unlock_bh(&b_ptr->lock);
+       spin_lock_bh(&b->lock);
+       b->blocked = 0;
+       spin_unlock_bh(&b->lock);
 }
 
 /*
- * Schedule link for sending of messages after the bearer
- * has been deblocked by 'continue()'. This method is called
- * when somebody tries to send a message via this link while
- * the bearer is congested. 'tipc_net_lock' is in read_lock here
- * bearer.lock is busy
+ * tipc_bearer_blocked - determines if bearer is currently blocked
  */
-static void tipc_bearer_schedule_unlocked(struct tipc_bearer *b_ptr,
-                                               struct tipc_link *l_ptr)
+int tipc_bearer_blocked(struct tipc_bearer *b)
 {
-       list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
-}
-
-/*
- * Schedule link for sending of messages after the bearer
- * has been deblocked by 'continue()'. This method is called
- * when somebody tries to send a message via this link while
- * the bearer is congested. 'tipc_net_lock' is in read_lock here,
- * bearer.lock is free
- */
-void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr)
-{
-       spin_lock_bh(&b_ptr->lock);
-       tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
-       spin_unlock_bh(&b_ptr->lock);
-}
-
+       int res;
 
-/*
- * tipc_bearer_resolve_congestion(): Check if there is bearer congestion,
- * and if there is, try to resolve it before returning.
- * 'tipc_net_lock' is read_locked when this function is called
- */
-int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr,
-                                       struct tipc_link *l_ptr)
-{
-       int res = 1;
+       spin_lock_bh(&b->lock);
+       res = b->blocked;
+       spin_unlock_bh(&b->lock);
 
-       if (list_empty(&b_ptr->cong_links))
-               return 1;
-       spin_lock_bh(&b_ptr->lock);
-       if (!bearer_push(b_ptr)) {
-               tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
-               res = 0;
-       }
-       spin_unlock_bh(&b_ptr->lock);
        return res;
 }
 
-/**
- * tipc_bearer_congested - determines if bearer is currently congested
- */
-int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr)
-{
-       if (unlikely(b_ptr->blocked))
-               return 1;
-       if (likely(list_empty(&b_ptr->cong_links)))
-               return 0;
-       return !tipc_bearer_resolve_congestion(b_ptr, l_ptr);
-}
-
 /**
  * tipc_enable_bearer - enable bearer with the given name
  */
@@ -489,7 +404,6 @@ restart:
        b_ptr->net_plane = bearer_id + 'A';
        b_ptr->active = 1;
        b_ptr->priority = priority;
-       INIT_LIST_HEAD(&b_ptr->cong_links);
        INIT_LIST_HEAD(&b_ptr->links);
        spin_lock_init(&b_ptr->lock);
 
@@ -528,7 +442,6 @@ int tipc_block_bearer(const char *name)
        pr_info("Blocking bearer <%s>\n", name);
        spin_lock_bh(&b_ptr->lock);
        b_ptr->blocked = 1;
-       list_splice_init(&b_ptr->cong_links, &b_ptr->links);
        list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
                struct tipc_node *n_ptr = l_ptr->owner;
 
@@ -555,7 +468,6 @@ static void bearer_disable(struct tipc_bearer *b_ptr)
        spin_lock_bh(&b_ptr->lock);
        b_ptr->blocked = 1;
        b_ptr->media->disable_bearer(b_ptr);
-       list_splice_init(&b_ptr->cong_links, &b_ptr->links);
        list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
                tipc_link_delete(l_ptr);
        }
index dd4c2abf08e7de95085fb6b3e9e87cf22eb4b9ec..39f1192d04bff34dfd2295cbe99b491d603e7cbb 100644 (file)
@@ -120,7 +120,6 @@ struct tipc_media {
  * @identity: array index of this bearer within TIPC bearer array
  * @link_req: ptr to (optional) structure making periodic link setup requests
  * @links: list of non-congested links associated with bearer
- * @cong_links: list of congested links associated with bearer
  * @active: non-zero if bearer structure is represents a bearer
  * @net_plane: network plane ('A' through 'H') currently associated with bearer
  * @nodes: indicates which nodes in cluster can be reached through bearer
@@ -143,7 +142,6 @@ struct tipc_bearer {
        u32 identity;
        struct tipc_link_req *link_req;
        struct list_head links;
-       struct list_head cong_links;
        int active;
        char net_plane;
        struct tipc_node_map nodes;
@@ -185,39 +183,23 @@ struct sk_buff *tipc_media_get_names(void);
 struct sk_buff *tipc_bearer_get_names(void);
 void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest);
 void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest);
-void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr);
 struct tipc_bearer *tipc_bearer_find(const char *name);
 struct tipc_bearer *tipc_bearer_find_interface(const char *if_name);
 struct tipc_media *tipc_media_find(const char *name);
-int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr,
-                                  struct tipc_link *l_ptr);
-int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct tipc_link *l_ptr);
+int tipc_bearer_blocked(struct tipc_bearer *b_ptr);
 void tipc_bearer_stop(void);
-void tipc_bearer_lock_push(struct tipc_bearer *b_ptr);
-
 
 /**
  * tipc_bearer_send- sends buffer to destination over bearer
  *
- * Returns true (1) if successful, or false (0) if unable to send
- *
  * IMPORTANT:
  * The media send routine must not alter the buffer being passed in
  * as it may be needed for later retransmission!
- *
- * If the media send routine returns a non-zero value (indicating that
- * it was unable to send the buffer), it must:
- *   1) mark the bearer as blocked,
- *   2) call tipc_continue() once the bearer is able to send again.
- * Media types that are unable to meet these two critera must ensure their
- * send routine always returns success -- even if the buffer was not sent --
- * and let TIPC's link code deal with the undelivered message.
  */
-static inline int tipc_bearer_send(struct tipc_bearer *b_ptr,
-                                  struct sk_buff *buf,
+static inline void tipc_bearer_send(struct tipc_bearer *b, struct sk_buff *buf,
                                   struct tipc_media_addr *dest)
 {
-       return !b_ptr->media->send_msg(buf, b_ptr, dest);
+       b->media->send_msg(buf, b, dest);
 }
 
 #endif /* _TIPC_BEARER_H */
index bfe8af88469a95b5012d1cb34e3e9415120a2808..fc05cecd7481652dd57431727dc2355d39627859 100644 (file)
 
 #include <linux/module.h>
 
-#ifndef CONFIG_TIPC_PORTS
-#define CONFIG_TIPC_PORTS 8191
-#endif
-
-
 /* global variables used by multiple sub-systems within TIPC */
 int tipc_random __read_mostly;
 
index 50eaa403eb6e696b6a8e8a9a552f9ca60eb25e2b..1074b9587e81ed57a77bc20042c829be18bfc4a0 100644 (file)
@@ -243,7 +243,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr)
        if ((type == DSC_REQ_MSG) && !link_fully_up && !b_ptr->blocked) {
                rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr);
                if (rbuf) {
-                       b_ptr->media->send_msg(rbuf, b_ptr, &media_addr);
+                       tipc_bearer_send(b_ptr, rbuf, &media_addr);
                        kfree_skb(rbuf);
                }
        }
index 111ff8300ae52ed43226f3ec8ab079bdb2e00b9c..b36f0fcd9bdfe76d04adf287687190ada3e9ccca 100644 (file)
@@ -116,7 +116,6 @@ void tipc_handler_stop(void)
                return;
 
        handler_enabled = 0;
-       tasklet_disable(&tipc_tasklet);
        tasklet_kill(&tipc_tasklet);
 
        spin_lock_bh(&qitem_lock);
index a79c755cb41714bf40c66de615ce6d0cc737cb3b..daa6080a2a0c459a663f6453247a838f43fb0eca 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * net/tipc/link.c: TIPC link code
  *
- * Copyright (c) 1996-2007, Ericsson AB
+ * Copyright (c) 1996-2007, 2012, Ericsson AB
  * Copyright (c) 2004-2007, 2010-2011, Wind River Systems
  * All rights reserved.
  *
@@ -97,12 +97,13 @@ static int  link_send_sections_long(struct tipc_port *sender,
                                    struct iovec const *msg_sect,
                                    u32 num_sect, unsigned int total_len,
                                    u32 destnode);
-static void link_check_defragm_bufs(struct tipc_link *l_ptr);
 static void link_state_event(struct tipc_link *l_ptr, u32 event);
 static void link_reset_statistics(struct tipc_link *l_ptr);
 static void link_print(struct tipc_link *l_ptr, const char *str);
 static void link_start(struct tipc_link *l_ptr);
 static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf);
+static void tipc_link_send_sync(struct tipc_link *l);
+static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf);
 
 /*
  *  Simple link routines
@@ -269,7 +270,6 @@ static void link_timeout(struct tipc_link *l_ptr)
        }
 
        /* do all other link processing performed on a periodic basis */
-       link_check_defragm_bufs(l_ptr);
 
        link_state_event(l_ptr, TIMEOUT_EVT);
 
@@ -712,6 +712,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
                        link_activate(l_ptr);
                        tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
                        l_ptr->fsm_msg_cnt++;
+                       if (l_ptr->owner->working_links == 1)
+                               tipc_link_send_sync(l_ptr);
                        link_set_timer(l_ptr, cont_intv);
                        break;
                case RESET_MSG:
@@ -745,6 +747,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event)
                        link_activate(l_ptr);
                        tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0);
                        l_ptr->fsm_msg_cnt++;
+                       if (l_ptr->owner->working_links == 1)
+                               tipc_link_send_sync(l_ptr);
                        link_set_timer(l_ptr, cont_intv);
                        break;
                case RESET_MSG:
@@ -872,17 +876,12 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
                return link_send_long_buf(l_ptr, buf);
 
        /* Packet can be queued or sent. */
-       if (likely(!tipc_bearer_congested(l_ptr->b_ptr, l_ptr) &&
+       if (likely(!tipc_bearer_blocked(l_ptr->b_ptr) &&
                   !link_congested(l_ptr))) {
                link_add_to_outqueue(l_ptr, buf, msg);
 
-               if (likely(tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr))) {
-                       l_ptr->unacked_window = 0;
-               } else {
-                       tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
-                       l_ptr->stats.bearer_congs++;
-                       l_ptr->next_out = buf;
-               }
+               tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+               l_ptr->unacked_window = 0;
                return dsz;
        }
        /* Congestion: can message be bundled ? */
@@ -891,10 +890,8 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
 
                /* Try adding message to an existing bundle */
                if (l_ptr->next_out &&
-                   link_bundle_buf(l_ptr, l_ptr->last_out, buf)) {
-                       tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
+                   link_bundle_buf(l_ptr, l_ptr->last_out, buf))
                        return dsz;
-               }
 
                /* Try creating a new bundle */
                if (size <= max_packet * 2 / 3) {
@@ -917,7 +914,6 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf)
        if (!l_ptr->next_out)
                l_ptr->next_out = buf;
        link_add_to_outqueue(l_ptr, buf, msg);
-       tipc_bearer_resolve_congestion(l_ptr->b_ptr, l_ptr);
        return dsz;
 }
 
@@ -949,7 +945,48 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector)
        return res;
 }
 
-/**
+/*
+ * tipc_link_send_sync - synchronize broadcast link endpoints.
+ *
+ * Give a newly added peer node the sequence number where it should
+ * start receiving and acking broadcast packets.
+ *
+ * Called with node locked
+ */
+static void tipc_link_send_sync(struct tipc_link *l)
+{
+       struct sk_buff *buf;
+       struct tipc_msg *msg;
+
+       buf = tipc_buf_acquire(INT_H_SIZE);
+       if (!buf)
+               return;
+
+       msg = buf_msg(buf);
+       tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, l->addr);
+       msg_set_last_bcast(msg, l->owner->bclink.acked);
+       link_add_chain_to_outqueue(l, buf, 0);
+       tipc_link_push_queue(l);
+}
+
+/*
+ * tipc_link_recv_sync - synchronize broadcast link endpoints.
+ * Receive the sequence number where we should start receiving and
+ * acking broadcast packets from a newly added peer node, and open
+ * up for reception of such packets.
+ *
+ * Called with node locked
+ */
+static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf)
+{
+       struct tipc_msg *msg = buf_msg(buf);
+
+       n->bclink.last_sent = n->bclink.last_in = msg_last_bcast(msg);
+       n->bclink.recv_permitted = true;
+       kfree_skb(buf);
+}
+
+/*
  * tipc_link_send_names - send name table entries to new neighbor
  *
  * Send routine for bulk delivery of name table messages when contact
@@ -1006,16 +1043,11 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf,
 
        if (likely(!link_congested(l_ptr))) {
                if (likely(msg_size(msg) <= l_ptr->max_pkt)) {
-                       if (likely(list_empty(&l_ptr->b_ptr->cong_links))) {
+                       if (likely(!tipc_bearer_blocked(l_ptr->b_ptr))) {
                                link_add_to_outqueue(l_ptr, buf, msg);
-                               if (likely(tipc_bearer_send(l_ptr->b_ptr, buf,
-                                                           &l_ptr->media_addr))) {
-                                       l_ptr->unacked_window = 0;
-                                       return res;
-                               }
-                               tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
-                               l_ptr->stats.bearer_congs++;
-                               l_ptr->next_out = buf;
+                               tipc_bearer_send(l_ptr->b_ptr, buf,
+                                                &l_ptr->media_addr);
+                               l_ptr->unacked_window = 0;
                                return res;
                        }
                } else
@@ -1106,7 +1138,7 @@ exit:
 
                        /* Exit if link (or bearer) is congested */
                        if (link_congested(l_ptr) ||
-                           !list_empty(&l_ptr->b_ptr->cong_links)) {
+                           tipc_bearer_blocked(l_ptr->b_ptr)) {
                                res = link_schedule_port(l_ptr,
                                                         sender->ref, res);
                                goto exit;
@@ -1329,15 +1361,11 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr)
        if (r_q_size && buf) {
                msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
                msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
-               if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
-                       l_ptr->retransm_queue_head = mod(++r_q_head);
-                       l_ptr->retransm_queue_size = --r_q_size;
-                       l_ptr->stats.retransmitted++;
-                       return 0;
-               } else {
-                       l_ptr->stats.bearer_congs++;
-                       return PUSH_FAILED;
-               }
+               tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+               l_ptr->retransm_queue_head = mod(++r_q_head);
+               l_ptr->retransm_queue_size = --r_q_size;
+               l_ptr->stats.retransmitted++;
+               return 0;
        }
 
        /* Send deferred protocol message, if any: */
@@ -1345,15 +1373,11 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr)
        if (buf) {
                msg_set_ack(buf_msg(buf), mod(l_ptr->next_in_no - 1));
                msg_set_bcast_ack(buf_msg(buf), l_ptr->owner->bclink.last_in);
-               if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
-                       l_ptr->unacked_window = 0;
-                       kfree_skb(buf);
-                       l_ptr->proto_msg_queue = NULL;
-                       return 0;
-               } else {
-                       l_ptr->stats.bearer_congs++;
-                       return PUSH_FAILED;
-               }
+               tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+               l_ptr->unacked_window = 0;
+               kfree_skb(buf);
+               l_ptr->proto_msg_queue = NULL;
+               return 0;
        }
 
        /* Send one deferred data message, if send window not full: */
@@ -1366,18 +1390,14 @@ u32 tipc_link_push_packet(struct tipc_link *l_ptr)
                if (mod(next - first) < l_ptr->queue_limit[0]) {
                        msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
                        msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
-                       if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
-                               if (msg_user(msg) == MSG_BUNDLER)
-                                       msg_set_type(msg, CLOSED_MSG);
-                               l_ptr->next_out = buf->next;
-                               return 0;
-                       } else {
-                               l_ptr->stats.bearer_congs++;
-                               return PUSH_FAILED;
-                       }
+                       tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+                       if (msg_user(msg) == MSG_BUNDLER)
+                               msg_set_type(msg, CLOSED_MSG);
+                       l_ptr->next_out = buf->next;
+                       return 0;
                }
        }
-       return PUSH_FINISHED;
+       return 1;
 }
 
 /*
@@ -1388,15 +1408,12 @@ void tipc_link_push_queue(struct tipc_link *l_ptr)
 {
        u32 res;
 
-       if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr))
+       if (tipc_bearer_blocked(l_ptr->b_ptr))
                return;
 
        do {
                res = tipc_link_push_packet(l_ptr);
        } while (!res);
-
-       if (res == PUSH_FAILED)
-               tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
 }
 
 static void link_reset_all(unsigned long addr)
@@ -1454,9 +1471,8 @@ static void link_retransmit_failure(struct tipc_link *l_ptr,
 
                tipc_addr_string_fill(addr_string, n_ptr->addr);
                pr_info("Broadcast link info for %s\n", addr_string);
-               pr_info("Supportable: %d,  Supported: %d,  Acked: %u\n",
-                       n_ptr->bclink.supportable,
-                       n_ptr->bclink.supported,
+               pr_info("Reception permitted: %d,  Acked: %u\n",
+                       n_ptr->bclink.recv_permitted,
                        n_ptr->bclink.acked);
                pr_info("Last in: %u,  Oos state: %u,  Last sent: %u\n",
                        n_ptr->bclink.last_in,
@@ -1481,7 +1497,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf,
 
        msg = buf_msg(buf);
 
-       if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
+       if (tipc_bearer_blocked(l_ptr->b_ptr)) {
                if (l_ptr->retransm_queue_size == 0) {
                        l_ptr->retransm_queue_head = msg_seqno(msg);
                        l_ptr->retransm_queue_size = retransmits;
@@ -1491,7 +1507,7 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf,
                }
                return;
        } else {
-               /* Detect repeated retransmit failures on uncongested bearer */
+               /* Detect repeated retransmit failures on unblocked bearer */
                if (l_ptr->last_retransmitted == msg_seqno(msg)) {
                        if (++l_ptr->stale_count > 100) {
                                link_retransmit_failure(l_ptr, buf);
@@ -1507,17 +1523,10 @@ void tipc_link_retransmit(struct tipc_link *l_ptr, struct sk_buff *buf,
                msg = buf_msg(buf);
                msg_set_ack(msg, mod(l_ptr->next_in_no - 1));
                msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in);
-               if (tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
-                       buf = buf->next;
-                       retransmits--;
-                       l_ptr->stats.retransmitted++;
-               } else {
-                       tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
-                       l_ptr->stats.bearer_congs++;
-                       l_ptr->retransm_queue_head = buf_seqno(buf);
-                       l_ptr->retransm_queue_size = retransmits;
-                       return;
-               }
+               tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
+               buf = buf->next;
+               retransmits--;
+               l_ptr->stats.retransmitted++;
        }
 
        l_ptr->retransm_queue_head = l_ptr->retransm_queue_size = 0;
@@ -1676,7 +1685,7 @@ void tipc_recv_msg(struct sk_buff *head, struct tipc_bearer *b_ptr)
                ackd = msg_ack(msg);
 
                /* Release acked messages */
-               if (n_ptr->bclink.supported)
+               if (n_ptr->bclink.recv_permitted)
                        tipc_bclink_acknowledge(n_ptr, msg_bcast_ack(msg));
 
                crs = l_ptr->first_out;
@@ -1727,9 +1736,14 @@ deliver:
                                        tipc_link_recv_bundle(buf);
                                        continue;
                                case NAME_DISTRIBUTOR:
+                                       n_ptr->bclink.recv_permitted = true;
                                        tipc_node_unlock(n_ptr);
                                        tipc_named_recv(buf);
                                        continue;
+                               case BCAST_PROTOCOL:
+                                       tipc_link_recv_sync(n_ptr, buf);
+                                       tipc_node_unlock(n_ptr);
+                                       continue;
                                case CONN_MANAGER:
                                        tipc_node_unlock(n_ptr);
                                        tipc_port_recv_proto_msg(buf);
@@ -1772,16 +1786,19 @@ deliver:
                        continue;
                }
 
+               /* Link is not in state WORKING_WORKING */
                if (msg_user(msg) == LINK_PROTOCOL) {
                        link_recv_proto_msg(l_ptr, buf);
                        head = link_insert_deferred_queue(l_ptr, head);
                        tipc_node_unlock(n_ptr);
                        continue;
                }
+
+               /* Traffic message. Conditionally activate link */
                link_state_event(l_ptr, TRAFFIC_MSG_EVT);
 
                if (link_working_working(l_ptr)) {
-                       /* Re-insert in front of queue */
+                       /* Re-insert buffer in front of queue */
                        buf->next = head;
                        head = buf;
                        tipc_node_unlock(n_ptr);
@@ -1972,21 +1989,13 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ,
 
        skb_copy_to_linear_data(buf, msg, sizeof(l_ptr->proto_msg));
 
-       /* Defer message if bearer is already congested */
-       if (tipc_bearer_congested(l_ptr->b_ptr, l_ptr)) {
-               l_ptr->proto_msg_queue = buf;
-               return;
-       }
-
-       /* Defer message if attempting to send results in bearer congestion */
-       if (!tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr)) {
-               tipc_bearer_schedule(l_ptr->b_ptr, l_ptr);
+       /* Defer message if bearer is already blocked */
+       if (tipc_bearer_blocked(l_ptr->b_ptr)) {
                l_ptr->proto_msg_queue = buf;
-               l_ptr->stats.bearer_congs++;
                return;
        }
 
-       /* Discard message if it was sent successfully */
+       tipc_bearer_send(l_ptr->b_ptr, buf, &l_ptr->media_addr);
        l_ptr->unacked_window = 0;
        kfree_skb(buf);
 }
@@ -2057,7 +2066,6 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
                } else {
                        l_ptr->max_pkt = l_ptr->max_pkt_target;
                }
-               l_ptr->owner->bclink.supportable = (max_pkt_info != 0);
 
                /* Synchronize broadcast link info, if not done previously */
                if (!tipc_node_is_up(l_ptr->owner)) {
@@ -2112,7 +2120,7 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf)
                }
 
                /* Protocol message before retransmits, reduce loss risk */
-               if (l_ptr->owner->bclink.supported)
+               if (l_ptr->owner->bclink.recv_permitted)
                        tipc_bclink_update_link_state(l_ptr->owner,
                                                      msg_last_bcast(msg));
 
@@ -2487,16 +2495,6 @@ static void set_expected_frags(struct sk_buff *buf, u32 exp)
        msg_set_bcast_ack(buf_msg(buf), exp);
 }
 
-static u32 get_timer_cnt(struct sk_buff *buf)
-{
-       return msg_reroute_cnt(buf_msg(buf));
-}
-
-static void incr_timer_cnt(struct sk_buff *buf)
-{
-       msg_incr_reroute_cnt(buf_msg(buf));
-}
-
 /*
  * tipc_link_recv_fragment(): Called with node lock on. Returns
  * the reassembled buffer if message is complete.
@@ -2575,38 +2573,6 @@ int tipc_link_recv_fragment(struct sk_buff **pending, struct sk_buff **fb,
        return 0;
 }
 
-/**
- * link_check_defragm_bufs - flush stale incoming message fragments
- * @l_ptr: pointer to link
- */
-static void link_check_defragm_bufs(struct tipc_link *l_ptr)
-{
-       struct sk_buff *prev = NULL;
-       struct sk_buff *next = NULL;
-       struct sk_buff *buf = l_ptr->defragm_buf;
-
-       if (!buf)
-               return;
-       if (!link_working_working(l_ptr))
-               return;
-       while (buf) {
-               u32 cnt = get_timer_cnt(buf);
-
-               next = buf->next;
-               if (cnt < 4) {
-                       incr_timer_cnt(buf);
-                       prev = buf;
-               } else {
-                       if (prev)
-                               prev->next = buf->next;
-                       else
-                               l_ptr->defragm_buf = buf->next;
-                       kfree_skb(buf);
-               }
-               buf = next;
-       }
-}
-
 static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance)
 {
        if ((tolerance < TIPC_MIN_LINK_TOL) || (tolerance > TIPC_MAX_LINK_TOL))
@@ -2937,8 +2903,8 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size)
                             s->sent_nacks, s->sent_acks, s->retransmitted);
 
        ret += tipc_snprintf(buf + ret, buf_size - ret,
-                            "  Congestion bearer:%u link:%u  Send queue"
-                            " max:%u avg:%u\n", s->bearer_congs, s->link_congs,
+                            "  Congestion link:%u  Send queue"
+                            " max:%u avg:%u\n", s->link_congs,
                             s->max_queue_sz, s->queue_sz_counts ?
                             (s->accu_queue_sz / s->queue_sz_counts) : 0);
 
index 6e921121be0616f9f1e1bca2a7625adb527fade3..c048ed1cbd765aa3417c945d2913d0c994cb7d3f 100644 (file)
@@ -40,9 +40,6 @@
 #include "msg.h"
 #include "node.h"
 
-#define PUSH_FAILED   1
-#define PUSH_FINISHED 2
-
 /*
  * Out-of-range value for link sequence numbers
  */
@@ -82,7 +79,6 @@ struct tipc_stats {
        u32 recv_fragmented;
        u32 recv_fragments;
        u32 link_congs;         /* # port sends blocked by congestion */
-       u32 bearer_congs;
        u32 deferred_recv;
        u32 duplicates;
        u32 max_queue_sz;       /* send queue size high water mark */
index 55d3928dfd6702c423c04abea5aa7ec6fc870d2e..e0d08055754ea656ab1afdd5dee59a51f16bb163 100644 (file)
@@ -262,7 +262,7 @@ void tipc_named_node_up(unsigned long nodearg)
        named_distribute(&message_list, node, &publ_zone, max_item_buf);
        read_unlock_bh(&tipc_nametbl_lock);
 
-       tipc_link_send_names(&message_list, (u32)node);
+       tipc_link_send_names(&message_list, node);
 }
 
 /**
index d21db204e25a181527822fa02599e391b4c40fe8..48f39dd3eae8801ff2eb1638b7ac4551c4035237 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * net/tipc/node.c: TIPC node management routines
  *
- * Copyright (c) 2000-2006, Ericsson AB
+ * Copyright (c) 2000-2006, 2012 Ericsson AB
  * Copyright (c) 2005-2006, 2010-2011, Wind River Systems
  * All rights reserved.
  *
@@ -263,12 +263,9 @@ void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr)
 static void node_established_contact(struct tipc_node *n_ptr)
 {
        tipc_k_signal((Handler)tipc_named_node_up, n_ptr->addr);
-
-       if (n_ptr->bclink.supportable) {
-               n_ptr->bclink.acked = tipc_bclink_get_last_sent();
-               tipc_bclink_add_node(n_ptr->addr);
-               n_ptr->bclink.supported = 1;
-       }
+       n_ptr->bclink.oos_state = 0;
+       n_ptr->bclink.acked = tipc_bclink_get_last_sent();
+       tipc_bclink_add_node(n_ptr->addr);
 }
 
 static void node_name_purge_complete(unsigned long node_addr)
@@ -294,7 +291,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
                tipc_addr_string_fill(addr_string, n_ptr->addr));
 
        /* Flush broadcast link info associated with lost node */
-       if (n_ptr->bclink.supported) {
+       if (n_ptr->bclink.recv_permitted) {
                while (n_ptr->bclink.deferred_head) {
                        struct sk_buff *buf = n_ptr->bclink.deferred_head;
                        n_ptr->bclink.deferred_head = buf->next;
@@ -310,7 +307,7 @@ static void node_lost_contact(struct tipc_node *n_ptr)
                tipc_bclink_remove_node(n_ptr->addr);
                tipc_bclink_acknowledge(n_ptr, INVALID_LINK_SEQ);
 
-               n_ptr->bclink.supported = 0;
+               n_ptr->bclink.recv_permitted = false;
        }
 
        /* Abort link changeover */
index cfcaf4d6e4801c5047f665a8c4b272948e260bf6..3c189b35b102a378914b59236f555438f7c198d4 100644 (file)
@@ -67,8 +67,6 @@
  * @permit_changeover: non-zero if node has redundant links to this system
  * @signature: node instance identifier
  * @bclink: broadcast-related info
- *    @supportable: non-zero if node supports TIPC b'cast link capability
- *    @supported: non-zero if node supports TIPC b'cast capability
  *    @acked: sequence # of last outbound b'cast message acknowledged by node
  *    @last_in: sequence # of last in-sequence b'cast message received from node
  *    @last_sent: sequence # of last b'cast message sent by node
@@ -77,6 +75,7 @@
  *    @deferred_head: oldest OOS b'cast message received from node
  *    @deferred_tail: newest OOS b'cast message received from node
  *    @defragm: list of partially reassembled b'cast message fragments from node
+ *    @recv_permitted: true if node is allowed to receive b'cast messages
  */
 struct tipc_node {
        u32 addr;
@@ -92,8 +91,6 @@ struct tipc_node {
        int permit_changeover;
        u32 signature;
        struct {
-               u8 supportable;
-               u8 supported;
                u32 acked;
                u32 last_in;
                u32 last_sent;
@@ -102,6 +99,7 @@ struct tipc_node {
                struct sk_buff *deferred_head;
                struct sk_buff *deferred_tail;
                struct sk_buff *defragm;
+               bool recv_permitted;
        } bclink;
 };
 
index 07c42fba672be17a4a127b8907f52a3520801f1f..18098cac62f23e942b6c3e42839bb3c2e4fdcea3 100644 (file)
@@ -726,7 +726,7 @@ static void port_dispatcher_sigh(void *dummy)
                                if (unlikely(!cb))
                                        goto reject;
                                if (unlikely(!connected)) {
-                                       if (tipc_connect2port(dref, &orig))
+                                       if (tipc_connect(dref, &orig))
                                                goto reject;
                                } else if (peer_invalid)
                                        goto reject;
@@ -1036,15 +1036,30 @@ int tipc_withdraw(u32 ref, unsigned int scope, struct tipc_name_seq const *seq)
        return res;
 }
 
-int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
+int tipc_connect(u32 ref, struct tipc_portid const *peer)
 {
        struct tipc_port *p_ptr;
-       struct tipc_msg *msg;
-       int res = -EINVAL;
+       int res;
 
        p_ptr = tipc_port_lock(ref);
        if (!p_ptr)
                return -EINVAL;
+       res = __tipc_connect(ref, p_ptr, peer);
+       tipc_port_unlock(p_ptr);
+       return res;
+}
+
+/*
+ * __tipc_connect - connect to a remote peer
+ *
+ * Port must be locked.
+ */
+int __tipc_connect(u32 ref, struct tipc_port *p_ptr,
+                       struct tipc_portid const *peer)
+{
+       struct tipc_msg *msg;
+       int res = -EINVAL;
+
        if (p_ptr->published || p_ptr->connected)
                goto exit;
        if (!peer->ref)
@@ -1067,17 +1082,16 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer)
                          (net_ev_handler)port_handle_node_down);
        res = 0;
 exit:
-       tipc_port_unlock(p_ptr);
        p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref);
        return res;
 }
 
-/**
- * tipc_disconnect_port - disconnect port from peer
+/*
+ * __tipc_disconnect - disconnect port from peer
  *
  * Port must be locked.
  */
-int tipc_disconnect_port(struct tipc_port *tp_ptr)
+int __tipc_disconnect(struct tipc_port *tp_ptr)
 {
        int res;
 
@@ -1104,7 +1118,7 @@ int tipc_disconnect(u32 ref)
        p_ptr = tipc_port_lock(ref);
        if (!p_ptr)
                return -EINVAL;
-       res = tipc_disconnect_port(p_ptr);
+       res = __tipc_disconnect(p_ptr);
        tipc_port_unlock(p_ptr);
        return res;
 }
index 4660e30657906bc318494f91485e2826fac46c34..fb66e2e5f4d1a93348c24e212946d74c776c0331 100644 (file)
@@ -190,7 +190,7 @@ int tipc_publish(u32 portref, unsigned int scope,
 int tipc_withdraw(u32 portref, unsigned int scope,
                struct tipc_name_seq const *name_seq);
 
-int tipc_connect2port(u32 portref, struct tipc_portid const *port);
+int tipc_connect(u32 portref, struct tipc_portid const *port);
 
 int tipc_disconnect(u32 portref);
 
@@ -200,7 +200,9 @@ int tipc_shutdown(u32 ref);
 /*
  * The following routines require that the port be locked on entry
  */
-int tipc_disconnect_port(struct tipc_port *tp_ptr);
+int __tipc_disconnect(struct tipc_port *tp_ptr);
+int __tipc_connect(u32 ref, struct tipc_port *p_ptr,
+                  struct tipc_portid const *peer);
 int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg);
 
 /*
index fd5f042dbff4d8a8a47c2a532e0d0ac5d0a70cd2..9b4e4833a484f959a891d5022ff468c671f38239 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * net/tipc/socket.c: TIPC socket API
  *
- * Copyright (c) 2001-2007, Ericsson AB
- * Copyright (c) 2004-2008, 2010-2011, Wind River Systems
+ * Copyright (c) 2001-2007, 2012 Ericsson AB
+ * Copyright (c) 2004-2008, 2010-2012, Wind River Systems
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -43,7 +43,7 @@
 #define SS_LISTENING   -1      /* socket is listening */
 #define SS_READY       -2      /* socket is connectionless */
 
-#define OVERLOAD_LIMIT_BASE    5000
+#define OVERLOAD_LIMIT_BASE    10000
 #define CONN_TIMEOUT_DEFAULT   8000    /* default connect timeout = 8s */
 
 struct tipc_sock {
@@ -62,6 +62,8 @@ struct tipc_sock {
 static int backlog_rcv(struct sock *sk, struct sk_buff *skb);
 static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf);
 static void wakeupdispatch(struct tipc_port *tport);
+static void tipc_data_ready(struct sock *sk, int len);
+static void tipc_write_space(struct sock *sk);
 
 static const struct proto_ops packet_ops;
 static const struct proto_ops stream_ops;
@@ -71,8 +73,6 @@ static struct proto tipc_proto;
 
 static int sockets_enabled;
 
-static atomic_t tipc_queue_size = ATOMIC_INIT(0);
-
 /*
  * Revised TIPC socket locking policy:
  *
@@ -126,7 +126,6 @@ static atomic_t tipc_queue_size = ATOMIC_INIT(0);
 static void advance_rx_queue(struct sock *sk)
 {
        kfree_skb(__skb_dequeue(&sk->sk_receive_queue));
-       atomic_dec(&tipc_queue_size);
 }
 
 /**
@@ -138,10 +137,8 @@ static void discard_rx_queue(struct sock *sk)
 {
        struct sk_buff *buf;
 
-       while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
-               atomic_dec(&tipc_queue_size);
+       while ((buf = __skb_dequeue(&sk->sk_receive_queue)))
                kfree_skb(buf);
-       }
 }
 
 /**
@@ -153,10 +150,8 @@ static void reject_rx_queue(struct sock *sk)
 {
        struct sk_buff *buf;
 
-       while ((buf = __skb_dequeue(&sk->sk_receive_queue))) {
+       while ((buf = __skb_dequeue(&sk->sk_receive_queue)))
                tipc_reject_msg(buf, TIPC_ERR_NO_PORT);
-               atomic_dec(&tipc_queue_size);
-       }
 }
 
 /**
@@ -221,6 +216,8 @@ static int tipc_create(struct net *net, struct socket *sock, int protocol,
        sock_init_data(sock, sk);
        sk->sk_backlog_rcv = backlog_rcv;
        sk->sk_rcvbuf = TIPC_FLOW_CONTROL_WIN * 2 * TIPC_MAX_USER_MSG_SIZE * 2;
+       sk->sk_data_ready = tipc_data_ready;
+       sk->sk_write_space = tipc_write_space;
        tipc_sk(sk)->p = tp_ptr;
        tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT;
 
@@ -276,7 +273,6 @@ static int release(struct socket *sock)
                buf = __skb_dequeue(&sk->sk_receive_queue);
                if (buf == NULL)
                        break;
-               atomic_dec(&tipc_queue_size);
                if (TIPC_SKB_CB(buf)->handle != 0)
                        kfree_skb(buf);
                else {
@@ -408,7 +404,7 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr,
  * socket state                flags set
  * ------------                ---------
  * unconnected         no read flags
- *                     no write flags
+ *                     POLLOUT if port is not congested
  *
  * connecting          POLLIN/POLLRDNORM if ACK/NACK in rx queue
  *                     no write flags
@@ -435,9 +431,13 @@ static unsigned int poll(struct file *file, struct socket *sock,
        struct sock *sk = sock->sk;
        u32 mask = 0;
 
-       poll_wait(file, sk_sleep(sk), wait);
+       sock_poll_wait(file, sk_sleep(sk), wait);
 
        switch ((int)sock->state) {
+       case SS_UNCONNECTED:
+               if (!tipc_sk_port(sk)->congested)
+                       mask |= POLLOUT;
+               break;
        case SS_READY:
        case SS_CONNECTED:
                if (!tipc_sk_port(sk)->congested)
@@ -775,16 +775,19 @@ exit:
 static int auto_connect(struct socket *sock, struct tipc_msg *msg)
 {
        struct tipc_sock *tsock = tipc_sk(sock->sk);
-
-       if (msg_errcode(msg)) {
-               sock->state = SS_DISCONNECTING;
-               return -ECONNREFUSED;
-       }
+       struct tipc_port *p_ptr;
 
        tsock->peer_name.ref = msg_origport(msg);
        tsock->peer_name.node = msg_orignode(msg);
-       tipc_connect2port(tsock->p->ref, &tsock->peer_name);
-       tipc_set_portimportance(tsock->p->ref, msg_importance(msg));
+       p_ptr = tipc_port_deref(tsock->p->ref);
+       if (!p_ptr)
+               return -EINVAL;
+
+       __tipc_connect(tsock->p->ref, p_ptr, &tsock->peer_name);
+
+       if (msg_importance(msg) > TIPC_CRITICAL_IMPORTANCE)
+               return -EINVAL;
+       msg_set_importance(&p_ptr->phdr, (u32)msg_importance(msg));
        sock->state = SS_CONNECTED;
        return 0;
 }
@@ -943,13 +946,6 @@ restart:
        sz = msg_data_sz(msg);
        err = msg_errcode(msg);
 
-       /* Complete connection setup for an implied connect */
-       if (unlikely(sock->state == SS_CONNECTING)) {
-               res = auto_connect(sock, msg);
-               if (res)
-                       goto exit;
-       }
-
        /* Discard an empty non-errored message & try again */
        if ((!sz) && (!err)) {
                advance_rx_queue(sk);
@@ -1125,6 +1121,39 @@ exit:
        return sz_copied ? sz_copied : res;
 }
 
+/**
+ * tipc_write_space - wake up thread if port congestion is released
+ * @sk: socket
+ */
+static void tipc_write_space(struct sock *sk)
+{
+       struct socket_wq *wq;
+
+       rcu_read_lock();
+       wq = rcu_dereference(sk->sk_wq);
+       if (wq_has_sleeper(wq))
+               wake_up_interruptible_sync_poll(&wq->wait, POLLOUT |
+                                               POLLWRNORM | POLLWRBAND);
+       rcu_read_unlock();
+}
+
+/**
+ * tipc_data_ready - wake up threads to indicate messages have been received
+ * @sk: socket
+ * @len: the length of messages
+ */
+static void tipc_data_ready(struct sock *sk, int len)
+{
+       struct socket_wq *wq;
+
+       rcu_read_lock();
+       wq = rcu_dereference(sk->sk_wq);
+       if (wq_has_sleeper(wq))
+               wake_up_interruptible_sync_poll(&wq->wait, POLLIN |
+                                               POLLRDNORM | POLLRDBAND);
+       rcu_read_unlock();
+}
+
 /**
  * rx_queue_full - determine if receive queue can accept another message
  * @msg: message to be added to queue
@@ -1153,6 +1182,83 @@ static int rx_queue_full(struct tipc_msg *msg, u32 queue_size, u32 base)
        return queue_size >= threshold;
 }
 
+/**
+ * filter_connect - Handle all incoming messages for a connection-based socket
+ * @tsock: TIPC socket
+ * @msg: message
+ *
+ * Returns TIPC error status code and socket error status code
+ * once it encounters some errors
+ */
+static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf)
+{
+       struct socket *sock = tsock->sk.sk_socket;
+       struct tipc_msg *msg = buf_msg(*buf);
+       struct sock *sk = &tsock->sk;
+       u32 retval = TIPC_ERR_NO_PORT;
+       int res;
+
+       if (msg_mcast(msg))
+               return retval;
+
+       switch ((int)sock->state) {
+       case SS_CONNECTED:
+               /* Accept only connection-based messages sent by peer */
+               if (msg_connected(msg) && tipc_port_peer_msg(tsock->p, msg)) {
+                       if (unlikely(msg_errcode(msg))) {
+                               sock->state = SS_DISCONNECTING;
+                               __tipc_disconnect(tsock->p);
+                       }
+                       retval = TIPC_OK;
+               }
+               break;
+       case SS_CONNECTING:
+               /* Accept only ACK or NACK message */
+               if (unlikely(msg_errcode(msg))) {
+                       sock->state = SS_DISCONNECTING;
+                       sk->sk_err = -ECONNREFUSED;
+                       retval = TIPC_OK;
+                       break;
+               }
+
+               if (unlikely(!msg_connected(msg)))
+                       break;
+
+               res = auto_connect(sock, msg);
+               if (res) {
+                       sock->state = SS_DISCONNECTING;
+                       sk->sk_err = res;
+                       retval = TIPC_OK;
+                       break;
+               }
+
+               /* If an incoming message is an 'ACK-', it should be
+                * discarded here because it doesn't contain useful
+                * data. In addition, we should try to wake up
+                * connect() routine if sleeping.
+                */
+               if (msg_data_sz(msg) == 0) {
+                       kfree_skb(*buf);
+                       *buf = NULL;
+                       if (waitqueue_active(sk_sleep(sk)))
+                               wake_up_interruptible(sk_sleep(sk));
+               }
+               retval = TIPC_OK;
+               break;
+       case SS_LISTENING:
+       case SS_UNCONNECTED:
+               /* Accept only SYN message */
+               if (!msg_connected(msg) && !(msg_errcode(msg)))
+                       retval = TIPC_OK;
+               break;
+       case SS_DISCONNECTING:
+               break;
+       default:
+               pr_err("Unknown socket state %u\n", sock->state);
+       }
+       return retval;
+}
+
 /**
  * filter_rcv - validate incoming message
  * @sk: socket
@@ -1170,6 +1276,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
        struct socket *sock = sk->sk_socket;
        struct tipc_msg *msg = buf_msg(buf);
        u32 recv_q_len;
+       u32 res = TIPC_OK;
 
        /* Reject message if it is wrong sort of message for socket */
        if (msg_type(msg) > TIPC_DIRECT_MSG)
@@ -1179,32 +1286,12 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
                if (msg_connected(msg))
                        return TIPC_ERR_NO_PORT;
        } else {
-               if (msg_mcast(msg))
-                       return TIPC_ERR_NO_PORT;
-               if (sock->state == SS_CONNECTED) {
-                       if (!msg_connected(msg) ||
-                           !tipc_port_peer_msg(tipc_sk_port(sk), msg))
-                               return TIPC_ERR_NO_PORT;
-               } else if (sock->state == SS_CONNECTING) {
-                       if (!msg_connected(msg) && (msg_errcode(msg) == 0))
-                               return TIPC_ERR_NO_PORT;
-               } else if (sock->state == SS_LISTENING) {
-                       if (msg_connected(msg) || msg_errcode(msg))
-                               return TIPC_ERR_NO_PORT;
-               } else if (sock->state == SS_DISCONNECTING) {
-                       return TIPC_ERR_NO_PORT;
-               } else /* (sock->state == SS_UNCONNECTED) */ {
-                       if (msg_connected(msg) || msg_errcode(msg))
-                               return TIPC_ERR_NO_PORT;
-               }
+               res = filter_connect(tipc_sk(sk), &buf);
+               if (res != TIPC_OK || buf == NULL)
+                       return res;
        }
 
        /* Reject message if there isn't room to queue it */
-       recv_q_len = (u32)atomic_read(&tipc_queue_size);
-       if (unlikely(recv_q_len >= OVERLOAD_LIMIT_BASE)) {
-               if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE))
-                       return TIPC_ERR_OVERLOAD;
-       }
        recv_q_len = skb_queue_len(&sk->sk_receive_queue);
        if (unlikely(recv_q_len >= (OVERLOAD_LIMIT_BASE / 2))) {
                if (rx_queue_full(msg, recv_q_len, OVERLOAD_LIMIT_BASE / 2))
@@ -1213,17 +1300,9 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf)
 
        /* Enqueue message (finally!) */
        TIPC_SKB_CB(buf)->handle = 0;
-       atomic_inc(&tipc_queue_size);
        __skb_queue_tail(&sk->sk_receive_queue, buf);
 
-       /* Initiate connection termination for an incoming 'FIN' */
-       if (unlikely(msg_errcode(msg) && (sock->state == SS_CONNECTED))) {
-               sock->state = SS_DISCONNECTING;
-               tipc_disconnect_port(tipc_sk_port(sk));
-       }
-
-       if (waitqueue_active(sk_sleep(sk)))
-               wake_up_interruptible(sk_sleep(sk));
+       sk->sk_data_ready(sk, 0);
        return TIPC_OK;
 }
 
@@ -1290,8 +1369,7 @@ static void wakeupdispatch(struct tipc_port *tport)
 {
        struct sock *sk = (struct sock *)tport->usr_handle;
 
-       if (waitqueue_active(sk_sleep(sk)))
-               wake_up_interruptible(sk_sleep(sk));
+       sk->sk_write_space(sk);
 }
 
 /**
@@ -1309,8 +1387,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
        struct sock *sk = sock->sk;
        struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest;
        struct msghdr m = {NULL,};
-       struct sk_buff *buf;
-       struct tipc_msg *msg;
        unsigned int timeout;
        int res;
 
@@ -1322,26 +1398,6 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
                goto exit;
        }
 
-       /* For now, TIPC does not support the non-blocking form of connect() */
-       if (flags & O_NONBLOCK) {
-               res = -EOPNOTSUPP;
-               goto exit;
-       }
-
-       /* Issue Posix-compliant error code if socket is in the wrong state */
-       if (sock->state == SS_LISTENING) {
-               res = -EOPNOTSUPP;
-               goto exit;
-       }
-       if (sock->state == SS_CONNECTING) {
-               res = -EALREADY;
-               goto exit;
-       }
-       if (sock->state != SS_UNCONNECTED) {
-               res = -EISCONN;
-               goto exit;
-       }
-
        /*
         * Reject connection attempt using multicast address
         *
@@ -1353,49 +1409,66 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen,
                goto exit;
        }
 
-       /* Reject any messages already in receive queue (very unlikely) */
-       reject_rx_queue(sk);
+       timeout = (flags & O_NONBLOCK) ? 0 : tipc_sk(sk)->conn_timeout;
 
-       /* Send a 'SYN-' to destination */
-       m.msg_name = dest;
-       m.msg_namelen = destlen;
-       res = send_msg(NULL, sock, &m, 0);
-       if (res < 0)
+       switch (sock->state) {
+       case SS_UNCONNECTED:
+               /* Send a 'SYN-' to destination */
+               m.msg_name = dest;
+               m.msg_namelen = destlen;
+
+               /* If connect is in non-blocking case, set MSG_DONTWAIT to
+                * indicate send_msg() is never blocked.
+                */
+               if (!timeout)
+                       m.msg_flags = MSG_DONTWAIT;
+
+               res = send_msg(NULL, sock, &m, 0);
+               if ((res < 0) && (res != -EWOULDBLOCK))
+                       goto exit;
+
+               /* Just entered SS_CONNECTING state; the only
+                * difference is that return value in non-blocking
+                * case is EINPROGRESS, rather than EALREADY.
+                */
+               res = -EINPROGRESS;
+               break;
+       case SS_CONNECTING:
+               res = -EALREADY;
+               break;
+       case SS_CONNECTED:
+               res = -EISCONN;
+               break;
+       default:
+               res = -EINVAL;
                goto exit;
+       }
 
-       /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
-       timeout = tipc_sk(sk)->conn_timeout;
-       release_sock(sk);
-       res = wait_event_interruptible_timeout(*sk_sleep(sk),
-                       (!skb_queue_empty(&sk->sk_receive_queue) ||
-                       (sock->state != SS_CONNECTING)),
-                       timeout ? (long)msecs_to_jiffies(timeout)
-                               : MAX_SCHEDULE_TIMEOUT);
-       lock_sock(sk);
+       if (sock->state == SS_CONNECTING) {
+               if (!timeout)
+                       goto exit;
 
-       if (res > 0) {
-               buf = skb_peek(&sk->sk_receive_queue);
-               if (buf != NULL) {
-                       msg = buf_msg(buf);
-                       res = auto_connect(sock, msg);
-                       if (!res) {
-                               if (!msg_data_sz(msg))
-                                       advance_rx_queue(sk);
-                       }
-               } else {
-                       if (sock->state == SS_CONNECTED)
-                               res = -EISCONN;
+               /* Wait until an 'ACK' or 'RST' arrives, or a timeout occurs */
+               release_sock(sk);
+               res = wait_event_interruptible_timeout(*sk_sleep(sk),
+                               sock->state != SS_CONNECTING,
+                               timeout ? (long)msecs_to_jiffies(timeout)
+                                       : MAX_SCHEDULE_TIMEOUT);
+               lock_sock(sk);
+               if (res <= 0) {
+                       if (res == 0)
+                               res = -ETIMEDOUT;
                        else
-                               res = -ECONNREFUSED;
+                               ; /* leave "res" unchanged */
+                       goto exit;
                }
-       } else {
-               if (res == 0)
-                       res = -ETIMEDOUT;
-               else
-                       ; /* leave "res" unchanged */
-               sock->state = SS_DISCONNECTING;
        }
 
+       if (unlikely(sock->state == SS_DISCONNECTING))
+               res = sock_error(sk);
+       else
+               res = 0;
+
 exit:
        release_sock(sk);
        return res;
@@ -1436,8 +1509,13 @@ static int listen(struct socket *sock, int len)
  */
 static int accept(struct socket *sock, struct socket *new_sock, int flags)
 {
-       struct sock *sk = sock->sk;
+       struct sock *new_sk, *sk = sock->sk;
        struct sk_buff *buf;
+       struct tipc_sock *new_tsock;
+       struct tipc_port *new_tport;
+       struct tipc_msg *msg;
+       u32 new_ref;
+
        int res;
 
        lock_sock(sk);
@@ -1463,48 +1541,51 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags)
        buf = skb_peek(&sk->sk_receive_queue);
 
        res = tipc_create(sock_net(sock->sk), new_sock, 0, 0);
-       if (!res) {
-               struct sock *new_sk = new_sock->sk;
-               struct tipc_sock *new_tsock = tipc_sk(new_sk);
-               struct tipc_port *new_tport = new_tsock->p;
-               u32 new_ref = new_tport->ref;
-               struct tipc_msg *msg = buf_msg(buf);
-
-               lock_sock(new_sk);
-
-               /*
-                * Reject any stray messages received by new socket
-                * before the socket lock was taken (very, very unlikely)
-                */
-               reject_rx_queue(new_sk);
-
-               /* Connect new socket to it's peer */
-               new_tsock->peer_name.ref = msg_origport(msg);
-               new_tsock->peer_name.node = msg_orignode(msg);
-               tipc_connect2port(new_ref, &new_tsock->peer_name);
-               new_sock->state = SS_CONNECTED;
-
-               tipc_set_portimportance(new_ref, msg_importance(msg));
-               if (msg_named(msg)) {
-                       new_tport->conn_type = msg_nametype(msg);
-                       new_tport->conn_instance = msg_nameinst(msg);
-               }
+       if (res)
+               goto exit;
 
-               /*
-                * Respond to 'SYN-' by discarding it & returning 'ACK'-.
-                * Respond to 'SYN+' by queuing it on new socket.
-                */
-               if (!msg_data_sz(msg)) {
-                       struct msghdr m = {NULL,};
+       new_sk = new_sock->sk;
+       new_tsock = tipc_sk(new_sk);
+       new_tport = new_tsock->p;
+       new_ref = new_tport->ref;
+       msg = buf_msg(buf);
 
-                       advance_rx_queue(sk);
-                       send_packet(NULL, new_sock, &m, 0);
-               } else {
-                       __skb_dequeue(&sk->sk_receive_queue);
-                       __skb_queue_head(&new_sk->sk_receive_queue, buf);
-               }
-               release_sock(new_sk);
+       /* we lock on new_sk; but lockdep sees the lock on sk */
+       lock_sock_nested(new_sk, SINGLE_DEPTH_NESTING);
+
+       /*
+        * Reject any stray messages received by new socket
+        * before the socket lock was taken (very, very unlikely)
+        */
+       reject_rx_queue(new_sk);
+
+       /* Connect new socket to it's peer */
+       new_tsock->peer_name.ref = msg_origport(msg);
+       new_tsock->peer_name.node = msg_orignode(msg);
+       tipc_connect(new_ref, &new_tsock->peer_name);
+       new_sock->state = SS_CONNECTED;
+
+       tipc_set_portimportance(new_ref, msg_importance(msg));
+       if (msg_named(msg)) {
+               new_tport->conn_type = msg_nametype(msg);
+               new_tport->conn_instance = msg_nameinst(msg);
        }
+
+       /*
+        * Respond to 'SYN-' by discarding it & returning 'ACK'-.
+        * Respond to 'SYN+' by queuing it on new socket.
+        */
+       if (!msg_data_sz(msg)) {
+               struct msghdr m = {NULL,};
+
+               advance_rx_queue(sk);
+               send_packet(NULL, new_sock, &m, 0);
+       } else {
+               __skb_dequeue(&sk->sk_receive_queue);
+               __skb_queue_head(&new_sk->sk_receive_queue, buf);
+       }
+       release_sock(new_sk);
+
 exit:
        release_sock(sk);
        return res;
@@ -1539,7 +1620,6 @@ restart:
                /* Disconnect and send a 'FIN+' or 'FIN-' message to peer */
                buf = __skb_dequeue(&sk->sk_receive_queue);
                if (buf) {
-                       atomic_dec(&tipc_queue_size);
                        if (TIPC_SKB_CB(buf)->handle != 0) {
                                kfree_skb(buf);
                                goto restart;
@@ -1556,10 +1636,11 @@ restart:
 
        case SS_DISCONNECTING:
 
-               /* Discard any unreceived messages; wake up sleeping tasks */
+               /* Discard any unreceived messages */
                discard_rx_queue(sk);
-               if (waitqueue_active(sk_sleep(sk)))
-                       wake_up_interruptible(sk_sleep(sk));
+
+               /* Wake up anyone sleeping in poll */
+               sk->sk_state_change(sk);
                res = 0;
                break;
 
@@ -1677,7 +1758,7 @@ static int getsockopt(struct socket *sock,
                /* no need to set "res", since already 0 at this point */
                break;
        case TIPC_NODE_RECVQ_DEPTH:
-               value = (u32)atomic_read(&tipc_queue_size);
+               value = 0; /* was tipc_queue_size, now obsolete */
                break;
        case TIPC_SOCK_RECVQ_DEPTH:
                value = skb_queue_len(&sk->sk_receive_queue);
index 0f7d0d007e22b9cbe94665c19b1d1ac2d6328f02..6b42d47029af4f2d959a593578fc68bd174ebce6 100644 (file)
@@ -462,7 +462,7 @@ static void subscr_named_msg_event(void *usr_handle,
                kfree(subscriber);
                return;
        }
-       tipc_connect2port(subscriber->port_ref, orig);
+       tipc_connect(subscriber->port_ref, orig);
 
        /* Lock server port (& save lock address for future use) */
        subscriber->lock = tipc_port_lock(subscriber->port_ref)->lock;
index 06748f108a5732e9f847cdffd0dafe0cb996c191..5ac19dc1d5e4ffe31394f7f8721efb7a0c2073bb 100644 (file)
@@ -151,6 +151,9 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
            sock_diag_put_meminfo(sk, skb, UNIX_DIAG_MEMINFO))
                goto out_nlmsg_trim;
 
+       if (nla_put_u8(skb, UNIX_DIAG_SHUTDOWN, sk->sk_shutdown))
+               goto out_nlmsg_trim;
+
        return nlmsg_end(skb, nlh);
 
 out_nlmsg_trim:
index b34b5b9792f0eb7dd677525b543082d4f521115f..8800604c93f459e1db124aa2a9cafb1a7b5cdb8f 100644 (file)
@@ -34,6 +34,10 @@ int __net_init unix_sysctl_register(struct net *net)
        if (table == NULL)
                goto err_alloc;
 
+       /* Don't export sysctls to unprivileged users */
+       if (net->user_ns != &init_user_ns)
+               table[0].procname = NULL;
+
        table[0].data = &net->unx.sysctl_max_dgram_qlen;
        net->unx.ctl = register_net_sysctl(net, "net/unix", table);
        if (net->unx.ctl == NULL)
index e5246fbe36c4e661698242370b800043e12ce545..2906d520eea7c2b7636fc94f3a60f5131701f57d 100644 (file)
@@ -276,18 +276,16 @@ static struct crypto_comp * __percpu *ipcomp_alloc_tfms(const char *alg_name)
        struct crypto_comp * __percpu *tfms;
        int cpu;
 
-       /* This can be any valid CPU ID so we don't need locking. */
-       cpu = raw_smp_processor_id();
 
        list_for_each_entry(pos, &ipcomp_tfms_list, list) {
                struct crypto_comp *tfm;
 
-               tfms = pos->tfms;
-               tfm = *per_cpu_ptr(tfms, cpu);
+               /* This can be any valid CPU ID so we don't need locking. */
+               tfm = __this_cpu_read(*pos->tfms);
 
                if (!strcmp(crypto_comp_name(tfm), alg_name)) {
                        pos->users++;
-                       return tfms;
+                       return pos->tfms;
                }
        }
 
index 3efb07d3eb27425c8b9b5114c925eb9e7f402c9e..765f6fe951ebc7ed8fabaed3a4dc6ea4299aebfa 100644 (file)
@@ -521,13 +521,12 @@ int xfrm_init_replay(struct xfrm_state *x)
                    replay_esn->bmp_len * sizeof(__u32) * 8)
                        return -EINVAL;
 
-       if ((x->props.flags & XFRM_STATE_ESN) && replay_esn->replay_window == 0)
-               return -EINVAL;
-
-       if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn)
-               x->repl = &xfrm_replay_esn;
-       else
-               x->repl = &xfrm_replay_bmp;
+               if (x->props.flags & XFRM_STATE_ESN) {
+                       if (replay_esn->replay_window == 0)
+                               return -EINVAL;
+                       x->repl = &xfrm_replay_esn;
+               } else
+                       x->repl = &xfrm_replay_bmp;
        } else
                x->repl = &xfrm_replay_legacy;
 
index 380976f74c4c90f0159c11740be35dc40602c6c6..05a6e3d9c258c0815e870db6660fda8e4802d31f 100644 (file)
@@ -54,6 +54,10 @@ int __net_init xfrm_sysctl_init(struct net *net)
        table[2].data = &net->xfrm.sysctl_larval_drop;
        table[3].data = &net->xfrm.sysctl_acq_expires;
 
+       /* Don't export sysctls to unprivileged users */
+       if (net->user_ns != &init_user_ns)
+               table[0].procname = NULL;
+
        net->xfrm.sysctl_hdr = register_net_sysctl(net, "net/core", table);
        if (!net->xfrm.sysctl_hdr)
                goto out_register;
index 421f9844433519eac0c41e24265d2be9c1155b49..eb872b2e366e1209993efe470bed7f614a299098 100644 (file)
@@ -2349,7 +2349,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
        link = &xfrm_dispatch[type];
 
        /* All operations require privileges, even GET */
-       if (!capable(CAP_NET_ADMIN))
+       if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
        if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
index 40caf3c26cd5abdb3b22493715ebba38aa691a8a..d17e0ea911edd568a039c905330420810223d07f 100644 (file)
@@ -5,7 +5,7 @@
 # and for each file listed in this file with generic-y creates
 # a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/asm)
 
-kbuild-file := $(srctree)/arch/$(SRCARCH)/include/asm/Kbuild
+kbuild-file := $(srctree)/arch/$(SRCARCH)/include/$(src)/Kbuild
 -include $(kbuild-file)
 
 include scripts/Kbuild.include
index c3f69ae275d1f7710b5f38c02e9daf6b45b947a4..4d908d16c035c4e6c582e254e531998e7f6156ae 100644 (file)
@@ -27,7 +27,7 @@ endif
 installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw))
 
 installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all))
-installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/.
+installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./
 
 # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work.
 PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs
@@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
 $(installed-fw-dirs):
        $(call cmd,mkdir)
 
-$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%)
+$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %)
        $(call cmd,install)
 
 PHONY +=  __fw_install __fw_modinst FORCE
index 3d13d3a3edfe821c9663de081d78045c96e69809..ecbb44797e28226e85027c277435d053415aec8c 100644 (file)
@@ -16,8 +16,9 @@ PHONY += $(modules)
 __modinst: $(modules)
        @:
 
+# Don't stop modules_install if we can't sign external modules.
 quiet_cmd_modules_install = INSTALL $@
-      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
+      cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@) $(patsubst %,|| true,$(KBUILD_EXTMOD))
 
 # Modules built outside the kernel source tree go into extra by default
 INSTALL_MOD_DIR ?= extra
index 002089141df448fa569688a3e5e57b130d68e88b..a1cb0222ebe642b6fd91093f2a01bd301b026e6e 100644 (file)
@@ -14,8 +14,7 @@
 # 3)  create one <module>.mod.c file pr. module
 # 4)  create one Module.symvers file with CRC for all exported symbols
 # 5) compile all <module>.mod.c files
-# 6) final link of the module to a <module.ko> (or <module.unsigned>) file
-# 7) signs the modules to a <module.ko> file
+# 6) final link of the module to a <module.ko> file
 
 # Step 3 is used to place certain information in the module's ELF
 # section, including information such as:
@@ -33,8 +32,6 @@
 # Step 4 is solely used to allow module versioning in external modules,
 # where the CRC of each module is retrieved from the Module.symvers file.
 
-# Step 7 is dependent on CONFIG_MODULE_SIG being enabled.
-
 # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
 # symbols in the final module linking stage
 # KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
@@ -119,7 +116,6 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
 targets += $(modules:.ko=.mod.o)
 
 # Step 6), final link of the modules
-ifneq ($(CONFIG_MODULE_SIG),y)
 quiet_cmd_ld_ko_o = LD [M]  $@
       cmd_ld_ko_o = $(LD) -r $(LDFLAGS)                                 \
                              $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
@@ -129,78 +125,7 @@ $(modules): %.ko :%.o %.mod.o FORCE
        $(call if_changed,ld_ko_o)
 
 targets += $(modules)
-else
-quiet_cmd_ld_ko_unsigned_o = LD [M]  $@
-      cmd_ld_ko_unsigned_o =                                           \
-               $(LD) -r $(LDFLAGS)                                     \
-                        $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE)     \
-                        -o $@ $(filter-out FORCE,$^)                   \
-               $(if $(AFTER_LINK),; $(AFTER_LINK))
-
-$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE
-       $(call if_changed,ld_ko_unsigned_o)
-
-targets += $(modules:.ko=.ko.unsigned)
-
-# Step 7), sign the modules
-MODSECKEY = ./signing_key.priv
-MODPUBKEY = ./signing_key.x509
-
-ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY))
-ifeq ($(KBUILD_SRC),)
-       # no O= is being used
-       SCRIPTS_DIR := scripts
-else
-       SCRIPTS_DIR := $(KBUILD_SRC)/scripts
-endif
-SIGN_MODULES := 1
-else
-SIGN_MODULES := 0
-endif
-
-# only sign if it's an in-tree module
-ifneq ($(KBUILD_EXTMOD),)
-SIGN_MODULES := 0
-endif
 
-# We strip the module as best we can - note that using both strip and eu-strip
-# results in a smaller module than using either alone.
-EU_STRIP = $(shell which eu-strip || echo true)
-
-quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@
-      cmd_sign_ko_stripped_ko_unsigned = \
-               cp $< $@ && \
-               strip -x -g $@ && \
-               $(EU_STRIP) $@
-
-ifeq ($(SIGN_MODULES),1)
-
-quiet_cmd_genkeyid = GENKEYID $@
-      cmd_genkeyid = \
-               perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid
-
-%.signer %.keyid: %
-       $(call if_changed,genkeyid)
-
-KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid
-quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@
-      cmd_sign_ko_ko_stripped = \
-               sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@
-else
-KEYRING_DEP :=
-quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@
-      cmd_sign_ko_ko_unsigned = \
-               cp $< $@
-endif
-
-$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE
-       $(call if_changed,sign_ko_ko_stripped)
-
-$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE
-       $(call if_changed,sign_ko_stripped_ko_unsigned)
-
-targets += $(modules)
-endif
 
 # Add FORCE to the prequisites of a target to force it to be always rebuilt.
 # ---------------------------------------------------------------------------
index 21a9f5de0a2120c26b5f3bd0e70529078766a247..f18750e3bd6c290b285464b193d7d65972b6de19 100755 (executable)
@@ -1890,8 +1890,10 @@ sub process {
                }
 
                if ($realfile =~ m@^(drivers/net/|net/)@ &&
-                   $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ &&
-                   $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {
+                   $rawline !~ m@^\+[ \t]*\*/[ \t]*$@ &&       #trailing */
+                   $rawline !~ m@^\+.*/\*.*\*/[ \t]*$@ &&      #inline /*...*/
+                   $rawline !~ m@^\+.*\*{2,}/[ \t]*$@ &&       #trailing **/
+                   $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {    #non blank */
                        WARN("NETWORKING_BLOCK_COMMENT_STYLE",
                             "networking block comments put the trailing */ on a separate line\n" . $herecurr);
                }
index d501c8605f2670627b4a03fe92d47c2be9b65af1..3e42a071070e6bbf985bf4a0c813f1e677327748 100644 (file)
@@ -161,51 +161,27 @@ struct node {
        struct label *labels;
 };
 
-static inline struct label *for_each_label_next(struct label *l)
-{
-       do {
-               l = l->next;
-       } while (l && l->deleted);
-
-       return l;
-}
-
-#define for_each_label(l0, l) \
-       for ((l) = (l0); (l); (l) = for_each_label_next(l))
-
 #define for_each_label_withdel(l0, l) \
        for ((l) = (l0); (l); (l) = (l)->next)
 
-static inline struct property *for_each_property_next(struct property *p)
-{
-       do {
-               p = p->next;
-       } while (p && p->deleted);
-
-       return p;
-}
-
-#define for_each_property(n, p) \
-       for ((p) = (n)->proplist; (p); (p) = for_each_property_next(p))
+#define for_each_label(l0, l) \
+       for_each_label_withdel(l0, l) \
+               if (!(l)->deleted)
 
 #define for_each_property_withdel(n, p) \
        for ((p) = (n)->proplist; (p); (p) = (p)->next)
 
-static inline struct node *for_each_child_next(struct node *c)
-{
-       do {
-               c = c->next_sibling;
-       } while (c && c->deleted);
-
-       return c;
-}
-
-#define for_each_child(n, c) \
-       for ((c) = (n)->children; (c); (c) = for_each_child_next(c))
+#define for_each_property(n, p) \
+       for_each_property_withdel(n, p) \
+               if (!(p)->deleted)
 
 #define for_each_child_withdel(n, c) \
        for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
 
+#define for_each_child(n, c) \
+       for_each_child_withdel(n, c) \
+               if (!(c)->deleted)
+
 void add_label(struct label **labels, char *label);
 void delete_labels(struct label **labels);
 
index 239d22d4207b92aee3fb0a9233375acf673d2311..6c353ae8a4517b1e7ab4b2b4fa28012e96de9921 100644 (file)
@@ -42,6 +42,9 @@ foreach my $filename (@files) {
                $line =~ s/(^|\s)(inline)\b/$1__$2__/g;
                $line =~ s/(^|\s)(asm)\b(\s|[(]|$)/$1__$2__$3/g;
                $line =~ s/(^|\s|[(])(volatile)\b(\s|[(]|$)/$1__$2__$3/g;
+               $line =~ s/#ifndef _UAPI/#ifndef /;
+               $line =~ s/#define _UAPI/#define /;
+               $line =~ s!#endif /[*] _UAPI!#endif /* !;
                printf {$out} "%s", $line;
        }
        close $out;
index bd2e098955532a26a3935e44ad58283598cbf673..cdd48600e02a9bd842f2e43ab6b7f263949451ec 100644 (file)
@@ -12,7 +12,7 @@ extern "C" {
 
 #include <assert.h>
 #include <stdio.h>
-#include <sys/queue.h>
+#include "list.h"
 #ifndef __cplusplus
 #include <stdbool.h>
 #endif
@@ -175,12 +175,11 @@ struct menu {
 #define MENU_ROOT              0x0002
 
 struct jump_key {
-       CIRCLEQ_ENTRY(jump_key) entries;
+       struct list_head entries;
        size_t offset;
        struct menu *target;
        int index;
 };
-CIRCLEQ_HEAD(jk_head, jump_key);
 
 #define JUMP_NB                        9
 
diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h
new file mode 100644 (file)
index 0000000..0ae730b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * Copied from include/linux/...
+ */
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:        the pointer to the member.
+ * @type:       the type of the container struct this is embedded in.
+ * @member:     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+       return head->next == head;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *_new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = _new;
+       _new->next = next;
+       _new->prev = prev;
+       prev->next = _new;
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *_new, struct list_head *head)
+{
+       __list_add(_new, head->prev, head);
+}
+
+#endif
index 1d1c08537f1e59b2cab76bd88437489fcbea393b..ef1a7381f956d5e7d0ebb8d3ba6af2361a0c3c74 100644 (file)
@@ -21,9 +21,9 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head
                         *head));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head
                                   *head));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
index 48f67448af7b67cf6c8df7394702a65767891992..53975cf876083ecba455a7033222b2ccc3690686 100644 (file)
@@ -312,7 +312,7 @@ static void set_config_filename(const char *config_filename)
 
 
 struct search_data {
-       struct jk_head *head;
+       struct list_head *head;
        struct menu **targets;
        int *keys;
 };
@@ -323,7 +323,7 @@ static void update_text(char *buf, size_t start, size_t end, void *_data)
        struct jump_key *pos;
        int k = 0;
 
-       CIRCLEQ_FOREACH(pos, data->head, entries) {
+       list_for_each_entry(pos, data->head, entries) {
                if (pos->offset >= start && pos->offset < end) {
                        char header[4];
 
@@ -375,7 +375,7 @@ again:
 
        sym_arr = sym_re_search(dialog_input);
        do {
-               struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
+               LIST_HEAD(head);
                struct menu *targets[JUMP_NB];
                int keys[JUMP_NB + 1], i;
                struct search_data data = {
index a3cade659f89cb5f67828b797ae49b9311bf1d98..e98a05c8e50882d3b2833a2f4d05761dcffd22d3 100644 (file)
@@ -508,7 +508,7 @@ const char *menu_get_help(struct menu *menu)
 }
 
 static void get_prompt_str(struct gstr *r, struct property *prop,
-                          struct jk_head *head)
+                          struct list_head *head)
 {
        int i, j;
        struct menu *submenu[8], *menu, *location = NULL;
@@ -544,12 +544,13 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
                } else
                        jump->target = location;
 
-               if (CIRCLEQ_EMPTY(head))
+               if (list_empty(head))
                        jump->index = 0;
                else
-                       jump->index = CIRCLEQ_LAST(head)->index + 1;
+                       jump->index = list_entry(head->prev, struct jump_key,
+                                                entries)->index + 1;
 
-               CIRCLEQ_INSERT_TAIL(head, jump, entries);
+               list_add_tail(&jump->entries, head);
        }
 
        if (i > 0) {
@@ -573,7 +574,8 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
 /*
  * head is optional and may be NULL
  */
-void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
+void get_symbol_str(struct gstr *r, struct symbol *sym,
+                   struct list_head *head)
 {
        bool hit;
        struct property *prop;
@@ -612,7 +614,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
        str_append(r, "\n\n");
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
old mode 100644 (file)
new mode 100755 (executable)
index e58e34e..974a20b
-#!/bin/sh
+#!/usr/bin/perl -w
 #
 # Sign a module file using the given key.
 #
-# Format: sign-file <key> <x509> <src-file> <dst-file>
-#
-
-scripts=`dirname $0`
-
-CONFIG_MODULE_SIG_SHA512=y
-if [ -r .config ]
-then
-    . ./.config
-fi
-
-key="$1"
-x509="$2"
-src="$3"
-dst="$4"
-
-if [ ! -r "$key" ]
-then
-    echo "Can't read private key" >&2
-    exit 2
-fi
-
-if [ ! -r "$x509" ]
-then
-    echo "Can't read X.509 certificate" >&2
-    exit 2
-fi
-if [ ! -r "$x509.signer" ]
-then
-    echo "Can't read Signer name" >&2
-    exit 2;
-fi
-if [ ! -r "$x509.keyid" ]
-then
-    echo "Can't read Key identifier" >&2
-    exit 2;
-fi
+# Format:
+#
+#      ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]
+#
+#
+use strict;
+use FileHandle;
+use IPC::Open2;
+
+my $verbose = 0;
+if ($#ARGV >= 0 && $ARGV[0] eq "-v") {
+    $verbose = 1;
+    shift;
+}
+
+die "Format: ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]\n"
+    if ($#ARGV != 2 && $#ARGV != 3);
+
+my $private_key = $ARGV[0];
+my $x509 = $ARGV[1];
+my $module = $ARGV[2];
+my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~";
+
+die "Can't read private key\n" unless (-r $private_key);
+die "Can't read X.509 certificate\n" unless (-r $x509);
+die "Can't read module\n" unless (-r $module);
+
+#
+# Read the kernel configuration
+#
+my %config = (
+    CONFIG_MODULE_SIG_SHA512 => 1
+    );
+
+if (-r ".config") {
+    open(FD, "<.config") || die ".config";
+    while (<FD>) {
+       if ($_ =~ /^(CONFIG_.*)=[ym]/) {
+           $config{$1} = 1;
+       }
+    }
+    close(FD);
+}
+
+#
+# Function to read the contents of a file into a variable.
+#
+sub read_file($)
+{
+    my ($file) = @_;
+    my $contents;
+    my $len;
+
+    open(FD, "<$file") || die $file;
+    binmode FD;
+    my @st = stat(FD);
+    die $file if (!@st);
+    $len = read(FD, $contents, $st[7]) || die $file;
+    close(FD) || die $file;
+    die "$file: Wanted length ", $st[7], ", got ", $len, "\n"
+       if ($len != $st[7]);
+    return $contents;
+}
+
+###############################################################################
+#
+# First of all, we have to parse the X.509 certificate to find certain details
+# about it.
+#
+# We read the DER-encoded X509 certificate and parse it to extract the Subject
+# name and Subject Key Identifier.  Theis provides the data we need to build
+# the certificate identifier.
+#
+# The signer's name part of the identifier is fabricated from the commonName,
+# the organizationName or the emailAddress components of the X.509 subject
+# name.
+#
+# The subject key ID is used to select which of that signer's certificates
+# we're intending to use to sign the module.
+#
+###############################################################################
+my $x509_certificate = read_file($x509);
+
+my $UNIV = 0 << 6;
+my $APPL = 1 << 6;
+my $CONT = 2 << 6;
+my $PRIV = 3 << 6;
+
+my $CONS = 0x20;
+
+my $BOOLEAN    = 0x01;
+my $INTEGER    = 0x02;
+my $BIT_STRING = 0x03;
+my $OCTET_STRING = 0x04;
+my $NULL       = 0x05;
+my $OBJ_ID     = 0x06;
+my $UTF8String = 0x0c;
+my $SEQUENCE   = 0x10;
+my $SET                = 0x11;
+my $UTCTime    = 0x17;
+my $GeneralizedTime = 0x18;
+
+my %OIDs = (
+    pack("CCC", 85, 4, 3)      => "commonName",
+    pack("CCC", 85, 4, 6)      => "countryName",
+    pack("CCC", 85, 4, 10)     => "organizationName",
+    pack("CCC", 85, 4, 11)     => "organizationUnitName",
+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
+    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
+    pack("CCC", 85, 29, 35)    => "authorityKeyIdentifier",
+    pack("CCC", 85, 29, 14)    => "subjectKeyIdentifier",
+    pack("CCC", 85, 29, 19)    => "basicConstraints"
+);
+
+###############################################################################
+#
+# Extract an ASN.1 element from a string and return information about it.
+#
+###############################################################################
+sub asn1_extract($$@)
+{
+    my ($cursor, $expected_tag, $optional) = @_;
+
+    return [ -1 ]
+       if ($cursor->[1] == 0 && $optional);
+
+    die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
+       if ($cursor->[1] < 2);
+
+    my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
+
+    if ($expected_tag != -1 && $tag != $expected_tag) {
+       return [ -1 ]
+           if ($optional);
+       die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
+       " not ", $expected_tag, ")\n";
+    }
+
+    $cursor->[0] += 2;
+    $cursor->[1] -= 2;
+
+    die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n"
+       if (($tag & 0x1f) == 0x1f);
+    die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
+       if ($len == 0x80);
+
+    if ($len > 0x80) {
+       my $l = $len - 0x80;
+       die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
+           if ($cursor->[1] < $l);
+
+       if ($l == 0x1) {
+           $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
+       } elsif ($l == 0x2) {
+           $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
+       } elsif ($l == 0x3) {
+           $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
+           $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
+       } elsif ($l == 0x4) {
+           $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
+       } else {
+           die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
+       }
+
+       $cursor->[0] += $l;
+       $cursor->[1] -= $l;
+    }
+
+    die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
+       if ($cursor->[1] < $len);
+
+    my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
+    $cursor->[0] += $len;
+    $cursor->[1] -= $len;
+
+    return $ret;
+}
+
+###############################################################################
+#
+# Retrieve the data referred to by a cursor
+#
+###############################################################################
+sub asn1_retrieve($)
+{
+    my ($cursor) = @_;
+    my ($offset, $len, $data) = @$cursor;
+    return substr($$data, $offset, $len);
+}
+
+###############################################################################
+#
+# Roughly parse the X.509 certificate
+#
+###############################################################################
+my $cursor = [ 0, length($x509_certificate), \$x509_certificate ];
+
+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
+
+my $subject_key_id = ();
+my $authority_key_id = ();
+
+#
+# Parse the extension list
+#
+if ($extension_list->[0] != -1) {
+    my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
+
+    while ($extensions->[1]->[1] > 0) {
+       my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
+       my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
+       my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
+       my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
+
+       my $raw_oid = asn1_retrieve($x_oid->[1]);
+       next if (!exists($OIDs{$raw_oid}));
+       my $x_type = $OIDs{$raw_oid};
+
+       my $raw_value = asn1_retrieve($x_val->[1]);
+
+       if ($x_type eq "subjectKeyIdentifier") {
+           my $vcursor = [ 0, length($raw_value), \$raw_value ];
+
+           $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
+       }
+    }
+}
+
+###############################################################################
+#
+# Determine what we're going to use as the signer's name.  In order of
+# preference, take one of: commonName, organizationName or emailAddress.
+#
+###############################################################################
+my $org = "";
+my $cn = "";
+my $email = "";
+
+while ($subject->[1]->[1] > 0) {
+    my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
+    my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
+    my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
+    my $n_val = asn1_extract($attr->[1], -1);
+
+    my $raw_oid = asn1_retrieve($n_oid->[1]);
+    next if (!exists($OIDs{$raw_oid}));
+    my $n_type = $OIDs{$raw_oid};
+
+    my $raw_value = asn1_retrieve($n_val->[1]);
+
+    if ($n_type eq "organizationName") {
+       $org = $raw_value;
+    } elsif ($n_type eq "commonName") {
+       $cn = $raw_value;
+    } elsif ($n_type eq "emailAddress") {
+       $email = $raw_value;
+    }
+}
+
+my $signers_name = $email;
+
+if ($org && $cn) {
+    # Don't use the organizationName if the commonName repeats it
+    if (length($org) <= length($cn) &&
+       substr($cn, 0, length($org)) eq $org) {
+       $signers_name = $cn;
+       goto got_id_name;
+    }
+
+    # Or a signifcant chunk of it
+    if (length($org) >= 7 &&
+       length($cn) >= 7 &&
+       substr($cn, 0, 7) eq substr($org, 0, 7)) {
+       $signers_name = $cn;
+       goto got_id_name;
+    }
+
+    $signers_name = $org . ": " . $cn;
+} elsif ($org) {
+    $signers_name = $org;
+} elsif ($cn) {
+    $signers_name = $cn;
+}
+
+got_id_name:
+
+die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
+    if (!$subject_key_id);
+
+my $key_identifier = asn1_retrieve($subject_key_id->[1]);
+
+###############################################################################
+#
+# Create and attach the module signature
+#
+###############################################################################
 
 #
 # Signature parameters
 #
-algo=1         # Public-key crypto algorithm: RSA
-hash=          # Digest algorithm
-id_type=1      # Identifier type: X.509
+my $algo = 1;          # Public-key crypto algorithm: RSA
+my $hash = 0;          # Digest algorithm
+my $id_type = 1;       # Identifier type: X.509
 
 #
 # Digest the data
 #
-dgst=
-if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ]
-then
-    prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14"
-    dgst=-sha1
-    hash=2
-elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ]
-then
-    prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C"
-    dgst=-sha224
-    hash=7
-elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ]
-then
-    prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20"
-    dgst=-sha256
-    hash=4
-elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ]
-then
-    prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30"
-    dgst=-sha384
-    hash=5
-elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ]
-then
-    prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40"
-    dgst=-sha512
-    hash=6
-else
-    echo "$0: Can't determine hash algorithm" >&2
-    exit 2
-fi
-
-(
-perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $?
-openssl dgst $dgst -binary $src || exit $?
-) >$src.dig || exit $?
+my ($dgst, $prologue) = ();
+if (exists $config{"CONFIG_MODULE_SIG_SHA1"}) {
+    $prologue = pack("C*",
+                    0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+                    0x2B, 0x0E, 0x03, 0x02, 0x1A,
+                    0x05, 0x00, 0x04, 0x14);
+    $dgst = "-sha1";
+    $hash = 2;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA224"}) {
+    $prologue = pack("C*",
+                    0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+                    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+                    0x05, 0x00, 0x04, 0x1C);
+    $dgst = "-sha224";
+    $hash = 7;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA256"}) {
+    $prologue = pack("C*",
+                    0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+                    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+                    0x05, 0x00, 0x04, 0x20);
+    $dgst = "-sha256";
+    $hash = 4;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA384"}) {
+    $prologue = pack("C*",
+                    0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+                    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+                    0x05, 0x00, 0x04, 0x30);
+    $dgst = "-sha384";
+    $hash = 5;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA512"}) {
+    $prologue = pack("C*",
+                    0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+                    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+                    0x05, 0x00, 0x04, 0x40);
+    $dgst = "-sha512";
+    $hash = 6;
+} else {
+    die "Can't determine hash algorithm";
+}
+
+#
+# Generate the digest and read from openssl's stdout
+#
+my $digest;
+$digest = readpipe("openssl dgst $dgst -binary $module") || die "openssl dgst";
 
 #
 # Generate the binary signature, which will be just the integer that comprises
 # the signature with no metadata attached.
 #
-openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $?
-signerlen=`stat -c %s $x509.signer`
-keyidlen=`stat -c %s $x509.keyid`
-siglen=`stat -c %s $src.sig`
+my $pid;
+$pid = open2(*read_from, *write_to,
+            "openssl rsautl -sign -inkey $private_key -keyform PEM") ||
+    die "openssl rsautl";
+binmode write_to;
+print write_to $prologue . $digest || die "pipe to openssl rsautl";
+close(write_to) || die "pipe to openssl rsautl";
+
+binmode read_from;
+my $signature;
+read(read_from, $signature, 4096) || die "pipe from openssl rsautl";
+close(read_from) || die "pipe from openssl rsautl";
+$signature = pack("n", length($signature)) . $signature,
+
+waitpid($pid, 0) || die;
+die "openssl rsautl died: $?" if ($? >> 8);
 
 #
 # Build the signed binary
 #
-(
-    cat $src || exit $?
-    echo '~Module signature appended~' || exit $?
-    cat $x509.signer $x509.keyid || exit $?
+my $unsigned_module = read_file($module);
+
+my $magic_number = "~Module signature appended~\n";
+
+my $info = pack("CCCCCxxxN",
+               $algo, $hash, $id_type,
+               length($signers_name),
+               length($key_identifier),
+               length($signature));
 
-    # Preface each signature integer with a 2-byte BE length
-    perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $?
-    cat $src.sig || exit $?
+if ($verbose) {
+    print "Size of unsigned module: ", length($unsigned_module), "\n";
+    print "Size of signer's name  : ", length($signers_name), "\n";
+    print "Size of key identifier : ", length($key_identifier), "\n";
+    print "Size of signature      : ", length($signature), "\n";
+    print "Size of informaton     : ", length($info), "\n";
+    print "Size of magic number   : ", length($magic_number), "\n";
+    print "Signer's name          : '", $signers_name, "'\n";
+    print "Digest                 : $dgst\n";
+}
 
-    # Generate the information block
-    perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $?
-) >$dst~ || exit $?
+open(FD, ">$dest") || die $dest;
+binmode FD;
+print FD
+    $unsigned_module,
+    $signers_name,
+    $key_identifier,
+    $signature,
+    $info,
+    $magic_number
+    ;
+close FD || die $dest;
 
-# Permit in-place signing
-mv $dst~ $dst || exit $?
+if ($#ARGV != 3) {
+    rename($dest, $module) || die $module;
+}
diff --git a/scripts/x509keyid b/scripts/x509keyid
deleted file mode 100755 (executable)
index c8e91a4..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-#!/usr/bin/perl -w
-#
-# Generate an identifier from an X.509 certificate that can be placed in a
-# module signature to indentify the key to use.
-#
-# Format:
-#
-#      ./scripts/x509keyid <x509-cert> <signer's-name> <key-id>
-#
-# We read the DER-encoded X509 certificate and parse it to extract the Subject
-# name and Subject Key Identifier.  The provide the data we need to build the
-# certificate identifier.
-#
-# The signer's name part of the identifier is fabricated from the commonName,
-# the organizationName or the emailAddress components of the X.509 subject
-# name and written to the second named file.
-#
-# The subject key ID to select which of that signer's certificates we're
-# intending to use to sign the module is written to the third named file.
-#
-use strict;
-
-my $raw_data;
-
-die "Need three filenames\n" if ($#ARGV != 2);
-
-my $src = $ARGV[0];
-
-open(FD, "<$src") || die $src;
-binmode FD;
-my @st = stat(FD);
-die $src if (!@st);
-read(FD, $raw_data, $st[7]) || die $src;
-close(FD);
-
-my $UNIV = 0 << 6;
-my $APPL = 1 << 6;
-my $CONT = 2 << 6;
-my $PRIV = 3 << 6;
-
-my $CONS = 0x20;
-
-my $BOOLEAN    = 0x01;
-my $INTEGER    = 0x02;
-my $BIT_STRING = 0x03;
-my $OCTET_STRING = 0x04;
-my $NULL       = 0x05;
-my $OBJ_ID     = 0x06;
-my $UTF8String = 0x0c;
-my $SEQUENCE   = 0x10;
-my $SET                = 0x11;
-my $UTCTime    = 0x17;
-my $GeneralizedTime = 0x18;
-
-my %OIDs = (
-    pack("CCC", 85, 4, 3)      => "commonName",
-    pack("CCC", 85, 4, 6)      => "countryName",
-    pack("CCC", 85, 4, 10)     => "organizationName",
-    pack("CCC", 85, 4, 11)     => "organizationUnitName",
-    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
-    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
-    pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
-    pack("CCC", 85, 29, 35)    => "authorityKeyIdentifier",
-    pack("CCC", 85, 29, 14)    => "subjectKeyIdentifier",
-    pack("CCC", 85, 29, 19)    => "basicConstraints"
-);
-
-###############################################################################
-#
-# Extract an ASN.1 element from a string and return information about it.
-#
-###############################################################################
-sub asn1_extract($$@)
-{
-    my ($cursor, $expected_tag, $optional) = @_;
-
-    return [ -1 ]
-       if ($cursor->[1] == 0 && $optional);
-
-    die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
-       if ($cursor->[1] < 2);
-
-    my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
-
-    if ($expected_tag != -1 && $tag != $expected_tag) {
-       return [ -1 ]
-           if ($optional);
-       die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
-       " not ", $expected_tag, ")\n";
-    }
-
-    $cursor->[0] += 2;
-    $cursor->[1] -= 2;
-
-    die $src, ": ", $cursor->[0], ": ASN.1 long tag\n"
-       if (($tag & 0x1f) == 0x1f);
-    die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
-       if ($len == 0x80);
-
-    if ($len > 0x80) {
-       my $l = $len - 0x80;
-       die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
-           if ($cursor->[1] < $l);
-
-       if ($l == 0x1) {
-           $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
-       } elsif ($l = 0x2) {
-           $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
-       } elsif ($l = 0x3) {
-           $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
-           $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
-       } elsif ($l = 0x4) {
-           $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
-       } else {
-           die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
-       }
-
-       $cursor->[0] += $l;
-       $cursor->[1] -= $l;
-    }
-
-    die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
-       if ($cursor->[1] < $len);
-
-    my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
-    $cursor->[0] += $len;
-    $cursor->[1] -= $len;
-
-    return $ret;
-}
-
-###############################################################################
-#
-# Retrieve the data referred to by a cursor
-#
-###############################################################################
-sub asn1_retrieve($)
-{
-    my ($cursor) = @_;
-    my ($offset, $len, $data) = @$cursor;
-    return substr($$data, $offset, $len);
-}
-
-###############################################################################
-#
-# Roughly parse the X.509 certificate
-#
-###############################################################################
-my $cursor = [ 0, length($raw_data), \$raw_data ];
-
-my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
-my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
-my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
-my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
-my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
-my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
-my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
-my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
-
-my $subject_key_id = ();
-my $authority_key_id = ();
-
-#
-# Parse the extension list
-#
-if ($extension_list->[0] != -1) {
-    my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
-
-    while ($extensions->[1]->[1] > 0) {
-       my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
-       my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
-       my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
-       my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
-
-       my $raw_oid = asn1_retrieve($x_oid->[1]);
-       next if (!exists($OIDs{$raw_oid}));
-       my $x_type = $OIDs{$raw_oid};
-
-       my $raw_value = asn1_retrieve($x_val->[1]);
-
-       if ($x_type eq "subjectKeyIdentifier") {
-           my $vcursor = [ 0, length($raw_value), \$raw_value ];
-
-           $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
-       }
-    }
-}
-
-###############################################################################
-#
-# Determine what we're going to use as the signer's name.  In order of
-# preference, take one of: commonName, organizationName or emailAddress.
-#
-###############################################################################
-my $org = "";
-my $cn = "";
-my $email = "";
-
-while ($subject->[1]->[1] > 0) {
-    my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
-    my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
-    my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
-    my $n_val = asn1_extract($attr->[1], -1);
-
-    my $raw_oid = asn1_retrieve($n_oid->[1]);
-    next if (!exists($OIDs{$raw_oid}));
-    my $n_type = $OIDs{$raw_oid};
-
-    my $raw_value = asn1_retrieve($n_val->[1]);
-
-    if ($n_type eq "organizationName") {
-       $org = $raw_value;
-    } elsif ($n_type eq "commonName") {
-       $cn = $raw_value;
-    } elsif ($n_type eq "emailAddress") {
-       $email = $raw_value;
-    }
-}
-
-my $id_name = $email;
-
-if ($org && $cn) {
-    # Don't use the organizationName if the commonName repeats it
-    if (length($org) <= length($cn) &&
-       substr($cn, 0, length($org)) eq $org) {
-       $id_name = $cn;
-       goto got_id_name;
-    }
-
-    # Or a signifcant chunk of it
-    if (length($org) >= 7 &&
-       length($cn) >= 7 &&
-       substr($cn, 0, 7) eq substr($org, 0, 7)) {
-       $id_name = $cn;
-       goto got_id_name;
-    }
-
-    $id_name = $org . ": " . $cn;
-} elsif ($org) {
-    $id_name = $org;
-} elsif ($cn) {
-    $id_name = $cn;
-}
-
-got_id_name:
-
-###############################################################################
-#
-# Output the signer's name and the key identifier that we're going to include
-# in module signatures.
-#
-###############################################################################
-die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
-    if (!$subject_key_id);
-
-my $id_key_id = asn1_retrieve($subject_key_id->[1]);
-
-open(OUTFD, ">$ARGV[1]") || die $ARGV[1];
-print OUTFD $id_name;
-close OUTFD || die $ARGV[1];
-
-open(OUTFD, ">$ARGV[2]") || die $ARGV[2];
-print OUTFD $id_key_id;
-close OUTFD || die $ARGV[2];
index 7b3021cebbea3f2cf68d8cc3ed833459a626e153..5706b74c857f550a2515dc445164063154a12cac 100644 (file)
@@ -57,7 +57,7 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
 
 $(obj)/capability.o : $(obj)/capability_names.h
 $(obj)/resource.o : $(obj)/rlim_names.h
-$(obj)/capability_names.h : $(srctree)/include/linux/capability.h \
+$(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
                            $(src)/Makefile
        $(call cmd,make-caps)
 $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
index cf5fd220309be40d597ac7ca02e0d61658cd8eee..813200384d97cfc7f06a76e9b2f6286be7dfa7ab 100644 (file)
@@ -724,6 +724,8 @@ fail:
  */
 static void free_profile(struct aa_profile *profile)
 {
+       struct aa_profile *p;
+
        AA_DEBUG("%s(%p)\n", __func__, profile);
 
        if (!profile)
@@ -751,7 +753,27 @@ static void free_profile(struct aa_profile *profile)
        aa_put_dfa(profile->xmatch);
        aa_put_dfa(profile->policy.dfa);
 
-       aa_put_profile(profile->replacedby);
+       /* put the profile reference for replacedby, but not via
+        * put_profile(kref_put).
+        * replacedby can form a long chain that can result in cascading
+        * frees that blows the stack because kref_put makes a nested fn
+        * call (it looks like recursion, with free_profile calling
+        * free_profile) for each profile in the chain lp#1056078.
+        */
+       for (p = profile->replacedby; p; ) {
+               if (atomic_dec_and_test(&p->base.count.refcount)) {
+                       /* no more refs on p, grab its replacedby */
+                       struct aa_profile *next = p->replacedby;
+                       /* break the chain */
+                       p->replacedby = NULL;
+                       /* now free p, chain is broken */
+                       free_profile(p);
+
+                       /* follow up with next profile in the chain */
+                       p = next;
+               } else
+                       break;
+       }
 
        kzfree(profile);
 }
index 44dfc415a379afc9c327388664e949bfcc855bcb..b08d20c66c2e17e0fa8333984df8eb4a82595e0b 100644 (file)
@@ -42,7 +42,10 @@ struct dev_exception_item {
 struct dev_cgroup {
        struct cgroup_subsys_state css;
        struct list_head exceptions;
-       bool deny_all;
+       enum {
+               DEVCG_DEFAULT_ALLOW,
+               DEVCG_DEFAULT_DENY,
+       } behavior;
 };
 
 static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -161,8 +164,8 @@ static void dev_exception_clean(struct dev_cgroup *dev_cgroup)
        struct dev_exception_item *ex, *tmp;
 
        list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) {
-               list_del(&ex->list);
-               kfree(ex);
+               list_del_rcu(&ex->list);
+               kfree_rcu(ex, rcu);
        }
 }
 
@@ -182,13 +185,13 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup *cgroup)
        parent_cgroup = cgroup->parent;
 
        if (parent_cgroup == NULL)
-               dev_cgroup->deny_all = false;
+               dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
        else {
                parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
                mutex_lock(&devcgroup_mutex);
                ret = dev_exceptions_copy(&dev_cgroup->exceptions,
                                          &parent_dev_cgroup->exceptions);
-               dev_cgroup->deny_all = parent_dev_cgroup->deny_all;
+               dev_cgroup->behavior = parent_dev_cgroup->behavior;
                mutex_unlock(&devcgroup_mutex);
                if (ret) {
                        kfree(dev_cgroup);
@@ -260,7 +263,7 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft,
         * - List the exceptions in case the default policy is to deny
         * This way, the file remains as a "whitelist of devices"
         */
-       if (devcgroup->deny_all == false) {
+       if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                set_access(acc, ACC_MASK);
                set_majmin(maj, ~0);
                set_majmin(min, ~0);
@@ -295,7 +298,7 @@ static int may_access(struct dev_cgroup *dev_cgroup,
        struct dev_exception_item *ex;
        bool match = false;
 
-       list_for_each_entry(ex, &dev_cgroup->exceptions, list) {
+       list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) {
                if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
                        continue;
                if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR))
@@ -314,12 +317,12 @@ static int may_access(struct dev_cgroup *dev_cgroup,
         * In two cases we'll consider this new exception valid:
         * - the dev cgroup has its default policy to allow + exception list:
         *   the new exception should *not* match any of the exceptions
-        *   (!deny_all, !match)
+        *   (behavior == DEVCG_DEFAULT_ALLOW, !match)
         * - the dev cgroup has its default policy to deny + exception list:
         *   the new exception *should* match the exceptions
-        *   (deny_all, match)
+        *   (behavior == DEVCG_DEFAULT_DENY, match)
         */
-       if (dev_cgroup->deny_all == match)
+       if ((dev_cgroup->behavior == DEVCG_DEFAULT_DENY) == match)
                return 1;
        return 0;
 }
@@ -341,6 +344,19 @@ static int parent_has_perm(struct dev_cgroup *childcg,
        return may_access(parent, ex);
 }
 
+/**
+ * may_allow_all - checks if it's possible to change the behavior to
+ *                allow based on parent's rules.
+ * @parent: device cgroup's parent
+ * returns: != 0 in case it's allowed, 0 otherwise
+ */
+static inline int may_allow_all(struct dev_cgroup *parent)
+{
+       if (!parent)
+               return 1;
+       return parent->behavior == DEVCG_DEFAULT_ALLOW;
+}
+
 /*
  * Modify the exception list using allow/deny rules.
  * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
@@ -358,13 +374,18 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                                   int filetype, const char *buffer)
 {
        const char *b;
-       char *endp;
-       int count;
+       char temp[12];          /* 11 + 1 characters needed for a u32 */
+       int count, rc;
        struct dev_exception_item ex;
+       struct cgroup *p = devcgroup->css.cgroup;
+       struct dev_cgroup *parent = NULL;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (p->parent)
+               parent = cgroup_to_devcgroup(p->parent);
+
        memset(&ex, 0, sizeof(ex));
        b = buffer;
 
@@ -372,14 +393,21 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
        case 'a':
                switch (filetype) {
                case DEVCG_ALLOW:
-                       if (!parent_has_perm(devcgroup, &ex))
+                       if (!may_allow_all(parent))
                                return -EPERM;
                        dev_exception_clean(devcgroup);
-                       devcgroup->deny_all = false;
+                       devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
+                       if (!parent)
+                               break;
+
+                       rc = dev_exceptions_copy(&devcgroup->exceptions,
+                                                &parent->exceptions);
+                       if (rc)
+                               return rc;
                        break;
                case DEVCG_DENY:
                        dev_exception_clean(devcgroup);
-                       devcgroup->deny_all = true;
+                       devcgroup->behavior = DEVCG_DEFAULT_DENY;
                        break;
                default:
                        return -EINVAL;
@@ -402,8 +430,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                ex.major = ~0;
                b++;
        } else if (isdigit(*b)) {
-               ex.major = simple_strtoul(b, &endp, 10);
-               b = endp;
+               memset(temp, 0, sizeof(temp));
+               for (count = 0; count < sizeof(temp) - 1; count++) {
+                       temp[count] = *b;
+                       b++;
+                       if (!isdigit(*b))
+                               break;
+               }
+               rc = kstrtou32(temp, 10, &ex.major);
+               if (rc)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
@@ -416,8 +452,16 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                ex.minor = ~0;
                b++;
        } else if (isdigit(*b)) {
-               ex.minor = simple_strtoul(b, &endp, 10);
-               b = endp;
+               memset(temp, 0, sizeof(temp));
+               for (count = 0; count < sizeof(temp) - 1; count++) {
+                       temp[count] = *b;
+                       b++;
+                       if (!isdigit(*b))
+                               break;
+               }
+               rc = kstrtou32(temp, 10, &ex.minor);
+               if (rc)
+                       return -EINVAL;
        } else {
                return -EINVAL;
        }
@@ -452,7 +496,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
-               if (devcgroup->deny_all == false) {
+               if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
                        dev_exception_rm(devcgroup, &ex);
                        return 0;
                }
@@ -463,7 +507,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                 * an matching exception instead. And be silent about it: we
                 * don't want to break compatibility
                 */
-               if (devcgroup->deny_all == true) {
+               if (devcgroup->behavior == DEVCG_DEFAULT_DENY) {
                        dev_exception_rm(devcgroup, &ex);
                        return 0;
                }
@@ -533,10 +577,10 @@ struct cgroup_subsys devices_subsys = {
  *
  * returns 0 on success, -EPERM case the operation is not permitted
  */
-static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
-                                       short type, u32 major, u32 minor,
+static int __devcgroup_check_permission(short type, u32 major, u32 minor,
                                        short access)
 {
+       struct dev_cgroup *dev_cgroup;
        struct dev_exception_item ex;
        int rc;
 
@@ -547,6 +591,7 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
        ex.access = access;
 
        rcu_read_lock();
+       dev_cgroup = task_devcgroup(current);
        rc = may_access(dev_cgroup, &ex);
        rcu_read_unlock();
 
@@ -558,7 +603,6 @@ static int __devcgroup_check_permission(struct dev_cgroup *dev_cgroup,
 
 int __devcgroup_inode_permission(struct inode *inode, int mask)
 {
-       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
        short type, access = 0;
 
        if (S_ISBLK(inode->i_mode))
@@ -570,13 +614,12 @@ int __devcgroup_inode_permission(struct inode *inode, int mask)
        if (mask & MAY_READ)
                access |= ACC_READ;
 
-       return __devcgroup_check_permission(dev_cgroup, type, imajor(inode),
-                                           iminor(inode), access);
+       return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
+                       access);
 }
 
 int devcgroup_inode_mknod(int mode, dev_t dev)
 {
-       struct dev_cgroup *dev_cgroup = task_devcgroup(current);
        short type;
 
        if (!S_ISBLK(mode) && !S_ISCHR(mode))
@@ -587,7 +630,7 @@ int devcgroup_inode_mknod(int mode, dev_t dev)
        else
                type = DEV_CHAR;
 
-       return __devcgroup_check_permission(dev_cgroup, type, MAJOR(dev),
-                                           MINOR(dev), ACC_MKNOD);
+       return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
+                       ACC_MKNOD);
 
 }
index 24ab4148547c2ba925042126ca9350a25a9969f8..61a53367d0292600fbb2d11da95c21118164fca4 100644 (file)
@@ -2132,18 +2132,14 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                return;
 
        devnull = dentry_open(&selinux_null, O_RDWR, cred);
-       if (!IS_ERR(devnull)) {
-               /* replace all the matching ones with this */
-               do {
-                       replace_fd(n - 1, get_file(devnull), 0);
-               } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
+       if (IS_ERR(devnull))
+               devnull = NULL;
+       /* replace all the matching ones with this */
+       do {
+               replace_fd(n - 1, devnull, 0);
+       } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
+       if (devnull)
                fput(devnull);
-       } else {
-               /* just close all the matching ones */
-               do {
-                       replace_fd(n - 1, NULL, 0);
-               } while ((n = iterate_fd(files, n, match_file, cred)) != 0);
-       }
 }
 
 /*
index 28f911cdd7c79dc292171fea10385adad51a27eb..c5454c0477c346e4d814f5ff209feba86e5b86ad 100644 (file)
@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node)
        if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
                struct sel_netnode *tail;
                tail = list_entry(
-                       rcu_dereference(sel_netnode_hash[idx].list.prev),
+                       rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
+                                                 lockdep_is_held(&sel_netnode_lock)),
                        struct sel_netnode, list);
                list_del_rcu(&tail->list);
                kfree_rcu(tail, rcu);
index d309e7f472d86ae7010f99edba87ced2c0957727..370a6468b3ba662ffe08d89a8d3e70bf6a540a98 100644 (file)
@@ -67,6 +67,9 @@ static struct nlmsg_perm nlmsg_route_perms[] =
        { RTM_GETADDRLABEL,     NETLINK_ROUTE_SOCKET__NLMSG_READ  },
        { RTM_GETDCB,           NETLINK_ROUTE_SOCKET__NLMSG_READ  },
        { RTM_SETDCB,           NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+       { RTM_NEWNETCONF,       NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+       { RTM_GETNETCONF,       NETLINK_ROUTE_SOCKET__NLMSG_READ  },
+       { RTM_GETMDB,           NETLINK_ROUTE_SOCKET__NLMSG_READ  },
 };
 
 static struct nlmsg_perm nlmsg_tcpdiag_perms[] =
index c40ae573346dd140031af773c532dd4f32f32240..ad11dc994792b4bb080c49a7036b8761731e5a1d 100644 (file)
@@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f)
 
        if (dirn != compr->direction) {
                pr_err("this device doesn't support this direction\n");
+               snd_card_unref(compr->card);
                return -EINVAL;
        }
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
+       if (!data) {
+               snd_card_unref(compr->card);
                return -ENOMEM;
+       }
        data->stream.ops = compr->ops;
        data->stream.direction = dirn;
        data->stream.private_data = compr->private_data;
@@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)
        runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
        if (!runtime) {
                kfree(data);
+               snd_card_unref(compr->card);
                return -ENOMEM;
        }
        runtime->state = SNDRV_PCM_STATE_OPEN;
@@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
                kfree(runtime);
                kfree(data);
        }
-       return ret;
+       snd_card_unref(compr->card);
+       return 0;
 }
 
 static int snd_compr_free(struct inode *inode, struct file *f)
index 7e86a5b9f3b572f9c97f351027ed4e1b9b7b75b3..8c7c2c9bba61e4dd421eb6a0c797bd0cf17b81ae 100644 (file)
@@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
        write_lock_irqsave(&card->ctl_files_rwlock, flags);
        list_add_tail(&ctl->list, &card->ctl_files);
        write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
+       snd_card_unref(card);
        return 0;
 
       __error:
@@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)
       __error2:
        snd_card_file_remove(card, file);
       __error1:
+       if (card)
+               snd_card_unref(card);
        return err;
 }
 
@@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,
                        spin_unlock_irq(&ctl->read_lock);
                        schedule();
                        remove_wait_queue(&ctl->change_sleep, &wait);
+                       if (ctl->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return -ERESTARTSYS;
                        spin_lock_irq(&ctl->read_lock);
index 75ea16f35b1aa1e1db985802e923c86e28f69af3..3f7f6628cf7b1704ed7cdb4094703416697af0a0 100644 (file)
@@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
        if (hw == NULL)
                return -ENODEV;
 
-       if (!try_module_get(hw->card->module))
+       if (!try_module_get(hw->card->module)) {
+               snd_card_unref(hw->card);
                return -EFAULT;
+       }
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(&hw->open_wait, &wait);
@@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
                mutex_unlock(&hw->open_mutex);
                schedule();
                mutex_lock(&hw->open_mutex);
+               if (hw->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
        mutex_unlock(&hw->open_mutex);
        if (err < 0)
                module_put(hw->card->module);
+       snd_card_unref(hw->card);
        return err;
 }
 
@@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)
                mutex_unlock(&register_mutex);
                return -EINVAL;
        }
+       mutex_lock(&hwdep->open_mutex);
+       wake_up(&hwdep->open_wait);
 #ifdef CONFIG_SND_OSSEMUL
        if (hwdep->ossreg)
                snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);
 #endif
        snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);
        list_del_init(&hwdep->list);
+       mutex_unlock(&hwdep->open_mutex);
        mutex_unlock(&register_mutex);
        return 0;
 }
index d8ec849af128ed1d248effdd2f606baa52a5f06d..7b012d15c2cf1599e92d0ddc832a6b0ece653e9e 100644 (file)
@@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid,
        spin_lock_init(&card->files_lock);
        INIT_LIST_HEAD(&card->files_list);
        init_waitqueue_head(&card->shutdown_sleep);
+       atomic_set(&card->refcount, 0);
 #ifdef CONFIG_PM
        mutex_init(&card->power_lock);
        init_waitqueue_head(&card->power_sleep);
@@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card)
        return 0;
 }
 
+/**
+ * snd_card_unref - release the reference counter
+ * @card: the card instance
+ *
+ * Decrements the reference counter.  When it reaches to zero, wake up
+ * the sleeper and call the destructor if needed.
+ */
+void snd_card_unref(struct snd_card *card)
+{
+       if (atomic_dec_and_test(&card->refcount)) {
+               wake_up(&card->shutdown_sleep);
+               if (card->free_on_last_close)
+                       snd_card_do_free(card);
+       }
+}
+EXPORT_SYMBOL(snd_card_unref);
+
 int snd_card_free_when_closed(struct snd_card *card)
 {
-       int free_now = 0;
-       int ret = snd_card_disconnect(card);
-       if (ret)
-               return ret;
+       int ret;
 
-       spin_lock(&card->files_lock);
-       if (list_empty(&card->files_list))
-               free_now = 1;
-       else
-               card->free_on_last_close = 1;
-       spin_unlock(&card->files_lock);
+       atomic_inc(&card->refcount);
+       ret = snd_card_disconnect(card);
+       if (ret) {
+               atomic_dec(&card->refcount);
+               return ret;
+       }
 
-       if (free_now)
+       card->free_on_last_close = 1;
+       if (atomic_dec_and_test(&card->refcount))
                snd_card_do_free(card);
        return 0;
 }
@@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card)
                return ret;
 
        /* wait, until all devices are ready for the free operation */
-       wait_event(card->shutdown_sleep, list_empty(&card->files_list));
+       wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));
        snd_card_do_free(card);
        return 0;
 }
@@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
                return -ENODEV;
        }
        list_add(&mfile->list, &card->files_list);
+       atomic_inc(&card->refcount);
        spin_unlock(&card->files_lock);
        return 0;
 }
@@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add);
 int snd_card_file_remove(struct snd_card *card, struct file *file)
 {
        struct snd_monitor_file *mfile, *found = NULL;
-       int last_close = 0;
 
        spin_lock(&card->files_lock);
        list_for_each_entry(mfile, &card->files_list, list) {
@@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
                        break;
                }
        }
-       if (list_empty(&card->files_list))
-               last_close = 1;
        spin_unlock(&card->files_lock);
-       if (last_close) {
-               wake_up(&card->shutdown_sleep);
-               if (card->free_on_last_close)
-                       snd_card_do_free(card);
-       }
        if (!found) {
                snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
                return -ENOENT;
        }
        kfree(found);
+       snd_card_unref(card);
        return 0;
 }
 
index 29f6ded02555568498473fb37547c9e7b0b96c2b..e8a1d18774b2073f997746f6d6f16881a1ecc4bc 100644 (file)
@@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
                                         SNDRV_OSS_DEVICE_TYPE_MIXER);
        if (card == NULL)
                return -ENODEV;
-       if (card->mixer_oss == NULL)
+       if (card->mixer_oss == NULL) {
+               snd_card_unref(card);
                return -ENODEV;
+       }
        err = snd_card_file_add(card, file);
-       if (err < 0)
+       if (err < 0) {
+               snd_card_unref(card);
                return err;
+       }
        fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);
        if (fmixer == NULL) {
                snd_card_file_remove(card, file);
+               snd_card_unref(card);
                return -ENOMEM;
        }
        fmixer->card = card;
@@ -68,8 +73,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)
        if (!try_module_get(card->module)) {
                kfree(fmixer);
                snd_card_file_remove(card, file);
+               snd_card_unref(card);
                return -EFAULT;
        }
+       snd_card_unref(card);
        return 0;
 }
 
index 08fde0060fd9377ee9f5e12dc1113858c73b3d20..4c1cc51772e6f18e9ab03671069c738471ca8c04 100644 (file)
@@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
                mutex_unlock(&pcm->open_mutex);
                schedule();
                mutex_lock(&pcm->open_mutex);
+               if (pcm->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -2450,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
        mutex_unlock(&pcm->open_mutex);
        if (err < 0)
                goto __error;
+       snd_card_unref(pcm->card);
        return err;
 
       __error:
@@ -2457,6 +2462,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)
       __error2:
        snd_card_file_remove(pcm->card, file);
       __error1:
+       if (pcm)
+               snd_card_unref(pcm->card);
        return err;
 }
 
index f2991940b271df46ef503173750a89d874fec6ad..030102caeee96b8080d9af6f2c99217278ec5a86 100644 (file)
@@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
        if (list_empty(&pcm->list))
                goto unlock;
 
+       mutex_lock(&pcm->open_mutex);
+       wake_up(&pcm->open_wait);
        list_del_init(&pcm->list);
        for (cidx = 0; cidx < 2; cidx++)
-               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
-                       if (substream->runtime)
+               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
+                       snd_pcm_stream_lock_irq(substream);
+                       if (substream->runtime) {
                                substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
+                               wake_up(&substream->runtime->sleep);
+                               wake_up(&substream->runtime->tsleep);
+                       }
+                       snd_pcm_stream_unlock_irq(substream);
+               }
        list_for_each_entry(notify, &snd_pcm_notify_list, list) {
                notify->n_disconnect(pcm);
        }
@@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
                        pcm->streams[cidx].chmap_kctl = NULL;
                }
        }
+       mutex_unlock(&pcm->open_mutex);
  unlock:
        mutex_unlock(&register_mutex);
        return 0;
index 5e12e5bacbba36cdf64c41a1d6e7e3d984902cf9..f9ddecf2f4cd7a17ebc0d5f0ba92405c03ab904a 100644 (file)
@@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
        return usecs;
 }
 
+static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
+{
+       snd_pcm_stream_lock_irq(substream);
+       if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
+               substream->runtime->status->state = state;
+       snd_pcm_stream_unlock_irq(substream);
+}
+
 static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *params)
 {
@@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                runtime->boundary *= 2;
 
        snd_pcm_timer_resolution_change(substream);
-       runtime->status->state = SNDRV_PCM_STATE_SETUP;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
 
        if (pm_qos_request_active(&substream->latency_pm_qos_req))
                pm_qos_remove_request(&substream->latency_pm_qos_req);
@@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
        /* hardware might be unusable from this time,
           so we force application to retry to set
           the correct hardware parameter settings */
-       runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        if (substream->ops->hw_free != NULL)
                substream->ops->hw_free(substream);
        return err;
@@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
                return -EBADFD;
        if (substream->ops->hw_free)
                result = substream->ops->hw_free(substream);
-       runtime->status->state = SNDRV_PCM_STATE_OPEN;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        pm_qos_remove_request(&substream->latency_pm_qos_req);
        return result;
 }
@@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        runtime->control->appl_ptr = runtime->status->hw_ptr;
-       runtime->status->state = SNDRV_PCM_STATE_PREPARED;
+       snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);
 }
 
 static struct action_ops snd_pcm_action_prepare = {
@@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
                down_read(&snd_pcm_link_rwsem);
                snd_pcm_stream_lock_irq(substream);
                remove_wait_queue(&to_check->sleep, &wait);
+               if (card->shutdown) {
+                       result = -ENODEV;
+                       break;
+               }
                if (tout == 0) {
                        if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)
                                result = -ESTRPIPE;
@@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
        write_unlock_irq(&snd_pcm_link_rwlock);
        up_write(&snd_pcm_link_rwsem);
  _nolock:
+       snd_card_unref(substream1->pcm->card);
        fput_light(file, fput_needed);
        if (res < 0)
                kfree(group);
@@ -2108,7 +2121,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)
                return err;
        pcm = snd_lookup_minor_data(iminor(inode),
                                    SNDRV_DEVICE_TYPE_PCM_PLAYBACK);
-       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK);
+       if (pcm)
+               snd_card_unref(pcm->card);
+       return err;
 }
 
 static int snd_pcm_capture_open(struct inode *inode, struct file *file)
@@ -2119,7 +2135,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)
                return err;
        pcm = snd_lookup_minor_data(iminor(inode),
                                    SNDRV_DEVICE_TYPE_PCM_CAPTURE);
-       return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+       err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE);
+       if (pcm)
+               snd_card_unref(pcm->card);
+       return err;
 }
 
 static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
@@ -2156,6 +2175,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
                mutex_unlock(&pcm->open_mutex);
                schedule();
                mutex_lock(&pcm->open_mutex);
+               if (pcm->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
index ebf6e49ad3d461ba843131d903b0c66cc7840ba4..1bb95aeea084d33cd8225c53257058a23c25cf4e 100644 (file)
@@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
        if (rmidi == NULL)
                return -ENODEV;
 
-       if (!try_module_get(rmidi->card->module))
+       if (!try_module_get(rmidi->card->module)) {
+               snd_card_unref(rmidi->card);
                return -ENXIO;
+       }
 
        mutex_lock(&rmidi->open_mutex);
        card = rmidi->card;
@@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
                mutex_unlock(&rmidi->open_mutex);
                schedule();
                mutex_lock(&rmidi->open_mutex);
+               if (rmidi->card->shutdown) {
+                       err = -ENODEV;
+                       break;
+               }
                if (signal_pending(current)) {
                        err = -ERESTARTSYS;
                        break;
@@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 #endif
        file->private_data = rawmidi_file;
        mutex_unlock(&rmidi->open_mutex);
+       snd_card_unref(rmidi->card);
        return 0;
 
  __error:
@@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
  __error_card:
        mutex_unlock(&rmidi->open_mutex);
        module_put(rmidi->card->module);
+       snd_card_unref(rmidi->card);
        return err;
 }
 
@@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun
                        spin_unlock_irq(&runtime->lock);
                        schedule();
                        remove_wait_queue(&runtime->sleep, &wait);
+                       if (rfile->rmidi->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return result > 0 ? result : -ERESTARTSYS;
                        if (!runtime->avail)
@@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,
                        spin_unlock_irq(&runtime->lock);
                        timeout = schedule_timeout(30 * HZ);
                        remove_wait_queue(&runtime->sleep, &wait);
+                       if (rfile->rmidi->card->shutdown)
+                               return -ENODEV;
                        if (signal_pending(current))
                                return result > 0 ? result : -ERESTARTSYS;
                        if (!runtime->avail && !timeout)
@@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)
 static int snd_rawmidi_dev_disconnect(struct snd_device *device)
 {
        struct snd_rawmidi *rmidi = device->device_data;
+       int dir;
 
        mutex_lock(&register_mutex);
+       mutex_lock(&rmidi->open_mutex);
+       wake_up(&rmidi->open_wait);
        list_del_init(&rmidi->list);
+       for (dir = 0; dir < 2; dir++) {
+               struct snd_rawmidi_substream *s;
+               list_for_each_entry(s, &rmidi->streams[dir].substreams, list) {
+                       if (s->runtime)
+                               wake_up(&s->runtime->sleep);
+               }
+       }
+
 #ifdef CONFIG_SND_OSSEMUL
        if (rmidi->ossreg) {
                if ((int)rmidi->device == midi_map[rmidi->card->number]) {
@@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
        }
 #endif /* CONFIG_SND_OSSEMUL */
        snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device);
+       mutex_unlock(&rmidi->open_mutex);
        mutex_unlock(&register_mutex);
        return 0;
 }
index 643976000ce825d1857fd3a3192fadeff0da4e5b..70ccdab7415320e3b20a2aba6c5837f42962f758 100644 (file)
@@ -98,6 +98,10 @@ static void snd_request_other(int minor)
  *
  * Checks that a minor device with the specified type is registered, and returns
  * its user data pointer.
+ *
+ * This function increments the reference counter of the card instance
+ * if an associated instance with the given minor number and type is found.
+ * The caller must call snd_card_unref() appropriately later.
  */
 void *snd_lookup_minor_data(unsigned int minor, int type)
 {
@@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type)
                return NULL;
        mutex_lock(&sound_mutex);
        mreg = snd_minors[minor];
-       if (mreg && mreg->type == type)
+       if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
-       else
+               if (private_data && mreg->card_ptr)
+                       atomic_inc(&mreg->card_ptr->refcount);
+       } else
                private_data = NULL;
        mutex_unlock(&sound_mutex);
        return private_data;
@@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
        preg->device = dev;
        preg->f_ops = f_ops;
        preg->private_data = private_data;
+       preg->card_ptr = card;
        mutex_lock(&sound_mutex);
 #ifdef CONFIG_SND_DYNAMIC_MINORS
        minor = snd_find_free_minor(type);
index e9528333e36d01e6e0282255639da08b7174e505..726a49ac97253d50634313265abc5699480c7e71 100644 (file)
@@ -40,6 +40,9 @@
 static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];
 static DEFINE_MUTEX(sound_oss_mutex);
 
+/* NOTE: This function increments the refcount of the associated card like
+ * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately
+ */
 void *snd_lookup_oss_minor_data(unsigned int minor, int type)
 {
        struct snd_minor *mreg;
@@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)
                return NULL;
        mutex_lock(&sound_oss_mutex);
        mreg = snd_oss_minors[minor];
-       if (mreg && mreg->type == type)
+       if (mreg && mreg->type == type) {
                private_data = mreg->private_data;
-       else
+               if (private_data && mreg->card_ptr)
+                       atomic_inc(&mreg->card_ptr->refcount);
+       } else
                private_data = NULL;
        mutex_unlock(&sound_oss_mutex);
        return private_data;
@@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,
        preg->device = dev;
        preg->f_ops = f_ops;
        preg->private_data = private_data;
+       preg->card_ptr = card;
        mutex_lock(&sound_oss_mutex);
        snd_oss_minors[minor] = preg;
        minor_unit = SNDRV_MINOR_OSS_DEVICE(minor);
index ef68d710d08cfc13121089ae5f86f97dfb813ebb..e04e750a77ed4bac80875bf05e979bbd946f2219 100644 (file)
@@ -426,7 +426,7 @@ static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ |
                SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4113_spdif_pinfo,
index 816e7d225fb0a626147eb6d339d141edede00dc9..5bf4fca19e48656916180ecc353109018b771aa3 100644 (file)
@@ -401,7 +401,7 @@ static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4114_spdif_pinfo,
        .get =          snd_ak4114_spdif_pget,
index b4b2a51fc117a98b667e10de335a86c5e2c1ce00..40e33c9f2b095f1eb7488729afe20f1f991d994f 100644 (file)
@@ -380,7 +380,7 @@ static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
 },
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
-       .name =         "IEC958 Preample Capture Default",
+       .name =         "IEC958 Preamble Capture Default",
        .access =       SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
        .info =         snd_ak4117_spdif_pinfo,
        .get =          snd_ak4117_spdif_pget,
index 3d1afb612b3548ade1db68d1b60af8f3e7e6ce4b..4a7ff4e8985ba2fe3b71ac7b57a191e694063ae2 100644 (file)
@@ -1286,7 +1286,6 @@ static int __devinit snd_miro_probe(struct snd_card *card)
 
        error = snd_card_miro_aci_detect(card, miro);
        if (error < 0) {
-               snd_card_free(card);
                snd_printk(KERN_ERR "unable to detect aci chip\n");
                return -ENODEV;
        }
index 9473fca9681dd7e291595501a6270c47793aa3bc..8b0f996883034c4b99b4823ea7a6f01b6d064587 100644 (file)
@@ -1271,6 +1271,8 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne
                tmp.index = ac97->num;
                kctl = snd_ctl_new1(&tmp, ac97);
        }
+       if (!kctl)
+               return -ENOMEM;
        if (reg >= AC97_PHONE && reg <= AC97_PCM)
                set_tlv_db_scale(kctl, db_scale_5bit_12db_max);
        else
index 00f157a2cf6411d8b1ad1b1ffef32f566d5e02b8..5af3cb6b0c18d36345aadfefee3d509404bbba80 100644 (file)
@@ -394,6 +394,8 @@ static int snd_als300_playback_open(struct snd_pcm_substream *substream)
        struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
                                                                GFP_KERNEL);
 
+       if (!data)
+               return -ENOMEM;
        snd_als300_dbgcallenter();
        chip->playback_substream = substream;
        runtime->hw = snd_als300_playback_hw;
@@ -425,6 +427,8 @@ static int snd_als300_capture_open(struct snd_pcm_substream *substream)
        struct snd_als300_substream_data *data = kzalloc(sizeof(*data),
                                                                GFP_KERNEL);
 
+       if (!data)
+               return -ENOMEM;
        snd_als300_dbgcallenter();
        chip->capture_substream = substream;
        runtime->hw = snd_als300_capture_hw;
index bed4485f34f61fa7b90cfaa6bc5a3da3b9e55150..c21adb6ef1d5d5b642c375febb1274e40b0cc9df 100644 (file)
@@ -1416,6 +1416,15 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0108_chip = 1,
         .spk71 = 1,
         .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */
+       /* Tested by Maxim Kachur <mcdebugger@duganet.ru> 17th Oct 2012. */
+       /* This is MAEM8986, 0202 is MAEM8980 */
+       {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102,
+        .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]",
+        .id = "EMU1010",
+        .emu10k2_chip = 1,
+        .ca0108_chip = 1,
+        .spk71 = 1,
+        .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */
        /* Tested by James@superbug.co.uk 8th July 2005. */
        /* This is MAEM8810, 0202 is MAEM8820 */
        {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
index 5d0e568fdea1b39e6a4c94f9c4fa360edffa5ede..7266020c16cb3a489a22418fd3b1f32e3dbd9fdb 100644 (file)
@@ -2581,9 +2581,14 @@ static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea)
        struct es1968 *chip = tea->private_data;
        unsigned long io = chip->io_port + GPIO_DATA;
        u16 val = inw(io);
+       u8 ret;
 
-       return  (val & STR_DATA) ? TEA575X_DATA : 0 |
-               (val & STR_MOST) ? TEA575X_MOST : 0;
+       ret = 0;
+       if (val & STR_DATA)
+               ret |= TEA575X_DATA;
+       if (val & STR_MOST)
+               ret |= TEA575X_MOST;
+       return ret;
 }
 
 static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output)
@@ -2655,6 +2660,8 @@ static struct ess_device_list pm_whitelist[] __devinitdata = {
        { TYPE_MAESTRO2E, 0x1179 },
        { TYPE_MAESTRO2E, 0x14c0 },     /* HP omnibook 4150 */
        { TYPE_MAESTRO2E, 0x1558 },
+       { TYPE_MAESTRO2E, 0x125d },     /* a PCI card, e.g. Terratec DMX */
+       { TYPE_MAESTRO2, 0x125d },      /* a PCI card, e.g. SF64-PCE2 */
 };
 
 static struct ess_device_list mpu_blacklist[] __devinitdata = {
index cc2e91d1553822699251c15baf950e406243df8d..c5806f89be1ed8b23e0ad5e0ace6344815bb13f2 100644 (file)
@@ -767,9 +767,14 @@ static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea)
        struct fm801 *chip = tea->private_data;
        unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
        struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip);
-
-       return  (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 |
-               (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0;
+       u8 ret;
+
+       ret = 0;
+       if (reg & FM801_GPIO_GP(gpio.data))
+               ret |= TEA575X_DATA;
+       if (reg & FM801_GPIO_GP(gpio.most))
+               ret |= TEA575X_MOST;
+       return ret;
 }
 
 static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output)
index 70d4848b5cd0ad25ce272877f9c759ed010dfc58..d010de12335e16525df3219cbe33647262316f7e 100644 (file)
@@ -95,6 +95,7 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
 EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
 
 #ifdef CONFIG_PM
+#define codec_in_pm(codec)     ((codec)->in_pm)
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
 #define hda_codec_is_power_on(codec)   ((codec)->power_on)
@@ -104,6 +105,7 @@ static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
                bus->ops.pm_notify(bus, power_up);
 }
 #else
+#define codec_in_pm(codec)     0
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
 #define hda_codec_is_power_on(codec)   1
 #define hda_call_pm_notify(bus, state) {}
@@ -228,7 +230,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
        }
        mutex_unlock(&bus->cmd_mutex);
        snd_hda_power_down(codec);
-       if (res && *res == -1 && bus->rirb_error) {
+       if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
                if (bus->response_reset) {
                        snd_printd("hda_codec: resetting BUS due to "
                                   "fatal communication error\n");
@@ -238,7 +240,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
                goto again;
        }
        /* clear reset-flag when the communication gets recovered */
-       if (!err)
+       if (!err || codec_in_pm(codec))
                bus->response_reset = 0;
        return err;
 }
@@ -3616,6 +3618,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
 {
        unsigned int state;
 
+       codec->in_pm = 1;
+
        if (codec->patch_ops.suspend)
                codec->patch_ops.suspend(codec);
        hda_cleanup_all_streams(codec);
@@ -3630,6 +3634,7 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
        codec->power_transition = 0;
        codec->power_jiffies = jiffies;
        spin_unlock(&codec->power_lock);
+       codec->in_pm = 0;
        return state;
 }
 
@@ -3638,6 +3643,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
  */
 static void hda_call_codec_resume(struct hda_codec *codec)
 {
+       codec->in_pm = 1;
+
        /* set as if powered on for avoiding re-entering the resume
         * in the resume / power-save sequence
         */
@@ -3656,6 +3663,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
                snd_hda_codec_resume_cache(codec);
        }
        snd_hda_jack_report_sync(codec);
+
+       codec->in_pm = 0;
        snd_hda_power_down(codec); /* flag down before returning */
 }
 #endif /* CONFIG_PM */
index 507fe8a917b69b09993193ef460f4fbc3f3af31a..4f4e545c0f4b2ded6029d21851b3443973ea7d23 100644 (file)
@@ -869,6 +869,7 @@ struct hda_codec {
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int d3_stop_clk:1;     /* support D3 operation without BCLK */
        unsigned int pm_down_notified:1; /* PM notified to controller */
+       unsigned int in_pm:1;           /* suspend/resume being performed */
        int power_transition;   /* power-state in transition */
        int power_count;        /* current (global) power refcount */
        struct delayed_work power_work; /* delayed task for powerdown */
index 6833835a218b9f581a58c5c0b3fe6aa36d8df51d..f9d870e554d98d2fabe8791e904d7a393c8925e6 100644 (file)
@@ -501,6 +501,7 @@ struct azx {
 
        /* VGA-switcheroo setup */
        unsigned int use_vga_switcheroo:1;
+       unsigned int vga_switcheroo_registered:1;
        unsigned int init_failed:1; /* delayed init failed */
        unsigned int disabled:1; /* disabled by VGA-switcher */
 
@@ -555,6 +556,12 @@ enum {
 #define AZX_DCAPS_ALIGN_BUFSIZE        (1 << 22)       /* buffer size alignment */
 #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)   /* BDLE in 4k boundary */
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
+#define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
+
+/* quirks for Intel PCH */
+#define AZX_DCAPS_INTEL_PCH \
+       (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \
+        AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME)
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -2157,9 +2164,12 @@ static unsigned int azx_get_position(struct azx *chip,
                if (delay < 0)
                        delay += azx_dev->bufsize;
                if (delay >= azx_dev->period_bytes) {
-                       snd_printdd("delay %d > period_bytes %d\n",
-                               delay, azx_dev->period_bytes);
-                       delay = 0; /* something is wrong */
+                       snd_printk(KERN_WARNING SFX
+                                  "Unstable LPIB (%d >= %d); "
+                                  "disabling LPIB delay counting\n",
+                                  delay, azx_dev->period_bytes);
+                       delay = 0;
+                       chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
                }
                azx_dev->substream->runtime->delay =
                        bytes_to_frames(azx_dev->substream->runtime, delay);
@@ -2429,6 +2439,9 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up)
 {
        struct azx *chip = bus->private_data;
 
+       if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
+               return;
+
        if (power_up)
                pm_runtime_get_sync(&chip->pci->dev);
        else
@@ -2544,7 +2557,8 @@ static int azx_runtime_suspend(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
 
-       if (!power_save_controller)
+       if (!power_save_controller ||
+           !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
                return -EAGAIN;
 
        azx_stop_chip(chip);
@@ -2640,7 +2654,9 @@ static void azx_vs_set_state(struct pci_dev *pci,
                if (disabled) {
                        azx_suspend(&pci->dev);
                        chip->disabled = true;
-                       snd_hda_lock_devices(chip->bus);
+                       if (snd_hda_lock_devices(chip->bus))
+                               snd_printk(KERN_WARNING SFX
+                                          "Cannot lock devices!\n");
                } else {
                        snd_hda_unlock_devices(chip->bus);
                        chip->disabled = false;
@@ -2683,14 +2699,20 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
 
 static int __devinit register_vga_switcheroo(struct azx *chip)
 {
+       int err;
+
        if (!chip->use_vga_switcheroo)
                return 0;
        /* FIXME: currently only handling DIS controller
         * is there any machine with two switchable HDMI audio controllers?
         */
-       return vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
+       err = vga_switcheroo_register_audio_client(chip->pci, &azx_vs_ops,
                                                    VGA_SWITCHEROO_DIS,
                                                    chip->bus != NULL);
+       if (err < 0)
+               return err;
+       chip->vga_switcheroo_registered = 1;
+       return 0;
 }
 #else
 #define init_vga_switcheroo(chip)              /* NOP */
@@ -2712,7 +2734,8 @@ static int azx_free(struct azx *chip)
        if (use_vga_switcheroo(chip)) {
                if (chip->disabled && chip->bus)
                        snd_hda_unlock_devices(chip->bus);
-               vga_switcheroo_unregister_client(chip->pci);
+               if (chip->vga_switcheroo_registered)
+                       vga_switcheroo_unregister_client(chip->pci);
        }
 
        if (chip->initialized) {
@@ -2813,8 +2836,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
-       SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF),
-       SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF),
        SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
@@ -3062,14 +3083,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        }
 
  ok:
-       err = register_vga_switcheroo(chip);
-       if (err < 0) {
-               snd_printk(KERN_ERR SFX
-                          "Error registering VGA-switcheroo client\n");
-               azx_free(chip);
-               return err;
-       }
-
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
        if (err < 0) {
                snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
@@ -3340,6 +3353,13 @@ static int __devinit azx_probe(struct pci_dev *pci,
        if (pci_dev_run_wake(pci))
                pm_runtime_put_noidle(&pci->dev);
 
+       err = register_vga_switcheroo(chip);
+       if (err < 0) {
+               snd_printk(KERN_ERR SFX
+                          "Error registering VGA-switcheroo client\n");
+               goto out_free;
+       }
+
        dev++;
        return 0;
 
@@ -3419,39 +3439,30 @@ static void __devexit azx_remove(struct pci_dev *pci)
 static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* CPT */
        { PCI_DEVICE(0x8086, 0x1c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* PBG */
        { PCI_DEVICE(0x8086, 0x1d20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE},
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Panther Point */
        { PCI_DEVICE(0x8086, 0x1e20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point-LP */
        { PCI_DEVICE(0x8086, 0x9c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point-LP */
        { PCI_DEVICE(0x8086, 0x9c21),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Haswell */
        { PCI_DEVICE(0x8086, 0x0c0c),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        { PCI_DEVICE(0x8086, 0x0d0c),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        /* 5 Series/3400 */
        { PCI_DEVICE(0x8086, 0x3b56),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        /* SCH */
        { PCI_DEVICE(0x8086, 0x811b),
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
@@ -3553,6 +3564,8 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* Teradici */
        { PCI_DEVICE(0x6549, 0x1200),
          .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
+       { PCI_DEVICE(0x6549, 0x2200),
+         .driver_data = AZX_DRIVER_TERA | AZX_DCAPS_NO_64BIT },
        /* Creative X-Fi (CA0110-IBG) */
        /* CTHDA chips */
        { PCI_DEVICE(0x1102, 0x0010),
index cdd43eadbc67425e80237b7da979c778b6bd835b..1eeba738666634329d17a76149618c1c6f3e8c26 100644 (file)
@@ -545,6 +545,7 @@ static int ad198x_build_pcms(struct hda_codec *codec)
        if (spec->multiout.dig_out_nid) {
                info++;
                codec->num_pcms++;
+               codec->spdif_status_reset = 1;
                info->name = "AD198x Digital";
                info->pcm_type = HDA_PCM_TYPE_SPDIF;
                info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback;
index 61a71131711c734556249b17fc61fc51f1218c1a..3bcb671723583ed852ec97aa844d2736ffd4b330 100644 (file)
@@ -101,8 +101,8 @@ enum {
 #define CS420X_VENDOR_NID      0x11
 #define CS_DIG_OUT1_PIN_NID    0x10
 #define CS_DIG_OUT2_PIN_NID    0x15
-#define CS_DMIC1_PIN_NID       0x12
-#define CS_DMIC2_PIN_NID       0x0e
+#define CS_DMIC1_PIN_NID       0x0e
+#define CS_DMIC2_PIN_NID       0x12
 
 /* coef indices */
 #define IDX_SPDIF_STAT         0x0000
@@ -466,6 +466,7 @@ static int parse_output(struct hda_codec *codec)
                memcpy(cfg->speaker_pins, cfg->line_out_pins,
                       sizeof(cfg->speaker_pins));
                cfg->line_outs = 0;
+               memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins));
        }
 
        return 0;
@@ -1079,14 +1080,18 @@ static void init_input(struct hda_codec *codec)
                        cs_automic(codec, NULL);
 
                coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */
+               cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+
+               coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG);
                if (is_active_pin(codec, CS_DMIC2_PIN_NID))
-                       coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */
+                       coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */
                if (is_active_pin(codec, CS_DMIC1_PIN_NID))
-                       coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off
+                       coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off
                                         * No effect if SPDIF_OUT2 is
                                         * selected in IDX_SPDIF_CTL.
                                        */
-               cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+
+               cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef);
        } else {
                if (spec->mic_detect)
                        cs_automic(codec, NULL);
@@ -1107,7 +1112,7 @@ static const struct hda_verb cs_coef_init_verbs[] = {
          | 0x0400 /* Disable Coefficient Auto increment */
          )},
        /* Beep */
-       {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG},
+       {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG},
        {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */
 
        {} /* terminator */
@@ -1728,8 +1733,7 @@ static int cs421x_mux_enum_put(struct snd_kcontrol *kcontrol,
 
 }
 
-static struct snd_kcontrol_new cs421x_capture_source = {
-
+static const struct snd_kcontrol_new cs421x_capture_source = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Capture Source",
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -1946,7 +1950,7 @@ static int cs421x_suspend(struct hda_codec *codec)
 }
 #endif
 
-static struct hda_codec_ops cs421x_patch_ops = {
+static const struct hda_codec_ops cs421x_patch_ops = {
        .build_controls = cs421x_build_controls,
        .build_pcms = cs_build_pcms,
        .init = cs421x_init,
index 8253b4eeb6a1bea0687675e8ac66ca41b9a84758..ad68d223f8af9e7dc43d24af303aab1eec64ca3d 100644 (file)
@@ -2598,8 +2598,10 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
                        return "PCM";
                break;
        }
-       if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name)))
+       if (ch >= ARRAY_SIZE(channel_name)) {
+               snd_BUG();
                return "PCM";
+       }
 
        return channel_name[ch];
 }
@@ -5405,6 +5407,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
@@ -5675,6 +5678,7 @@ static const struct hda_verb alc268_beep_init_verbs[] = {
 
 enum {
        ALC268_FIXUP_INV_DMIC,
+       ALC268_FIXUP_HP_EAPD,
 };
 
 static const struct alc_fixup alc268_fixups[] = {
@@ -5682,10 +5686,26 @@ static const struct alc_fixup alc268_fixups[] = {
                .type = ALC_FIXUP_FUNC,
                .v.func = alc_fixup_inv_dmic_0x12,
        },
+       [ALC268_FIXUP_HP_EAPD] = {
+               .type = ALC_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       {0x15, AC_VERB_SET_EAPD_BTLENABLE, 0},
+                       {}
+               }
+       },
 };
 
 static const struct alc_model_fixup alc268_fixup_models[] = {
        {.id = ALC268_FIXUP_INV_DMIC, .name = "inv-dmic"},
+       {.id = ALC268_FIXUP_HP_EAPD, .name = "hp-eapd"},
+       {}
+};
+
+static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+       /* below is codec SSID since multiple Toshiba laptops have the
+        * same PCI SSID 1179:ff00
+        */
+       SND_PCI_QUIRK(0x1179, 0xff06, "Toshiba P200", ALC268_FIXUP_HP_EAPD),
        {}
 };
 
@@ -5720,7 +5740,7 @@ static int patch_alc268(struct hda_codec *codec)
 
        spec = codec->spec;
 
-       alc_pick_fixup(codec, alc268_fixup_models, NULL, alc268_fixups);
+       alc_pick_fixup(codec, alc268_fixup_models, alc268_fixup_tbl, alc268_fixups);
        alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
 
        /* automatic parse from the BIOS config */
@@ -5821,7 +5841,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        return alc_parse_auto_config(codec, alc269_ignore, ssids);
 }
 
-static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
+static void alc269vb_toggle_power_output(struct hda_codec *codec, int power_up)
 {
        int val = alc_read_coef_idx(codec, 0x04);
        if (power_up)
@@ -5838,10 +5858,10 @@ static void alc269_shutup(struct hda_codec *codec)
        if (spec->codec_variant != ALC269_TYPE_ALC269VB)
                return;
 
-       if ((alc_get_coef0(codec) & 0x00ff) == 0x017)
-               alc269_toggle_power_output(codec, 0);
-       if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
-               alc269_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
+                       (alc_get_coef0(codec) & 0x00ff) == 0x018) {
                msleep(150);
        }
 }
@@ -5851,24 +5871,22 @@ static int alc269_resume(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 0);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
                        (alc_get_coef0(codec) & 0x00ff) == 0x018) {
-               alc269_toggle_power_output(codec, 0);
                msleep(150);
        }
 
        codec->patch_ops.init(codec);
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB)
+               alc269vb_toggle_power_output(codec, 1);
+       if (spec->codec_variant == ALC269_TYPE_ALC269VB &&
                        (alc_get_coef0(codec) & 0x00ff) == 0x017) {
-               alc269_toggle_power_output(codec, 1);
                msleep(200);
        }
 
-       if (spec->codec_variant == ALC269_TYPE_ALC269VB ||
-                       (alc_get_coef0(codec) & 0x00ff) == 0x018)
-               alc269_toggle_power_output(codec, 1);
-
        snd_hda_codec_resume_amp(codec);
        snd_hda_codec_resume_cache(codec);
        hda_call_check_power_status(codec, 0x01);
@@ -6186,6 +6204,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK),
+       SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
@@ -7046,6 +7065,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
        { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
        { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
+       { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
          .patch = patch_alc861 },
        { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
@@ -7059,6 +7079,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
          .patch = patch_alc662 },
        { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
        { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
+       { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
        { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
        { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
@@ -7076,6 +7097,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
        { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
        { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
+       { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 },
        {} /* terminator */
 };
 
index 770013ff556f6be0500b14039a8e60df2fa74b2a..9ba8af05617080f8081a5a69d68bcaec81cfb847 100644 (file)
@@ -1763,6 +1763,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
                          "HP", STAC_HP_ZEPHYR),
        SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660,
                          "HP Mini", STAC_92HD83XXX_HP_LED),
+       SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E,
+                         "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED),
        {} /* terminator */
 };
 
index 72a2f60b087c8ba066b52e5aaf4cda500227471f..019e1a00414a460cb7a43c8c6bf142ecc2f01d38 100644 (file)
@@ -1809,11 +1809,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec)
 {
        struct via_spec *spec = codec->spec;
        const struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i, dac_num;
+       int i;
        hda_nid_t nid;
 
+       spec->multiout.num_dacs = 0;
        spec->multiout.dac_nids = spec->private_dac_nids;
-       dac_num = 0;
        for (i = 0; i < cfg->line_outs; i++) {
                hda_nid_t dac = 0;
                nid = cfg->line_out_pins[i];
@@ -1824,16 +1824,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec)
                if (!i && parse_output_path(codec, nid, dac, 1,
                                            &spec->out_mix_path))
                        dac = spec->out_mix_path.path[0];
-               if (dac) {
-                       spec->private_dac_nids[i] = dac;
-                       dac_num++;
-               }
+               if (dac)
+                       spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
        }
        if (!spec->out_path[0].depth && spec->out_mix_path.depth) {
                spec->out_path[0] = spec->out_mix_path;
                spec->out_mix_path.depth = 0;
        }
-       spec->multiout.num_dacs = dac_num;
        return 0;
 }
 
@@ -3628,6 +3625,7 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
  */
 enum {
        VIA_FIXUP_INTMIC_BOOST,
+       VIA_FIXUP_ASUS_G75,
 };
 
 static void via_fixup_intmic_boost(struct hda_codec *codec,
@@ -3642,13 +3640,35 @@ static const struct hda_fixup via_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = via_fixup_intmic_boost,
        },
+       [VIA_FIXUP_ASUS_G75] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       /* set 0x24 and 0x33 as speakers */
+                       { 0x24, 0x991301f0 },
+                       { 0x33, 0x991301f1 }, /* subwoofer */
+                       { }
+               }
+       },
 };
 
 static const struct snd_pci_quirk vt2002p_fixups[] = {
+       SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
        SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
        {}
 };
 
+/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e
+ * Replace this with mixer NID 0x1c
+ */
+static void fix_vt1802_connections(struct hda_codec *codec)
+{
+       static hda_nid_t conn_24[] = { 0x14, 0x1c };
+       static hda_nid_t conn_33[] = { 0x1c };
+
+       snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
+       snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
+}
+
 /* patch for vt2002P */
 static int patch_vt2002P(struct hda_codec *codec)
 {
@@ -3663,6 +3683,8 @@ static int patch_vt2002P(struct hda_codec *codec)
        spec->aa_mix_nid = 0x21;
        override_mic_boost(codec, 0x2b, 0, 3, 40);
        override_mic_boost(codec, 0x29, 0, 3, 40);
+       if (spec->codec_type == VT1802)
+               fix_vt1802_connections(codec);
        add_secret_dac_path(codec);
 
        snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups);
index 3050a52792532ad3a58303f54a800dcc7c0ab883..245d874891ba25c2d993ea9de44536e0ab27ae6e 100644 (file)
@@ -2859,7 +2859,12 @@ static int snd_vt1724_resume(struct device *dev)
                ice->set_spdif_clock(ice, 0);
        } else {
                /* internal on-card clock */
-               snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1);
+               int rate;
+               if (ice->cur_rate)
+                       rate = ice->cur_rate;
+               else
+                       rate = ice->pro_rate_default;
+               snd_vt1724_set_pro_rate(ice, rate, 1);
        }
 
        update_spdif_bits(ice, ice->pm_saved_spdif_ctrl);
index b12308b5ba2a01170b56b5cd7b69a9d1d93aa6e3..748e36c66603a7f9928f70a6f13ea8e64b875f76 100644 (file)
@@ -971,6 +971,7 @@ static inline void snd_hdspm_initialize_midi_flush(struct hdspm *hdspm);
 static int hdspm_update_simple_mixer_controls(struct hdspm *hdspm);
 static int hdspm_autosync_ref(struct hdspm *hdspm);
 static int snd_hdspm_set_defaults(struct hdspm *hdspm);
+static int hdspm_system_clock_mode(struct hdspm *hdspm);
 static void hdspm_set_sgbuf(struct hdspm *hdspm,
                            struct snd_pcm_substream *substream,
                             unsigned int reg, int channels);
@@ -1989,10 +1990,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
        rate = hdspm_calc_dds_value(hdspm, period);
 
        if (rate > 207000) {
-               /* Unreasonable high sample rate as seen on PCI MADI cards.
-                * Use the cached value instead.
-                */
-               rate = hdspm->system_sample_rate;
+               /* Unreasonable high sample rate as seen on PCI MADI cards. */
+               if (0 == hdspm_system_clock_mode(hdspm)) {
+                       /* master mode, return internal sample rate */
+                       rate = hdspm->system_sample_rate;
+               } else {
+                       /* slave mode, return external sample rate */
+                       rate = hdspm_external_sample_rate(hdspm);
+               }
        }
 
        return rate;
@@ -2000,12 +2005,14 @@ static int hdspm_get_system_sample_rate(struct hdspm *hdspm)
 
 
 #define HDSPM_SYSTEM_SAMPLE_RATE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_system_sample_rate, \
-  .get = snd_hdspm_get_system_sample_rate \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_system_sample_rate, \
+       .put = snd_hdspm_put_system_sample_rate, \
+       .get = snd_hdspm_get_system_sample_rate \
 }
 
 static int snd_hdspm_info_system_sample_rate(struct snd_kcontrol *kcontrol,
@@ -2030,6 +2037,16 @@ static int snd_hdspm_get_system_sample_rate(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
+static int snd_hdspm_put_system_sample_rate(struct snd_kcontrol *kcontrol,
+                                           struct snd_ctl_elem_value *
+                                           ucontrol)
+{
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+
+       hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
+       return 0;
+}
+
 
 /**
  * Returns the WordClock sample rate class for the given card.
@@ -2163,6 +2180,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                kcontrol->private_value-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -2183,6 +2201,7 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                ucontrol->id.index-1);
                }
+               break;
 
        case AES32:
 
@@ -2204,8 +2223,23 @@ static int snd_hdspm_get_autosync_sample_rate(struct snd_kcontrol *kcontrol,
                                hdspm_get_s1_sample_rate(hdspm,
                                                kcontrol->private_value-1);
                        break;
+               }
+               break;
 
+       case MADI:
+       case MADIface:
+               {
+                       int rate = hdspm_external_sample_rate(hdspm);
+                       int i, selected_rate = 0;
+                       for (i = 1; i < 10; i++)
+                               if (HDSPM_bit2freq(i) == rate) {
+                                       selected_rate = i;
+                                       break;
+                               }
+                       ucontrol->value.enumerated.item[0] = selected_rate;
                }
+               break;
+
        default:
                break;
        }
@@ -2430,7 +2464,7 @@ static int snd_hdspm_put_clock_source(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_PREF_SYNC_REF(xname, xindex) \
-{.iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
        .name = xname, \
        .index = xindex, \
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\
@@ -2766,12 +2800,12 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_AUTOSYNC_REF(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ, \
-  .info = snd_hdspm_info_autosync_ref, \
-  .get = snd_hdspm_get_autosync_ref, \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READ, \
+       .info = snd_hdspm_info_autosync_ref, \
+       .get = snd_hdspm_get_autosync_ref, \
 }
 
 static int hdspm_autosync_ref(struct hdspm *hdspm)
@@ -2855,12 +2889,12 @@ static int snd_hdspm_get_autosync_ref(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_LINE_OUT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_line_out, \
-  .get = snd_hdspm_get_line_out, \
-  .put = snd_hdspm_put_line_out \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_line_out, \
+       .get = snd_hdspm_get_line_out, \
+       .put = snd_hdspm_put_line_out \
 }
 
 static int hdspm_line_out(struct hdspm * hdspm)
@@ -2912,12 +2946,12 @@ static int snd_hdspm_put_line_out(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_TX_64(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_tx_64, \
-  .get = snd_hdspm_get_tx_64, \
-  .put = snd_hdspm_put_tx_64 \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_tx_64, \
+       .get = snd_hdspm_get_tx_64, \
+       .put = snd_hdspm_put_tx_64 \
 }
 
 static int hdspm_tx_64(struct hdspm * hdspm)
@@ -2968,12 +3002,12 @@ static int snd_hdspm_put_tx_64(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_C_TMS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_c_tms, \
-  .get = snd_hdspm_get_c_tms, \
-  .put = snd_hdspm_put_c_tms \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_c_tms, \
+       .get = snd_hdspm_get_c_tms, \
+       .put = snd_hdspm_put_c_tms \
 }
 
 static int hdspm_c_tms(struct hdspm * hdspm)
@@ -3024,12 +3058,12 @@ static int snd_hdspm_put_c_tms(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_SAFE_MODE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_safe_mode, \
-  .get = snd_hdspm_get_safe_mode, \
-  .put = snd_hdspm_put_safe_mode \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_safe_mode, \
+       .get = snd_hdspm_get_safe_mode, \
+       .put = snd_hdspm_put_safe_mode \
 }
 
 static int hdspm_safe_mode(struct hdspm * hdspm)
@@ -3080,12 +3114,12 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_EMPHASIS(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_emphasis, \
-  .get = snd_hdspm_get_emphasis, \
-  .put = snd_hdspm_put_emphasis \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_emphasis, \
+       .get = snd_hdspm_get_emphasis, \
+       .put = snd_hdspm_put_emphasis \
 }
 
 static int hdspm_emphasis(struct hdspm * hdspm)
@@ -3136,12 +3170,12 @@ static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_DOLBY(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_dolby, \
-  .get = snd_hdspm_get_dolby, \
-  .put = snd_hdspm_put_dolby \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_dolby, \
+       .get = snd_hdspm_get_dolby, \
+       .put = snd_hdspm_put_dolby \
 }
 
 static int hdspm_dolby(struct hdspm * hdspm)
@@ -3192,12 +3226,12 @@ static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_PROFESSIONAL(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_professional, \
-  .get = snd_hdspm_get_professional, \
-  .put = snd_hdspm_put_professional \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_professional, \
+       .get = snd_hdspm_get_professional, \
+       .put = snd_hdspm_put_professional \
 }
 
 static int hdspm_professional(struct hdspm * hdspm)
@@ -3247,12 +3281,12 @@ static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
 }
 
 #define HDSPM_INPUT_SELECT(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_input_select, \
-  .get = snd_hdspm_get_input_select, \
-  .put = snd_hdspm_put_input_select \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_input_select, \
+       .get = snd_hdspm_get_input_select, \
+       .put = snd_hdspm_put_input_select \
 }
 
 static int hdspm_input_select(struct hdspm * hdspm)
@@ -3319,12 +3353,12 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_DS_WIRE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_ds_wire, \
-  .get = snd_hdspm_get_ds_wire, \
-  .put = snd_hdspm_put_ds_wire \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_ds_wire, \
+       .get = snd_hdspm_get_ds_wire, \
+       .put = snd_hdspm_put_ds_wire \
 }
 
 static int hdspm_ds_wire(struct hdspm * hdspm)
@@ -3391,12 +3425,12 @@ static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
 
 
 #define HDSPM_QS_WIRE(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .name = xname, \
-  .index = xindex, \
-  .info = snd_hdspm_info_qs_wire, \
-  .get = snd_hdspm_get_qs_wire, \
-  .put = snd_hdspm_put_qs_wire \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .name = xname, \
+       .index = xindex, \
+       .info = snd_hdspm_info_qs_wire, \
+       .get = snd_hdspm_get_qs_wire, \
+       .put = snd_hdspm_put_qs_wire \
 }
 
 static int hdspm_qs_wire(struct hdspm * hdspm)
@@ -3563,15 +3597,15 @@ static int snd_hdspm_put_madi_speedmode(struct snd_kcontrol *kcontrol,
 }
 
 #define HDSPM_MIXER(xname, xindex) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
-  .name = xname, \
-  .index = xindex, \
-  .device = 0, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
-                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_mixer, \
-  .get = snd_hdspm_get_mixer, \
-  .put = snd_hdspm_put_mixer \
+{      .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+       .name = xname, \
+       .index = xindex, \
+       .device = 0, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_mixer, \
+       .get = snd_hdspm_get_mixer, \
+       .put = snd_hdspm_put_mixer \
 }
 
 static int snd_hdspm_info_mixer(struct snd_kcontrol *kcontrol,
@@ -3670,12 +3704,12 @@ static int snd_hdspm_put_mixer(struct snd_kcontrol *kcontrol,
 */
 
 #define HDSPM_PLAYBACK_MIXER \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
-  .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
-                SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
-  .info = snd_hdspm_info_playback_mixer, \
-  .get = snd_hdspm_get_playback_mixer, \
-  .put = snd_hdspm_put_playback_mixer \
+{      .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | \
+               SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+       .info = snd_hdspm_info_playback_mixer, \
+       .get = snd_hdspm_get_playback_mixer, \
+       .put = snd_hdspm_put_playback_mixer \
 }
 
 static int snd_hdspm_info_playback_mixer(struct snd_kcontrol *kcontrol,
@@ -3851,12 +3885,17 @@ static int hdspm_sync_in_sync_check(struct hdspm *hdspm)
                break;
 
        case MADI:
-       case AES32:
-               status = hdspm_read(hdspm, HDSPM_statusRegister2);
+               status = hdspm_read(hdspm, HDSPM_statusRegister);
                lock = (status & HDSPM_syncInLock) ? 1 : 0;
                sync = (status & HDSPM_syncInSync) ? 1 : 0;
                break;
 
+       case AES32:
+               status = hdspm_read(hdspm, HDSPM_statusRegister2);
+               lock = (status & 0x100000) ? 1 : 0;
+               sync = (status & 0x200000) ? 1 : 0;
+               break;
+
        case MADIface:
                break;
        }
@@ -3940,8 +3979,10 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                case 8: /* SYNC IN */
                        val = hdspm_sync_in_sync_check(hdspm); break;
                default:
-                       val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
+                       val = hdspm_s1_sync_check(hdspm,
+                                       kcontrol->private_value-1);
                }
+               break;
 
        case AIO:
                switch (kcontrol->private_value) {
@@ -3954,6 +3995,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                default:
                        val = hdspm_s1_sync_check(hdspm, ucontrol->id.index-1);
                }
+               break;
 
        case MADI:
                switch (kcontrol->private_value) {
@@ -3966,6 +4008,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                case 3: /* SYNC_IN */
                        val = hdspm_sync_in_sync_check(hdspm); break;
                }
+               break;
 
        case MADIface:
                val = hdspm_madi_sync_check(hdspm); /* MADI */
@@ -3983,6 +4026,7 @@ static int snd_hdspm_get_sync_check(struct snd_kcontrol *kcontrol,
                         val = hdspm_aes_sync_check(hdspm,
                                         kcontrol->private_value-1);
                }
+               break;
 
        }
 
@@ -4427,9 +4471,10 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
        HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
        HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
        HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
+       HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
        HDSPM_SYNC_CHECK("WC SyncCheck", 0),
        HDSPM_SYNC_CHECK("MADI SyncCheck", 1),
-       HDSPM_SYNC_CHECK("TCO SyncCHeck", 2),
+       HDSPM_SYNC_CHECK("TCO SyncCheck", 2),
        HDSPM_SYNC_CHECK("SYNC IN SyncCheck", 3),
        HDSPM_LINE_OUT("Line Out", 0),
        HDSPM_TX_64("TX 64 channels mode", 0),
@@ -4855,7 +4900,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
                insel = "Coaxial";
                break;
        default:
-               insel = "Unkown";
+               insel = "Unknown";
        }
 
        snd_iprintf(buffer,
index bcbf1d00aa858ef62fc11d4767c0cb3b4f270eb3..99f32f7c0692713f90ca1d917dd23103bcebc601 100644 (file)
@@ -1,8 +1,9 @@
 snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
 snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o
 
-snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o
-obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o
+ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
+snd-soc-core-objs += soc-dmaengine-pcm.o
+endif
 
 obj-$(CONFIG_SND_SOC)  += snd-soc-core.o
 obj-$(CONFIG_SND_SOC)  += codecs/
index c03b65af30598f8f03dfba2d7353913a33a0bfe9..054967d8bac2f6d089214e390b1bd6ce416f64b2 100644 (file)
@@ -268,7 +268,7 @@ EXPORT_SYMBOL_GPL(arizona_out_ev);
 static unsigned int arizona_sysclk_48k_rates[] = {
        6144000,
        12288000,
-       22579200,
+       24576000,
        49152000,
        73728000,
        98304000,
@@ -278,7 +278,7 @@ static unsigned int arizona_sysclk_48k_rates[] = {
 static unsigned int arizona_sysclk_44k1_rates[] = {
        5644800,
        11289600,
-       24576000,
+       22579200,
        45158400,
        67737600,
        90316800,
index f994af34f552f4b08c4e01880c3410a4890afb7c..e3f0a7f3131e14b7895aadf2daf8bf81f6058d8b 100644 (file)
@@ -485,7 +485,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
                gpio_nreset = cs4271plat->gpio_nreset;
 
        if (gpio_nreset >= 0)
-               if (gpio_request(gpio_nreset, "CS4271 Reset"))
+               if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
                        gpio_nreset = -EINVAL;
        if (gpio_nreset >= 0) {
                /* Reset codec */
@@ -535,15 +535,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
 static int cs4271_remove(struct snd_soc_codec *codec)
 {
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
-       int gpio_nreset;
 
-       gpio_nreset = cs4271->gpio_nreset;
-
-       if (gpio_is_valid(gpio_nreset)) {
+       if (gpio_is_valid(cs4271->gpio_nreset))
                /* Set codec to the reset state */
-               gpio_set_value(gpio_nreset, 0);
-               gpio_free(gpio_nreset);
-       }
+               gpio_set_value(cs4271->gpio_nreset, 0);
 
        return 0;
 };
index 61599298fb26c32bdb193e1be0ccb33d2490a0af..97a81051e88d125c9937057e3b51324a7bb0f9ae 100644 (file)
@@ -763,7 +763,7 @@ static int cs42l52_set_sysclk(struct snd_soc_dai *codec_dai,
        if ((freq >= CS42L52_MIN_CLK) && (freq <= CS42L52_MAX_CLK)) {
                cs42l52->sysclk = freq;
        } else {
-               dev_err(codec->dev, "Invalid freq paramter\n");
+               dev_err(codec->dev, "Invalid freq parameter\n");
                return -EINVAL;
        }
        return 0;
@@ -773,7 +773,6 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0;
        u8 iface = 0;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -822,7 +821,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_NB_IF:
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
        }
        cs42l52->config.format = iface;
        snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format);
index 185d8dd36399ef28ada474fac14823fc1f67065c..f379b085c39204dfeb2a6fc34d7c07d9f15c9f0b 100644 (file)
 #define DA9055_AIF_WORD_S24_LE         (2 << 2)
 #define DA9055_AIF_WORD_S32_LE         (3 << 2)
 
+/* MIC_L_CTRL bit fields */
+#define DA9055_MIC_L_MUTE_EN           (1 << 6)
+
+/* MIC_R_CTRL bit fields */
+#define DA9055_MIC_R_MUTE_EN           (1 << 6)
+
 /* MIXIN_L_CTRL bit fields */
 #define DA9055_MIXIN_L_MIX_EN          (1 << 3)
 
@@ -476,7 +482,7 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol,
                             struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       u8 reg_val, adc_left, adc_right;
+       u8 reg_val, adc_left, adc_right, mic_left, mic_right;
        int avg_left_data, avg_right_data, offset_l, offset_r;
 
        if (ucontrol->value.integer.value[0]) {
@@ -485,6 +491,16 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol,
                 * offsets must be done first
                 */
 
+               /* Save current values from Mic control registers */
+               mic_left = snd_soc_read(codec, DA9055_MIC_L_CTRL);
+               mic_right = snd_soc_read(codec, DA9055_MIC_R_CTRL);
+
+               /* Mute Mic PGA Left and Right */
+               snd_soc_update_bits(codec, DA9055_MIC_L_CTRL,
+                                   DA9055_MIC_L_MUTE_EN, DA9055_MIC_L_MUTE_EN);
+               snd_soc_update_bits(codec, DA9055_MIC_R_CTRL,
+                                   DA9055_MIC_R_MUTE_EN, DA9055_MIC_R_MUTE_EN);
+
                /* Save current values from ADC control registers */
                adc_left = snd_soc_read(codec, DA9055_ADC_L_CTRL);
                adc_right = snd_soc_read(codec, DA9055_ADC_R_CTRL);
@@ -520,6 +536,10 @@ static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol,
                /* Restore original values of ADC control registers */
                snd_soc_write(codec, DA9055_ADC_L_CTRL, adc_left);
                snd_soc_write(codec, DA9055_ADC_R_CTRL, adc_right);
+
+               /* Restore original values of Mic control registers */
+               snd_soc_write(codec, DA9055_MIC_L_CTRL, mic_left);
+               snd_soc_write(codec, DA9055_MIC_R_CTRL, mic_right);
        }
 
        return snd_soc_put_volsw(kcontrol, ucontrol);
index e8f97af75928ea3548c0d389f9e70d7f676ba2c3..00b85cc1b9a3508f8db9a677bac90d4e2af50038 100644 (file)
@@ -820,10 +820,10 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"VIBRA DAC", NULL, "Vibra Playback"},
 
        /* ADC -> Stream mapping */
-       {"ADC Left", NULL, "Legacy Capture"},
-       {"ADC Left", NULL, "Capture"},
-       {"ADC Right", NULL, "Legacy Capture"},
-       {"ADC Right", NULL, "Capture"},
+       {"Legacy Capture" , NULL, "ADC Left"},
+       {"Capture", NULL, "ADC Left"},
+       {"Legacy Capture", NULL, "ADC Right"},
+       {"Capture" , NULL, "ADC Right"},
 
        /* Capture path */
        {"Analog Left Capture Route", "Headset Mic", "HSMIC"},
index efa93dbb01915a2112582e2c0a4f939bb96ff643..eab64a193989ac2917773a4df7613cbf644dd58f 100644 (file)
@@ -1028,7 +1028,7 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
                 WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
                 digital_tlv),
 SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
-          WM2200_SPK1R_MUTE_SHIFT, 1, 0),
+          WM2200_SPK1R_MUTE_SHIFT, 1, 1),
 };
 
 WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
@@ -2091,6 +2091,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
 
        switch (wm2200->rev) {
        case 0:
+       case 1:
                ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
                                            ARRAY_SIZE(wm2200_reva_patch));
                if (ret != 0) {
index 1722b586bdba65bde94d9d3cb5cc1ca51cd44aee..7394e73fa43c0e526e7ab4e83480fb89bbf9891d 100644 (file)
@@ -42,6 +42,556 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
 
+static const struct reg_default wm5102_sysclk_reva_patch[] = {
+       { 0x3000, 0x2225 },
+       { 0x3001, 0x3a03 },
+       { 0x3002, 0x0225 },
+       { 0x3003, 0x0801 },
+       { 0x3004, 0x6249 },
+       { 0x3005, 0x0c04 },
+       { 0x3006, 0x0225 },
+       { 0x3007, 0x5901 },
+       { 0x3008, 0xe249 },
+       { 0x3009, 0x030d },
+       { 0x300a, 0x0249 },
+       { 0x300b, 0x2c01 },
+       { 0x300c, 0xe249 },
+       { 0x300d, 0x4342 },
+       { 0x300e, 0xe249 },
+       { 0x300f, 0x73c0 },
+       { 0x3010, 0x4249 },
+       { 0x3011, 0x0c00 },
+       { 0x3012, 0x0225 },
+       { 0x3013, 0x1f01 },
+       { 0x3014, 0x0225 },
+       { 0x3015, 0x1e01 },
+       { 0x3016, 0x0225 },
+       { 0x3017, 0xfa00 },
+       { 0x3018, 0x0000 },
+       { 0x3019, 0xf000 },
+       { 0x301a, 0x0000 },
+       { 0x301b, 0xf000 },
+       { 0x301c, 0x0000 },
+       { 0x301d, 0xf000 },
+       { 0x301e, 0x0000 },
+       { 0x301f, 0xf000 },
+       { 0x3020, 0x0000 },
+       { 0x3021, 0xf000 },
+       { 0x3022, 0x0000 },
+       { 0x3023, 0xf000 },
+       { 0x3024, 0x0000 },
+       { 0x3025, 0xf000 },
+       { 0x3026, 0x0000 },
+       { 0x3027, 0xf000 },
+       { 0x3028, 0x0000 },
+       { 0x3029, 0xf000 },
+       { 0x302a, 0x0000 },
+       { 0x302b, 0xf000 },
+       { 0x302c, 0x0000 },
+       { 0x302d, 0xf000 },
+       { 0x302e, 0x0000 },
+       { 0x302f, 0xf000 },
+       { 0x3030, 0x0225 },
+       { 0x3031, 0x1a01 },
+       { 0x3032, 0x0225 },
+       { 0x3033, 0x1e00 },
+       { 0x3034, 0x0225 },
+       { 0x3035, 0x1f00 },
+       { 0x3036, 0x6225 },
+       { 0x3037, 0xf800 },
+       { 0x3038, 0x0000 },
+       { 0x3039, 0xf000 },
+       { 0x303a, 0x0000 },
+       { 0x303b, 0xf000 },
+       { 0x303c, 0x0000 },
+       { 0x303d, 0xf000 },
+       { 0x303e, 0x0000 },
+       { 0x303f, 0xf000 },
+       { 0x3040, 0x2226 },
+       { 0x3041, 0x3a03 },
+       { 0x3042, 0x0226 },
+       { 0x3043, 0x0801 },
+       { 0x3044, 0x6249 },
+       { 0x3045, 0x0c06 },
+       { 0x3046, 0x0226 },
+       { 0x3047, 0x5901 },
+       { 0x3048, 0xe249 },
+       { 0x3049, 0x030d },
+       { 0x304a, 0x0249 },
+       { 0x304b, 0x2c01 },
+       { 0x304c, 0xe249 },
+       { 0x304d, 0x4342 },
+       { 0x304e, 0xe249 },
+       { 0x304f, 0x73c0 },
+       { 0x3050, 0x4249 },
+       { 0x3051, 0x0c00 },
+       { 0x3052, 0x0226 },
+       { 0x3053, 0x1f01 },
+       { 0x3054, 0x0226 },
+       { 0x3055, 0x1e01 },
+       { 0x3056, 0x0226 },
+       { 0x3057, 0xfa00 },
+       { 0x3058, 0x0000 },
+       { 0x3059, 0xf000 },
+       { 0x305a, 0x0000 },
+       { 0x305b, 0xf000 },
+       { 0x305c, 0x0000 },
+       { 0x305d, 0xf000 },
+       { 0x305e, 0x0000 },
+       { 0x305f, 0xf000 },
+       { 0x3060, 0x0000 },
+       { 0x3061, 0xf000 },
+       { 0x3062, 0x0000 },
+       { 0x3063, 0xf000 },
+       { 0x3064, 0x0000 },
+       { 0x3065, 0xf000 },
+       { 0x3066, 0x0000 },
+       { 0x3067, 0xf000 },
+       { 0x3068, 0x0000 },
+       { 0x3069, 0xf000 },
+       { 0x306a, 0x0000 },
+       { 0x306b, 0xf000 },
+       { 0x306c, 0x0000 },
+       { 0x306d, 0xf000 },
+       { 0x306e, 0x0000 },
+       { 0x306f, 0xf000 },
+       { 0x3070, 0x0226 },
+       { 0x3071, 0x1a01 },
+       { 0x3072, 0x0226 },
+       { 0x3073, 0x1e00 },
+       { 0x3074, 0x0226 },
+       { 0x3075, 0x1f00 },
+       { 0x3076, 0x6226 },
+       { 0x3077, 0xf800 },
+       { 0x3078, 0x0000 },
+       { 0x3079, 0xf000 },
+       { 0x307a, 0x0000 },
+       { 0x307b, 0xf000 },
+       { 0x307c, 0x0000 },
+       { 0x307d, 0xf000 },
+       { 0x307e, 0x0000 },
+       { 0x307f, 0xf000 },
+       { 0x3080, 0x2227 },
+       { 0x3081, 0x3a03 },
+       { 0x3082, 0x0227 },
+       { 0x3083, 0x0801 },
+       { 0x3084, 0x6255 },
+       { 0x3085, 0x0c04 },
+       { 0x3086, 0x0227 },
+       { 0x3087, 0x5901 },
+       { 0x3088, 0xe255 },
+       { 0x3089, 0x030d },
+       { 0x308a, 0x0255 },
+       { 0x308b, 0x2c01 },
+       { 0x308c, 0xe255 },
+       { 0x308d, 0x4342 },
+       { 0x308e, 0xe255 },
+       { 0x308f, 0x73c0 },
+       { 0x3090, 0x4255 },
+       { 0x3091, 0x0c00 },
+       { 0x3092, 0x0227 },
+       { 0x3093, 0x1f01 },
+       { 0x3094, 0x0227 },
+       { 0x3095, 0x1e01 },
+       { 0x3096, 0x0227 },
+       { 0x3097, 0xfa00 },
+       { 0x3098, 0x0000 },
+       { 0x3099, 0xf000 },
+       { 0x309a, 0x0000 },
+       { 0x309b, 0xf000 },
+       { 0x309c, 0x0000 },
+       { 0x309d, 0xf000 },
+       { 0x309e, 0x0000 },
+       { 0x309f, 0xf000 },
+       { 0x30a0, 0x0000 },
+       { 0x30a1, 0xf000 },
+       { 0x30a2, 0x0000 },
+       { 0x30a3, 0xf000 },
+       { 0x30a4, 0x0000 },
+       { 0x30a5, 0xf000 },
+       { 0x30a6, 0x0000 },
+       { 0x30a7, 0xf000 },
+       { 0x30a8, 0x0000 },
+       { 0x30a9, 0xf000 },
+       { 0x30aa, 0x0000 },
+       { 0x30ab, 0xf000 },
+       { 0x30ac, 0x0000 },
+       { 0x30ad, 0xf000 },
+       { 0x30ae, 0x0000 },
+       { 0x30af, 0xf000 },
+       { 0x30b0, 0x0227 },
+       { 0x30b1, 0x1a01 },
+       { 0x30b2, 0x0227 },
+       { 0x30b3, 0x1e00 },
+       { 0x30b4, 0x0227 },
+       { 0x30b5, 0x1f00 },
+       { 0x30b6, 0x6227 },
+       { 0x30b7, 0xf800 },
+       { 0x30b8, 0x0000 },
+       { 0x30b9, 0xf000 },
+       { 0x30ba, 0x0000 },
+       { 0x30bb, 0xf000 },
+       { 0x30bc, 0x0000 },
+       { 0x30bd, 0xf000 },
+       { 0x30be, 0x0000 },
+       { 0x30bf, 0xf000 },
+       { 0x30c0, 0x2228 },
+       { 0x30c1, 0x3a03 },
+       { 0x30c2, 0x0228 },
+       { 0x30c3, 0x0801 },
+       { 0x30c4, 0x6255 },
+       { 0x30c5, 0x0c06 },
+       { 0x30c6, 0x0228 },
+       { 0x30c7, 0x5901 },
+       { 0x30c8, 0xe255 },
+       { 0x30c9, 0x030d },
+       { 0x30ca, 0x0255 },
+       { 0x30cb, 0x2c01 },
+       { 0x30cc, 0xe255 },
+       { 0x30cd, 0x4342 },
+       { 0x30ce, 0xe255 },
+       { 0x30cf, 0x73c0 },
+       { 0x30d0, 0x4255 },
+       { 0x30d1, 0x0c00 },
+       { 0x30d2, 0x0228 },
+       { 0x30d3, 0x1f01 },
+       { 0x30d4, 0x0228 },
+       { 0x30d5, 0x1e01 },
+       { 0x30d6, 0x0228 },
+       { 0x30d7, 0xfa00 },
+       { 0x30d8, 0x0000 },
+       { 0x30d9, 0xf000 },
+       { 0x30da, 0x0000 },
+       { 0x30db, 0xf000 },
+       { 0x30dc, 0x0000 },
+       { 0x30dd, 0xf000 },
+       { 0x30de, 0x0000 },
+       { 0x30df, 0xf000 },
+       { 0x30e0, 0x0000 },
+       { 0x30e1, 0xf000 },
+       { 0x30e2, 0x0000 },
+       { 0x30e3, 0xf000 },
+       { 0x30e4, 0x0000 },
+       { 0x30e5, 0xf000 },
+       { 0x30e6, 0x0000 },
+       { 0x30e7, 0xf000 },
+       { 0x30e8, 0x0000 },
+       { 0x30e9, 0xf000 },
+       { 0x30ea, 0x0000 },
+       { 0x30eb, 0xf000 },
+       { 0x30ec, 0x0000 },
+       { 0x30ed, 0xf000 },
+       { 0x30ee, 0x0000 },
+       { 0x30ef, 0xf000 },
+       { 0x30f0, 0x0228 },
+       { 0x30f1, 0x1a01 },
+       { 0x30f2, 0x0228 },
+       { 0x30f3, 0x1e00 },
+       { 0x30f4, 0x0228 },
+       { 0x30f5, 0x1f00 },
+       { 0x30f6, 0x6228 },
+       { 0x30f7, 0xf800 },
+       { 0x30f8, 0x0000 },
+       { 0x30f9, 0xf000 },
+       { 0x30fa, 0x0000 },
+       { 0x30fb, 0xf000 },
+       { 0x30fc, 0x0000 },
+       { 0x30fd, 0xf000 },
+       { 0x30fe, 0x0000 },
+       { 0x30ff, 0xf000 },
+       { 0x3100, 0x222b },
+       { 0x3101, 0x3a03 },
+       { 0x3102, 0x222b },
+       { 0x3103, 0x5803 },
+       { 0x3104, 0xe26f },
+       { 0x3105, 0x030d },
+       { 0x3106, 0x626f },
+       { 0x3107, 0x2c01 },
+       { 0x3108, 0xe26f },
+       { 0x3109, 0x4342 },
+       { 0x310a, 0xe26f },
+       { 0x310b, 0x73c0 },
+       { 0x310c, 0x026f },
+       { 0x310d, 0x0c00 },
+       { 0x310e, 0x022b },
+       { 0x310f, 0x1f01 },
+       { 0x3110, 0x022b },
+       { 0x3111, 0x1e01 },
+       { 0x3112, 0x022b },
+       { 0x3113, 0xfa00 },
+       { 0x3114, 0x0000 },
+       { 0x3115, 0xf000 },
+       { 0x3116, 0x0000 },
+       { 0x3117, 0xf000 },
+       { 0x3118, 0x0000 },
+       { 0x3119, 0xf000 },
+       { 0x311a, 0x0000 },
+       { 0x311b, 0xf000 },
+       { 0x311c, 0x0000 },
+       { 0x311d, 0xf000 },
+       { 0x311e, 0x0000 },
+       { 0x311f, 0xf000 },
+       { 0x3120, 0x022b },
+       { 0x3121, 0x0a01 },
+       { 0x3122, 0x022b },
+       { 0x3123, 0x1e00 },
+       { 0x3124, 0x022b },
+       { 0x3125, 0x1f00 },
+       { 0x3126, 0x622b },
+       { 0x3127, 0xf800 },
+       { 0x3128, 0x0000 },
+       { 0x3129, 0xf000 },
+       { 0x312a, 0x0000 },
+       { 0x312b, 0xf000 },
+       { 0x312c, 0x0000 },
+       { 0x312d, 0xf000 },
+       { 0x312e, 0x0000 },
+       { 0x312f, 0xf000 },
+       { 0x3130, 0x0000 },
+       { 0x3131, 0xf000 },
+       { 0x3132, 0x0000 },
+       { 0x3133, 0xf000 },
+       { 0x3134, 0x0000 },
+       { 0x3135, 0xf000 },
+       { 0x3136, 0x0000 },
+       { 0x3137, 0xf000 },
+       { 0x3138, 0x0000 },
+       { 0x3139, 0xf000 },
+       { 0x313a, 0x0000 },
+       { 0x313b, 0xf000 },
+       { 0x313c, 0x0000 },
+       { 0x313d, 0xf000 },
+       { 0x313e, 0x0000 },
+       { 0x313f, 0xf000 },
+       { 0x3140, 0x0000 },
+       { 0x3141, 0xf000 },
+       { 0x3142, 0x0000 },
+       { 0x3143, 0xf000 },
+       { 0x3144, 0x0000 },
+       { 0x3145, 0xf000 },
+       { 0x3146, 0x0000 },
+       { 0x3147, 0xf000 },
+       { 0x3148, 0x0000 },
+       { 0x3149, 0xf000 },
+       { 0x314a, 0x0000 },
+       { 0x314b, 0xf000 },
+       { 0x314c, 0x0000 },
+       { 0x314d, 0xf000 },
+       { 0x314e, 0x0000 },
+       { 0x314f, 0xf000 },
+       { 0x3150, 0x0000 },
+       { 0x3151, 0xf000 },
+       { 0x3152, 0x0000 },
+       { 0x3153, 0xf000 },
+       { 0x3154, 0x0000 },
+       { 0x3155, 0xf000 },
+       { 0x3156, 0x0000 },
+       { 0x3157, 0xf000 },
+       { 0x3158, 0x0000 },
+       { 0x3159, 0xf000 },
+       { 0x315a, 0x0000 },
+       { 0x315b, 0xf000 },
+       { 0x315c, 0x0000 },
+       { 0x315d, 0xf000 },
+       { 0x315e, 0x0000 },
+       { 0x315f, 0xf000 },
+       { 0x3160, 0x0000 },
+       { 0x3161, 0xf000 },
+       { 0x3162, 0x0000 },
+       { 0x3163, 0xf000 },
+       { 0x3164, 0x0000 },
+       { 0x3165, 0xf000 },
+       { 0x3166, 0x0000 },
+       { 0x3167, 0xf000 },
+       { 0x3168, 0x0000 },
+       { 0x3169, 0xf000 },
+       { 0x316a, 0x0000 },
+       { 0x316b, 0xf000 },
+       { 0x316c, 0x0000 },
+       { 0x316d, 0xf000 },
+       { 0x316e, 0x0000 },
+       { 0x316f, 0xf000 },
+       { 0x3170, 0x0000 },
+       { 0x3171, 0xf000 },
+       { 0x3172, 0x0000 },
+       { 0x3173, 0xf000 },
+       { 0x3174, 0x0000 },
+       { 0x3175, 0xf000 },
+       { 0x3176, 0x0000 },
+       { 0x3177, 0xf000 },
+       { 0x3178, 0x0000 },
+       { 0x3179, 0xf000 },
+       { 0x317a, 0x0000 },
+       { 0x317b, 0xf000 },
+       { 0x317c, 0x0000 },
+       { 0x317d, 0xf000 },
+       { 0x317e, 0x0000 },
+       { 0x317f, 0xf000 },
+       { 0x3180, 0x2001 },
+       { 0x3181, 0xf101 },
+       { 0x3182, 0x0000 },
+       { 0x3183, 0xf000 },
+       { 0x3184, 0x0000 },
+       { 0x3185, 0xf000 },
+       { 0x3186, 0x0000 },
+       { 0x3187, 0xf000 },
+       { 0x3188, 0x0000 },
+       { 0x3189, 0xf000 },
+       { 0x318a, 0x0000 },
+       { 0x318b, 0xf000 },
+       { 0x318c, 0x0000 },
+       { 0x318d, 0xf000 },
+       { 0x318e, 0x0000 },
+       { 0x318f, 0xf000 },
+       { 0x3190, 0x0000 },
+       { 0x3191, 0xf000 },
+       { 0x3192, 0x0000 },
+       { 0x3193, 0xf000 },
+       { 0x3194, 0x0000 },
+       { 0x3195, 0xf000 },
+       { 0x3196, 0x0000 },
+       { 0x3197, 0xf000 },
+       { 0x3198, 0x0000 },
+       { 0x3199, 0xf000 },
+       { 0x319a, 0x0000 },
+       { 0x319b, 0xf000 },
+       { 0x319c, 0x0000 },
+       { 0x319d, 0xf000 },
+       { 0x319e, 0x0000 },
+       { 0x319f, 0xf000 },
+       { 0x31a0, 0x0000 },
+       { 0x31a1, 0xf000 },
+       { 0x31a2, 0x0000 },
+       { 0x31a3, 0xf000 },
+       { 0x31a4, 0x0000 },
+       { 0x31a5, 0xf000 },
+       { 0x31a6, 0x0000 },
+       { 0x31a7, 0xf000 },
+       { 0x31a8, 0x0000 },
+       { 0x31a9, 0xf000 },
+       { 0x31aa, 0x0000 },
+       { 0x31ab, 0xf000 },
+       { 0x31ac, 0x0000 },
+       { 0x31ad, 0xf000 },
+       { 0x31ae, 0x0000 },
+       { 0x31af, 0xf000 },
+       { 0x31b0, 0x0000 },
+       { 0x31b1, 0xf000 },
+       { 0x31b2, 0x0000 },
+       { 0x31b3, 0xf000 },
+       { 0x31b4, 0x0000 },
+       { 0x31b5, 0xf000 },
+       { 0x31b6, 0x0000 },
+       { 0x31b7, 0xf000 },
+       { 0x31b8, 0x0000 },
+       { 0x31b9, 0xf000 },
+       { 0x31ba, 0x0000 },
+       { 0x31bb, 0xf000 },
+       { 0x31bc, 0x0000 },
+       { 0x31bd, 0xf000 },
+       { 0x31be, 0x0000 },
+       { 0x31bf, 0xf000 },
+       { 0x31c0, 0x0000 },
+       { 0x31c1, 0xf000 },
+       { 0x31c2, 0x0000 },
+       { 0x31c3, 0xf000 },
+       { 0x31c4, 0x0000 },
+       { 0x31c5, 0xf000 },
+       { 0x31c6, 0x0000 },
+       { 0x31c7, 0xf000 },
+       { 0x31c8, 0x0000 },
+       { 0x31c9, 0xf000 },
+       { 0x31ca, 0x0000 },
+       { 0x31cb, 0xf000 },
+       { 0x31cc, 0x0000 },
+       { 0x31cd, 0xf000 },
+       { 0x31ce, 0x0000 },
+       { 0x31cf, 0xf000 },
+       { 0x31d0, 0x0000 },
+       { 0x31d1, 0xf000 },
+       { 0x31d2, 0x0000 },
+       { 0x31d3, 0xf000 },
+       { 0x31d4, 0x0000 },
+       { 0x31d5, 0xf000 },
+       { 0x31d6, 0x0000 },
+       { 0x31d7, 0xf000 },
+       { 0x31d8, 0x0000 },
+       { 0x31d9, 0xf000 },
+       { 0x31da, 0x0000 },
+       { 0x31db, 0xf000 },
+       { 0x31dc, 0x0000 },
+       { 0x31dd, 0xf000 },
+       { 0x31de, 0x0000 },
+       { 0x31df, 0xf000 },
+       { 0x31e0, 0x0000 },
+       { 0x31e1, 0xf000 },
+       { 0x31e2, 0x0000 },
+       { 0x31e3, 0xf000 },
+       { 0x31e4, 0x0000 },
+       { 0x31e5, 0xf000 },
+       { 0x31e6, 0x0000 },
+       { 0x31e7, 0xf000 },
+       { 0x31e8, 0x0000 },
+       { 0x31e9, 0xf000 },
+       { 0x31ea, 0x0000 },
+       { 0x31eb, 0xf000 },
+       { 0x31ec, 0x0000 },
+       { 0x31ed, 0xf000 },
+       { 0x31ee, 0x0000 },
+       { 0x31ef, 0xf000 },
+       { 0x31f0, 0x0000 },
+       { 0x31f1, 0xf000 },
+       { 0x31f2, 0x0000 },
+       { 0x31f3, 0xf000 },
+       { 0x31f4, 0x0000 },
+       { 0x31f5, 0xf000 },
+       { 0x31f6, 0x0000 },
+       { 0x31f7, 0xf000 },
+       { 0x31f8, 0x0000 },
+       { 0x31f9, 0xf000 },
+       { 0x31fa, 0x0000 },
+       { 0x31fb, 0xf000 },
+       { 0x31fc, 0x0000 },
+       { 0x31fd, 0xf000 },
+       { 0x31fe, 0x0000 },
+       { 0x31ff, 0xf000 },
+       { 0x024d, 0xff50 },
+       { 0x0252, 0xff50 },
+       { 0x0259, 0x0112 },
+       { 0x025e, 0x0112 },
+};
+
+static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
+                           struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct arizona *arizona = dev_get_drvdata(codec->dev);
+       struct regmap *regmap = codec->control_data;
+       const struct reg_default *patch = NULL;
+       int i, patch_size;
+
+       switch (arizona->rev) {
+       case 0:
+               patch = wm5102_sysclk_reva_patch;
+               patch_size = ARRAY_SIZE(wm5102_sysclk_reva_patch);
+               break;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               if (patch)
+                       for (i = 0; i < patch_size; i++)
+                               regmap_write(regmap, patch[i].reg,
+                                            patch[i].def);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new wm5102_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
           ARIZONA_IN1_OSR_SHIFT, 1, 0),
@@ -297,7 +847,7 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
 
 static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
-                   0, NULL, 0),
+                   0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
                    ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
index 5421fd9fbcb5d37954e77f88962c31e9d953e2dc..4c0a8e496131c1cc2bf9933605dee7664928520d 100644 (file)
@@ -782,7 +782,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
                wm8978->mclk_idx = -1;
                f_sel = wm8978->f_mclk;
        } else {
-               if (!wm8978->f_pllout) {
+               if (!wm8978->f_opclk) {
                        /* We only enter here, if OPCLK is not used */
                        int ret = wm8978_configure_pll(codec);
                        if (ret < 0)
index 2b2dadc54dac5cfe729ddc2fd402e748195a6882..b2b2b37131bddc4acfb8fb0e51a9bba220da9907 100644 (file)
@@ -1045,6 +1045,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
                      struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
+       struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
        struct wm8994 *control = codec->control_data;
        int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA;
        int i;
@@ -1063,6 +1064,10 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w,
 
        switch (event) {
        case SND_SOC_DAPM_PRE_PMU:
+               /* Don't enable timeslot 2 if not in use */
+               if (wm8994->channels[0] <= 2)
+                       mask &= ~(WM8994_AIF1DAC2L_ENA | WM8994_AIF1DAC2R_ENA);
+
                val = snd_soc_read(codec, WM8994_AIF1_CONTROL_1);
                if ((val & WM8994_AIF1ADCL_SRC) &&
                    (val & WM8994_AIF1ADCR_SRC))
@@ -2687,7 +2692,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       bclk_rate = params_rate(params) * 4;
+       bclk_rate = params_rate(params);
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                bclk_rate *= 16;
@@ -2708,6 +2713,17 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
+       wm8994->channels[id] = params_channels(params);
+       switch (params_channels(params)) {
+       case 1:
+       case 2:
+               bclk_rate *= 2;
+               break;
+       default:
+               bclk_rate *= 4;
+               break;
+       }
+
        /* Try to find an appropriate sample rate; look for an exact match. */
        for (i = 0; i < ARRAY_SIZE(srs); i++)
                if (srs[i].rate == params_rate(params))
@@ -3706,7 +3722,7 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
        } while (count--);
 
        if (count == 0)
-               dev_warn(codec->dev, "No impedence range reported for jack\n");
+               dev_warn(codec->dev, "No impedance range reported for jack\n");
 
 #ifndef CONFIG_SND_SOC_WM8994_MODULE
        trace_snd_soc_jack_irq(dev_name(codec->dev));
index f142ec198db3dabfcfc5d1e20a51cdfd5e42874b..ccbce5791e95829b5d98ce472ac50d922e6e4703 100644 (file)
@@ -77,6 +77,7 @@ struct wm8994_priv {
        int sysclk_rate[2];
        int mclk[2];
        int aifclk[2];
+       int channels[2];
        struct wm8994_fll_config fll[2], fll_suspend[2];
        struct completion fll_locked[2];
        bool fll_locked_irq;
index b9f16598324c9b4b85373b6f55d785011c4d8b68..2ba08148655f32ee2fa7301c44d65b54e7ea02fb 100644 (file)
@@ -71,7 +71,6 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
                printk(KERN_WARNING "%s: got err interrupt 0x%lx\n",
                                __func__, cause);
                writel(cause, priv->io + KIRKWOOD_ERR_CAUSE);
-               return IRQ_HANDLED;
        }
 
        /* we've enabled only bytes interrupts ... */
@@ -178,7 +177,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
        }
 
        dram = mv_mbus_dram_info();
-       addr = virt_to_phys(substream->dma_buffer.area);
+       addr = substream->dma_buffer.addr;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                prdata->play_stream = substream;
                kirkwood_dma_conf_mbus_windows(priv->io,
index 542538d10ab7df46b02fc2b6bb3630c8bed45322..1d5db484d2df331b15e8e385cd32e2acd79e4d79 100644 (file)
@@ -95,7 +95,7 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
        do {
                cpu_relax();
                value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
-               value &= KIRKWOOD_DCO_SPCR_STATUS;
+               value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
        } while (value == 0);
 }
 
@@ -180,67 +180,72 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
-       unsigned long value;
-
-       /*
-        * specs says KIRKWOOD_PLAYCTL must be read 2 times before
-        * changing it. So read 1 time here and 1 later.
-        */
-       value = readl(priv->io + KIRKWOOD_PLAYCTL);
+       uint32_t ctl, value;
+
+       ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+       if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
+               unsigned timeout = 5000;
+               /*
+                * The Armada510 spec says that if we enter pause mode, the
+                * busy bit must be read back as clear _twice_.  Make sure
+                * we respect that otherwise we get DMA underruns.
+                */
+               do {
+                       value = ctl;
+                       ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+                       if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
+                               break;
+                       udelay(1);
+               } while (timeout--);
+
+               if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
+                       dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
+                                  ctl);
+       }
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               /* stop audio, enable interrupts */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
-
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
                /* configure audio & enable i2s playback */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
-               value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
+               ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
+               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
                                | KIRKWOOD_PLAYCTL_SPDIF_EN);
 
                if (priv->burst == 32)
-                       value |= KIRKWOOD_PLAYCTL_BURST_32;
+                       ctl |= KIRKWOOD_PLAYCTL_BURST_32;
                else
-                       value |= KIRKWOOD_PLAYCTL_BURST_128;
-               value |= KIRKWOOD_PLAYCTL_I2S_EN;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+                       ctl |= KIRKWOOD_PLAYCTL_BURST_128;
+               ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
                /* stop audio, disable interrupts */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
                /* disable all playbacks */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        default:
@@ -260,11 +265,6 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               /* stop audio, enable interrupts */
-               value = readl(priv->io + KIRKWOOD_RECCTL);
-               value |= KIRKWOOD_RECCTL_PAUSE;
-               writel(value, priv->io + KIRKWOOD_RECCTL);
-
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
index aa037b292f3dc05a9b6300c3cc4890988c0c2faf..c294fbb523fce2dac76a70d9e5537a47fee40042 100644 (file)
@@ -523,16 +523,24 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
 
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        /*
-                        * write a data to saif data register to trigger
-                        * the transfer
+                        * write data to saif data register to trigger
+                        * the transfer.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to write twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_writel(0, saif->base + SAIF_DATA);
+                       __raw_writel(0, saif->base + SAIF_DATA);
                } else {
                        /*
-                        * read a data from saif data register to trigger
-                        * the receive
+                        * read data from saif data register to trigger
+                        * the receive.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to read twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_readl(saif->base + SAIF_DATA);
+                       __raw_readl(saif->base + SAIF_DATA);
                }
 
                master_saif->ongoing = 1;
@@ -812,3 +820,4 @@ module_platform_driver(mxs_saif_driver);
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ASoC SAIF driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-saif");
index dc0ee76266261c998ec58a0f433dea92272767b3..d8e96b2cd03ec201306ceaebf3962531f48f0cac 100644 (file)
@@ -575,56 +575,53 @@ static struct snd_soc_card ams_delta_audio_card = {
 };
 
 /* Module init/exit */
-static struct platform_device *ams_delta_audio_platform_device;
-static struct platform_device *cx20442_platform_device;
-
-static int __init ams_delta_module_init(void)
+static __devinit int ams_delta_probe(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = &ams_delta_audio_card;
        int ret;
 
-       if (!(machine_is_ams_delta()))
-               return -ENODEV;
-
-       ams_delta_audio_platform_device =
-                       platform_device_alloc("soc-audio", -1);
-       if (!ams_delta_audio_platform_device)
-               return -ENOMEM;
+       card->dev = &pdev->dev;
 
-       platform_set_drvdata(ams_delta_audio_platform_device,
-                               &ams_delta_audio_card);
-
-       ret = platform_device_add(ams_delta_audio_platform_device);
-       if (ret)
-               goto err;
-
-       /*
-        * Codec platform device could be registered from elsewhere (board?),
-        * but I do it here as it makes sense only if used with the card.
-        */
-       cx20442_platform_device =
-               platform_device_register_simple("cx20442-codec", -1, NULL, 0);
+       ret = snd_soc_register_card(card);
+       if (ret) {
+               dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+               card->dev = NULL;
+               return ret;
+       }
        return 0;
-err:
-       platform_device_put(ams_delta_audio_platform_device);
-       return ret;
 }
-late_initcall(ams_delta_module_init);
 
-static void __exit ams_delta_module_exit(void)
+static int __devexit ams_delta_remove(struct platform_device *pdev)
 {
+       struct snd_soc_card *card = platform_get_drvdata(pdev);
+
        if (tty_unregister_ldisc(N_V253) != 0)
-               dev_warn(&ams_delta_audio_platform_device->dev,
+               dev_warn(&pdev->dev,
                        "failed to unregister V253 line discipline\n");
 
        snd_soc_jack_free_gpios(&ams_delta_hook_switch,
                        ARRAY_SIZE(ams_delta_hook_switch_gpios),
                        ams_delta_hook_switch_gpios);
 
-       platform_device_unregister(cx20442_platform_device);
-       platform_device_unregister(ams_delta_audio_platform_device);
+       snd_soc_unregister_card(card);
+       card->dev = NULL;
+       return 0;
 }
-module_exit(ams_delta_module_exit);
+
+#define DRV_NAME "ams-delta-audio"
+
+static struct platform_driver ams_delta_driver = {
+       .driver = {
+               .name = DRV_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = ams_delta_probe,
+       .remove = __devexit_p(ams_delta_remove),
+};
+
+module_platform_driver(ams_delta_driver);
 
 MODULE_AUTHOR("Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>");
 MODULE_DESCRIPTION("ALSA SoC driver for Amstrad E3 (Delta) videophone");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
index 4a73ef3ae12fdb35bced35e444f45b2eb144275c..a57a4e68dcc6166a2161b49b1d21ab7a8e49dc87 100644 (file)
@@ -216,7 +216,7 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
        twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
        twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
        twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
-       twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
+       twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator");
        twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
        twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
        twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
index 68f2cd1a92061504bd332c683d286c8ffe8414eb..5a6aeaf552a89666672e4bc2a46a3106ba26a532 100644 (file)
@@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev)
 
        mutex_init(&dmic->mutex);
 
-       dmic->fclk = clk_get(dmic->dev, "dmic_fck");
+       dmic->fclk = clk_get(dmic->dev, "fck");
        if (IS_ERR(dmic->fclk)) {
-               dev_err(dmic->dev, "cant get dmic_fck\n");
+               dev_err(dmic->dev, "cant get fck\n");
                return -ENODEV;
        }
 
index c02b001ee4b51816235147ddb420186c525ecd43..56965bb3275ccd5c2fea1dc3fe143e3e3e7b622d 100644 (file)
@@ -40,7 +40,6 @@
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
 
-#include <plat/omap_hwmod.h>
 #include "omap-mcpdm.h"
 #include "omap-pcm.h"
 
@@ -260,13 +259,9 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
        mutex_lock(&mcpdm->mutex);
 
        if (!dai->active) {
-               /* Enable watch dog for ES above ES 1.0 to avoid saturation */
-               if (omap_rev() != OMAP4430_REV_ES1_0) {
-                       u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+               u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
 
-                       omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL,
-                                        ctrl | MCPDM_WD_EN);
-               }
+               omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl | MCPDM_WD_EN);
                omap_mcpdm_open_streams(mcpdm);
        }
        mutex_unlock(&mcpdm->mutex);
index 677b567935f8055b6899f74e276bd4c0a39dd213..1ff6bb9ade5c98fd1ac644b0567f42f367d543d8 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/soc.h>
 
 #include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/board-zoom.h>
 #include <linux/platform_data/asoc-ti-mcbsp.h>
+#include <linux/platform_data/gpio-omap.h>
 
 /* Register descriptions for twl4030 codec part */
 #include <linux/mfd/twl4030-audio.h>
index 73ac5463c9e49efdee1dea93704e30438d1c7c37..e834faf859fdcf91e5c1889b1975b2fff357e206 100644 (file)
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
+#include <linux/platform_data/dma-mmp_tdma.h>
 #include <linux/platform_data/mmp_audio.h>
 #include <sound/pxa2xx-lib.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
-#include <mach/sram.h>
 #include <sound/dmaengine_pcm.h>
 
 struct mmp_dma_data {
index e7b83179aca2b1469af4ec1e03f35e62df1227b2..3c7c3a59ed3987b9017e89c07cf130a2a54c4a39 100644 (file)
@@ -207,6 +207,8 @@ config SND_SOC_BELLS
        select SND_SOC_WM5102
        select SND_SOC_WM5110
        select SND_SOC_WM9081
+       select SND_SOC_WM0010
+       select SND_SOC_WM1250_EV1
 
 config SND_SOC_LOWLAND
        tristate "Audio support for Wolfson Lowland"
index 5dc10dfc0d421e1f5722f53def90f868598efc8c..a2ca1567b9e4ff93a481d99065820d887ff8a72c 100644 (file)
@@ -247,7 +247,7 @@ static struct snd_soc_dai_link bells_dai_wm5110[] = {
        {
                .name = "Sub",
                .stream_name = "Sub",
-               .cpu_dai_name = "wm5102-aif3",
+               .cpu_dai_name = "wm5110-aif3",
                .codec_dai_name = "wm9081-hifi",
                .codec_name = "wm9081.1-006c",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
index 5328ae5539f16e67571566f313a5d9689f79cac5..9d7f30774a44d9524cb71f6697fc0ce96825295c 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/sh_dma.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/workqueue.h>
 #include <sound/soc.h>
 #include <sound/sh_fsi.h>
 
@@ -223,7 +224,7 @@ struct fsi_stream {
         */
        struct dma_chan         *chan;
        struct sh_dmae_slave    slave; /* see fsi_handler_init() */
-       struct tasklet_struct   tasklet;
+       struct work_struct      work;
        dma_addr_t              dma;
 };
 
@@ -1085,9 +1086,9 @@ static void fsi_dma_complete(void *data)
        snd_pcm_period_elapsed(io->substream);
 }
 
-static void fsi_dma_do_tasklet(unsigned long data)
+static void fsi_dma_do_work(struct work_struct *work)
 {
-       struct fsi_stream *io = (struct fsi_stream *)data;
+       struct fsi_stream *io = container_of(work, struct fsi_stream, work);
        struct fsi_priv *fsi = fsi_stream_to_priv(io);
        struct snd_soc_dai *dai;
        struct dma_async_tx_descriptor *desc;
@@ -1129,7 +1130,7 @@ static void fsi_dma_do_tasklet(unsigned long data)
         * FIXME
         *
         * In DMAEngine case, codec and FSI cannot be started simultaneously
-        * since FSI is using tasklet.
+        * since FSI is using the scheduler work queue.
         * Therefore, in capture case, probably FSI FIFO will have got
         * overflow error in this point.
         * in that case, DMA cannot start transfer until error was cleared.
@@ -1153,7 +1154,7 @@ static bool fsi_dma_filter(struct dma_chan *chan, void *param)
 
 static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       tasklet_schedule(&io->tasklet);
+       schedule_work(&io->work);
 
        return 0;
 }
@@ -1195,14 +1196,14 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev
                return fsi_stream_probe(fsi, dev);
        }
 
-       tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
+       INIT_WORK(&io->work, fsi_dma_do_work);
 
        return 0;
 }
 
 static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
 {
-       tasklet_kill(&io->tasklet);
+       cancel_work_sync(&io->work);
 
        fsi_stream_stop(fsi, io);
 
index d1198627fc40397b772adad1104579c35842507f..10d21be383f6d511221094a1fa3a9a3b9657a464 100644 (file)
@@ -2786,8 +2786,9 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
        val = (ucontrol->value.integer.value[0] + min) & mask;
        val = val << shift;
 
-       if (snd_soc_update_bits_locked(codec, reg, val_mask, val))
-                       return err;
+       err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
+       if (err < 0)
+               return err;
 
        if (snd_soc_volsw_is_stereo(mc)) {
                val_mask = mask << rshift;
index d0a4be38dc0f0473bdafe38d6b18ca30b11de61b..6e35bcae02df4b6a0e79709482a018f099615e21 100644 (file)
@@ -3745,7 +3745,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
 {
        struct snd_soc_codec *codec;
 
-       list_for_each_entry(codec, &card->codec_dev_list, list) {
+       list_for_each_entry(codec, &card->codec_dev_list, card_list) {
                soc_dapm_shutdown_codec(&codec->dapm);
                if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
                        snd_soc_dapm_set_bias_level(&codec->dapm,
index fa0fd8ddae90fc17f280543c9399741c9a33038b..1ab5fe04bfccb066853fc664d9db9bea68a9f8ce 100644 (file)
@@ -22,7 +22,7 @@
 
 /**
  * snd_soc_jack_new - Create a new jack
- * @card:  ASoC card
+ * @codec: ASoC codec
  * @id:    an identifying string for this jack
  * @type:  a bitmask of enum snd_jack_type values that can be detected by
  *         this jack
@@ -133,12 +133,13 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_add_zones);
 
 /**
  * snd_soc_jack_get_type - Based on the mic bias value, this function returns
- * the type of jack from the zones delcared in the jack type
+ * the type of jack from the zones declared in the jack type
  *
+ * @jack:  ASoC jack
  * @micbias_voltage:  mic bias voltage at adc channel when jack is plugged in
  *
  * Based on the mic bias value passed, this function helps identify
- * the type of jack from the already delcared jack zones
+ * the type of jack from the already declared jack zones
  */
 int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage)
 {
index 356611d9654db90e1f0206995de6b7064b83bdf9..54f7e25b6f7d479d30bed372ba5d12ce1abacb22 100644 (file)
@@ -57,6 +57,20 @@ static struct snd_soc_card mop500_card = {
        .num_links = ARRAY_SIZE(mop500_dai_links),
 };
 
+static void mop500_of_node_put(void)
+{
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               if (mop500_dai_links[i].cpu_of_node)
+                       of_node_put((struct device_node *)
+                               mop500_dai_links[i].cpu_of_node);
+               if (mop500_dai_links[i].codec_of_node)
+                       of_node_put((struct device_node *)
+                               mop500_dai_links[i].codec_of_node);
+       }
+}
+
 static int __devinit mop500_of_probe(struct platform_device *pdev,
                                struct device_node *np)
 {
@@ -69,6 +83,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
 
        if (!(msp_np[0] && msp_np[1] && codec_np)) {
                dev_err(&pdev->dev, "Phandle missing or invalid\n");
+               mop500_of_node_put();
                return -EINVAL;
        }
 
@@ -83,6 +98,7 @@ static int __devinit mop500_of_probe(struct platform_device *pdev,
 
        return 0;
 }
+
 static int __devinit mop500_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -128,6 +144,7 @@ static int __devexit mop500_remove(struct platform_device *pdev)
 
        snd_soc_unregister_card(mop500_card);
        mop500_ab8500_remove(mop500_card);
+       mop500_of_node_put();
 
        return 0;
 }
index b7c996e77570bd527a0a92fd904276a40c44cd2b..a26c6bf0a29b2ad570050519b7e6c87e418e62a5 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/pinctrl/consumer.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 #include <linux/of.h>
 
 #include <mach/hardware.h>
@@ -697,14 +698,11 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
                        platform_data = devm_kzalloc(&pdev->dev,
                                sizeof(struct msp_i2s_platform_data), GFP_KERNEL);
                        if (!platform_data)
-                               ret = -ENOMEM;
+                               return -ENOMEM;
                }
        } else
                if (!platform_data)
-                       ret = -EINVAL;
-
-       if (ret)
-               goto err_res;
+                       return -EINVAL;
 
        dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
                pdev->name, platform_data->id);
index 561bb74fd364ae388cb8dc2af548e014b0bb801b..dbf7999d18b4e7b300c0063f73aadf5dfa3f0f95 100644 (file)
@@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
        }
 
        mutex_init(&chip->mutex);
-       mutex_init(&chip->shutdown_mutex);
+       init_rwsem(&chip->shutdown_rwsem);
        chip->index = idx;
        chip->dev = dev;
        chip->card = card;
@@ -559,9 +559,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                return;
 
        card = chip->card;
-       mutex_lock(&register_mutex);
-       mutex_lock(&chip->shutdown_mutex);
+       down_write(&chip->shutdown_rwsem);
        chip->shutdown = 1;
+       up_write(&chip->shutdown_rwsem);
+
+       mutex_lock(&register_mutex);
        chip->num_interfaces--;
        if (chip->num_interfaces <= 0) {
                snd_card_disconnect(card);
@@ -582,11 +584,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                        snd_usb_mixer_disconnect(p);
                }
                usb_chip[chip->index] = NULL;
-               mutex_unlock(&chip->shutdown_mutex);
                mutex_unlock(&register_mutex);
                snd_card_free_when_closed(card);
        } else {
-               mutex_unlock(&chip->shutdown_mutex);
                mutex_unlock(&register_mutex);
        }
 }
@@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)
 {
        int err = -ENODEV;
 
+       down_read(&chip->shutdown_rwsem);
        if (!chip->shutdown && !chip->probing)
                err = usb_autopm_get_interface(chip->pm_intf);
+       up_read(&chip->shutdown_rwsem);
 
        return err;
 }
 
 void snd_usb_autosuspend(struct snd_usb_audio *chip)
 {
+       down_read(&chip->shutdown_rwsem);
        if (!chip->shutdown && !chip->probing)
                usb_autopm_put_interface(chip->pm_intf);
+       up_read(&chip->shutdown_rwsem);
 }
 
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
index afa4f9e9b27a2673b1fc955d680859cb7f964f02..814cb357ff88235dd87f37425985602867e3f5d5 100644 (file)
@@ -126,6 +126,7 @@ struct snd_usb_substream {
        struct snd_usb_endpoint *sync_endpoint;
        unsigned long flags;
        bool need_setup_ep;             /* (re)configure EP at prepare? */
+       unsigned int speed;             /* USB_SPEED_XXX */
 
        u64 formats;                    /* format bitmasks (all or'ed) */
        unsigned int num_formats;               /* number of supported audio formats (list) */
index 7f78c6d782b079d621d007f7c757e7cfd93587c7..34de6f2faf6120b492eb65208b9c9805aafe44e3 100644 (file)
@@ -35,6 +35,7 @@
 
 #define EP_FLAG_ACTIVATED      0
 #define EP_FLAG_RUNNING                1
+#define EP_FLAG_STOPPING       2
 
 /*
  * snd_usb_endpoint is a model that abstracts everything related to an
@@ -502,10 +503,20 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
        if (alive)
                snd_printk(KERN_ERR "timeout: still %d active urbs on EP #%x\n",
                                        alive, ep->ep_num);
+       clear_bit(EP_FLAG_STOPPING, &ep->flags);
 
        return 0;
 }
 
+/* sync the pending stop operation;
+ * this function itself doesn't trigger the stop operation
+ */
+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
+{
+       if (ep && test_bit(EP_FLAG_STOPPING, &ep->flags))
+               wait_clear_urbs(ep);
+}
+
 /*
  * unlink active urbs.
  */
@@ -918,6 +929,8 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
 
                if (wait)
                        wait_clear_urbs(ep);
+               else
+                       set_bit(EP_FLAG_STOPPING, &ep->flags);
        }
 }
 
index 6376ccf10fd470688daf103b37ff74bcf67af3ea..3d4c9705041ff5074c609dd2bfb303781a523c4e 100644 (file)
@@ -19,6 +19,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
                           int force, int can_sleep, int wait);
+void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
 int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct list_head *head);
index c83f6143c0eb34d8f77f969e1928427458b4268a..eeefbce3873c11dc35a6e174c4ace79daeeaa8c1 100644 (file)
@@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint {
                struct snd_usb_midi_out_endpoint* ep;
                struct snd_rawmidi_substream *substream;
                int active;
+               bool autopm_reference;
                uint8_t cable;          /* cable number << 4 */
                uint8_t state;
 #define STATE_UNKNOWN  0
@@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
                return -ENXIO;
        }
        err = usb_autopm_get_interface(umidi->iface);
-       if (err < 0)
+       port->autopm_reference = err >= 0;
+       if (err < 0 && err != -EACCES)
                return -EIO;
        substream->runtime->private_data = port;
        port->state = STATE_UNKNOWN;
@@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
        struct snd_usb_midi* umidi = substream->rmidi->private_data;
+       struct usbmidi_out_port *port = substream->runtime->private_data;
 
        substream_open(substream, 0);
-       usb_autopm_put_interface(umidi->iface);
+       if (port->autopm_reference)
+               usb_autopm_put_interface(umidi->iface);
        return 0;
 }
 
index fe56c9da38e9e6c78cdd6706f09e9639d8a502ab..298070e8f2d4e354da19dbca3e3d704a7b799321 100644 (file)
@@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
        unsigned char buf[2];
        int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
        int timeout = 10;
-       int err;
+       int idx = 0, err;
 
        err = snd_usb_autoresume(cval->mixer->chip);
        if (err < 0)
                return -EIO;
+       down_read(&chip->shutdown_rwsem);
        while (timeout-- > 0) {
+               if (chip->shutdown)
+                       break;
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
                if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                                   validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                                   buf, val_len) >= val_len) {
+                                   validx, idx, buf, val_len) >= val_len) {
                        *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
-                       snd_usb_autosuspend(cval->mixer->chip);
-                       return 0;
+                       err = 0;
+                       goto out;
                }
        }
-       snd_usb_autosuspend(cval->mixer->chip);
        snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
-       return -EINVAL;
+                   request, validx, idx, cval->val_type);
+       err = -EINVAL;
+
+ out:
+       up_read(&chip->shutdown_rwsem);
+       snd_usb_autosuspend(cval->mixer->chip);
+       return err;
 }
 
 static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
@@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
        struct snd_usb_audio *chip = cval->mixer->chip;
        unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
        unsigned char *val;
-       int ret, size;
+       int idx = 0, ret, size;
        __u8 bRequest;
 
        if (request == UAC_GET_CUR) {
@@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
        if (ret)
                goto error;
 
-       ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
+       down_read(&chip->shutdown_rwsem);
+       if (chip->shutdown)
+               ret = -ENODEV;
+       else {
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
+               ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
                              USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-                             validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                             buf, size);
+                             validx, idx, buf, size);
+       }
+       up_read(&chip->shutdown_rwsem);
        snd_usb_autosuspend(chip);
 
        if (ret < 0) {
 error:
                snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-                          request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
+                          request, validx, idx, cval->val_type);
                return ret;
        }
 
@@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 {
        struct snd_usb_audio *chip = cval->mixer->chip;
        unsigned char buf[2];
-       int val_len, err, timeout = 10;
+       int idx = 0, val_len, err, timeout = 10;
 
        if (cval->mixer->protocol == UAC_VERSION_1) {
                val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
        err = snd_usb_autoresume(chip);
        if (err < 0)
                return -EIO;
-       while (timeout-- > 0)
+       down_read(&chip->shutdown_rwsem);
+       while (timeout-- > 0) {
+               if (chip->shutdown)
+                       break;
+               idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);
                if (snd_usb_ctl_msg(chip->dev,
                                    usb_sndctrlpipe(chip->dev, 0), request,
                                    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-                                   validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-                                   buf, val_len) >= 0) {
-                       snd_usb_autosuspend(chip);
-                       return 0;
+                                   validx, idx, buf, val_len) >= 0) {
+                       err = 0;
+                       goto out;
                }
-       snd_usb_autosuspend(chip);
+       }
        snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
-                   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
-       return -EINVAL;
+                   request, validx, idx, cval->val_type, buf[0], buf[1]);
+       err = -EINVAL;
+
+ out:
+       up_read(&chip->shutdown_rwsem);
+       snd_usb_autosuspend(chip);
+       return err;
 }
 
 static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value)
index 690000db0ec01bb97e215f1b8470bd278a544ebd..ae2b7143522097bffd2a6060721d4f3db6b8000e 100644 (file)
@@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        if (value > 1)
                return -EINVAL;
        changed = value != mixer->audigy2nx_leds[index];
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown) {
+               err = -ENODEV;
+               goto out;
+       }
        if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))
                err = snd_usb_ctl_msg(mixer->chip->dev,
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
@@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                              value, index + 2, NULL, 0);
+ out:
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
        mixer->audigy2nx_leds[index] = value;
@@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
 
        for (i = 0; jacks[i].name; ++i) {
                snd_iprintf(buffer, "%s: ", jacks[i].name);
-               err = snd_usb_ctl_msg(mixer->chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = 0;
+               else
+                       err = snd_usb_ctl_msg(mixer->chip->dev,
                                      usb_rcvctrlpipe(mixer->chip->dev, 0),
                                      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
                                      USB_RECIP_INTERFACE, 0,
                                      jacks[i].unitid << 8, buf, 3);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err == 3 && (buf[0] == 3 || buf[0] == 6))
                        snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
                else
@@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
        else
                new_status = old_status & ~0x02;
        changed = new_status != old_status;
-       err = snd_usb_ctl_msg(mixer->chip->dev,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               err = -ENODEV;
+       else
+               err = snd_usb_ctl_msg(mixer->chip->dev,
                              usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                              50, 0, &new_status, 1);
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
        mixer->xonar_u1_status = new_status;
@@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
        u16 wIndex = kcontrol->private_value & 0xffff;
        u8 tmp;
+       int ret;
 
-       int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
                                  0, cpu_to_le16(wIndex),
                                  &tmp, sizeof(tmp), 1000);
+       up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
                snd_printk(KERN_ERR
@@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
        u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
        u16 wIndex = kcontrol->private_value & 0xffff;
        u16 wValue = ucontrol->value.integer.value[0];
+       int ret;
 
-       int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
                                  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
                                  cpu_to_le16(wValue), cpu_to_le16(wIndex),
                                  NULL, 0, 1000);
+       up_read(&mixer->chip->shutdown_rwsem);
 
        if (ret < 0) {
                snd_printk(KERN_ERR
@@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
                return -EINVAL;
 
 
-       err = snd_usb_ctl_msg(chip->dev,
+       down_read(&mixer->chip->shutdown_rwsem);
+       if (mixer->chip->shutdown)
+               err = -ENODEV;
+       else
+               err = snd_usb_ctl_msg(chip->dev,
                        usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
                        USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                        validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                        value, val_len);
+       up_read(&mixer->chip->shutdown_rwsem);
        if (err < 0)
                return err;
 
@@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
 
        if (!pval->is_cached) {
                /* Read current value */
-               err = snd_usb_ctl_msg(chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = -ENODEV;
+               else
+                       err = snd_usb_ctl_msg(chip->dev,
                                usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                                value, val_len);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err < 0)
                        return err;
 
@@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
        if (cur_val != new_val) {
                value[0] = new_val;
                value[1] = 0;
-               err = snd_usb_ctl_msg(chip->dev,
+               down_read(&mixer->chip->shutdown_rwsem);
+               if (mixer->chip->shutdown)
+                       err = -ENODEV;
+               else
+                       err = snd_usb_ctl_msg(chip->dev,
                                usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
                                USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
                                validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
                                value, val_len);
+               up_read(&mixer->chip->shutdown_rwsem);
                if (err < 0)
                        return err;
 
index 55e19e1b80ec4eeb282c91cea482ef7434cf8dce..ef6fa24fc473b08a89dd33ef8158f004185f54cb 100644 (file)
@@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
        unsigned int hwptr_done;
 
        subs = (struct snd_usb_substream *)substream->runtime->private_data;
+       if (subs->stream->chip->shutdown)
+               return SNDRV_PCM_POS_XRUN;
        spin_lock(&subs->lock);
        hwptr_done = subs->hwptr_done;
        substream->runtime->delay = snd_usb_pcm_delay(subs,
@@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)
 {
        int ret;
 
-       mutex_lock(&subs->stream->chip->shutdown_mutex);
        /* format changed */
        stop_endpoints(subs, 0, 0, 0);
        ret = snd_usb_endpoint_set_params(subs->data_endpoint,
@@ -455,19 +456,16 @@ static int configure_endpoint(struct snd_usb_substream *subs)
                                          subs->cur_audiofmt,
                                          subs->sync_endpoint);
        if (ret < 0)
-               goto unlock;
+               return ret;
 
        if (subs->sync_endpoint)
-               ret = snd_usb_endpoint_set_params(subs->data_endpoint,
+               ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
                                                  subs->pcm_format,
                                                  subs->channels,
                                                  subs->period_bytes,
                                                  subs->cur_rate,
                                                  subs->cur_audiofmt,
                                                  NULL);
-
-unlock:
-       mutex_unlock(&subs->stream->chip->shutdown_mutex);
        return ret;
 }
 
@@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
                return -EINVAL;
        }
 
-       if ((ret = set_format(subs, fmt)) < 0)
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (subs->stream->chip->shutdown)
+               ret = -ENODEV;
+       else
+               ret = set_format(subs, fmt);
+       up_read(&subs->stream->chip->shutdown_rwsem);
+       if (ret < 0)
                return ret;
 
        subs->interface = fmt->iface;
@@ -527,10 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
        subs->cur_audiofmt = NULL;
        subs->cur_rate = 0;
        subs->period_bytes = 0;
-       mutex_lock(&subs->stream->chip->shutdown_mutex);
-       stop_endpoints(subs, 0, 1, 1);
-       deactivate_endpoints(subs);
-       mutex_unlock(&subs->stream->chip->shutdown_mutex);
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (!subs->stream->chip->shutdown) {
+               stop_endpoints(subs, 0, 1, 1);
+               deactivate_endpoints(subs);
+       }
+       up_read(&subs->stream->chip->shutdown_rwsem);
        return snd_pcm_lib_free_vmalloc_buffer(substream);
 }
 
@@ -552,12 +558,22 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                return -ENXIO;
        }
 
-       if (snd_BUG_ON(!subs->data_endpoint))
-               return -EIO;
+       down_read(&subs->stream->chip->shutdown_rwsem);
+       if (subs->stream->chip->shutdown) {
+               ret = -ENODEV;
+               goto unlock;
+       }
+       if (snd_BUG_ON(!subs->data_endpoint)) {
+               ret = -EIO;
+               goto unlock;
+       }
+
+       snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
+       snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
 
        ret = set_format(subs, subs->cur_audiofmt);
        if (ret < 0)
-               return ret;
+               goto unlock;
 
        iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);
        alts = &iface->altsetting[subs->cur_audiofmt->altset_idx];
@@ -567,12 +583,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                                       subs->cur_audiofmt,
                                       subs->cur_rate);
        if (ret < 0)
-               return ret;
+               goto unlock;
 
        if (subs->need_setup_ep) {
                ret = configure_endpoint(subs);
                if (ret < 0)
-                       return ret;
+                       goto unlock;
                subs->need_setup_ep = false;
        }
 
@@ -592,9 +608,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        /* for playback, submit the URBs now; otherwise, the first hwptr_done
         * updates for all URBs would happen at the same time when starting */
        if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               return start_endpoints(subs, 1);
+               ret = start_endpoints(subs, 1);
 
-       return 0;
+ unlock:
+       up_read(&subs->stream->chip->shutdown_rwsem);
+       return ret;
 }
 
 static struct snd_pcm_hardware snd_usb_hardware =
@@ -647,7 +665,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,
                return 0;
        }
        /* check whether the period time is >= the data packet interval */
-       if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) {
+       if (subs->speed != USB_SPEED_FULL) {
                ptime = 125 * (1 << fp->datainterval);
                if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {
                        hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max);
@@ -925,7 +943,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
                return err;
 
        param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
-       if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+       if (subs->speed == USB_SPEED_FULL)
                /* full speed devices have fixed data packet interval */
                ptmin = 1000;
        if (ptmin == 1000)
index ebc1a5b5b3f1ba79c4c25ea66aadd34fd053e6d6..d218f763501fcdb9c4d038826a4bb12b14e4197b 100644 (file)
@@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s
                        }
                        snd_iprintf(buffer, "\n");
                }
-               if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
+               if (subs->speed != USB_SPEED_FULL)
                        snd_iprintf(buffer, "    Data packet interval: %d us\n",
                                    125 * (1 << fp->datainterval));
                // snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize);
@@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs,
                return;
        snd_iprintf(buffer, "    Packet Size = %d\n", ep->curpacksize);
        snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n",
-                   snd_usb_get_speed(subs->dev) == USB_SPEED_FULL
+                   subs->speed == USB_SPEED_FULL
                    ? get_full_speed_hz(ep->freqm)
                    : get_high_speed_hz(ep->freqm),
                    ep->freqm >> 16, ep->freqm & 0xffff);
index 083ed81160e58b094ee8f4fca637371aa5b5fff4..1de0c8c002a8a2d35bc80e7de9a9c764a5945fc2 100644 (file)
@@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
        subs->direction = stream;
        subs->dev = as->chip->dev;
        subs->txfr_quirk = as->chip->txfr_quirk;
+       subs->speed = snd_usb_get_speed(subs->dev);
 
        snd_usb_set_pcm_ops(as->pcm, stream);
 
index b8233ebe250f88648cc0baf2f6cfcfd13aa6de8f..ef42797f56fb56adf950eef3b764c5533263a8d9 100644 (file)
@@ -37,7 +37,7 @@ struct snd_usb_audio {
        struct usb_interface *pm_intf;
        u32 usb_id;
        struct mutex mutex;
-       struct mutex shutdown_mutex;
+       struct rw_semaphore shutdown_rwsem;
        unsigned int shutdown:1;
        unsigned int probing:1;
        unsigned int autosuspended:1;   
index 47264b4652b990f3d237531607060f94036ad7cf..f2989c525e48a6865729cff8962fca28d39532fc 100644 (file)
@@ -2602,6 +2602,9 @@ find_func_handler(struct pevent *pevent, char *func_name)
 {
        struct pevent_function_handler *func;
 
+       if (!pevent)
+               return NULL;
+
        for (func = pevent->func_handlers; func; func = func->next) {
                if (strcmp(func->name, func_name) == 0)
                        break;
@@ -4938,6 +4941,9 @@ enum pevent_errno __pevent_parse_format(struct event_format **eventp,
                goto event_alloc_failed;
        }
 
+       /* Add pevent to event so that it can be referenced */
+       event->pevent = pevent;
+
        ret = event_read_format(event);
        if (ret < 0) {
                ret = PEVENT_ERRNO__READ_FORMAT_FAILED;
@@ -5041,9 +5047,6 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf,
        if (event == NULL)
                return ret;
 
-       /* Add pevent to event so that it can be referenced */
-       event->pevent = pevent;
-
        if (add_event(pevent, event)) {
                ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
                goto event_add_failed;
index ad17855528f9adaa82cb37b0e6a8fe7ede2ed755..5ea4326ad11f5d16901d49ff68ddc36648671bf4 100644 (file)
@@ -209,7 +209,16 @@ static void free_arg(struct filter_arg *arg)
        switch (arg->type) {
        case FILTER_ARG_NONE:
        case FILTER_ARG_BOOLEAN:
+               break;
+
        case FILTER_ARG_NUM:
+               free_arg(arg->num.left);
+               free_arg(arg->num.right);
+               break;
+
+       case FILTER_ARG_EXP:
+               free_arg(arg->exp.left);
+               free_arg(arg->exp.right);
                break;
 
        case FILTER_ARG_STR:
@@ -218,6 +227,12 @@ static void free_arg(struct filter_arg *arg)
                free(arg->str.buffer);
                break;
 
+       case FILTER_ARG_VALUE:
+               if (arg->value.type == FILTER_STRING ||
+                   arg->value.type == FILTER_CHAR)
+                       free(arg->value.str);
+               break;
+
        case FILTER_ARG_OP:
                free_arg(arg->op.left);
                free_arg(arg->op.right);
index f7c968ad51780760fb5630e35b5091a8b0699826..00deed4d61598c5d40d8c607a0da1f42402cefd6 100644 (file)
@@ -184,9 +184,22 @@ SCRIPT_SH += perf-archive.sh
 grep-libs = $(filter -l%,$(1))
 strip-libs = $(filter-out -l%,$(1))
 
+TRACE_EVENT_DIR = ../lib/traceevent/
+
+ifneq ($(OUTPUT),)
+       TE_PATH=$(OUTPUT)
+else
+       TE_PATH=$(TRACE_EVENT_DIR)
+endif
+
+LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
+TE_LIB := -L$(TE_PATH) -ltraceevent
+
 PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
 PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py
 
+export LIBTRACEEVENT
+
 $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
        $(QUIET_GEN)CFLAGS='$(BASIC_CFLAGS)' $(PYTHON_WORD) util/setup.py \
          --quiet build_ext; \
@@ -198,17 +211,6 @@ $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS)
 
 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH))
 
-TRACE_EVENT_DIR = ../lib/traceevent/
-
-ifneq ($(OUTPUT),)
-       TE_PATH=$(OUTPUT)
-else
-       TE_PATH=$(TRACE_EVENT_DIR)
-endif
-
-LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
-TE_LIB := -L$(TE_PATH) -ltraceevent
-
 #
 # Single 'perf' binary right now:
 #
index 411ee5664e98e1e765bf992f379c16ec30569585..178b88ae3d2f174a5a085f233163d54cef152337 100644 (file)
@@ -414,7 +414,7 @@ static int show_html_page(const char *perf_cmd)
 int cmd_help(int argc, const char **argv, const char *prefix __maybe_unused)
 {
        bool show_all = false;
-       enum help_format help_format = HELP_FORMAT_NONE;
+       enum help_format help_format = HELP_FORMAT_MAN;
        struct option builtin_help_options[] = {
        OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
        OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
index dec8ced61fb00c2bc7114346db3edaf0f7dd89b7..7aaee39f6774f1fc49131dd7a3d67f002bee823c 100644 (file)
@@ -56,6 +56,10 @@ static int trace__read_syscall_info(struct trace *trace, int id)
 {
        char tp_name[128];
        struct syscall *sc;
+       const char *name = audit_syscall_to_name(id, trace->audit_machine);
+
+       if (name == NULL)
+               return -1;
 
        if (id > trace->syscalls.max) {
                struct syscall *nsyscalls = realloc(trace->syscalls.table, (id + 1) * sizeof(*sc));
@@ -75,11 +79,8 @@ static int trace__read_syscall_info(struct trace *trace, int id)
        }
 
        sc = trace->syscalls.table + id;
-       sc->name = audit_syscall_to_name(id, trace->audit_machine);
-       if (sc->name == NULL)
-               return -1;
-
-       sc->fmt = syscall_fmt__find(sc->name);
+       sc->name = name;
+       sc->fmt  = syscall_fmt__find(sc->name);
 
        snprintf(tp_name, sizeof(tp_name), "sys_enter_%s", sc->name);
        sc->tp_format = event_format__new("syscalls", tp_name);
@@ -267,6 +268,13 @@ again:
                        if (evlist->threads->map[0] == -1 || evlist->threads->nr > 1)
                                printf("%d ", sample.tid);
 
+                       if (sample.raw_data == NULL) {
+                               printf("%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
+                                      perf_evsel__name(evsel), sample.tid,
+                                      sample.cpu, sample.raw_size);
+                               continue;
+                       }
+
                        handler = evsel->handler.func;
                        handler(trace, evsel, &sample);
                }
index 276287783a03759af243ff3d55c3b848cd357d3f..c50985eaec41f479d2593dab749d061d3cb03c3d 100644 (file)
@@ -57,7 +57,7 @@ void get_term_dimensions(struct winsize *ws);
 #endif
 
 #ifdef __sparc__
-#include "../../arch/sparc/include/asm/unistd.h"
+#include "../../arch/sparc/include/uapi/asm/unistd.h"
 #define rmb()          asm volatile("":::"memory")
 #define cpu_relax()    asm volatile("":::"memory")
 #define CPUINFO_PROC   "cpu"
index 0568536ecf674fd3ce7e1b397e900a9fd515edcf..ef2f93ca7496d677592255d3bfaf91ed9ebb7c58 100644 (file)
@@ -610,6 +610,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
        char folded_sign = ' ';
        bool current_entry = ui_browser__is_current_entry(&browser->b, row);
        off_t row_offset = entry->row_offset;
+       bool first = true;
 
        if (current_entry) {
                browser->he_selection = entry;
@@ -633,10 +634,11 @@ static int hist_browser__show_entry(struct hist_browser *browser,
                        if (!perf_hpp__format[i].cond)
                                continue;
 
-                       if (i) {
+                       if (!first) {
                                slsmg_printf("  ");
                                width -= 2;
                        }
+                       first = false;
 
                        if (perf_hpp__format[i].color) {
                                hpp.ptr = &percent;
@@ -645,7 +647,7 @@ static int hist_browser__show_entry(struct hist_browser *browser,
 
                                ui_browser__set_percent_color(&browser->b, percent, current_entry);
 
-                               if (i == 0 && symbol_conf.use_callchain) {
+                               if (i == PERF_HPP__OVERHEAD && symbol_conf.use_callchain) {
                                        slsmg_printf("%c ", folded_sign);
                                        width -= 2;
                                }
index 28c18d1d52c3efceeb2847a1b68bd3dd000d45b6..516ecd9ddd6ee275c1e3144abc8a3d091b6114bb 100644 (file)
@@ -513,7 +513,8 @@ static int test__group1(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -599,7 +600,8 @@ static int test__group3(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 3);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
@@ -662,7 +664,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", !evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 1);
        TEST_ASSERT_VAL("wrong group name", !evsel->group_name);
@@ -676,7 +679,8 @@ static int test__group4(struct perf_evlist *evlist __maybe_unused)
        TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
-       TEST_ASSERT_VAL("wrong exclude guest", !evsel->attr.exclude_guest);
+       /* use of precise requires exclude_guest */
+       TEST_ASSERT_VAL("wrong exclude guest", evsel->attr.exclude_guest);
        TEST_ASSERT_VAL("wrong exclude host", !evsel->attr.exclude_host);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip == 2);
        TEST_ASSERT_VAL("wrong leader", evsel->leader == leader);
index aed38e4b9dfaf143020d3502c56a913acf9b0bb4..75c7b0fca6d96baadc7b084c84a73d3f89ea3273 100644 (file)
@@ -690,6 +690,9 @@ static int get_event_modifier(struct event_modifier *mod, char *str,
                        eH = 0;
                } else if (*str == 'p') {
                        precise++;
+                       /* use of precise requires exclude_guest */
+                       if (!exclude_GH)
+                               eG = 1;
                } else
                        break;
 
index d0f9f29cf181ad98900ebd9fe6baf2a915a32866..73d510269784a9ec1c68e3860f8f15dd24553567 100644 (file)
@@ -23,6 +23,7 @@ cflags += getenv('CFLAGS', '').split()
 
 build_lib = getenv('PYTHON_EXTBUILD_LIB')
 build_tmp = getenv('PYTHON_EXTBUILD_TMP')
+libtraceevent = getenv('LIBTRACEEVENT')
 
 ext_sources = [f.strip() for f in file('util/python-ext-sources')
                                if len(f.strip()) > 0 and f[0] != '#']
@@ -31,6 +32,7 @@ perf = Extension('perf',
                  sources = ext_sources,
                  include_dirs = ['util/include'],
                  extra_compile_args = cflags,
+                 extra_objects = [libtraceevent],
                  )
 
 setup(name='perf',
index b5b1b9211960884efd1a4c707fa8c56910db01f1..cfd1c0feb32d7da84d0b8b73b81883729fa623df 100644 (file)
@@ -260,6 +260,12 @@ static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
        if (path != NULL)
                goto out_path;
 
+       if (!self->ms.map)
+               goto out_ip;
+
+       if (!strncmp(self->ms.map->dso->long_name, "/tmp/perf-", 10))
+               goto out_ip;
+
        snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
                 self->ms.map->dso->long_name, self->ip);
        fp = popen(cmd, "r");
index fb4b7ea6752fd86121a968fa77212727f603d7e9..8b3e5939afb6ea00ef6cd74275eae99f35de0c25 100644 (file)
@@ -39,7 +39,6 @@ int thread__set_comm(struct thread *self, const char *comm)
        err = self->comm == NULL ? -ENOMEM : 0;
        if (!err) {
                self->comm_set = true;
-               map_groups__flush(&self->mg);
        }
        return err;
 }
index 2655ae9a3ad8d9e6f7676006336a5e3b8fec99d1..ea095abbe97e7cc7bec26c575a1d177dc1e2c61d 100644 (file)
@@ -206,8 +206,10 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
        retval = pread(fd, msr, sizeof *msr, offset);
        close(fd);
 
-       if (retval != sizeof *msr)
+       if (retval != sizeof *msr) {
+               fprintf(stderr, "%s offset 0x%zx read failed\n", pathname, offset);
                return -1;
+       }
 
        return 0;
 }
@@ -1101,7 +1103,9 @@ void turbostat_loop()
 
 restart:
        retval = for_all_cpus(get_counters, EVEN_COUNTERS);
-       if (retval) {
+       if (retval < -1) {
+               exit(retval);
+       } else if (retval == -1) {
                re_initialize();
                goto restart;
        }
@@ -1114,7 +1118,9 @@ restart:
                }
                sleep(interval_sec);
                retval = for_all_cpus(get_counters, ODD_COUNTERS);
-               if (retval) {
+               if (retval < -1) {
+                       exit(retval);
+               } else if (retval == -1) {
                        re_initialize();
                        goto restart;
                }
@@ -1126,7 +1132,9 @@ restart:
                flush_stdout();
                sleep(interval_sec);
                retval = for_all_cpus(get_counters, EVEN_COUNTERS);
-               if (retval) {
+               if (retval < -1) {
+                       exit(retval);
+               } else if (retval == -1) {
                        re_initialize();
                        goto restart;
                }
@@ -1545,8 +1553,11 @@ void turbostat_init()
 int fork_it(char **argv)
 {
        pid_t child_pid;
+       int status;
 
-       for_all_cpus(get_counters, EVEN_COUNTERS);
+       status = for_all_cpus(get_counters, EVEN_COUNTERS);
+       if (status)
+               exit(status);
        /* clear affinity side-effect of get_counters() */
        sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
        gettimeofday(&tv_even, (struct timezone *)NULL);
@@ -1556,7 +1567,6 @@ int fork_it(char **argv)
                /* child */
                execvp(argv[0], argv);
        } else {
-               int status;
 
                /* parent */
                if (child_pid == -1) {
@@ -1568,7 +1578,7 @@ int fork_it(char **argv)
                signal(SIGQUIT, SIG_IGN);
                if (waitpid(child_pid, &status, 0) == -1) {
                        perror("wait");
-                       exit(1);
+                       exit(status);
                }
        }
        /*
@@ -1585,7 +1595,7 @@ int fork_it(char **argv)
 
        fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
 
-       return 0;
+       return status;
 }
 
 void cmdline(int argc, char **argv)
@@ -1594,7 +1604,7 @@ void cmdline(int argc, char **argv)
 
        progname = argv[0];
 
-       while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) {
+       while ((opt = getopt(argc, argv, "+pPSvi:sc:sC:m:M:")) != -1) {
                switch (opt) {
                case 'p':
                        show_core_only++;
index b51d787176d323bb3a2d6f0016b2d2cf4db16d3d..c7ba7614061b22f04d78b5d60e3669dd8767fbed 100755 (executable)
@@ -1740,8 +1740,10 @@ sub install {
     open(IN, "$output_config") or dodie("Can't read config file");
     while (<IN>) {
        if (/CONFIG_MODULES(=y)?/) {
-           $install_mods = 1 if (defined($1));
-           last;
+           if (defined($1)) {
+               $install_mods = 1;
+               last;
+           }
        }
     }
     close(IN);
index 43480149119ee773f0a32cc8abe995903609fd11..85baf11e2acd7d11aa4990a0f7f53f8d28689a20 100644 (file)
@@ -1,4 +1,4 @@
-TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug epoll
+TARGETS = breakpoints kcmp mqueue vm cpu-hotplug memory-hotplug
 
 all:
        for TARGET in $(TARGETS); do \
diff --git a/tools/testing/selftests/epoll/Makefile b/tools/testing/selftests/epoll/Makefile
deleted file mode 100644 (file)
index 19806ed..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Makefile for epoll selftests
-
-all: test_epoll
-%: %.c
-       gcc -pthread -g -o $@ $^
-
-run_tests: all
-       ./test_epoll
-
-clean:
-       $(RM) test_epoll
diff --git a/tools/testing/selftests/epoll/test_epoll.c b/tools/testing/selftests/epoll/test_epoll.c
deleted file mode 100644 (file)
index e0fcff1..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- *  tools/testing/selftests/epoll/test_epoll.c
- *
- *  Copyright 2012 Adobe Systems Incorporated
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  Paton J. Lewis <palewis@adobe.com>
- *
- */
-
-#include <errno.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/epoll.h>
-#include <sys/socket.h>
-
-/*
- * A pointer to an epoll_item_private structure will be stored in the epoll
- * item's event structure so that we can get access to the epoll_item_private
- * data after calling epoll_wait:
- */
-struct epoll_item_private {
-       int index;  /* Position of this struct within the epoll_items array. */
-       int fd;
-       uint32_t events;
-       pthread_mutex_t mutex;  /* Guards the following variables... */
-       int stop;
-       int status;  /* Stores any error encountered while handling item. */
-       /* The following variable allows us to test whether we have encountered
-          a problem while attempting to cancel and delete the associated
-          event. When the test program exits, 'deleted' should be exactly
-          one. If it is greater than one, then the failed test reflects a real
-          world situation where we would have tried to access the epoll item's
-          private data after deleting it: */
-       int deleted;
-};
-
-struct epoll_item_private *epoll_items;
-
-/*
- * Delete the specified item from the epoll set. In a real-world secneario this
- * is where we would free the associated data structure, but in this testing
- * environment we retain the structure so that we can test for double-deletion:
- */
-void delete_item(int index)
-{
-       __sync_fetch_and_add(&epoll_items[index].deleted, 1);
-}
-
-/*
- * A pointer to a read_thread_data structure will be passed as the argument to
- * each read thread:
- */
-struct read_thread_data {
-       int stop;
-       int status;  /* Indicates any error encountered by the read thread. */
-       int epoll_set;
-};
-
-/*
- * The function executed by the read threads:
- */
-void *read_thread_function(void *function_data)
-{
-       struct read_thread_data *thread_data =
-               (struct read_thread_data *)function_data;
-       struct epoll_event event_data;
-       struct epoll_item_private *item_data;
-       char socket_data;
-
-       /* Handle events until we encounter an error or this thread's 'stop'
-          condition is set: */
-       while (1) {
-               int result = epoll_wait(thread_data->epoll_set,
-                                       &event_data,
-                                       1,      /* Number of desired events */
-                                       1000);  /* Timeout in ms */
-               if (result < 0) {
-                       /* Breakpoints signal all threads. Ignore that while
-                          debugging: */
-                       if (errno == EINTR)
-                               continue;
-                       thread_data->status = errno;
-                       return 0;
-               } else if (thread_data->stop)
-                       return 0;
-               else if (result == 0)  /* Timeout */
-                       continue;
-
-               /* We need the mutex here because checking for the stop
-                  condition and re-enabling the epoll item need to be done
-                  together as one atomic operation when EPOLL_CTL_DISABLE is
-                  available: */
-               item_data = (struct epoll_item_private *)event_data.data.ptr;
-               pthread_mutex_lock(&item_data->mutex);
-
-               /* Remove the item from the epoll set if we want to stop
-                  handling that event: */
-               if (item_data->stop)
-                       delete_item(item_data->index);
-               else {
-                       /* Clear the data that was written to the other end of
-                          our non-blocking socket: */
-                       do {
-                               if (read(item_data->fd, &socket_data, 1) < 1) {
-                                       if ((errno == EAGAIN) ||
-                                           (errno == EWOULDBLOCK))
-                                               break;
-                                       else
-                                               goto error_unlock;
-                               }
-                       } while (item_data->events & EPOLLET);
-
-                       /* The item was one-shot, so re-enable it: */
-                       event_data.events = item_data->events;
-                       if (epoll_ctl(thread_data->epoll_set,
-                                                 EPOLL_CTL_MOD,
-                                                 item_data->fd,
-                                                 &event_data) < 0)
-                               goto error_unlock;
-               }
-
-               pthread_mutex_unlock(&item_data->mutex);
-       }
-
-error_unlock:
-       thread_data->status = item_data->status = errno;
-       pthread_mutex_unlock(&item_data->mutex);
-       return 0;
-}
-
-/*
- * A pointer to a write_thread_data structure will be passed as the argument to
- * the write thread:
- */
-struct write_thread_data {
-       int stop;
-       int status;  /* Indicates any error encountered by the write thread. */
-       int n_fds;
-       int *fds;
-};
-
-/*
- * The function executed by the write thread. It writes a single byte to each
- * socket in turn until the stop condition for this thread is set. If writing to
- * a socket would block (i.e. errno was EAGAIN), we leave that socket alone for
- * the moment and just move on to the next socket in the list. We don't care
- * about the order in which we deliver events to the epoll set. In fact we don't
- * care about the data we're writing to the pipes at all; we just want to
- * trigger epoll events:
- */
-void *write_thread_function(void *function_data)
-{
-       const char data = 'X';
-       int index;
-       struct write_thread_data *thread_data =
-               (struct write_thread_data *)function_data;
-       while (!write_thread_data->stop)
-               for (index = 0;
-                    !thread_data->stop && (index < thread_data->n_fds);
-                    ++index)
-                       if ((write(thread_data->fds[index], &data, 1) < 1) &&
-                               (errno != EAGAIN) &&
-                               (errno != EWOULDBLOCK)) {
-                               write_thread_data->status = errno;
-                               return;
-                       }
-}
-
-/*
- * Arguments are currently ignored:
- */
-int main(int argc, char **argv)
-{
-       const int n_read_threads = 100;
-       const int n_epoll_items = 500;
-       int index;
-       int epoll_set = epoll_create1(0);
-       struct write_thread_data write_thread_data = {
-               0, 0, n_epoll_items, malloc(n_epoll_items * sizeof(int))
-       };
-       struct read_thread_data *read_thread_data =
-               malloc(n_read_threads * sizeof(struct read_thread_data));
-       pthread_t *read_threads = malloc(n_read_threads * sizeof(pthread_t));
-       pthread_t write_thread;
-
-       printf("-----------------\n");
-       printf("Runing test_epoll\n");
-       printf("-----------------\n");
-
-       epoll_items = malloc(n_epoll_items * sizeof(struct epoll_item_private));
-
-       if (epoll_set < 0 || epoll_items == 0 || write_thread_data.fds == 0 ||
-               read_thread_data == 0 || read_threads == 0)
-               goto error;
-
-       if (sysconf(_SC_NPROCESSORS_ONLN) < 2) {
-               printf("Error: please run this test on a multi-core system.\n");
-               goto error;
-       }
-
-       /* Create the socket pairs and epoll items: */
-       for (index = 0; index < n_epoll_items; ++index) {
-               int socket_pair[2];
-               struct epoll_event event_data;
-               if (socketpair(AF_UNIX,
-                              SOCK_STREAM | SOCK_NONBLOCK,
-                              0,
-                              socket_pair) < 0)
-                       goto error;
-               write_thread_data.fds[index] = socket_pair[0];
-               epoll_items[index].index = index;
-               epoll_items[index].fd = socket_pair[1];
-               if (pthread_mutex_init(&epoll_items[index].mutex, NULL) != 0)
-                       goto error;
-               /* We always use EPOLLONESHOT because this test is currently
-                  structured to demonstrate the need for EPOLL_CTL_DISABLE,
-                  which only produces useful information in the EPOLLONESHOT
-                  case (without EPOLLONESHOT, calling epoll_ctl with
-                  EPOLL_CTL_DISABLE will never return EBUSY). If support for
-                  testing events without EPOLLONESHOT is desired, it should
-                  probably be implemented in a separate unit test. */
-               epoll_items[index].events = EPOLLIN | EPOLLONESHOT;
-               if (index < n_epoll_items / 2)
-                       epoll_items[index].events |= EPOLLET;
-               epoll_items[index].stop = 0;
-               epoll_items[index].status = 0;
-               epoll_items[index].deleted = 0;
-               event_data.events = epoll_items[index].events;
-               event_data.data.ptr = &epoll_items[index];
-               if (epoll_ctl(epoll_set,
-                             EPOLL_CTL_ADD,
-                             epoll_items[index].fd,
-                             &event_data) < 0)
-                       goto error;
-       }
-
-       /* Create and start the read threads: */
-       for (index = 0; index < n_read_threads; ++index) {
-               read_thread_data[index].stop = 0;
-               read_thread_data[index].status = 0;
-               read_thread_data[index].epoll_set = epoll_set;
-               if (pthread_create(&read_threads[index],
-                                  NULL,
-                                  read_thread_function,
-                                  &read_thread_data[index]) != 0)
-                       goto error;
-       }
-
-       if (pthread_create(&write_thread,
-                          NULL,
-                          write_thread_function,
-                          &write_thread_data) != 0)
-               goto error;
-
-       /* Cancel all event pollers: */
-#ifdef EPOLL_CTL_DISABLE
-       for (index = 0; index < n_epoll_items; ++index) {
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               ++epoll_items[index].stop;
-               if (epoll_ctl(epoll_set,
-                             EPOLL_CTL_DISABLE,
-                             epoll_items[index].fd,
-                             NULL) == 0)
-                       delete_item(index);
-               else if (errno != EBUSY) {
-                       pthread_mutex_unlock(&epoll_items[index].mutex);
-                       goto error;
-               }
-               /* EBUSY means events were being handled; allow the other thread
-                  to delete the item. */
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-       }
-#else
-       for (index = 0; index < n_epoll_items; ++index) {
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               ++epoll_items[index].stop;
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-               /* Wait in case a thread running read_thread_function is
-                  currently executing code between epoll_wait and
-                  pthread_mutex_lock with this item. Note that a longer delay
-                  would make double-deletion less likely (at the expense of
-                  performance), but there is no guarantee that any delay would
-                  ever be sufficient. Note also that we delete all event
-                  pollers at once for testing purposes, but in a real-world
-                  environment we are likely to want to be able to cancel event
-                  pollers at arbitrary times. Therefore we can't improve this
-                  situation by just splitting this loop into two loops
-                  (i.e. signal 'stop' for all items, sleep, and then delete all
-                  items). We also can't fix the problem via EPOLL_CTL_DEL
-                  because that command can't prevent the case where some other
-                  thread is executing read_thread_function within the region
-                  mentioned above: */
-               usleep(1);
-               pthread_mutex_lock(&epoll_items[index].mutex);
-               if (!epoll_items[index].deleted)
-                       delete_item(index);
-               pthread_mutex_unlock(&epoll_items[index].mutex);
-       }
-#endif
-
-       /* Shut down the read threads: */
-       for (index = 0; index < n_read_threads; ++index)
-               __sync_fetch_and_add(&read_thread_data[index].stop, 1);
-       for (index = 0; index < n_read_threads; ++index) {
-               if (pthread_join(read_threads[index], NULL) != 0)
-                       goto error;
-               if (read_thread_data[index].status)
-                       goto error;
-       }
-
-       /* Shut down the write thread: */
-       __sync_fetch_and_add(&write_thread_data.stop, 1);
-       if ((pthread_join(write_thread, NULL) != 0) || write_thread_data.status)
-               goto error;
-
-       /* Check for final error conditions: */
-       for (index = 0; index < n_epoll_items; ++index) {
-               if (epoll_items[index].status != 0)
-                       goto error;
-               if (pthread_mutex_destroy(&epoll_items[index].mutex) < 0)
-                       goto error;
-       }
-       for (index = 0; index < n_epoll_items; ++index)
-               if (epoll_items[index].deleted != 1) {
-                       printf("Error: item data deleted %1d times.\n",
-                                  epoll_items[index].deleted);
-                       goto error;
-               }
-
-       printf("[PASS]\n");
-       return 0;
-
- error:
-       printf("[FAIL]\n");
-       return errno;
-}
index e626fa553c5ae1b2db0f044fe0c987e13e5af9ec..6d25dcd2e97a9015da4c927c36b13d3763dc5827 100644 (file)
@@ -232,7 +232,7 @@ const struct option longopts[] = {
        }
 };
 
-static void help()
+static void help(void)
 {
        fprintf(stderr, "Usage: virtio_test [--help]"
                " [--no-indirect]"
index cd1b03e80899960147c9fc18777a1f5a35f9e08f..b76edf2f833349c8762c95ec4fc20d36f44c73f0 100644 (file)
@@ -35,7 +35,7 @@
 #include <sys/mount.h>
 #include <sys/statfs.h>
 #include "../../include/uapi/linux/magic.h"
-#include "../../include/linux/kernel-page-flags.h"
+#include "../../include/uapi/linux/kernel-page-flags.h"
 
 
 #ifndef MAX_PATH
index af0f22fb1ef71e6dc94c620873bc3241c2883430..aca6edcbbc6fa09113389e87b3e76a55a871da98 100644 (file)
@@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location,
        int retval;
        int rc = -1;
        int namesize;
-       int i;
+       unsigned int i;
 
        mode |= S_IFREG;
 
@@ -381,25 +381,28 @@ error:
 
 static char *cpio_replace_env(char *new_location)
 {
-       char expanded[PATH_MAX + 1];
-       char env_var[PATH_MAX + 1];
-       char *start;
-       char *end;
-
-       for (start = NULL; (start = strstr(new_location, "${")); ) {
-               end = strchr(start, '}');
-               if (start < end) {
-                       *env_var = *expanded = '\0';
-                       strncat(env_var, start + 2, end - start - 2);
-                       strncat(expanded, new_location, start - new_location);
-                       strncat(expanded, getenv(env_var), PATH_MAX);
-                       strncat(expanded, end + 1, PATH_MAX);
-                       strncpy(new_location, expanded, PATH_MAX);
-               } else
-                       break;
-       }
-
-       return new_location;
+       char expanded[PATH_MAX + 1];
+       char env_var[PATH_MAX + 1];
+       char *start;
+       char *end;
+
+       for (start = NULL; (start = strstr(new_location, "${")); ) {
+               end = strchr(start, '}');
+               if (start < end) {
+                       *env_var = *expanded = '\0';
+                       strncat(env_var, start + 2, end - start - 2);
+                       strncat(expanded, new_location, start - new_location);
+                       strncat(expanded, getenv(env_var),
+                               PATH_MAX - strlen(expanded));
+                       strncat(expanded, end + 1,
+                               PATH_MAX - strlen(expanded));
+                       strncpy(new_location, expanded, PATH_MAX);
+                       new_location[PATH_MAX] = 0;
+               } else
+                       break;
+       }
+
+       return new_location;
 }
 
 
index e59bb63cb089634c7d9bed701be0581bf536726a..be70035fd42a14edad4c24ae411c4b9d3fdf396c 100644 (file)
@@ -1322,9 +1322,7 @@ EXPORT_SYMBOL_GPL(kvm_release_page_clean);
 
 void kvm_release_pfn_clean(pfn_t pfn)
 {
-       WARN_ON(is_error_pfn(pfn));
-
-       if (!kvm_is_mmio_pfn(pfn))
+       if (!is_error_pfn(pfn) && !kvm_is_mmio_pfn(pfn))
                put_page(pfn_to_page(pfn));
 }
 EXPORT_SYMBOL_GPL(kvm_release_pfn_clean);